[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.20

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.20    ! markus     27: RCSID("$OpenBSD: scard.c,v 1.19 2002/03/21 16:54:53 markus Exp $");
1.1       markus     28:
                     29: #include <openssl/engine.h>
1.19      markus     30: #include <openssl/evp.h>
1.1       markus     31: #include <sectok.h>
                     32:
                     33: #include "key.h"
                     34: #include "log.h"
                     35: #include "xmalloc.h"
                     36: #include "scard.h"
1.19      markus     37: #include "readpass.h"
1.1       markus     38:
1.18      markus     39: #ifdef OPENSSL_VERSION_NUMBER
                     40: #if OPENSSL_VERSION_NUMBER >= 0x00907000L
                     41: #define RSA_get_default_openssl_method RSA_get_default_method
                     42: #define DSA_get_default_openssl_method DSA_get_default_method
                     43: #define DH_get_default_openssl_method DH_get_default_method
                     44: #define ENGINE_set_BN_mod_exp(x,y)
                     45: #endif
                     46: #endif
                     47:
1.1       markus     48: #define CLA_SSH 0x05
                     49: #define INS_DECRYPT 0x10
                     50: #define INS_GET_KEYLENGTH 0x20
                     51: #define INS_GET_PUBKEY 0x30
                     52: #define INS_GET_RESPONSE 0xc0
                     53:
                     54: #define MAX_BUF_SIZE 256
                     55:
                     56: static int sc_fd = -1;
1.11      markus     57: static char *sc_reader_id = NULL;
1.1       markus     58: static int cla = 0x00; /* class */
                     59:
                     60: /* interface to libsectok */
                     61:
1.16      deraadt    62: static int
1.5       markus     63: sc_open(void)
1.1       markus     64: {
1.4       markus     65:        int sw;
1.1       markus     66:
                     67:        if (sc_fd >= 0)
                     68:                return sc_fd;
                     69:
1.11      markus     70:        sc_fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
1.1       markus     71:        if (sc_fd < 0) {
1.5       markus     72:                error("sectok_open failed: %s", sectok_get_sw(sw));
1.8       jakob      73:                return SCARD_ERROR_FAIL;
                     74:        }
                     75:        if (! sectok_cardpresent(sc_fd)) {
1.11      markus     76:                debug("smartcard in reader %s not present, skipping",
                     77:                    sc_reader_id);
1.10      jakob      78:                sc_close();
1.8       jakob      79:                return SCARD_ERROR_NOCARD;
1.1       markus     80:        }
1.7       rees       81:        if (sectok_reset(sc_fd, 0, NULL, &sw) <= 0) {
1.4       markus     82:                error("sectok_reset failed: %s", sectok_get_sw(sw));
1.1       markus     83:                sc_fd = -1;
1.8       jakob      84:                return SCARD_ERROR_FAIL;
1.1       markus     85:        }
1.7       rees       86:        if ((cla = cyberflex_inq_class(sc_fd)) < 0)
                     87:                cla = 0;
1.5       markus     88:
1.4       markus     89:        debug("sc_open ok %d", sc_fd);
1.1       markus     90:        return sc_fd;
                     91: }
                     92:
1.16      deraadt    93: static int
1.4       markus     94: sc_enable_applet(void)
1.1       markus     95: {
1.7       rees       96:        static u_char aid[] = {0xfc, 0x53, 0x73, 0x68, 0x2e, 0x62, 0x69, 0x6e};
                     97:        int sw = 0;
1.1       markus     98:
1.7       rees       99:        /* select applet id */
                    100:        sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, sizeof aid, aid, 0, NULL, &sw);
1.4       markus    101:        if (!sectok_swOK(sw)) {
                    102:                error("sectok_apdu failed: %s", sectok_get_sw(sw));
1.5       markus    103:                sc_close();
                    104:                return -1;
                    105:        }
                    106:        return 0;
                    107: }
                    108:
1.16      deraadt   109: static int
1.5       markus    110: sc_init(void)
                    111: {
1.8       jakob     112:        int status;
                    113:
                    114:        status = sc_open();
                    115:        if (status == SCARD_ERROR_NOCARD) {
                    116:                return SCARD_ERROR_NOCARD;
                    117:        }
                    118:        if (status < 0 ) {
1.5       markus    119:                error("sc_open failed");
1.8       jakob     120:                return status;
1.5       markus    121:        }
                    122:        if (sc_enable_applet() < 0) {
                    123:                error("sc_enable_applet failed");
1.8       jakob     124:                return SCARD_ERROR_APPLET;
1.1       markus    125:        }
                    126:        return 0;
                    127: }
                    128:
1.16      deraadt   129: static int
1.1       markus    130: sc_read_pubkey(Key * k)
                    131: {
1.4       markus    132:        u_char buf[2], *n;
                    133:        char *p;
1.14      markus    134:        int len, sw, status = -1;
1.1       markus    135:
1.4       markus    136:        len = sw = 0;
1.15      djm       137:        n = NULL;
1.1       markus    138:
1.8       jakob     139:        if (sc_fd < 0) {
                    140:                status = sc_init();
                    141:                if (status < 0 )
1.14      markus    142:                        goto err;
1.8       jakob     143:        }
1.5       markus    144:
1.1       markus    145:        /* get key size */
1.4       markus    146:        sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,
1.16      deraadt   147:            sizeof(buf), buf, &sw);
1.4       markus    148:        if (!sectok_swOK(sw)) {
                    149:                error("could not obtain key length: %s", sectok_get_sw(sw));
1.14      markus    150:                goto err;
1.1       markus    151:        }
                    152:        len = (buf[0] << 8) | buf[1];
                    153:        len /= 8;
1.4       markus    154:        debug("INS_GET_KEYLENGTH: len %d sw %s", len, sectok_get_sw(sw));
1.1       markus    155:
1.4       markus    156:        n = xmalloc(len);
1.1       markus    157:        /* get n */
1.4       markus    158:        sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
                    159:        if (!sectok_swOK(sw)) {
                    160:                error("could not obtain public key: %s", sectok_get_sw(sw));
1.14      markus    161:                goto err;
1.1       markus    162:        }
1.14      markus    163:
1.4       markus    164:        debug("INS_GET_KEYLENGTH: sw %s", sectok_get_sw(sw));
                    165:
                    166:        if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
                    167:                error("c_read_pubkey: BN_bin2bn failed");
1.14      markus    168:                goto err;
1.4       markus    169:        }
1.1       markus    170:
                    171:        /* currently the java applet just stores 'n' */
1.4       markus    172:        if (!BN_set_word(k->rsa->e, 35)) {
                    173:                error("c_read_pubkey: BN_set_word(e, 35) failed");
1.14      markus    174:                goto err;
1.4       markus    175:        }
1.1       markus    176:
1.14      markus    177:        status = 0;
1.1       markus    178:        p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
                    179:        debug("fingerprint %d %s", key_size(k), p);
                    180:        xfree(p);
                    181:
1.14      markus    182: err:
                    183:        if (n != NULL)
                    184:                xfree(n);
                    185:        sc_close();
                    186:        return status;
1.1       markus    187: }
                    188:
                    189: /* private key operations */
                    190:
                    191: static int
1.20    ! markus    192: sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa,
1.18      markus    193:     int padding)
1.1       markus    194: {
1.4       markus    195:        u_char *padded = NULL;
1.14      markus    196:        int sw, len, olen, status = -1;
1.1       markus    197:
                    198:        debug("sc_private_decrypt called");
                    199:
1.4       markus    200:        olen = len = sw = 0;
1.8       jakob     201:        if (sc_fd < 0) {
                    202:                status = sc_init();
                    203:                if (status < 0 )
1.5       markus    204:                        goto err;
1.8       jakob     205:        }
1.4       markus    206:        if (padding != RSA_PKCS1_PADDING)
1.1       markus    207:                goto err;
                    208:
1.4       markus    209:        len = BN_num_bytes(rsa->n);
                    210:        padded = xmalloc(len);
1.1       markus    211:
1.18      markus    212:        sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, (u_char *)from,
                    213:            0, NULL, &sw);
1.4       markus    214:        if (!sectok_swOK(sw)) {
                    215:                error("sc_private_decrypt: INS_DECRYPT failed: %s",
                    216:                    sectok_get_sw(sw));
1.1       markus    217:                goto err;
                    218:        }
1.4       markus    219:        sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
1.16      deraadt   220:            len, padded, &sw);
1.4       markus    221:        if (!sectok_swOK(sw)) {
                    222:                error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
                    223:                    sectok_get_sw(sw));
1.1       markus    224:                goto err;
                    225:        }
1.4       markus    226:        olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
                    227:            len);
1.1       markus    228: err:
                    229:        if (padded)
                    230:                xfree(padded);
1.14      markus    231:        sc_close();
1.8       jakob     232:        return (olen >= 0 ? olen : status);
1.1       markus    233: }
                    234:
                    235: static int
1.20    ! markus    236: sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa,
1.18      markus    237:     int padding)
1.1       markus    238: {
1.4       markus    239:        u_char *padded = NULL;
1.14      markus    240:        int sw, len, status = -1;
1.1       markus    241:
1.4       markus    242:        len = sw = 0;
1.8       jakob     243:        if (sc_fd < 0) {
                    244:                status = sc_init();
                    245:                if (status < 0 )
1.5       markus    246:                        goto err;
1.8       jakob     247:        }
1.4       markus    248:        if (padding != RSA_PKCS1_PADDING)
1.1       markus    249:                goto err;
                    250:
1.3       markus    251:        debug("sc_private_encrypt called");
1.4       markus    252:        len = BN_num_bytes(rsa->n);
                    253:        padded = xmalloc(len);
                    254:
1.18      markus    255:        if (RSA_padding_add_PKCS1_type_1(padded, len, (u_char *)from, flen) <= 0) {
1.1       markus    256:                error("RSA_padding_add_PKCS1_type_1 failed");
                    257:                goto err;
                    258:        }
1.4       markus    259:        sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw);
                    260:        if (!sectok_swOK(sw)) {
                    261:                error("sc_private_decrypt: INS_DECRYPT failed: %s",
                    262:                    sectok_get_sw(sw));
                    263:                goto err;
                    264:        }
                    265:        sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
1.16      deraadt   266:            len, to, &sw);
1.4       markus    267:        if (!sectok_swOK(sw)) {
                    268:                error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
                    269:                    sectok_get_sw(sw));
                    270:                goto err;
1.1       markus    271:        }
                    272: err:
                    273:        if (padded)
                    274:                xfree(padded);
1.14      markus    275:        sc_close();
1.8       jakob     276:        return (len >= 0 ? len : status);
1.1       markus    277: }
                    278:
1.12      markus    279: /* called on free */
                    280:
                    281: static int (*orig_finish)(RSA *rsa) = NULL;
                    282:
                    283: static int
                    284: sc_finish(RSA *rsa)
                    285: {
                    286:        if (orig_finish)
                    287:                orig_finish(rsa);
                    288:        sc_close();
                    289:        return 1;
                    290: }
                    291:
                    292:
1.1       markus    293: /* engine for overloading private key operations */
                    294:
                    295: static ENGINE *smart_engine = NULL;
1.18      markus    296: static RSA_METHOD smart_rsa;
1.1       markus    297:
                    298: ENGINE *
1.2       itojun    299: sc_get_engine(void)
1.1       markus    300: {
1.18      markus    301:        const RSA_METHOD *def;
1.1       markus    302:
                    303:        def = RSA_get_default_openssl_method();
                    304:
1.18      markus    305:        /* use the OpenSSL version */
                    306:        memcpy(&smart_rsa, def, sizeof(smart_rsa));
                    307:
                    308:        smart_rsa.name          = "sectok";
                    309:
1.1       markus    310:        /* overload */
                    311:        smart_rsa.rsa_priv_enc  = sc_private_encrypt;
                    312:        smart_rsa.rsa_priv_dec  = sc_private_decrypt;
                    313:
1.12      markus    314:        /* save original */
                    315:        orig_finish             = def->finish;
                    316:        smart_rsa.finish        = sc_finish;
                    317:
1.17      markus    318:        if ((smart_engine = ENGINE_new()) == NULL)
                    319:                fatal("ENGINE_new failed");
1.1       markus    320:
1.4       markus    321:        ENGINE_set_id(smart_engine, "sectok");
                    322:        ENGINE_set_name(smart_engine, "libsectok");
1.18      markus    323:
1.1       markus    324:        ENGINE_set_RSA(smart_engine, &smart_rsa);
                    325:        ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
                    326:        ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
                    327:        ENGINE_set_RAND(smart_engine, RAND_SSLeay());
                    328:        ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
                    329:
                    330:        return smart_engine;
                    331: }
                    332:
1.5       markus    333: void
                    334: sc_close(void)
                    335: {
                    336:        if (sc_fd >= 0) {
                    337:                sectok_close(sc_fd);
                    338:                sc_fd = -1;
                    339:        }
                    340: }
                    341:
1.1       markus    342: Key *
1.11      markus    343: sc_get_key(const char *id)
1.1       markus    344: {
                    345:        Key *k;
1.9       jakob     346:        int status;
1.1       markus    347:
1.11      markus    348:        if (sc_reader_id != NULL)
                    349:                xfree(sc_reader_id);
                    350:        sc_reader_id = xstrdup(id);
                    351:
1.1       markus    352:        k = key_new(KEY_RSA);
                    353:        if (k == NULL) {
                    354:                return NULL;
                    355:        }
1.9       jakob     356:        status = sc_read_pubkey(k);
                    357:        if (status == SCARD_ERROR_NOCARD) {
                    358:                key_free(k);
                    359:                return NULL;
                    360:        }
                    361:        if (status < 0 ) {
1.1       markus    362:                error("sc_read_pubkey failed");
                    363:                key_free(k);
                    364:                return NULL;
                    365:        }
                    366:        return k;
1.19      markus    367: }
                    368:
                    369: #define NUM_RSA_KEY_ELEMENTS 5+1
                    370: #define COPY_RSA_KEY(x, i) \
                    371:        do { \
                    372:                len = BN_num_bytes(prv->rsa->x); \
                    373:                elements[i] = xmalloc(len); \
                    374:                debug("#bytes %d", len); \
                    375:                if (BN_bn2bin(prv->rsa->x, elements[i]) < 0) \
                    376:                        goto done; \
                    377:        } while (0)
                    378:
                    379: static int
                    380: get_AUT0(char *aut0)
                    381: {
                    382:        const EVP_MD *evp_md = EVP_sha1();
                    383:        EVP_MD_CTX md;
                    384:        char *pass;
                    385:
                    386:        pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN);
                    387:        if (pass == NULL)
                    388:                return -1;
                    389:        EVP_DigestInit(&md, evp_md);
                    390:        EVP_DigestUpdate(&md, pass, strlen(pass));
                    391:        EVP_DigestFinal(&md, aut0, NULL);
                    392:        memset(pass, 0, strlen(pass));
                    393:        xfree(pass);
                    394:        return 0;
                    395: }
                    396:
                    397: int
                    398: sc_put_key(Key *prv, const char *id)
                    399: {
                    400:        u_char *elements[NUM_RSA_KEY_ELEMENTS];
                    401:        u_char key_fid[2];
                    402:        u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63};
                    403:        u_char AUT0[EVP_MAX_MD_SIZE];
                    404:        int len, status = -1, i, fd = -1, ret;
                    405:        int sw = 0, cla = 0x00;
                    406:
                    407:        for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
                    408:                elements[i] = NULL;
                    409:
                    410:        COPY_RSA_KEY(q, 0);
                    411:        COPY_RSA_KEY(p, 1);
                    412:        COPY_RSA_KEY(iqmp, 2);
                    413:        COPY_RSA_KEY(dmq1, 3);
                    414:        COPY_RSA_KEY(dmp1, 4);
                    415:        COPY_RSA_KEY(n, 5);
                    416:        len = BN_num_bytes(prv->rsa->n);
                    417:        fd = sectok_friendly_open(sc_reader_id, STONOWAIT, &sw);
                    418:        if (fd < 0) {
                    419:                error("sectok_open failed: %s", sectok_get_sw(sw));
                    420:                goto done;
                    421:        }
                    422:        if (! sectok_cardpresent(fd)) {
                    423:                error("smartcard in reader %s not present",
                    424:                    sc_reader_id);
                    425:                goto done;
                    426:        }
                    427:        ret = sectok_reset(fd, 0, NULL, &sw);
                    428:        if (ret <= 0) {
                    429:                error("sectok_reset failed: %s", sectok_get_sw(sw));
                    430:                goto done;
                    431:        }
                    432:        if ((cla = cyberflex_inq_class(fd)) < 0) {
                    433:                error("cyberflex_inq_class failed");
                    434:                goto done;
                    435:        }
                    436:        memcpy(AUT0, DEFAUT0, sizeof(DEFAUT0));
                    437:        if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
                    438:                if (get_AUT0(AUT0) < 0 ||
                    439:                    cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) {
                    440:                        error("cyberflex_verify_AUT0 failed");
                    441:                        goto done;
                    442:                }
                    443:        }
                    444:        key_fid[0] = 0x00;
                    445:        key_fid[1] = 0x12;
                    446:        if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements,
                    447:            &sw) < 0) {
                    448:                error("cyberflex_load_rsa_priv failed: %s", sectok_get_sw(sw));
                    449:                goto done;
                    450:        }
                    451:        if (!sectok_swOK(sw))
                    452:                goto done;
                    453:        log("cyberflex_load_rsa_priv done");
                    454:        key_fid[0] = 0x73;
                    455:        key_fid[1] = 0x68;
                    456:        if (cyberflex_load_rsa_pub(fd, cla, key_fid, len, elements[5],
                    457:            &sw) < 0) {
                    458:                error("cyberflex_load_rsa_pub failed: %s", sectok_get_sw(sw));
                    459:                goto done;
                    460:        }
                    461:        if (!sectok_swOK(sw))
                    462:                goto done;
                    463:        log("cyberflex_load_rsa_pub done");
                    464:        status = 0;
                    465:
                    466: done:
                    467:        memset(elements[0], '\0', BN_num_bytes(prv->rsa->q));
                    468:        memset(elements[1], '\0', BN_num_bytes(prv->rsa->p));
                    469:        memset(elements[2], '\0', BN_num_bytes(prv->rsa->iqmp));
                    470:        memset(elements[3], '\0', BN_num_bytes(prv->rsa->dmq1));
                    471:        memset(elements[4], '\0', BN_num_bytes(prv->rsa->dmp1));
                    472:        memset(elements[5], '\0', BN_num_bytes(prv->rsa->n));
                    473:
                    474:        for (i = 0; i < NUM_RSA_KEY_ELEMENTS; i++)
                    475:                if (elements[i])
                    476:                        xfree(elements[i]);
                    477:        if (fd != -1)
                    478:                sectok_close(fd);
                    479:        return (status);
1.1       markus    480: }
1.13      jakob     481: #endif /* SMARTCARD */