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