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

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"
        !            27: RCSID("$OpenBSD: ssh-agent.c,v 1.56 2001/06/25 08:25:40 markus Exp $");
        !            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 *
        !           296: sc_get_engine()
        !           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