diff options
Diffstat (limited to 'scard.c')
-rw-r--r-- | scard.c | 84 |
1 files changed, 57 insertions, 27 deletions
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "includes.h" | 25 | #include "includes.h" |
26 | #ifdef SMARTCARD | 26 | #ifdef SMARTCARD |
27 | RCSID("$OpenBSD: scard.c,v 1.21 2002/03/21 18:08:15 rees Exp $"); | 27 | RCSID("$OpenBSD: scard.c,v 1.22 2002/03/21 21:54:34 rees Exp $"); |
28 | 28 | ||
29 | #include <openssl/engine.h> | 29 | #include <openssl/engine.h> |
30 | #include <openssl/evp.h> | 30 | #include <openssl/evp.h> |
@@ -33,8 +33,8 @@ RCSID("$OpenBSD: scard.c,v 1.21 2002/03/21 18:08:15 rees Exp $"); | |||
33 | #include "key.h" | 33 | #include "key.h" |
34 | #include "log.h" | 34 | #include "log.h" |
35 | #include "xmalloc.h" | 35 | #include "xmalloc.h" |
36 | #include "scard.h" | ||
37 | #include "readpass.h" | 36 | #include "readpass.h" |
37 | #include "scard.h" | ||
38 | 38 | ||
39 | #ifdef OPENSSL_VERSION_NUMBER | 39 | #ifdef OPENSSL_VERSION_NUMBER |
40 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L | 40 | #if OPENSSL_VERSION_NUMBER >= 0x00907000L |
@@ -53,10 +53,16 @@ RCSID("$OpenBSD: scard.c,v 1.21 2002/03/21 18:08:15 rees Exp $"); | |||
53 | 53 | ||
54 | #define MAX_BUF_SIZE 256 | 54 | #define MAX_BUF_SIZE 256 |
55 | 55 | ||
56 | u_char DEFAUT0[] = {0xad, 0x9f, 0x61, 0xfe, 0xfa, 0x20, 0xce, 0x63}; | ||
57 | |||
56 | static int sc_fd = -1; | 58 | static int sc_fd = -1; |
57 | static char *sc_reader_id = NULL; | 59 | static char *sc_reader_id = NULL; |
60 | static char *sc_pin = NULL; | ||
58 | static int cla = 0x00; /* class */ | 61 | static int cla = 0x00; /* class */ |
59 | 62 | ||
63 | static void sc_mk_digest(const char *pin, u_char *digest); | ||
64 | static int get_AUT0(u_char *aut0); | ||
65 | |||
60 | /* interface to libsectok */ | 66 | /* interface to libsectok */ |
61 | 67 | ||
62 | static int | 68 | static int |
@@ -193,6 +199,7 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, | |||
193 | int padding) | 199 | int padding) |
194 | { | 200 | { |
195 | u_char *padded = NULL; | 201 | u_char *padded = NULL; |
202 | u_char aut0[EVP_MAX_MD_SIZE]; | ||
196 | int sw, len, olen, status = -1; | 203 | int sw, len, olen, status = -1; |
197 | 204 | ||
198 | debug("sc_private_decrypt called"); | 205 | debug("sc_private_decrypt called"); |
@@ -209,17 +216,31 @@ sc_private_decrypt(int flen, u_char *from, u_char *to, RSA *rsa, | |||
209 | len = BN_num_bytes(rsa->n); | 216 | len = BN_num_bytes(rsa->n); |
210 | padded = xmalloc(len); | 217 | padded = xmalloc(len); |
211 | 218 | ||
212 | sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, (u_char *)from, | 219 | sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, from, len, padded, &sw); |
213 | 0, NULL, &sw); | 220 | |
214 | if (!sectok_swOK(sw)) { | 221 | if (sw == 0x6982) { |
215 | error("sc_private_decrypt: INS_DECRYPT failed: %s", | 222 | /* permission denied; try PIN if provided */ |
216 | sectok_get_sw(sw)); | 223 | if (sc_pin && strlen(sc_pin) > 0) { |
217 | goto err; | 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); | ||
218 | } | 241 | } |
219 | sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, | ||
220 | len, padded, &sw); | ||
221 | if (!sectok_swOK(sw)) { | 242 | if (!sectok_swOK(sw)) { |
222 | error("sc_private_decrypt: INS_GET_RESPONSE failed: %s", | 243 | error("sc_private_decrypt: INS_DECRYPT failed: %s", |
223 | sectok_get_sw(sw)); | 244 | sectok_get_sw(sw)); |
224 | goto err; | 245 | goto err; |
225 | } | 246 | } |
@@ -256,19 +277,12 @@ sc_private_encrypt(int flen, u_char *from, u_char *to, RSA *rsa, | |||
256 | error("RSA_padding_add_PKCS1_type_1 failed"); | 277 | error("RSA_padding_add_PKCS1_type_1 failed"); |
257 | goto err; | 278 | goto err; |
258 | } | 279 | } |
259 | sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, 0, NULL, &sw); | 280 | sectok_apdu(sc_fd, CLA_SSH, INS_DECRYPT, 0, 0, len, padded, len, to, &sw); |
260 | if (!sectok_swOK(sw)) { | 281 | if (!sectok_swOK(sw)) { |
261 | error("sc_private_decrypt: INS_DECRYPT failed: %s", | 282 | error("sc_private_decrypt: INS_DECRYPT failed: %s", |
262 | sectok_get_sw(sw)); | 283 | sectok_get_sw(sw)); |
263 | goto err; | 284 | goto err; |
264 | } | 285 | } |
265 | sectok_apdu(sc_fd, CLA_SSH, INS_GET_RESPONSE, 0, 0, 0, NULL, | ||
266 | len, to, &sw); | ||
267 | if (!sectok_swOK(sw)) { | ||
268 | error("sc_private_decrypt: INS_GET_RESPONSE failed: %s", | ||
269 | sectok_get_sw(sw)); | ||
270 | goto err; | ||
271 | } | ||
272 | err: | 286 | err: |
273 | if (padded) | 287 | if (padded) |
274 | xfree(padded); | 288 | xfree(padded); |
@@ -340,7 +354,7 @@ sc_close(void) | |||
340 | } | 354 | } |
341 | 355 | ||
342 | Key * | 356 | Key * |
343 | sc_get_key(const char *id) | 357 | sc_get_key(const char *id, const char *pin) |
344 | { | 358 | { |
345 | Key *k; | 359 | Key *k; |
346 | int status; | 360 | int status; |
@@ -349,6 +363,10 @@ sc_get_key(const char *id) | |||
349 | xfree(sc_reader_id); | 363 | xfree(sc_reader_id); |
350 | sc_reader_id = xstrdup(id); | 364 | sc_reader_id = xstrdup(id); |
351 | 365 | ||
366 | if (sc_pin != NULL) | ||
367 | xfree(sc_pin); | ||
368 | sc_pin = (pin == NULL) ? NULL : xstrdup(pin); | ||
369 | |||
352 | k = key_new(KEY_RSA); | 370 | k = key_new(KEY_RSA); |
353 | if (k == NULL) { | 371 | if (k == NULL) { |
354 | return NULL; | 372 | return NULL; |
@@ -376,19 +394,30 @@ sc_get_key(const char *id) | |||
376 | goto done; \ | 394 | goto done; \ |
377 | } while (0) | 395 | } while (0) |
378 | 396 | ||
379 | static int | 397 | static void |
380 | get_AUT0(char *aut0) | 398 | sc_mk_digest(const char *pin, u_char *digest) |
381 | { | 399 | { |
382 | const EVP_MD *evp_md = EVP_sha1(); | 400 | const EVP_MD *evp_md = EVP_sha1(); |
383 | EVP_MD_CTX md; | 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 | { | ||
384 | char *pass; | 411 | char *pass; |
385 | 412 | ||
386 | pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN); | 413 | pass = read_passphrase("Enter passphrase for smartcard: ", RP_ALLOW_STDIN); |
387 | if (pass == NULL) | 414 | if (pass == NULL) |
388 | return -1; | 415 | return -1; |
389 | EVP_DigestInit(&md, evp_md); | 416 | if (!strcmp(pass, "-")) { |
390 | EVP_DigestUpdate(&md, pass, strlen(pass)); | 417 | memcpy(aut0, DEFAUT0, sizeof DEFAUT0); |
391 | EVP_DigestFinal(&md, aut0, NULL); | 418 | return 0; |
419 | } | ||
420 | sc_mk_digest(pass, aut0); | ||
392 | memset(pass, 0, strlen(pass)); | 421 | memset(pass, 0, strlen(pass)); |
393 | xfree(pass); | 422 | xfree(pass); |
394 | return 0; | 423 | return 0; |
@@ -399,7 +428,6 @@ sc_put_key(Key *prv, const char *id) | |||
399 | { | 428 | { |
400 | u_char *elements[NUM_RSA_KEY_ELEMENTS]; | 429 | u_char *elements[NUM_RSA_KEY_ELEMENTS]; |
401 | u_char key_fid[2]; | 430 | 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]; | 431 | u_char AUT0[EVP_MAX_MD_SIZE]; |
404 | int len, status = -1, i, fd = -1, ret; | 432 | int len, status = -1, i, fd = -1, ret; |
405 | int sw = 0, cla = 0x00; | 433 | int sw = 0, cla = 0x00; |
@@ -436,10 +464,12 @@ sc_put_key(Key *prv, const char *id) | |||
436 | if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { | 464 | if (cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { |
437 | if (get_AUT0(AUT0) < 0 || | 465 | if (get_AUT0(AUT0) < 0 || |
438 | cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { | 466 | cyberflex_verify_AUT0(fd, cla, AUT0, sizeof(DEFAUT0)) < 0) { |
439 | error("cyberflex_verify_AUT0 failed"); | 467 | memset(AUT0, 0, sizeof(DEFAUT0)); |
468 | error("smartcard passphrase incorrect"); | ||
440 | goto done; | 469 | goto done; |
441 | } | 470 | } |
442 | } | 471 | } |
472 | memset(AUT0, 0, sizeof(DEFAUT0)); | ||
443 | key_fid[0] = 0x00; | 473 | key_fid[0] = 0x00; |
444 | key_fid[1] = 0x12; | 474 | key_fid[1] = 0x12; |
445 | if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements, | 475 | if (cyberflex_load_rsa_priv(fd, cla, key_fid, 5, 8*len, elements, |