From d2252c79191d069372ed6effce7c7a2de93448cd Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 4 Nov 2013 07:41:48 +1100 Subject: - markus@cvs.openbsd.org 2013/11/02 20:03:54 [ssh-pkcs11.c] support pkcs#11 tokes that only provide x509 zerts instead of raw pubkeys; fixes bz#1908; based on patch from Laurent Barbe; ok djm --- ssh-pkcs11.c | 141 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 40 deletions(-) (limited to 'ssh-pkcs11.c') diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 618c07526..6e8d2db36 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.8 2013/07/12 00:20:00 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.9 2013/11/02 20:03:54 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -31,6 +31,8 @@ #include "openbsd-compat/sys-queue.h" +#include + #define CRYPTOKI_COMPAT #include "pkcs11.h" @@ -225,24 +227,19 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, CK_OBJECT_HANDLE obj; CK_ULONG tlen = 0; CK_RV rv; - CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; + CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; CK_BBOOL true_val = CK_TRUE; CK_MECHANISM mech = { CKM_RSA_PKCS, NULL_PTR, 0 }; CK_ATTRIBUTE key_filter[] = { - {CKA_CLASS, NULL, sizeof(private_key_class) }, + {CKA_CLASS, &private_key_class, sizeof(private_key_class) }, {CKA_ID, NULL, 0}, - {CKA_SIGN, NULL, sizeof(true_val) } + {CKA_SIGN, &true_val, sizeof(true_val) } }; char *pin, prompt[1024]; int rval = -1; - /* some compilers complain about non-constant initializer so we - use NULL in CK_ATTRIBUTE above and set the values here */ - key_filter[0].pValue = &private_key_class; - key_filter[2].pValue = &true_val; - if ((k11 = RSA_get_app_data(rsa)) == NULL) { error("RSA_get_app_data failed for rsa %p", rsa); return (-1); @@ -384,36 +381,73 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) * add 'wrapped' public keys to the 'keysp' array and increment nkeys. * keysp points to an (possibly empty) array with *nkeys keys. */ +static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, + CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *) + __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); + +static int +pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, + Key ***keysp, int *nkeys) +{ + CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; + CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; + CK_ATTRIBUTE pubkey_filter[] = { + { CKA_CLASS, &pubkey_class, sizeof(pubkey_class) } + }; + CK_ATTRIBUTE cert_filter[] = { + { CKA_CLASS, &cert_class, sizeof(cert_class) } + }; + CK_ATTRIBUTE pubkey_attribs[] = { + { CKA_ID, NULL, 0 }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + CK_ATTRIBUTE cert_attribs[] = { + { CKA_ID, NULL, 0 }, + { CKA_SUBJECT, NULL, 0 }, + { CKA_VALUE, NULL, 0 } + }; + + if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs, + keysp, nkeys) < 0 || + pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs, + keysp, nkeys) < 0) + return (-1); + return (0); +} + static int -pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, - int *nkeys) +pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) +{ + int i; + + for (i = 0; i < *nkeys; i++) + if (key_equal(key, *keysp[i])) + return (1); + return (0); +} + +static int +pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], + Key ***keysp, int *nkeys) { Key *key; RSA *rsa; + X509 *x509; + EVP_PKEY *evp; int i; + const u_char *cp; CK_RV rv; CK_OBJECT_HANDLE obj; CK_ULONG nfound; CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f; - CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; - CK_ATTRIBUTE pubkey_filter[] = { - { CKA_CLASS, NULL, sizeof(pubkey_class) } - }; - CK_ATTRIBUTE attribs[] = { - { CKA_ID, NULL, 0 }, - { CKA_MODULUS, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 } - }; - - /* some compilers complain about non-constant initializer so we - use NULL in CK_ATTRIBUTE above and set the value here */ - pubkey_filter[0].pValue = &pubkey_class; f = p->function_list; session = p->slotinfo[slotidx].session; /* setup a filter the looks for public keys */ - if ((rv = f->C_FindObjectsInit(session, pubkey_filter, 1)) != CKR_OK) { + if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); return (-1); } @@ -441,32 +475,59 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, Key ***keysp, /* allocate buffers for attributes */ for (i = 0; i < 3; i++) attribs[i].pValue = xmalloc(attribs[i].ulValueLen); - /* retrieve ID, modulus and public exponent of RSA key */ + /* + * retrieve ID, modulus and public exponent of RSA key, + * or ID, subject and value for certificates. + */ + rsa = NULL; if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); - } else if ((rsa = RSA_new()) == NULL) { - error("RSA_new failed"); + } else if (attribs[1].type == CKA_MODULUS ) { + if ((rsa = RSA_new()) == NULL) { + error("RSA_new failed"); + } else { + rsa->n = BN_bin2bn(attribs[1].pValue, + attribs[1].ulValueLen, NULL); + rsa->e = BN_bin2bn(attribs[2].pValue, + attribs[2].ulValueLen, NULL); + } } else { - rsa->n = BN_bin2bn(attribs[1].pValue, - attribs[1].ulValueLen, NULL); - rsa->e = BN_bin2bn(attribs[2].pValue, - attribs[2].ulValueLen, NULL); - if (rsa->n && rsa->e && - pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { - key = key_new(KEY_UNSPEC); - key->rsa = rsa; - key->type = KEY_RSA; - key->flags |= KEY_FLAG_EXT; + cp = attribs[2].pValue; + if ((x509 = X509_new()) == NULL) { + error("X509_new failed"); + } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen) + == NULL) { + error("d2i_X509 failed"); + } else if ((evp = X509_get_pubkey(x509)) == NULL || + evp->type != EVP_PKEY_RSA || + evp->pkey.rsa == NULL) { + debug("X509_get_pubkey failed or no rsa"); + } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) + == NULL) { + error("RSAPublicKey_dup"); + } + if (x509) + X509_free(x509); + } + if (rsa && rsa->n && rsa->e && + pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { + key = key_new(KEY_UNSPEC); + key->rsa = rsa; + key->type = KEY_RSA; + key->flags |= KEY_FLAG_EXT; + if (pkcs11_key_included(keysp, nkeys, key)) { + key_free(key); + } else { /* expand key array and add key */ *keysp = xrealloc(*keysp, *nkeys + 1, sizeof(Key *)); (*keysp)[*nkeys] = key; *nkeys = *nkeys + 1; debug("have %d keys", *nkeys); - } else { - RSA_free(rsa); } + } else if (rsa) { + RSA_free(rsa); } for (i = 0; i < 3; i++) free(attribs[i].pValue); -- cgit v1.2.3 From 61c5c2319e84a58210810d39b062c8b8e3321160 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 7 Nov 2013 11:34:14 +1100 Subject: - (djm) [ssh-pkcs11.c] Bring back "non-constant initialiser" fix (rev 1.5) that got lost in recent merge. --- ChangeLog | 4 ++++ ssh-pkcs11.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'ssh-pkcs11.c') diff --git a/ChangeLog b/ChangeLog index 1d3e74671..44c47527c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +20131107 + - (djm) [ssh-pkcs11.c] Bring back "non-constant initialiser" fix (rev 1.5) + that got lost in recent merge. + 20131104 - (djm) OpenBSD CVS Sync - markus@cvs.openbsd.org 2013/11/02 20:03:54 diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 6e8d2db36..b785d822c 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -233,13 +233,16 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, CKM_RSA_PKCS, NULL_PTR, 0 }; CK_ATTRIBUTE key_filter[] = { - {CKA_CLASS, &private_key_class, sizeof(private_key_class) }, + {CKA_CLASS, NULL, sizeof(private_key_class) }, {CKA_ID, NULL, 0}, - {CKA_SIGN, &true_val, sizeof(true_val) } + {CKA_SIGN, NULL, sizeof(true_val) } }; char *pin, prompt[1024]; int rval = -1; + key_filter[0].pValue = &private_key_class; + key_filter[2].pValue = &true_val; + if ((k11 = RSA_get_app_data(rsa)) == NULL) { error("RSA_get_app_data failed for rsa %p", rsa); return (-1); @@ -392,10 +395,10 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; CK_ATTRIBUTE pubkey_filter[] = { - { CKA_CLASS, &pubkey_class, sizeof(pubkey_class) } + { CKA_CLASS, NULL, sizeof(pubkey_class) } }; CK_ATTRIBUTE cert_filter[] = { - { CKA_CLASS, &cert_class, sizeof(cert_class) } + { CKA_CLASS, NULL, sizeof(cert_class) } }; CK_ATTRIBUTE pubkey_attribs[] = { { CKA_ID, NULL, 0 }, @@ -407,6 +410,8 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, { CKA_SUBJECT, NULL, 0 }, { CKA_VALUE, NULL, 0 } }; + pubkey_filter[0].pValue = &pubkey_class; + cert_filter[0].pValue = &cert_class; if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs, keysp, nkeys) < 0 || -- cgit v1.2.3 From c8908aabff252f5da772d4e679479c2b7d18cac1 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 7 Nov 2013 13:38:35 +1100 Subject: - djm@cvs.openbsd.org 2013/11/06 23:05:59 [ssh-pkcs11.c] from portable: s/true/true_val/ to avoid name collisions on dump platforms RCSID sync only --- ChangeLog | 4 ++++ ssh-pkcs11.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'ssh-pkcs11.c') diff --git a/ChangeLog b/ChangeLog index 020dfd7f7..b8ca4d4bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ - markus@cvs.openbsd.org 2013/11/06 16:52:11 [monitor_wrap.c] fix rekeying for AES-GCM modes; ok deraadt + - djm@cvs.openbsd.org 2013/11/06 23:05:59 + [ssh-pkcs11.c] + from portable: s/true/true_val/ to avoid name collisions on dump platforms + RCSID sync only 20131104 - (djm) OpenBSD CVS Sync diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index b785d822c..9941e94ed 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.9 2013/11/02 20:03:54 markus Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.10 2013/11/06 23:05:59 djm Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * -- cgit v1.2.3 From 867e6934be6521f87f04a5ab86702e2d1b314245 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 21 Nov 2013 13:56:06 +1100 Subject: - markus@cvs.openbsd.org 2013/11/13 13:48:20 [ssh-pkcs11.c] add missing braces found by pedro --- ChangeLog | 3 +++ ssh-pkcs11.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'ssh-pkcs11.c') diff --git a/ChangeLog b/ChangeLog index eb78c12e5..381b2a961 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,9 @@ - dtucker@cvs.openbsd.org 2013/11/08 11:15:19 [bufaux.c bufbn.c buffer.c sftp-client.c sftp-common.c sftp-glob.c] [uidswap.c] Include stdlib.h for free() as per the man page. + - markus@cvs.openbsd.org 2013/11/13 13:48:20 + [ssh-pkcs11.c] + add missing braces found by pedro 20131110 - (dtucker) [regress/keytype.sh] Populate ECDSA key types to be tested by diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c index 9941e94ed..c49cbf42b 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-pkcs11.c,v 1.10 2013/11/06 23:05:59 djm Exp $ */ +/* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ /* * Copyright (c) 2010 Markus Friedl. All rights reserved. * @@ -427,7 +427,7 @@ pkcs11_key_included(Key ***keysp, int *nkeys, Key *key) int i; for (i = 0; i < *nkeys; i++) - if (key_equal(key, *keysp[i])) + if (key_equal(key, (*keysp)[i])) return (1); return (0); } -- cgit v1.2.3