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