diff options
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r-- | ssh-pkcs11.c | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 65a7b5897..775de9642 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <dlfcn.h> | 30 | #include <dlfcn.h> |
31 | 31 | ||
32 | #include "openbsd-compat/sys-queue.h" | 32 | #include "openbsd-compat/sys-queue.h" |
33 | #include "openbsd-compat/openssl-compat.h" | ||
33 | 34 | ||
34 | #include <openssl/x509.h> | 35 | #include <openssl/x509.h> |
35 | 36 | ||
@@ -67,7 +68,7 @@ struct pkcs11_key { | |||
67 | struct pkcs11_provider *provider; | 68 | struct pkcs11_provider *provider; |
68 | CK_ULONG slotidx; | 69 | CK_ULONG slotidx; |
69 | int (*orig_finish)(RSA *rsa); | 70 | int (*orig_finish)(RSA *rsa); |
70 | RSA_METHOD rsa_method; | 71 | RSA_METHOD *rsa_method; |
71 | char *keyid; | 72 | char *keyid; |
72 | int keyid_len; | 73 | int keyid_len; |
73 | }; | 74 | }; |
@@ -182,6 +183,7 @@ pkcs11_rsa_finish(RSA *rsa) | |||
182 | rv = k11->orig_finish(rsa); | 183 | rv = k11->orig_finish(rsa); |
183 | if (k11->provider) | 184 | if (k11->provider) |
184 | pkcs11_provider_unref(k11->provider); | 185 | pkcs11_provider_unref(k11->provider); |
186 | RSA_meth_free(k11->rsa_method); | ||
185 | free(k11->keyid); | 187 | free(k11->keyid); |
186 | free(k11); | 188 | free(k11); |
187 | } | 189 | } |
@@ -326,13 +328,18 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, | |||
326 | k11->keyid = xmalloc(k11->keyid_len); | 328 | k11->keyid = xmalloc(k11->keyid_len); |
327 | memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); | 329 | memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); |
328 | } | 330 | } |
329 | k11->orig_finish = def->finish; | 331 | k11->rsa_method = RSA_meth_dup(def); |
330 | memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); | 332 | if (k11->rsa_method == NULL) |
331 | k11->rsa_method.name = "pkcs11"; | 333 | fatal("%s: RSA_meth_dup failed", __func__); |
332 | k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt; | 334 | k11->orig_finish = RSA_meth_get_finish(def); |
333 | k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt; | 335 | if (!RSA_meth_set1_name(k11->rsa_method, "pkcs11") || |
334 | k11->rsa_method.finish = pkcs11_rsa_finish; | 336 | !RSA_meth_set_priv_enc(k11->rsa_method, |
335 | RSA_set_method(rsa, &k11->rsa_method); | 337 | pkcs11_rsa_private_encrypt) || |
338 | !RSA_meth_set_priv_dec(k11->rsa_method, | ||
339 | pkcs11_rsa_private_decrypt) || | ||
340 | !RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish)) | ||
341 | fatal("%s: setup pkcs11 method failed", __func__); | ||
342 | RSA_set_method(rsa, k11->rsa_method); | ||
336 | RSA_set_app_data(rsa, k11); | 343 | RSA_set_app_data(rsa, k11); |
337 | return (0); | 344 | return (0); |
338 | } | 345 | } |
@@ -445,6 +452,15 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) | |||
445 | } | 452 | } |
446 | 453 | ||
447 | static int | 454 | static int |
455 | have_rsa_key(const RSA *rsa) | ||
456 | { | ||
457 | const BIGNUM *rsa_n, *rsa_e; | ||
458 | |||
459 | RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); | ||
460 | return rsa_n != NULL && rsa_e != NULL; | ||
461 | } | ||
462 | |||
463 | static int | ||
448 | pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, | 464 | pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, |
449 | CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], | 465 | CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], |
450 | struct sshkey ***keysp, int *nkeys) | 466 | struct sshkey ***keysp, int *nkeys) |
@@ -512,10 +528,20 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, | |||
512 | if ((rsa = RSA_new()) == NULL) { | 528 | if ((rsa = RSA_new()) == NULL) { |
513 | error("RSA_new failed"); | 529 | error("RSA_new failed"); |
514 | } else { | 530 | } else { |
515 | rsa->n = BN_bin2bn(attribs[1].pValue, | 531 | BIGNUM *rsa_n, *rsa_e; |
532 | |||
533 | rsa_n = BN_bin2bn(attribs[1].pValue, | ||
516 | attribs[1].ulValueLen, NULL); | 534 | attribs[1].ulValueLen, NULL); |
517 | rsa->e = BN_bin2bn(attribs[2].pValue, | 535 | rsa_e = BN_bin2bn(attribs[2].pValue, |
518 | attribs[2].ulValueLen, NULL); | 536 | attribs[2].ulValueLen, NULL); |
537 | if (rsa_n != NULL && rsa_e != NULL) { | ||
538 | if (!RSA_set0_key(rsa, | ||
539 | rsa_n, rsa_e, NULL)) | ||
540 | fatal("%s: set key", __func__); | ||
541 | rsa_n = rsa_e = NULL; /* transferred */ | ||
542 | } | ||
543 | BN_free(rsa_n); | ||
544 | BN_free(rsa_e); | ||
519 | } | 545 | } |
520 | } else { | 546 | } else { |
521 | cp = attribs[2].pValue; | 547 | cp = attribs[2].pValue; |
@@ -525,16 +551,16 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, | |||
525 | == NULL) { | 551 | == NULL) { |
526 | error("d2i_X509 failed"); | 552 | error("d2i_X509 failed"); |
527 | } else if ((evp = X509_get_pubkey(x509)) == NULL || | 553 | } else if ((evp = X509_get_pubkey(x509)) == NULL || |
528 | evp->type != EVP_PKEY_RSA || | 554 | EVP_PKEY_base_id(evp) != EVP_PKEY_RSA || |
529 | evp->pkey.rsa == NULL) { | 555 | EVP_PKEY_get0_RSA(evp) == NULL) { |
530 | debug("X509_get_pubkey failed or no rsa"); | 556 | debug("X509_get_pubkey failed or no rsa"); |
531 | } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) | 557 | } else if ((rsa = RSAPublicKey_dup( |
532 | == NULL) { | 558 | EVP_PKEY_get0_RSA(evp))) == NULL) { |
533 | error("RSAPublicKey_dup"); | 559 | error("RSAPublicKey_dup"); |
534 | } | 560 | } |
535 | X509_free(x509); | 561 | X509_free(x509); |
536 | } | 562 | } |
537 | if (rsa && rsa->n && rsa->e && | 563 | if (rsa && have_rsa_key(rsa) && |
538 | pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { | 564 | pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { |
539 | if ((key = sshkey_new(KEY_UNSPEC)) == NULL) | 565 | if ((key = sshkey_new(KEY_UNSPEC)) == NULL) |
540 | fatal("sshkey_new failed"); | 566 | fatal("sshkey_new failed"); |