Annotation of src/usr.bin/ssh/scard.c, Revision 1.4
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.4 ! markus 27: RCSID("$OpenBSD: scard.c,v 1.3 2001/06/26 20:14:10 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: u_char atr[256];
1.4 ! markus 55: int sw;
1.1 markus 56:
57: if (sc_fd >= 0)
58: return sc_fd;
59: sc_reader_num = num;
60:
1.4 ! markus 61: sc_fd = sectok_open(sc_reader_num, 0, NULL);
1.1 markus 62: if (sc_fd < 0) {
1.4 ! markus 63: error("sectok_open failed %d", sc_fd);
1.1 markus 64: return sc_fd;
65: }
1.4 ! markus 66: if (sectok_reset(sc_fd, 0, atr, &sw) <= 0) {
! 67: error("sectok_reset failed: %s", sectok_get_sw(sw));
1.1 markus 68: sc_fd = -1;
69: return sc_fd;
70: }
1.4 ! markus 71: debug("sc_open ok %d", sc_fd);
1.1 markus 72: return sc_fd;
73: }
74:
75: static int
1.4 ! markus 76: sc_enable_applet(void)
1.1 markus 77: {
1.4 ! markus 78: u_char contID[2], aid[MAX_BUF_SIZE];
! 79: int i, len, sw, aid_len;
1.1 markus 80:
1.4 ! markus 81: len = sw = 0;
1.1 markus 82: contID[0] = 0x77;
83: contID[1] = 0x78;
84:
1.4 ! markus 85: if (sectok_selectfile(sc_fd, cla, root_fid, &sw) < 0) {
! 86: error("sectok_selectfile root_fid failed: %s",
! 87: sectok_get_sw(sw));
1.1 markus 88: return -1;
89: }
1.4 ! markus 90: if (sectok_selectfile(sc_fd, cla, contID, &sw) < 0) {
! 91: error("sectok_selectfile failed: %s", sectok_get_sw(sw));
! 92: return -1;
! 93: }
! 94: /* send appled id */
! 95: for (i = 0; i < sizeof(aid); i++)
! 96: aid[i] = 0x77;
! 97: aid_len = 5;
! 98: sectok_apdu(sc_fd, cla, 0xa4, 0x04, 0, aid_len, aid, 0, NULL, &sw);
! 99: if (!sectok_swOK(sw)) {
! 100: error("sectok_apdu failed: %s", sectok_get_sw(sw));
1.1 markus 101: return -1;
102: }
103: return 0;
104: }
105:
106: static int
107: sc_read_pubkey(Key * k)
108: {
1.4 ! markus 109: u_char buf[2], *n;
! 110: char *p;
! 111: int len, sw;
1.1 markus 112:
1.4 ! markus 113: len = sw = 0;
1.1 markus 114:
115: /* get key size */
1.4 ! markus 116: sectok_apdu(sc_fd, CLA_SSH, INS_GET_KEYLENGTH, 0, 0, 0, NULL,
! 117: sizeof(buf), buf, &sw);
! 118: if (!sectok_swOK(sw)) {
! 119: error("could not obtain key length: %s", sectok_get_sw(sw));
! 120: return -1;
1.1 markus 121: }
122: len = (buf[0] << 8) | buf[1];
123: len /= 8;
1.4 ! markus 124: debug("INS_GET_KEYLENGTH: len %d sw %s", len, sectok_get_sw(sw));
1.1 markus 125:
1.4 ! markus 126: n = xmalloc(len);
1.1 markus 127: /* get n */
1.4 ! markus 128: sectok_apdu(sc_fd, CLA_SSH, INS_GET_PUBKEY, 0, 0, 0, NULL, len, n, &sw);
! 129: if (!sectok_swOK(sw)) {
! 130: error("could not obtain public key: %s", sectok_get_sw(sw));
! 131: xfree(n);
! 132: return -1;
1.1 markus 133: }
1.4 ! markus 134: debug("INS_GET_KEYLENGTH: sw %s", sectok_get_sw(sw));
! 135:
! 136: if (BN_bin2bn(n, len, k->rsa->n) == NULL) {
! 137: error("c_read_pubkey: BN_bin2bn failed");
! 138: xfree(n);
! 139: return -1;
! 140: }
! 141: xfree(n);
1.1 markus 142:
143: /* currently the java applet just stores 'n' */
1.4 ! markus 144: if (!BN_set_word(k->rsa->e, 35)) {
! 145: error("c_read_pubkey: BN_set_word(e, 35) failed");
! 146: return -1;
! 147: }
1.1 markus 148:
149: p = key_fingerprint(k, SSH_FP_MD5, SSH_FP_HEX);
150: debug("fingerprint %d %s", key_size(k), p);
151: xfree(p);
152:
153: return 0;
154: }
155:
156: /* private key operations */
157:
158: static int
1.4 ! markus 159: sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
1.1 markus 160: {
1.4 ! markus 161: u_char *padded = NULL;
! 162: int sw, len, olen;
1.1 markus 163:
164: debug("sc_private_decrypt called");
165:
1.4 ! markus 166: olen = len = sw = 0;
! 167: if (padding != RSA_PKCS1_PADDING)
1.1 markus 168: goto err;
169:
1.4 ! markus 170: len = BN_num_bytes(rsa->n);
! 171: padded = xmalloc(len);
1.1 markus 172:
1.4 ! markus 173: sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, 0, NULL, &sw);
! 174: if (!sectok_swOK(sw)) {
! 175: error("sc_private_decrypt: INS_DECRYPT failed: %s",
! 176: sectok_get_sw(sw));
1.1 markus 177: goto err;
178: }
1.4 ! markus 179: sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
! 180: len, padded, &sw);
! 181: if (!sectok_swOK(sw)) {
! 182: error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
! 183: sectok_get_sw(sw));
1.1 markus 184: goto err;
185: }
1.4 ! markus 186: olen = RSA_padding_check_PKCS1_type_2(to, len, padded + 1, len - 1,
! 187: len);
1.1 markus 188: err:
189: if (padded)
190: xfree(padded);
191: return olen;
192: }
193:
194: static int
1.4 ! markus 195: sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, int padding)
1.1 markus 196: {
1.4 ! markus 197: u_char *padded = NULL;
! 198: int sw, len;
1.1 markus 199:
1.4 ! markus 200: len = sw = 0;
! 201: if (padding != RSA_PKCS1_PADDING)
1.1 markus 202: goto err;
203:
1.3 markus 204: debug("sc_private_encrypt called");
1.4 ! markus 205: len = BN_num_bytes(rsa->n);
! 206: padded = xmalloc(len);
! 207:
! 208: if (RSA_padding_add_PKCS1_type_1(padded, len, from, flen) <= 0) {
1.1 markus 209: error("RSA_padding_add_PKCS1_type_1 failed");
210: goto err;
211: }
1.4 ! markus 212: sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw);
! 213: if (!sectok_swOK(sw)) {
! 214: error("sc_private_decrypt: INS_DECRYPT failed: %s",
! 215: sectok_get_sw(sw));
! 216: goto err;
! 217: }
! 218: sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL,
! 219: len, to, &sw);
! 220: if (!sectok_swOK(sw)) {
! 221: error("sc_private_decrypt: INS_GET_RESPONSE failed: %s",
! 222: sectok_get_sw(sw));
! 223: goto err;
1.1 markus 224: }
225: err:
226: if (padded)
227: xfree(padded);
1.4 ! markus 228: return len;
1.1 markus 229: }
230:
231: /* engine for overloading private key operations */
232:
233: static ENGINE *smart_engine = NULL;
234: static RSA_METHOD smart_rsa =
235: {
1.4 ! markus 236: "sectok",
! 237: NULL,
! 238: NULL,
! 239: NULL,
! 240: NULL,
! 241: NULL,
! 242: NULL,
! 243: NULL,
! 244: NULL,
! 245: 0,
! 246: NULL,
1.1 markus 247: };
248:
249: ENGINE *
1.2 itojun 250: sc_get_engine(void)
1.1 markus 251: {
252: RSA_METHOD *def;
253:
254: def = RSA_get_default_openssl_method();
255:
256: /* overload */
257: smart_rsa.rsa_priv_enc = sc_private_encrypt;
258: smart_rsa.rsa_priv_dec = sc_private_decrypt;
259:
260: /* just use the OpenSSL version */
1.4 ! markus 261: smart_rsa.rsa_pub_enc = def->rsa_pub_enc;
! 262: smart_rsa.rsa_pub_dec = def->rsa_pub_dec;
1.1 markus 263: smart_rsa.rsa_mod_exp = def->rsa_mod_exp;
264: smart_rsa.bn_mod_exp = def->bn_mod_exp;
265: smart_rsa.init = def->init;
266: smart_rsa.finish = def->finish;
267: smart_rsa.flags = def->flags;
268: smart_rsa.app_data = def->app_data;
269: smart_rsa.rsa_sign = def->rsa_sign;
270: smart_rsa.rsa_verify = def->rsa_verify;
271:
272: smart_engine = ENGINE_new();
273:
1.4 ! markus 274: ENGINE_set_id(smart_engine, "sectok");
! 275: ENGINE_set_name(smart_engine, "libsectok");
1.1 markus 276: ENGINE_set_RSA(smart_engine, &smart_rsa);
277: ENGINE_set_DSA(smart_engine, DSA_get_default_openssl_method());
278: ENGINE_set_DH(smart_engine, DH_get_default_openssl_method());
279: ENGINE_set_RAND(smart_engine, RAND_SSLeay());
280: ENGINE_set_BN_mod_exp(smart_engine, BN_mod_exp);
281:
282: return smart_engine;
283: }
284:
285: Key *
286: sc_get_key(int sc_reader_num)
287: {
288: Key *k;
289:
1.4 ! markus 290: if (sc_open(sc_reader_num) < 0) {
1.1 markus 291: error("sc_open failed");
292: return NULL;
293: }
1.4 ! markus 294: if (sc_enable_applet() < 0) {
1.1 markus 295: error("sc_enable_applet failed");
296: return NULL;
297: }
298: k = key_new(KEY_RSA);
299: if (k == NULL) {
300: return NULL;
301: }
1.4 ! markus 302: if (sc_read_pubkey(k) < 0) {
1.1 markus 303: error("sc_read_pubkey failed");
304: key_free(k);
305: return NULL;
306: }
307: return k;
308: }
309: #endif