diff options
author | Colin Watson <cjwatson@debian.org> | 2014-02-10 00:18:28 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2014-02-10 00:18:28 +0000 |
commit | 9a975a9faed7c4f334e8c8490db3e77e102f2b21 (patch) | |
tree | 764a885ec9a963f6a8b15de6e1765f16b9ac4738 /ssh-pkcs11.c | |
parent | ee196dab7c5f97f0b80c8099343a375bead92010 (diff) | |
parent | cdb6c90811caa5df2df856be9b0b16db020fe31d (diff) |
Import openssh_6.5p1.orig.tar.gz
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r-- | ssh-pkcs11.c | 136 |
1 files changed, 101 insertions, 35 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 618c07526..c49cbf42b 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-pkcs11.c,v 1.8 2013/07/12 00:20:00 djm Exp $ */ | 1 | /* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2010 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #include "openbsd-compat/sys-queue.h" | 32 | #include "openbsd-compat/sys-queue.h" |
33 | 33 | ||
34 | #include <openssl/x509.h> | ||
35 | |||
34 | #define CRYPTOKI_COMPAT | 36 | #define CRYPTOKI_COMPAT |
35 | #include "pkcs11.h" | 37 | #include "pkcs11.h" |
36 | 38 | ||
@@ -225,7 +227,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, | |||
225 | CK_OBJECT_HANDLE obj; | 227 | CK_OBJECT_HANDLE obj; |
226 | CK_ULONG tlen = 0; | 228 | CK_ULONG tlen = 0; |
227 | CK_RV rv; | 229 | CK_RV rv; |
228 | CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; | 230 | CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; |
229 | CK_BBOOL true_val = CK_TRUE; | 231 | CK_BBOOL true_val = CK_TRUE; |
230 | CK_MECHANISM mech = { | 232 | CK_MECHANISM mech = { |
231 | CKM_RSA_PKCS, NULL_PTR, 0 | 233 | CKM_RSA_PKCS, NULL_PTR, 0 |
@@ -238,8 +240,6 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, | |||
238 | char *pin, prompt[1024]; | 240 | char *pin, prompt[1024]; |
239 | int rval = -1; | 241 | int rval = -1; |
240 | 242 | ||
241 | /* some compilers complain about non-constant initializer so we | ||
242 | use NULL in CK_ATTRIBUTE above and set the values here */ | ||
243 | key_filter[0].pValue = &private_key_class; | 243 | key_filter[0].pValue = &private_key_class; |
244 | key_filter[2].pValue = &true_val; | 244 | key_filter[2].pValue = &true_val; |
245 | 245 | ||
@@ -384,36 +384,75 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) | |||
384 | * add 'wrapped' public keys to the 'keysp' array and increment nkeys. | 384 | * add 'wrapped' public keys to the 'keysp' array and increment nkeys. |
385 | * keysp points to an (possibly empty) array with *nkeys keys. | 385 | * keysp points to an (possibly empty) array with *nkeys keys. |
386 | */ | 386 | */ |
387 | static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, | ||
388 | CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) | ||
389 | __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); | ||
390 | |||
387 | static int | 391 | static int |
388 | pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, | 392 | pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, |
389 | int *nkeys) | 393 | Key ***keysp, int *nkeys) |
390 | { | 394 | { |
391 | Key *key; | 395 | CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; |
392 | RSA *rsa; | 396 | CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; |
393 | int i; | ||
394 | CK_RV rv; | ||
395 | CK_OBJECT_HANDLE obj; | ||
396 | CK_ULONG nfound; | ||
397 | CK_SESSION_HANDLE session; | ||
398 | CK_FUNCTION_LIST *f; | ||
399 | CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; | ||
400 | CK_ATTRIBUTE pubkey_filter[] = { | 397 | CK_ATTRIBUTE pubkey_filter[] = { |
401 | { CKA_CLASS, NULL, sizeof(pubkey_class) } | 398 | { CKA_CLASS, NULL, sizeof(pubkey_class) } |
402 | }; | 399 | }; |
403 | CK_ATTRIBUTE attribs[] = { | 400 | CK_ATTRIBUTE cert_filter[] = { |
401 | { CKA_CLASS, NULL, sizeof(cert_class) } | ||
402 | }; | ||
403 | CK_ATTRIBUTE pubkey_attribs[] = { | ||
404 | { CKA_ID, NULL, 0 }, | 404 | { CKA_ID, NULL, 0 }, |
405 | { CKA_MODULUS, NULL, 0 }, | 405 | { CKA_MODULUS, NULL, 0 }, |
406 | { CKA_PUBLIC_EXPONENT, NULL, 0 } | 406 | { CKA_PUBLIC_EXPONENT, NULL, 0 } |
407 | }; | 407 | }; |
408 | 408 | CK_ATTRIBUTE cert_attribs[] = { | |
409 | /* some compilers complain about non-constant initializer so we | 409 | { CKA_ID, NULL, 0 }, |
410 | use NULL in CK_ATTRIBUTE above and set the value here */ | 410 | { CKA_SUBJECT, NULL, 0 }, |
411 | { CKA_VALUE, NULL, 0 } | ||
412 | }; | ||
411 | pubkey_filter[0].pValue = &pubkey_class; | 413 | pubkey_filter[0].pValue = &pubkey_class; |
414 | cert_filter[0].pValue = &cert_class; | ||
415 | |||
416 | if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs, | ||
417 | keysp, nkeys) < 0 || | ||
418 | pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs, | ||
419 | keysp, nkeys) < 0) | ||
420 | return (-1); | ||
421 | return (0); | ||
422 | } | ||
423 | |||
424 | static int | ||
425 | pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) | ||
426 | { | ||
427 | int i; | ||
428 | |||
429 | for (i = 0; i < *nkeys; i++) | ||
430 | if (key_equal(key, (*keysp)[i])) | ||
431 | return (1); | ||
432 | return (0); | ||
433 | } | ||
434 | |||
435 | static int | ||
436 | pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, | ||
437 | CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], | ||
438 | Key ***keysp, int *nkeys) | ||
439 | { | ||
440 | Key *key; | ||
441 | RSA *rsa; | ||
442 | X509 *x509; | ||
443 | EVP_PKEY *evp; | ||
444 | int i; | ||
445 | const u_char *cp; | ||
446 | CK_RV rv; | ||
447 | CK_OBJECT_HANDLE obj; | ||
448 | CK_ULONG nfound; | ||
449 | CK_SESSION_HANDLE session; | ||
450 | CK_FUNCTION_LIST *f; | ||
412 | 451 | ||
413 | f = p->function_list; | 452 | f = p->function_list; |
414 | session = p->slotinfo[slotidx].session; | 453 | session = p->slotinfo[slotidx].session; |
415 | /* setup a filter the looks for public keys */ | 454 | /* setup a filter the looks for public keys */ |
416 | if ((rv = f->C_FindObjectsInit(session, pubkey_filter, 1)) != CKR_OK) { | 455 | if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { |
417 | error("C_FindObjectsInit failed: %lu", rv); | 456 | error("C_FindObjectsInit failed: %lu", rv); |
418 | return (-1); | 457 | return (-1); |
419 | } | 458 | } |
@@ -441,32 +480,59 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, | |||
441 | /* allocate buffers for attributes */ | 480 | /* allocate buffers for attributes */ |
442 | for (i = 0; i < 3; i++) | 481 | for (i = 0; i < 3; i++) |
443 | attribs[i].pValue = xmalloc(attribs[i].ulValueLen); | 482 | attribs[i].pValue = xmalloc(attribs[i].ulValueLen); |
444 | /* retrieve ID, modulus and public exponent of RSA key */ | 483 | /* |
484 | * retrieve ID, modulus and public exponent of RSA key, | ||
485 | * or ID, subject and value for certificates. | ||
486 | */ | ||
487 | rsa = NULL; | ||
445 | if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) | 488 | if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) |
446 | != CKR_OK) { | 489 | != CKR_OK) { |
447 | error("C_GetAttributeValue failed: %lu", rv); | 490 | error("C_GetAttributeValue failed: %lu", rv); |
448 | } else if ((rsa = RSA_new()) == NULL) { | 491 | } else if (attribs[1].type == CKA_MODULUS ) { |
449 | error("RSA_new failed"); | 492 | if ((rsa = RSA_new()) == NULL) { |
493 | error("RSA_new failed"); | ||
494 | } else { | ||
495 | rsa->n = BN_bin2bn(attribs[1].pValue, | ||
496 | attribs[1].ulValueLen, NULL); | ||
497 | rsa->e = BN_bin2bn(attribs[2].pValue, | ||
498 | attribs[2].ulValueLen, NULL); | ||
499 | } | ||
450 | } else { | 500 | } else { |
451 | rsa->n = BN_bin2bn(attribs[1].pValue, | 501 | cp = attribs[2].pValue; |
452 | attribs[1].ulValueLen, NULL); | 502 | if ((x509 = X509_new()) == NULL) { |
453 | rsa->e = BN_bin2bn(attribs[2].pValue, | 503 | error("X509_new failed"); |
454 | attribs[2].ulValueLen, NULL); | 504 | } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen) |
455 | if (rsa->n && rsa->e && | 505 | == NULL) { |
456 | pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { | 506 | error("d2i_X509 failed"); |
457 | key = key_new(KEY_UNSPEC); | 507 | } else if ((evp = X509_get_pubkey(x509)) == NULL || |
458 | key->rsa = rsa; | 508 | evp->type != EVP_PKEY_RSA || |
459 | key->type = KEY_RSA; | 509 | evp->pkey.rsa == NULL) { |
460 | key->flags |= KEY_FLAG_EXT; | 510 | debug("X509_get_pubkey failed or no rsa"); |
511 | } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) | ||
512 | == NULL) { | ||
513 | error("RSAPublicKey_dup"); | ||
514 | } | ||
515 | if (x509) | ||
516 | X509_free(x509); | ||
517 | } | ||
518 | if (rsa && rsa->n && rsa->e && | ||
519 | pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { | ||
520 | key = key_new(KEY_UNSPEC); | ||
521 | key->rsa = rsa; | ||
522 | key->type = KEY_RSA; | ||
523 | key->flags |= KEY_FLAG_EXT; | ||
524 | if (pkcs11_key_included(keysp, nkeys, key)) { | ||
525 | key_free(key); | ||
526 | } else { | ||
461 | /* expand key array and add key */ | 527 | /* expand key array and add key */ |
462 | *keysp = xrealloc(*keysp, *nkeys + 1, | 528 | *keysp = xrealloc(*keysp, *nkeys + 1, |
463 | sizeof(Key *)); | 529 | sizeof(Key *)); |
464 | (*keysp)[*nkeys] = key; | 530 | (*keysp)[*nkeys] = key; |
465 | *nkeys = *nkeys + 1; | 531 | *nkeys = *nkeys + 1; |
466 | debug("have %d keys", *nkeys); | 532 | debug("have %d keys", *nkeys); |
467 | } else { | ||
468 | RSA_free(rsa); | ||
469 | } | 533 | } |
534 | } else if (rsa) { | ||
535 | RSA_free(rsa); | ||
470 | } | 536 | } |
471 | for (i = 0; i < 3; i++) | 537 | for (i = 0; i < 3; i++) |
472 | free(attribs[i].pValue); | 538 | free(attribs[i].pValue); |