[BACK]Return to scard.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/scard.c, Revision 1.2

1.1       markus      1: /*
                      2:  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
                      3:  *
                      4:  * Redistribution and use in source and binary forms, with or without
                      5:  * modification, are permitted provided that the following conditions
                      6:  * are met:
                      7:  * 1. Redistributions of source code must retain the above copyright
                      8:  *    notice, this list of conditions and the following disclaimer.
                      9:  * 2. Redistributions in binary form must reproduce the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer in the
                     11:  *    documentation and/or other materials provided with the distribution.
                     12:  *
                     13:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     14:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     15:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     16:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     17:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     18:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     19:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     20:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     21:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     22:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     23:  */
                     24:
                     25: #ifdef SMARTCARD
                     26: #include "includes.h"
1.2     ! itojun     27: RCSID("$OpenBSD: scard.c,v 1.1 2001/06/26 05:33:34 markus Exp $");
1.1       markus     28:
                     29: #include <openssl/engine.h>
                     30: #include <sectok.h>
                     31:
                     32: #include "key.h"
                     33: #include "log.h"
                     34: #include "xmalloc.h"
                     35: #include "scard.h"
                     36:
                     37: #define CLA_SSH 0x05
                     38: #define INS_DECRYPT 0x10
                     39: #define INS_GET_KEYLENGTH 0x20
                     40: #define INS_GET_PUBKEY 0x30
                     41: #define INS_GET_RESPONSE 0xc0
                     42:
                     43: #define MAX_BUF_SIZE 256
                     44:
                     45: static int sc_fd = -1;
                     46: static int sc_reader_num = 0;
                     47: static int cla = 0x00; /* class */
                     48:
                     49: /* interface to libsectok */
                     50:
                     51: static int
                     52: sc_open(int num)
                     53: {
                     54:        int n;
                     55:        u_char atr[256];
                     56:
                     57:        if (sc_fd >= 0)
                     58:                return sc_fd;
                     59:        sc_reader_num = num;
                     60:
                     61:        sc_fd = scopen(sc_reader_num, 0, NULL);
                     62:        if (sc_fd < 0) {
                     63:                error("scopen failed %d", sc_fd);
                     64:                return sc_fd;
                     65:        }
                     66:        n = screset(sc_fd, atr, NULL);
                     67:        if (n <= 0) {
                     68:                error("screset failed.");
                     69:                sc_fd = -1;
                     70:                return sc_fd;
                     71:        }
                     72:        debug("open ok %d", sc_fd);
                     73:        return sc_fd;
                     74: }
                     75:
                     76: static int
                     77: sc_reset(void)
                     78: {
                     79:        scclose(sc_fd);
                     80:        sc_fd = -1;
                     81:        return sc_open(sc_reader_num);
                     82: }
                     83:
                     84: static int
                     85: selectfile(int fd, int f0, int f1, int verbose)
                     86: {
                     87:        int n, r1, r2, code;
                     88:        u_char buf[2], obuf[256];
                     89:
                     90:        buf[0] = f0;
                     91:        buf[1] = f1;
                     92:        n = scrw(sc_fd, cla, 0xa4, 0, 0, 2, buf, sizeof obuf, obuf, &r1, &r2);
                     93:        if (n < 0) {
                     94:                error("selectfile: scwrite failed");
                     95:                return -2;
                     96:        }
                     97:        if (r1 == 0x90 || r1 == 0x61)
                     98:                code = 0;
                     99:        else if (r1 == 0x6a && r2 == 0x82)
                    100:                /* file not found */
                    101:                code = -1;
                    102:        else
                    103:                code = -2;
                    104:        if (verbose && n > 0)
                    105:                dump_reply(obuf, n, 0, 0);
                    106:        if (verbose || code == -2) {
                    107:                error("%x.%x: %s", f0, f1, get_r1r2s(r1, r2));
                    108:        }
                    109:        return code;
                    110: }
                    111:
                    112: static int
                    113: sc_enable_applet(void)
                    114: {
                    115:        u_char data[MAX_BUF_SIZE];
                    116:        u_char progID[2], contID[2], aid[MAX_BUF_SIZE];
                    117:        int i, len, rv, r1, r2, aid_len;
                    118:
                    119:        len = rv = r1 = r2 = 0;
                    120:        progID[0] = 0x77;
                    121:        progID[1] = 0x77;
                    122:        contID[0] = 0x77;
                    123:        contID[1] = 0x78;
                    124:        aid_len = 5;
                    125:
                    126:        for (i = 0; i < 16; i++)
                    127:                aid[i] = 0x77;
                    128:
                    129:        rv = selectfile(sc_fd, contID[0], contID[1], 0);
                    130:        if (rv < 0) {
                    131:                error("selectfile failed");
                    132:                return -1;
                    133:        }
                    134:        for (i = 0; i < aid_len; i++)
                    135:                data[i] = (u_char) aid[i];
                    136:        rv = scwrite(sc_fd, cla, 0xa4, 0x04, 0, aid_len, data, &r1, &r2);
                    137:        if (r1 != 0x90 && r1 != 0x61) {
                    138:                /* error */
                    139:                error("selecting the cardlet: ");
                    140:                for (i = 0; i < aid_len; i++) {
                    141:                        error("%02x", (u_char) aid[i]);
                    142:                }
                    143:                print_r1r2(r1, r2);
                    144:                return -1;
                    145:        }
                    146:        return 0;
                    147: }
                    148:
                    149: static int
                    150: sc_read_pubkey(Key * k)
                    151: {
                    152:        u_char          buf[256];
                    153:        char           *p;
                    154:        int             len, rv, r1, r2;
                    155:
                    156:        len = rv = r1 = r2 = 0;
                    157:
                    158:        /* get key size */
                    159:        rv = scread(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 2, buf, &r1, &r2);
                    160:        if (rv < 0) {
                    161:                error("could not obtain key length.");
                    162:                return rv;
                    163:        }
                    164:        len = (buf[0] << 8) | buf[1];
                    165:        error("len %d r1 %d r2 %d", len, r1, r2);
                    166:        len /= 8;
                    167:
                    168:        /* get n */
                    169:        rv = scread(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, len, buf, &r1, &r2);
                    170:        if (rv < 0) {
                    171:                error("could not obtain public key");
                    172:                return rv;
                    173:        }
                    174:        debug("len %d r1 %d r2 %d", len, r1, r2);
                    175:        BN_bin2bn(buf, len, k->rsa->n);
                    176:
                    177:        /* currently the java applet just stores 'n' */
                    178:        BN_set_word(k->rsa->e, 35);     /* XXX */
                    179:
                    180:        p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
                    181:        debug("fingerprint %d %s", key_size(k), p);
                    182:        xfree(p);
                    183:
                    184:        return 0;
                    185: }
                    186:
                    187: /* private key operations */
                    188:
                    189: static int
                    190: sc_private_decrypt(int flen, unsigned char *from,
                    191:     unsigned char *to, RSA *rsa, int padding)
                    192: {
                    193:         int rv, num, r1, r2, olen;
                    194:         u_char *padded = NULL;
                    195:
                    196:        debug("sc_private_decrypt called");
                    197:
                    198:        olen = num = r1 = r2 = 0;
                    199:         if (padding != RSA_PKCS1_PADDING)
                    200:                goto err;
                    201:
                    202:         num = BN_num_bytes(rsa->n);
                    203:        padded = xmalloc(num);
                    204:
                    205:        rv = scwrite(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, num, from, &r1, &r2);
                    206:        if (rv < 0) {
                    207:                error("scwrite() for decrypt failed.");
                    208:                goto err;
                    209:        }
                    210:        if (r1 != 0x90 && r1 != 0x61) {
                    211:                error("INS_DECRYPT: r1 %x r2 %x", r1, r2);
                    212:                 goto err;
                    213:        }
                    214:        rv = scread(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, num, padded, &r1, &r2);
                    215:        if (rv < 0) {
                    216:                error("scread() for decrypt failed");
                    217:                goto err;
                    218:        }
                    219:        if (r1 != 0x90 && r1 != 0x61) {
                    220:                error("INS_GET_RESPONSE: r1 %x r2 %x", r1, r2);
                    221:                 goto err;
                    222:        }
                    223:        debug("r1 %x r2 %x", r1, r2);
                    224:        olen = RSA_padding_check_PKCS1_type_2(to, num, padded + 1, num - 1, num);
                    225: err:
                    226:        if (padded)
                    227:                xfree(padded);
                    228:        return olen;
                    229: }
                    230:
                    231:
                    232: static int
                    233: sc_private_encrypt(int flen, unsigned char *from,
                    234:     unsigned char *to, RSA *rsa, int padding)
                    235: {
                    236:         int rv, i, num, r1, r2;
                    237:         u_char *padded = NULL;
                    238:
                    239:        num = r1 = r2 = 0;
                    240:         if (padding != RSA_PKCS1_PADDING)
                    241:                goto err;
                    242:
                    243:        error("sc_private_encrypt called");
                    244:         num = BN_num_bytes(rsa->n);
                    245:        padded = xmalloc(num);
                    246:        i = RSA_padding_add_PKCS1_type_1(padded, num, from, flen);
                    247:        if (i <= 0) {
                    248:                error("RSA_padding_add_PKCS1_type_1 failed");
                    249:                goto err;
                    250:        }
                    251:         rv = scwrite(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, num, padded, &r1, &r2);
                    252:         if (rv < 0) {
                    253:                 error("scwrite() for rsa failed");
                    254:                sc_reset();
                    255:                 goto err;
                    256:         }
                    257:        if (r1 != 0x90 && r1 != 0x61) {
                    258:                error("INS_DECRYPT: r1 %x r2 %x", r1, r2);
                    259:                 goto err;
                    260:        }
                    261:         rv = scread(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, num, to, &r1, &r2);
                    262:         if (rv < 0) {
                    263:                 error("scread() for rsa failed");
                    264:                sc_reset();
                    265:                 goto err;
                    266:         }
                    267:        if (r1 != 0x90 && r1 != 0x61) {
                    268:                error("INS_GET_RESPONSE: r1 %x r2 %x", r1, r2);
                    269:                 goto err;
                    270:        }
                    271: err:
                    272:        if (padded)
                    273:                xfree(padded);
                    274:        return num;
                    275: }
                    276:
                    277: /* engine for overloading private key operations */
                    278:
                    279: static ENGINE *smart_engine = NULL;
                    280: static RSA_METHOD smart_rsa =
                    281: {
                    282:         "smartcard",
                    283:         NULL,
                    284:         NULL,
                    285:         NULL,
                    286:         NULL,
                    287:         NULL,
                    288:         NULL,
                    289:         NULL,
                    290:         NULL,
                    291:         0,
                    292:         NULL,
                    293: };
                    294:
                    295: ENGINE *
1.2     ! itojun    296: sc_get_engine(void)
1.1       markus    297: {
                    298:        RSA_METHOD *def;
                    299:
                    300:        def = RSA_get_default_openssl_method();
                    301:
                    302:        /* overload */
                    303:        smart_rsa.rsa_priv_enc  = sc_private_encrypt;
                    304:        smart_rsa.rsa_priv_dec  = sc_private_decrypt;
                    305:
                    306:        /* just use the OpenSSL version */
                    307:         smart_rsa.rsa_pub_enc   = def->rsa_pub_enc;
                    308:         smart_rsa.rsa_pub_dec   = def->rsa_pub_dec;
                    309:        smart_rsa.rsa_mod_exp   = def->rsa_mod_exp;
                    310:        smart_rsa.bn_mod_exp    = def->bn_mod_exp;
                    311:        smart_rsa.init          = def->init;
                    312:        smart_rsa.finish        = def->finish;
                    313:        smart_rsa.flags         = def->flags;
                    314:        smart_rsa.app_data      = def->app_data;
                    315:        smart_rsa.rsa_sign      = def->rsa_sign;
                    316:        smart_rsa.rsa_verify    = def->rsa_verify;
                    317:
                    318:        smart_engine = ENGINE_new();
                    319:
                    320:        ENGINE_set_id(smart_engine, "xxx");
                    321:        ENGINE_set_name(smart_engine, "xxx");
                    322:        ENGINE_set_RSA(smart_engine, &smart_rsa);
                    323:        ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
                    324:        ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
                    325:        ENGINE_set_RAND(smart_engine, RAND_SSLeay());
                    326:        ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
                    327:
                    328:        return smart_engine;
                    329: }
                    330:
                    331: Key *
                    332: sc_get_key(int sc_reader_num)
                    333: {
                    334:        Key *k;
                    335:        int rv;
                    336:
                    337:        rv = sc_open (sc_reader_num);
                    338:        if (rv < 0) {
                    339:                error("sc_open failed");
                    340:                return NULL;
                    341:        }
                    342:        rv = sc_enable_applet();
                    343:        if (rv < 0) {
                    344:                error("sc_enable_applet failed");
                    345:                return NULL;
                    346:        }
                    347:        k = key_new(KEY_RSA);
                    348:        if (k == NULL) {
                    349:                return NULL;
                    350:        }
                    351:        rv = sc_read_pubkey (k);
                    352:        if (rv < 0) {
                    353:                error("sc_read_pubkey failed");
                    354:                key_free(k);
                    355:                return NULL;
                    356:        }
                    357:        return k;
                    358: }
                    359: #endif