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 */