summaryrefslogtreecommitdiff
path: root/ssh-pkcs11.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2019-06-05 06:41:44 +0100
committerColin Watson <cjwatson@debian.org>2019-06-09 22:09:07 +0100
commit865a97e05b6aab1619e1c8eeb33ccb8f9a9e48d3 (patch)
tree7bb2128eb663180bacfabca88f26d26bf0733824 /ssh-pkcs11.c
parentba627ba172d6649919baedff5ba2789610da382a (diff)
parent7d50f9e5be88179325983a1f58c9d51bb58f025a (diff)
New upstream release (8.0p1)
Diffstat (limited to 'ssh-pkcs11.c')
-rw-r--r--ssh-pkcs11.c1619
1 files changed, 1347 insertions, 272 deletions
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index 775de9642..70f06bffe 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.26 2018/02/07 02:06:51 jsing Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.43 2019/03/08 17:24:43 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * Copyright (c) 2014 Pedro Martelletto. All rights reserved.
4 * 5 *
5 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -19,20 +20,24 @@
19 20
20#ifdef ENABLE_PKCS11 21#ifdef ENABLE_PKCS11
21 22
22#include <sys/types.h>
23#ifdef HAVE_SYS_TIME_H 23#ifdef HAVE_SYS_TIME_H
24# include <sys/time.h> 24# include <sys/time.h>
25#endif 25#endif
26
27#include <sys/types.h>
26#include <stdarg.h> 28#include <stdarg.h>
27#include <stdio.h> 29#include <stdio.h>
28 30
31#include <ctype.h>
29#include <string.h> 32#include <string.h>
30#include <dlfcn.h> 33#include <dlfcn.h>
31 34
32#include "openbsd-compat/sys-queue.h" 35#include "openbsd-compat/sys-queue.h"
33#include "openbsd-compat/openssl-compat.h" 36#include "openbsd-compat/openssl-compat.h"
34 37
38#include <openssl/ecdsa.h>
35#include <openssl/x509.h> 39#include <openssl/x509.h>
40#include <openssl/err.h>
36 41
37#define CRYPTOKI_COMPAT 42#define CRYPTOKI_COMPAT
38#include "pkcs11.h" 43#include "pkcs11.h"
@@ -67,14 +72,25 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_providers;
67struct pkcs11_key { 72struct pkcs11_key {
68 struct pkcs11_provider *provider; 73 struct pkcs11_provider *provider;
69 CK_ULONG slotidx; 74 CK_ULONG slotidx;
70 int (*orig_finish)(RSA *rsa);
71 RSA_METHOD *rsa_method;
72 char *keyid; 75 char *keyid;
73 int keyid_len; 76 int keyid_len;
74}; 77};
75 78
76int pkcs11_interactive = 0; 79int pkcs11_interactive = 0;
77 80
81#ifdef HAVE_EC_KEY_METHOD_NEW
82static void
83ossl_error(const char *msg)
84{
85 unsigned long e;
86
87 error("%s: %s", __func__, msg);
88 while ((e = ERR_get_error()) != 0)
89 error("%s: libcrypto error: %.100s", __func__,
90 ERR_error_string(e, NULL));
91}
92#endif /* HAVE_EC_KEY_METHOD_NEW */
93
78int 94int
79pkcs11_init(int interactive) 95pkcs11_init(int interactive)
80{ 96{
@@ -84,9 +100,9 @@ pkcs11_init(int interactive)
84} 100}
85 101
86/* 102/*
87 * finalize a provider shared libarary, it's no longer usable. 103 * finalize a provider shared library, it's no longer usable.
88 * however, there might still be keys referencing this provider, 104 * however, there might still be keys referencing this provider,
89 * so the actuall freeing of memory is handled by pkcs11_provider_unref(). 105 * so the actual freeing of memory is handled by pkcs11_provider_unref().
90 * this is called when a provider gets unregistered. 106 * this is called when a provider gets unregistered.
91 */ 107 */
92static void 108static void
@@ -123,6 +139,7 @@ pkcs11_provider_unref(struct pkcs11_provider *p)
123 if (--p->refcount <= 0) { 139 if (--p->refcount <= 0) {
124 if (p->valid) 140 if (p->valid)
125 error("pkcs11_provider_unref: %p still valid", p); 141 error("pkcs11_provider_unref: %p still valid", p);
142 free(p->name);
126 free(p->slotlist); 143 free(p->slotlist);
127 free(p->slotinfo); 144 free(p->slotinfo);
128 free(p); 145 free(p);
@@ -171,23 +188,27 @@ pkcs11_del_provider(char *provider_id)
171 return (-1); 188 return (-1);
172} 189}
173 190
174/* openssl callback for freeing an RSA key */ 191static RSA_METHOD *rsa_method;
175static int 192static int rsa_idx = 0;
176pkcs11_rsa_finish(RSA *rsa) 193#ifdef HAVE_EC_KEY_METHOD_NEW
194static EC_KEY_METHOD *ec_key_method;
195static int ec_key_idx = 0;
196#endif
197
198/* release a wrapped object */
199static void
200pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
201 long argl, void *argp)
177{ 202{
178 struct pkcs11_key *k11; 203 struct pkcs11_key *k11 = ptr;
179 int rv = -1;
180 204
181 if ((k11 = RSA_get_app_data(rsa)) != NULL) { 205 debug("%s: parent %p ptr %p idx %d", __func__, parent, ptr, idx);
182 if (k11->orig_finish) 206 if (k11 == NULL)
183 rv = k11->orig_finish(rsa); 207 return;
184 if (k11->provider) 208 if (k11->provider)
185 pkcs11_provider_unref(k11->provider); 209 pkcs11_provider_unref(k11->provider);
186 RSA_meth_free(k11->rsa_method); 210 free(k11->keyid);
187 free(k11->keyid); 211 free(k11);
188 free(k11);
189 }
190 return (rv);
191} 212}
192 213
193/* find a single 'obj' for given attributes */ 214/* find a single 'obj' for given attributes */
@@ -218,88 +239,193 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr,
218 return (ret); 239 return (ret);
219} 240}
220 241
221/* openssl callback doing the actual signing operation */
222static int 242static int
223pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, 243pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type)
224 int padding)
225{ 244{
226 struct pkcs11_key *k11;
227 struct pkcs11_slotinfo *si; 245 struct pkcs11_slotinfo *si;
228 CK_FUNCTION_LIST *f; 246 CK_FUNCTION_LIST *f;
229 CK_OBJECT_HANDLE obj;
230 CK_ULONG tlen = 0;
231 CK_RV rv;
232 CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY;
233 CK_BBOOL true_val = CK_TRUE;
234 CK_MECHANISM mech = {
235 CKM_RSA_PKCS, NULL_PTR, 0
236 };
237 CK_ATTRIBUTE key_filter[] = {
238 {CKA_CLASS, NULL, sizeof(private_key_class) },
239 {CKA_ID, NULL, 0},
240 {CKA_SIGN, NULL, sizeof(true_val) }
241 };
242 char *pin = NULL, prompt[1024]; 247 char *pin = NULL, prompt[1024];
243 int rval = -1; 248 CK_RV rv;
244 249
245 key_filter[0].pValue = &private_key_class; 250 if (!k11->provider || !k11->provider->valid) {
246 key_filter[2].pValue = &true_val; 251 error("no pkcs11 (valid) provider found");
252 return (-1);
253 }
254
255 f = k11->provider->function_list;
256 si = &k11->provider->slotinfo[k11->slotidx];
257
258 if (!pkcs11_interactive) {
259 error("need pin entry%s",
260 (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ?
261 " on reader keypad" : "");
262 return (-1);
263 }
264 if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
265 verbose("Deferring PIN entry to reader keypad.");
266 else {
267 snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
268 si->token.label);
269 if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
270 debug("%s: no pin specified", __func__);
271 return (-1); /* bail out */
272 }
273 }
274 rv = f->C_Login(si->session, type, (u_char *)pin,
275 (pin != NULL) ? strlen(pin) : 0);
276 if (pin != NULL)
277 freezero(pin, strlen(pin));
278 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
279 error("C_Login failed: %lu", rv);
280 return (-1);
281 }
282 si->logged_in = 1;
283 return (0);
284}
285
286static int
287pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
288 CK_ATTRIBUTE_TYPE type, int *val)
289{
290 struct pkcs11_slotinfo *si;
291 CK_FUNCTION_LIST *f;
292 CK_BBOOL flag = 0;
293 CK_ATTRIBUTE attr;
294 CK_RV rv;
295
296 *val = 0;
247 297
248 if ((k11 = RSA_get_app_data(rsa)) == NULL) { 298 if (!k11->provider || !k11->provider->valid) {
249 error("RSA_get_app_data failed for rsa %p", rsa); 299 error("no pkcs11 (valid) provider found");
250 return (-1); 300 return (-1);
251 } 301 }
302
303 f = k11->provider->function_list;
304 si = &k11->provider->slotinfo[k11->slotidx];
305
306 attr.type = type;
307 attr.pValue = &flag;
308 attr.ulValueLen = sizeof(flag);
309
310 rv = f->C_GetAttributeValue(si->session, obj, &attr, 1);
311 if (rv != CKR_OK) {
312 error("C_GetAttributeValue failed: %lu", rv);
313 return (-1);
314 }
315 *val = flag != 0;
316 debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
317 __func__, k11->provider, k11->slotidx, obj, type, *val);
318 return (0);
319}
320
321static int
322pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
323{
324 struct pkcs11_slotinfo *si;
325 CK_FUNCTION_LIST *f;
326 CK_OBJECT_HANDLE obj;
327 CK_RV rv;
328 CK_OBJECT_CLASS private_key_class;
329 CK_BBOOL true_val;
330 CK_MECHANISM mech;
331 CK_ATTRIBUTE key_filter[3];
332 int always_auth = 0;
333 int did_login = 0;
334
252 if (!k11->provider || !k11->provider->valid) { 335 if (!k11->provider || !k11->provider->valid) {
253 error("no pkcs11 (valid) provider for rsa %p", rsa); 336 error("no pkcs11 (valid) provider found");
254 return (-1); 337 return (-1);
255 } 338 }
339
256 f = k11->provider->function_list; 340 f = k11->provider->function_list;
257 si = &k11->provider->slotinfo[k11->slotidx]; 341 si = &k11->provider->slotinfo[k11->slotidx];
342
258 if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { 343 if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) {
259 if (!pkcs11_interactive) { 344 if (pkcs11_login(k11, CKU_USER) < 0) {
260 error("need pin entry%s", (si->token.flags & 345 error("login failed");
261 CKF_PROTECTED_AUTHENTICATION_PATH) ?
262 " on reader keypad" : "");
263 return (-1);
264 }
265 if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH)
266 verbose("Deferring PIN entry to reader keypad.");
267 else {
268 snprintf(prompt, sizeof(prompt),
269 "Enter PIN for '%s': ", si->token.label);
270 pin = read_passphrase(prompt, RP_ALLOW_EOF);
271 if (pin == NULL)
272 return (-1); /* bail out */
273 }
274 rv = f->C_Login(si->session, CKU_USER, (u_char *)pin,
275 (pin != NULL) ? strlen(pin) : 0);
276 if (pin != NULL) {
277 explicit_bzero(pin, strlen(pin));
278 free(pin);
279 }
280 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
281 error("C_Login failed: %lu", rv);
282 return (-1); 346 return (-1);
283 } 347 }
284 si->logged_in = 1; 348 did_login = 1;
285 } 349 }
350
351 memset(&key_filter, 0, sizeof(key_filter));
352 private_key_class = CKO_PRIVATE_KEY;
353 key_filter[0].type = CKA_CLASS;
354 key_filter[0].pValue = &private_key_class;
355 key_filter[0].ulValueLen = sizeof(private_key_class);
356
357 key_filter[1].type = CKA_ID;
286 key_filter[1].pValue = k11->keyid; 358 key_filter[1].pValue = k11->keyid;
287 key_filter[1].ulValueLen = k11->keyid_len; 359 key_filter[1].ulValueLen = k11->keyid_len;
360
361 true_val = CK_TRUE;
362 key_filter[2].type = CKA_SIGN;
363 key_filter[2].pValue = &true_val;
364 key_filter[2].ulValueLen = sizeof(true_val);
365
288 /* try to find object w/CKA_SIGN first, retry w/o */ 366 /* try to find object w/CKA_SIGN first, retry w/o */
289 if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 && 367 if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 &&
290 pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) { 368 pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) {
291 error("cannot find private key"); 369 error("cannot find private key");
292 } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { 370 return (-1);
371 }
372
373 memset(&mech, 0, sizeof(mech));
374 mech.mechanism = mech_type;
375 mech.pParameter = NULL_PTR;
376 mech.ulParameterLen = 0;
377
378 if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) {
293 error("C_SignInit failed: %lu", rv); 379 error("C_SignInit failed: %lu", rv);
294 } else { 380 return (-1);
295 /* XXX handle CKR_BUFFER_TOO_SMALL */
296 tlen = RSA_size(rsa);
297 rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
298 if (rv == CKR_OK)
299 rval = tlen;
300 else
301 error("C_Sign failed: %lu", rv);
302 } 381 }
382
383 pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
384 &always_auth); /* ignore errors here */
385 if (always_auth && !did_login) {
386 debug("%s: always-auth key", __func__);
387 if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
388 error("login failed for always-auth key");
389 return (-1);
390 }
391 }
392
393 return (0);
394}
395
396/* openssl callback doing the actual signing operation */
397static int
398pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
399 int padding)
400{
401 struct pkcs11_key *k11;
402 struct pkcs11_slotinfo *si;
403 CK_FUNCTION_LIST *f;
404 CK_ULONG tlen = 0;
405 CK_RV rv;
406 int rval = -1;
407
408 if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) {
409 error("RSA_get_ex_data failed for rsa %p", rsa);
410 return (-1);
411 }
412
413 if (pkcs11_get_key(k11, CKM_RSA_PKCS) == -1) {
414 error("pkcs11_get_key failed");
415 return (-1);
416 }
417
418 f = k11->provider->function_list;
419 si = &k11->provider->slotinfo[k11->slotidx];
420 tlen = RSA_size(rsa);
421
422 /* XXX handle CKR_BUFFER_TOO_SMALL */
423 rv = f->C_Sign(si->session, (CK_BYTE *)from, flen, to, &tlen);
424 if (rv == CKR_OK)
425 rval = tlen;
426 else
427 error("C_Sign failed: %lu", rv);
428
303 return (rval); 429 return (rval);
304} 430}
305 431
@@ -310,13 +436,36 @@ pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
310 return (-1); 436 return (-1);
311} 437}
312 438
439static int
440pkcs11_rsa_start_wrapper(void)
441{
442 if (rsa_method != NULL)
443 return (0);
444 rsa_method = RSA_meth_dup(RSA_get_default_method());
445 if (rsa_method == NULL)
446 return (-1);
447 rsa_idx = RSA_get_ex_new_index(0, "ssh-pkcs11-rsa",
448 NULL, NULL, pkcs11_k11_free);
449 if (rsa_idx == -1)
450 return (-1);
451 if (!RSA_meth_set1_name(rsa_method, "pkcs11") ||
452 !RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) ||
453 !RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) {
454 error("%s: setup pkcs11 method failed", __func__);
455 return (-1);
456 }
457 return (0);
458}
459
313/* redirect private key operations for rsa key to pkcs11 token */ 460/* redirect private key operations for rsa key to pkcs11 token */
314static int 461static int
315pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, 462pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
316 CK_ATTRIBUTE *keyid_attrib, RSA *rsa) 463 CK_ATTRIBUTE *keyid_attrib, RSA *rsa)
317{ 464{
318 struct pkcs11_key *k11; 465 struct pkcs11_key *k11;
319 const RSA_METHOD *def = RSA_get_default_method(); 466
467 if (pkcs11_rsa_start_wrapper() == -1)
468 return (-1);
320 469
321 k11 = xcalloc(1, sizeof(*k11)); 470 k11 = xcalloc(1, sizeof(*k11));
322 k11->provider = provider; 471 k11->provider = provider;
@@ -328,22 +477,126 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
328 k11->keyid = xmalloc(k11->keyid_len); 477 k11->keyid = xmalloc(k11->keyid_len);
329 memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); 478 memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
330 } 479 }
331 k11->rsa_method = RSA_meth_dup(def); 480
332 if (k11->rsa_method == NULL) 481 RSA_set_method(rsa, rsa_method);
333 fatal("%s: RSA_meth_dup failed", __func__); 482 RSA_set_ex_data(rsa, rsa_idx, k11);
334 k11->orig_finish = RSA_meth_get_finish(def);
335 if (!RSA_meth_set1_name(k11->rsa_method, "pkcs11") ||
336 !RSA_meth_set_priv_enc(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);
343 RSA_set_app_data(rsa, k11);
344 return (0); 483 return (0);
345} 484}
346 485
486#ifdef HAVE_EC_KEY_METHOD_NEW
487/* openssl callback doing the actual signing operation */
488static ECDSA_SIG *
489ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
490 const BIGNUM *rp, EC_KEY *ec)
491{
492 struct pkcs11_key *k11;
493 struct pkcs11_slotinfo *si;
494 CK_FUNCTION_LIST *f;
495 CK_ULONG siglen = 0, bnlen;
496 CK_RV rv;
497 ECDSA_SIG *ret = NULL;
498 u_char *sig;
499 BIGNUM *r = NULL, *s = NULL;
500
501 if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
502 ossl_error("EC_KEY_get_key_method_data failed for ec");
503 return (NULL);
504 }
505
506 if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
507 error("pkcs11_get_key failed");
508 return (NULL);
509 }
510
511 f = k11->provider->function_list;
512 si = &k11->provider->slotinfo[k11->slotidx];
513
514 siglen = ECDSA_size(ec);
515 sig = xmalloc(siglen);
516
517 /* XXX handle CKR_BUFFER_TOO_SMALL */
518 rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
519 if (rv != CKR_OK) {
520 error("C_Sign failed: %lu", rv);
521 goto done;
522 }
523 if (siglen < 64 || siglen > 132 || siglen % 2) {
524 ossl_error("d2i_ECDSA_SIG failed");
525 goto done;
526 }
527 bnlen = siglen/2;
528 if ((ret = ECDSA_SIG_new()) == NULL) {
529 error("ECDSA_SIG_new failed");
530 goto done;
531 }
532 if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
533 (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
534 ossl_error("d2i_ECDSA_SIG failed");
535 ECDSA_SIG_free(ret);
536 ret = NULL;
537 goto done;
538 }
539 if (!ECDSA_SIG_set0(ret, r, s)) {
540 error("%s: ECDSA_SIG_set0 failed", __func__);
541 ECDSA_SIG_free(ret);
542 ret = NULL;
543 goto done;
544 }
545 r = s = NULL; /* now owned by ret */
546 /* success */
547 done:
548 BN_free(r);
549 BN_free(s);
550 free(sig);
551
552 return (ret);
553}
554
555static int
556pkcs11_ecdsa_start_wrapper(void)
557{
558 int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
559 unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
560
561 if (ec_key_method != NULL)
562 return (0);
563 ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
564 NULL, NULL, pkcs11_k11_free);
565 if (ec_key_idx == -1)
566 return (-1);
567 ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
568 if (ec_key_method == NULL)
569 return (-1);
570 EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL);
571 EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign);
572 return (0);
573}
574
575static int
576pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
577 CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
578{
579 struct pkcs11_key *k11;
580
581 if (pkcs11_ecdsa_start_wrapper() == -1)
582 return (-1);
583
584 k11 = xcalloc(1, sizeof(*k11));
585 k11->provider = provider;
586 provider->refcount++; /* provider referenced by ECDSA key */
587 k11->slotidx = slotidx;
588 /* identify key object on smartcard */
589 k11->keyid_len = keyid_attrib->ulValueLen;
590 k11->keyid = xmalloc(k11->keyid_len);
591 memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
592
593 EC_KEY_set_method(ec, ec_key_method);
594 EC_KEY_set_ex_data(ec, ec_key_idx, k11);
595
596 return (0);
597}
598#endif /* HAVE_EC_KEY_METHOD_NEW */
599
347/* remove trailing spaces */ 600/* remove trailing spaces */
348static void 601static void
349rmspace(u_char *buf, size_t len) 602rmspace(u_char *buf, size_t len)
@@ -364,79 +617,66 @@ rmspace(u_char *buf, size_t len)
364 * if pin == NULL we delay login until key use 617 * if pin == NULL we delay login until key use
365 */ 618 */
366static int 619static int
367pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) 620pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
621 CK_ULONG user)
368{ 622{
369 CK_RV rv; 623 struct pkcs11_slotinfo *si;
370 CK_FUNCTION_LIST *f; 624 CK_FUNCTION_LIST *f;
625 CK_RV rv;
371 CK_SESSION_HANDLE session; 626 CK_SESSION_HANDLE session;
372 int login_required; 627 int login_required, have_pinpad, ret;
628 char prompt[1024], *xpin = NULL;
373 629
374 f = p->function_list; 630 f = p->function_list;
375 login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED; 631 si = &p->slotinfo[slotidx];
376 if (pin && login_required && !strlen(pin)) { 632
633 have_pinpad = si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH;
634 login_required = si->token.flags & CKF_LOGIN_REQUIRED;
635
636 /* fail early before opening session */
637 if (login_required && !have_pinpad && !pkcs11_interactive &&
638 (pin == NULL || strlen(pin) == 0)) {
377 error("pin required"); 639 error("pin required");
378 return (-1); 640 return (-SSH_PKCS11_ERR_PIN_REQUIRED);
379 } 641 }
380 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| 642 if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
381 CKF_SERIAL_SESSION, NULL, NULL, &session)) 643 CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
382 != CKR_OK) {
383 error("C_OpenSession failed: %lu", rv); 644 error("C_OpenSession failed: %lu", rv);
384 return (-1); 645 return (-1);
385 } 646 }
386 if (login_required && pin) { 647 if (login_required) {
387 rv = f->C_Login(session, CKU_USER, 648 if (have_pinpad && (pin == NULL || strlen(pin) == 0)) {
388 (u_char *)pin, strlen(pin)); 649 /* defer PIN entry to the reader keypad */
650 rv = f->C_Login(session, CKU_USER, NULL_PTR, 0);
651 } else {
652 if (pkcs11_interactive) {
653 snprintf(prompt, sizeof(prompt),
654 "Enter PIN for '%s': ", si->token.label);
655 if ((xpin = read_passphrase(prompt,
656 RP_ALLOW_EOF)) == NULL) {
657 debug("%s: no pin specified",
658 __func__);
659 return (-SSH_PKCS11_ERR_PIN_REQUIRED);
660 }
661 pin = xpin;
662 }
663 rv = f->C_Login(session, CKU_USER,
664 (u_char *)pin, strlen(pin));
665 if (xpin != NULL)
666 freezero(xpin, strlen(xpin));
667 }
389 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { 668 if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
390 error("C_Login failed: %lu", rv); 669 error("C_Login failed: %lu", rv);
670 ret = (rv == CKR_PIN_LOCKED) ?
671 -SSH_PKCS11_ERR_PIN_LOCKED :
672 -SSH_PKCS11_ERR_LOGIN_FAIL;
391 if ((rv = f->C_CloseSession(session)) != CKR_OK) 673 if ((rv = f->C_CloseSession(session)) != CKR_OK)
392 error("C_CloseSession failed: %lu", rv); 674 error("C_CloseSession failed: %lu", rv);
393 return (-1); 675 return (ret);
394 } 676 }
395 p->slotinfo[slotidx].logged_in = 1; 677 si->logged_in = 1;
396 } 678 }
397 p->slotinfo[slotidx].session = session; 679 si->session = session;
398 return (0);
399}
400
401/*
402 * lookup public keys for token in slot identified by slotidx,
403 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
404 * keysp points to an (possibly empty) array with *nkeys keys.
405 */
406static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,
407 CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)
408 __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
409
410static int
411pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
412 struct sshkey ***keysp, int *nkeys)
413{
414 CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY;
415 CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
416 CK_ATTRIBUTE pubkey_filter[] = {
417 { CKA_CLASS, NULL, sizeof(pubkey_class) }
418 };
419 CK_ATTRIBUTE cert_filter[] = {
420 { CKA_CLASS, NULL, sizeof(cert_class) }
421 };
422 CK_ATTRIBUTE pubkey_attribs[] = {
423 { CKA_ID, NULL, 0 },
424 { CKA_MODULUS, NULL, 0 },
425 { CKA_PUBLIC_EXPONENT, NULL, 0 }
426 };
427 CK_ATTRIBUTE cert_attribs[] = {
428 { CKA_ID, NULL, 0 },
429 { CKA_SUBJECT, NULL, 0 },
430 { CKA_VALUE, NULL, 0 }
431 };
432 pubkey_filter[0].pValue = &pubkey_class;
433 cert_filter[0].pValue = &cert_class;
434
435 if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs,
436 keysp, nkeys) < 0 ||
437 pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs,
438 keysp, nkeys) < 0)
439 return (-1);
440 return (0); 680 return (0);
441} 681}
442 682
@@ -451,6 +691,364 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
451 return (0); 691 return (0);
452} 692}
453 693
694#ifdef HAVE_EC_KEY_METHOD_NEW
695static struct sshkey *
696pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
697 CK_OBJECT_HANDLE *obj)
698{
699 CK_ATTRIBUTE key_attr[3];
700 CK_SESSION_HANDLE session;
701 CK_FUNCTION_LIST *f = NULL;
702 CK_RV rv;
703 ASN1_OCTET_STRING *octet = NULL;
704 EC_KEY *ec = NULL;
705 EC_GROUP *group = NULL;
706 struct sshkey *key = NULL;
707 const unsigned char *attrp = NULL;
708 int i;
709 int nid;
710
711 memset(&key_attr, 0, sizeof(key_attr));
712 key_attr[0].type = CKA_ID;
713 key_attr[1].type = CKA_EC_POINT;
714 key_attr[2].type = CKA_EC_PARAMS;
715
716 session = p->slotinfo[slotidx].session;
717 f = p->function_list;
718
719 /* figure out size of the attributes */
720 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
721 if (rv != CKR_OK) {
722 error("C_GetAttributeValue failed: %lu", rv);
723 return (NULL);
724 }
725
726 /*
727 * Allow CKA_ID (always first attribute) to be empty, but
728 * ensure that none of the others are zero length.
729 * XXX assumes CKA_ID is always first.
730 */
731 if (key_attr[1].ulValueLen == 0 ||
732 key_attr[2].ulValueLen == 0) {
733 error("invalid attribute length");
734 return (NULL);
735 }
736
737 /* allocate buffers for attributes */
738 for (i = 0; i < 3; i++)
739 if (key_attr[i].ulValueLen > 0)
740 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
741
742 /* retrieve ID, public point and curve parameters of EC key */
743 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
744 if (rv != CKR_OK) {
745 error("C_GetAttributeValue failed: %lu", rv);
746 goto fail;
747 }
748
749 ec = EC_KEY_new();
750 if (ec == NULL) {
751 error("EC_KEY_new failed");
752 goto fail;
753 }
754
755 attrp = key_attr[2].pValue;
756 group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
757 if (group == NULL) {
758 ossl_error("d2i_ECPKParameters failed");
759 goto fail;
760 }
761
762 if (EC_KEY_set_group(ec, group) == 0) {
763 ossl_error("EC_KEY_set_group failed");
764 goto fail;
765 }
766
767 if (key_attr[1].ulValueLen <= 2) {
768 error("CKA_EC_POINT too small");
769 goto fail;
770 }
771
772 attrp = key_attr[1].pValue;
773 octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
774 if (octet == NULL) {
775 ossl_error("d2i_ASN1_OCTET_STRING failed");
776 goto fail;
777 }
778 attrp = octet->data;
779 if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
780 ossl_error("o2i_ECPublicKey failed");
781 goto fail;
782 }
783
784 nid = sshkey_ecdsa_key_to_nid(ec);
785 if (nid < 0) {
786 error("couldn't get curve nid");
787 goto fail;
788 }
789
790 if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
791 goto fail;
792
793 key = sshkey_new(KEY_UNSPEC);
794 if (key == NULL) {
795 error("sshkey_new failed");
796 goto fail;
797 }
798
799 key->ecdsa = ec;
800 key->ecdsa_nid = nid;
801 key->type = KEY_ECDSA;
802 key->flags |= SSHKEY_FLAG_EXT;
803 ec = NULL; /* now owned by key */
804
805fail:
806 for (i = 0; i < 3; i++)
807 free(key_attr[i].pValue);
808 if (ec)
809 EC_KEY_free(ec);
810 if (group)
811 EC_GROUP_free(group);
812 if (octet)
813 ASN1_OCTET_STRING_free(octet);
814
815 return (key);
816}
817#endif /* HAVE_EC_KEY_METHOD_NEW */
818
819static struct sshkey *
820pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
821 CK_OBJECT_HANDLE *obj)
822{
823 CK_ATTRIBUTE key_attr[3];
824 CK_SESSION_HANDLE session;
825 CK_FUNCTION_LIST *f = NULL;
826 CK_RV rv;
827 RSA *rsa = NULL;
828 BIGNUM *rsa_n, *rsa_e;
829 struct sshkey *key = NULL;
830 int i;
831
832 memset(&key_attr, 0, sizeof(key_attr));
833 key_attr[0].type = CKA_ID;
834 key_attr[1].type = CKA_MODULUS;
835 key_attr[2].type = CKA_PUBLIC_EXPONENT;
836
837 session = p->slotinfo[slotidx].session;
838 f = p->function_list;
839
840 /* figure out size of the attributes */
841 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
842 if (rv != CKR_OK) {
843 error("C_GetAttributeValue failed: %lu", rv);
844 return (NULL);
845 }
846
847 /*
848 * Allow CKA_ID (always first attribute) to be empty, but
849 * ensure that none of the others are zero length.
850 * XXX assumes CKA_ID is always first.
851 */
852 if (key_attr[1].ulValueLen == 0 ||
853 key_attr[2].ulValueLen == 0) {
854 error("invalid attribute length");
855 return (NULL);
856 }
857
858 /* allocate buffers for attributes */
859 for (i = 0; i < 3; i++)
860 if (key_attr[i].ulValueLen > 0)
861 key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
862
863 /* retrieve ID, modulus and public exponent of RSA key */
864 rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
865 if (rv != CKR_OK) {
866 error("C_GetAttributeValue failed: %lu", rv);
867 goto fail;
868 }
869
870 rsa = RSA_new();
871 if (rsa == NULL) {
872 error("RSA_new failed");
873 goto fail;
874 }
875
876 rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
877 rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
878 if (rsa_n == NULL || rsa_e == NULL) {
879 error("BN_bin2bn failed");
880 goto fail;
881 }
882 if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
883 fatal("%s: set key", __func__);
884 rsa_n = rsa_e = NULL; /* transferred */
885
886 if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
887 goto fail;
888
889 key = sshkey_new(KEY_UNSPEC);
890 if (key == NULL) {
891 error("sshkey_new failed");
892 goto fail;
893 }
894
895 key->rsa = rsa;
896 key->type = KEY_RSA;
897 key->flags |= SSHKEY_FLAG_EXT;
898 rsa = NULL; /* now owned by key */
899
900fail:
901 for (i = 0; i < 3; i++)
902 free(key_attr[i].pValue);
903 RSA_free(rsa);
904
905 return (key);
906}
907
908static struct sshkey *
909pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
910 CK_OBJECT_HANDLE *obj)
911{
912 CK_ATTRIBUTE cert_attr[3];
913 CK_SESSION_HANDLE session;
914 CK_FUNCTION_LIST *f = NULL;
915 CK_RV rv;
916 X509 *x509 = NULL;
917 EVP_PKEY *evp;
918 RSA *rsa = NULL;
919 EC_KEY *ec = NULL;
920 struct sshkey *key = NULL;
921 int i;
922#ifdef HAVE_EC_KEY_METHOD_NEW
923 int nid;
924#endif
925 const u_char *cp;
926
927 memset(&cert_attr, 0, sizeof(cert_attr));
928 cert_attr[0].type = CKA_ID;
929 cert_attr[1].type = CKA_SUBJECT;
930 cert_attr[2].type = CKA_VALUE;
931
932 session = p->slotinfo[slotidx].session;
933 f = p->function_list;
934
935 /* figure out size of the attributes */
936 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
937 if (rv != CKR_OK) {
938 error("C_GetAttributeValue failed: %lu", rv);
939 return (NULL);
940 }
941
942 /*
943 * Allow CKA_ID (always first attribute) to be empty, but
944 * ensure that none of the others are zero length.
945 * XXX assumes CKA_ID is always first.
946 */
947 if (cert_attr[1].ulValueLen == 0 ||
948 cert_attr[2].ulValueLen == 0) {
949 error("invalid attribute length");
950 return (NULL);
951 }
952
953 /* allocate buffers for attributes */
954 for (i = 0; i < 3; i++)
955 if (cert_attr[i].ulValueLen > 0)
956 cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
957
958 /* retrieve ID, subject and value of certificate */
959 rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
960 if (rv != CKR_OK) {
961 error("C_GetAttributeValue failed: %lu", rv);
962 goto fail;
963 }
964
965 x509 = X509_new();
966 if (x509 == NULL) {
967 error("x509_new failed");
968 goto fail;
969 }
970
971 cp = cert_attr[2].pValue;
972 if (d2i_X509(&x509, &cp, cert_attr[2].ulValueLen) == NULL) {
973 error("d2i_x509 failed");
974 goto fail;
975 }
976
977 evp = X509_get_pubkey(x509);
978 if (evp == NULL) {
979 error("X509_get_pubkey failed");
980 goto fail;
981 }
982
983 if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
984 if (EVP_PKEY_get0_RSA(evp) == NULL) {
985 error("invalid x509; no rsa key");
986 goto fail;
987 }
988 if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
989 error("RSAPublicKey_dup failed");
990 goto fail;
991 }
992
993 if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
994 goto fail;
995
996 key = sshkey_new(KEY_UNSPEC);
997 if (key == NULL) {
998 error("sshkey_new failed");
999 goto fail;
1000 }
1001
1002 key->rsa = rsa;
1003 key->type = KEY_RSA;
1004 key->flags |= SSHKEY_FLAG_EXT;
1005 rsa = NULL; /* now owned by key */
1006#ifdef HAVE_EC_KEY_METHOD_NEW
1007 } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
1008 if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
1009 error("invalid x509; no ec key");
1010 goto fail;
1011 }
1012 if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1013 error("EC_KEY_dup failed");
1014 goto fail;
1015 }
1016
1017 nid = sshkey_ecdsa_key_to_nid(ec);
1018 if (nid < 0) {
1019 error("couldn't get curve nid");
1020 goto fail;
1021 }
1022
1023 if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1024 goto fail;
1025
1026 key = sshkey_new(KEY_UNSPEC);
1027 if (key == NULL) {
1028 error("sshkey_new failed");
1029 goto fail;
1030 }
1031
1032 key->ecdsa = ec;
1033 key->ecdsa_nid = nid;
1034 key->type = KEY_ECDSA;
1035 key->flags |= SSHKEY_FLAG_EXT;
1036 ec = NULL; /* now owned by key */
1037#endif /* HAVE_EC_KEY_METHOD_NEW */
1038 } else
1039 error("unknown certificate key type");
1040
1041fail:
1042 for (i = 0; i < 3; i++)
1043 free(cert_attr[i].pValue);
1044 X509_free(x509);
1045 RSA_free(rsa);
1046 EC_KEY_free(ec);
1047
1048 return (key);
1049}
1050
1051#if 0
454static int 1052static int
455have_rsa_key(const RSA *rsa) 1053have_rsa_key(const RSA *rsa)
456{ 1054{
@@ -459,140 +1057,402 @@ have_rsa_key(const RSA *rsa)
459 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL); 1057 RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
460 return rsa_n != NULL && rsa_e != NULL; 1058 return rsa_n != NULL && rsa_e != NULL;
461} 1059}
1060#endif
462 1061
1062/*
1063 * lookup certificates for token in slot identified by slotidx,
1064 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1065 * keysp points to an (possibly empty) array with *nkeys keys.
1066 */
463static int 1067static int
464pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, 1068pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
465 CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
466 struct sshkey ***keysp, int *nkeys) 1069 struct sshkey ***keysp, int *nkeys)
467{ 1070{
468 struct sshkey *key; 1071 struct sshkey *key = NULL;
469 RSA *rsa; 1072 CK_OBJECT_CLASS key_class;
470 X509 *x509; 1073 CK_ATTRIBUTE key_attr[1];
471 EVP_PKEY *evp; 1074 CK_SESSION_HANDLE session;
472 int i; 1075 CK_FUNCTION_LIST *f = NULL;
473 const u_char *cp; 1076 CK_RV rv;
474 CK_RV rv; 1077 CK_OBJECT_HANDLE obj;
475 CK_OBJECT_HANDLE obj; 1078 CK_ULONG n = 0;
476 CK_ULONG nfound; 1079 int ret = -1;
477 CK_SESSION_HANDLE session; 1080
478 CK_FUNCTION_LIST *f; 1081 memset(&key_attr, 0, sizeof(key_attr));
1082 memset(&obj, 0, sizeof(obj));
1083
1084 key_class = CKO_CERTIFICATE;
1085 key_attr[0].type = CKA_CLASS;
1086 key_attr[0].pValue = &key_class;
1087 key_attr[0].ulValueLen = sizeof(key_class);
479 1088
480 f = p->function_list;
481 session = p->slotinfo[slotidx].session; 1089 session = p->slotinfo[slotidx].session;
482 /* setup a filter the looks for public keys */ 1090 f = p->function_list;
483 if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { 1091
1092 rv = f->C_FindObjectsInit(session, key_attr, 1);
1093 if (rv != CKR_OK) {
484 error("C_FindObjectsInit failed: %lu", rv); 1094 error("C_FindObjectsInit failed: %lu", rv);
485 return (-1); 1095 goto fail;
486 } 1096 }
1097
487 while (1) { 1098 while (1) {
488 /* XXX 3 attributes in attribs[] */ 1099 CK_CERTIFICATE_TYPE ck_cert_type;
489 for (i = 0; i < 3; i++) { 1100
490 attribs[i].pValue = NULL; 1101 rv = f->C_FindObjects(session, &obj, 1, &n);
491 attribs[i].ulValueLen = 0; 1102 if (rv != CKR_OK) {
1103 error("C_FindObjects failed: %lu", rv);
1104 goto fail;
492 } 1105 }
493 if ((rv = f->C_FindObjects(session, &obj, 1, &nfound)) != CKR_OK 1106 if (n == 0)
494 || nfound == 0)
495 break; 1107 break;
496 /* found a key, so figure out size of the attributes */ 1108
497 if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) 1109 memset(&ck_cert_type, 0, sizeof(ck_cert_type));
498 != CKR_OK) { 1110 memset(&key_attr, 0, sizeof(key_attr));
1111 key_attr[0].type = CKA_CERTIFICATE_TYPE;
1112 key_attr[0].pValue = &ck_cert_type;
1113 key_attr[0].ulValueLen = sizeof(ck_cert_type);
1114
1115 rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1116 if (rv != CKR_OK) {
499 error("C_GetAttributeValue failed: %lu", rv); 1117 error("C_GetAttributeValue failed: %lu", rv);
500 continue; 1118 goto fail;
501 } 1119 }
502 /* 1120
503 * Allow CKA_ID (always first attribute) to be empty, but 1121 switch (ck_cert_type) {
504 * ensure that none of the others are zero length. 1122 case CKC_X_509:
505 * XXX assumes CKA_ID is always first. 1123 key = pkcs11_fetch_x509_pubkey(p, slotidx, &obj);
506 */ 1124 break;
507 if (attribs[1].ulValueLen == 0 || 1125 default:
508 attribs[2].ulValueLen == 0) { 1126 /* XXX print key type? */
1127 key = NULL;
1128 error("skipping unsupported certificate type");
1129 }
1130
1131 if (key == NULL) {
1132 error("failed to fetch key");
509 continue; 1133 continue;
510 } 1134 }
511 /* allocate buffers for attributes */ 1135
512 for (i = 0; i < 3; i++) { 1136 if (pkcs11_key_included(keysp, nkeys, key)) {
513 if (attribs[i].ulValueLen > 0) { 1137 sshkey_free(key);
514 attribs[i].pValue = xmalloc( 1138 } else {
515 attribs[i].ulValueLen); 1139 /* expand key array and add key */
516 } 1140 *keysp = xrecallocarray(*keysp, *nkeys,
1141 *nkeys + 1, sizeof(struct sshkey *));
1142 (*keysp)[*nkeys] = key;
1143 *nkeys = *nkeys + 1;
1144 debug("have %d keys", *nkeys);
517 } 1145 }
1146 }
518 1147
519 /* 1148 ret = 0;
520 * retrieve ID, modulus and public exponent of RSA key, 1149fail:
521 * or ID, subject and value for certificates. 1150 rv = f->C_FindObjectsFinal(session);
522 */ 1151 if (rv != CKR_OK) {
523 rsa = NULL; 1152 error("C_FindObjectsFinal failed: %lu", rv);
524 if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) 1153 ret = -1;
525 != CKR_OK) { 1154 }
1155
1156 return (ret);
1157}
1158
1159/*
1160 * lookup public keys for token in slot identified by slotidx,
1161 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1162 * keysp points to an (possibly empty) array with *nkeys keys.
1163 */
1164static int
1165pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1166 struct sshkey ***keysp, int *nkeys)
1167{
1168 struct sshkey *key = NULL;
1169 CK_OBJECT_CLASS key_class;
1170 CK_ATTRIBUTE key_attr[1];
1171 CK_SESSION_HANDLE session;
1172 CK_FUNCTION_LIST *f = NULL;
1173 CK_RV rv;
1174 CK_OBJECT_HANDLE obj;
1175 CK_ULONG n = 0;
1176 int ret = -1;
1177
1178 memset(&key_attr, 0, sizeof(key_attr));
1179 memset(&obj, 0, sizeof(obj));
1180
1181 key_class = CKO_PUBLIC_KEY;
1182 key_attr[0].type = CKA_CLASS;
1183 key_attr[0].pValue = &key_class;
1184 key_attr[0].ulValueLen = sizeof(key_class);
1185
1186 session = p->slotinfo[slotidx].session;
1187 f = p->function_list;
1188
1189 rv = f->C_FindObjectsInit(session, key_attr, 1);
1190 if (rv != CKR_OK) {
1191 error("C_FindObjectsInit failed: %lu", rv);
1192 goto fail;
1193 }
1194
1195 while (1) {
1196 CK_KEY_TYPE ck_key_type;
1197
1198 rv = f->C_FindObjects(session, &obj, 1, &n);
1199 if (rv != CKR_OK) {
1200 error("C_FindObjects failed: %lu", rv);
1201 goto fail;
1202 }
1203 if (n == 0)
1204 break;
1205
1206 memset(&ck_key_type, 0, sizeof(ck_key_type));
1207 memset(&key_attr, 0, sizeof(key_attr));
1208 key_attr[0].type = CKA_KEY_TYPE;
1209 key_attr[0].pValue = &ck_key_type;
1210 key_attr[0].ulValueLen = sizeof(ck_key_type);
1211
1212 rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1213 if (rv != CKR_OK) {
526 error("C_GetAttributeValue failed: %lu", rv); 1214 error("C_GetAttributeValue failed: %lu", rv);
527 } else if (attribs[1].type == CKA_MODULUS ) { 1215 goto fail;
528 if ((rsa = RSA_new()) == NULL) {
529 error("RSA_new failed");
530 } else {
531 BIGNUM *rsa_n, *rsa_e;
532
533 rsa_n = BN_bin2bn(attribs[1].pValue,
534 attribs[1].ulValueLen, NULL);
535 rsa_e = BN_bin2bn(attribs[2].pValue,
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);
545 }
546 } else {
547 cp = attribs[2].pValue;
548 if ((x509 = X509_new()) == NULL) {
549 error("X509_new failed");
550 } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen)
551 == NULL) {
552 error("d2i_X509 failed");
553 } else if ((evp = X509_get_pubkey(x509)) == NULL ||
554 EVP_PKEY_base_id(evp) != EVP_PKEY_RSA ||
555 EVP_PKEY_get0_RSA(evp) == NULL) {
556 debug("X509_get_pubkey failed or no rsa");
557 } else if ((rsa = RSAPublicKey_dup(
558 EVP_PKEY_get0_RSA(evp))) == NULL) {
559 error("RSAPublicKey_dup");
560 }
561 X509_free(x509);
562 } 1216 }
563 if (rsa && have_rsa_key(rsa) && 1217
564 pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { 1218 switch (ck_key_type) {
565 if ((key = sshkey_new(KEY_UNSPEC)) == NULL) 1219 case CKK_RSA:
566 fatal("sshkey_new failed"); 1220 key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
567 key->rsa = rsa; 1221 break;
568 key->type = KEY_RSA; 1222#ifdef HAVE_EC_KEY_METHOD_NEW
569 key->flags |= SSHKEY_FLAG_EXT; 1223 case CKK_ECDSA:
570 if (pkcs11_key_included(keysp, nkeys, key)) { 1224 key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
571 sshkey_free(key); 1225 break;
572 } else { 1226#endif /* HAVE_EC_KEY_METHOD_NEW */
573 /* expand key array and add key */ 1227 default:
574 *keysp = xrecallocarray(*keysp, *nkeys, 1228 /* XXX print key type? */
575 *nkeys + 1, sizeof(struct sshkey *)); 1229 key = NULL;
576 (*keysp)[*nkeys] = key; 1230 error("skipping unsupported key type");
577 *nkeys = *nkeys + 1; 1231 }
578 debug("have %d keys", *nkeys); 1232
579 } 1233 if (key == NULL) {
580 } else if (rsa) { 1234 error("failed to fetch key");
581 RSA_free(rsa); 1235 continue;
1236 }
1237
1238 if (pkcs11_key_included(keysp, nkeys, key)) {
1239 sshkey_free(key);
1240 } else {
1241 /* expand key array and add key */
1242 *keysp = xrecallocarray(*keysp, *nkeys,
1243 *nkeys + 1, sizeof(struct sshkey *));
1244 (*keysp)[*nkeys] = key;
1245 *nkeys = *nkeys + 1;
1246 debug("have %d keys", *nkeys);
582 } 1247 }
583 for (i = 0; i < 3; i++)
584 free(attribs[i].pValue);
585 } 1248 }
586 if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) 1249
1250 ret = 0;
1251fail:
1252 rv = f->C_FindObjectsFinal(session);
1253 if (rv != CKR_OK) {
587 error("C_FindObjectsFinal failed: %lu", rv); 1254 error("C_FindObjectsFinal failed: %lu", rv);
588 return (0); 1255 ret = -1;
1256 }
1257
1258 return (ret);
589} 1259}
590 1260
591/* register a new provider, fails if provider already exists */ 1261#ifdef WITH_PKCS11_KEYGEN
592int 1262#define FILL_ATTR(attr, idx, typ, val, len) \
593pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) 1263 { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
1264
1265static struct sshkey *
1266pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1267 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1268{
1269 struct pkcs11_slotinfo *si;
1270 char *plabel = label ? label : "";
1271 int npub = 0, npriv = 0;
1272 CK_RV rv;
1273 CK_FUNCTION_LIST *f;
1274 CK_SESSION_HANDLE session;
1275 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
1276 CK_OBJECT_HANDLE pubKey, privKey;
1277 CK_ATTRIBUTE tpub[16], tpriv[16];
1278 CK_MECHANISM mech = {
1279 CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
1280 };
1281 CK_BYTE pubExponent[] = {
1282 0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1283 };
1284 pubkey_filter[0].pValue = &pubkey_class;
1285 cert_filter[0].pValue = &cert_class;
1286
1287 *err = 0;
1288
1289 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1290 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1291 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1292 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1293 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1294 sizeof(false_val));
1295 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1296 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1297 FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
1298 FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
1299 sizeof(pubExponent));
1300 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1301
1302 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
1303 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
1304 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
1305 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
1306 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
1307 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
1308 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
1309 sizeof(false_val));
1310 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
1311 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
1312 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1313
1314 f = p->function_list;
1315 si = &p->slotinfo[slotidx];
1316 session = si->session;
1317
1318 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1319 &pubKey, &privKey)) != CKR_OK) {
1320 error("%s: key generation failed: error 0x%lx", __func__, rv);
1321 *err = rv;
1322 return NULL;
1323 }
1324
1325 return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
1326}
1327
1328static int
1329pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
1330{
1331 size_t i, len;
1332 char ptr[3];
1333
1334 if (dest)
1335 *dest = NULL;
1336 if (rlen)
1337 *rlen = 0;
1338
1339 if ((len = strlen(hex)) % 2)
1340 return -1;
1341 len /= 2;
1342
1343 *dest = xmalloc(len);
1344
1345 ptr[2] = '\0';
1346 for (i = 0; i < len; i++) {
1347 ptr[0] = hex[2 * i];
1348 ptr[1] = hex[(2 * i) + 1];
1349 if (!isxdigit(ptr[0]) || !isxdigit(ptr[1]))
1350 return -1;
1351 (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16);
1352 }
1353
1354 if (rlen)
1355 *rlen = len;
1356
1357 return 0;
1358}
1359
1360static struct ec_curve_info {
1361 const char *name;
1362 const char *oid;
1363 const char *oid_encoded;
1364 size_t size;
1365} ec_curve_infos[] = {
1366 {"prime256v1", "1.2.840.10045.3.1.7", "06082A8648CE3D030107", 256},
1367 {"secp384r1", "1.3.132.0.34", "06052B81040022", 384},
1368 {"secp521r1", "1.3.132.0.35", "06052B81040023", 521},
1369 {NULL, NULL, NULL, 0},
1370};
1371
1372static struct sshkey *
1373pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1374 char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1375{
1376 struct pkcs11_slotinfo *si;
1377 char *plabel = label ? label : "";
1378 int i;
1379 size_t ecparams_size;
1380 unsigned char *ecparams = NULL;
1381 int npub = 0, npriv = 0;
1382 CK_RV rv;
1383 CK_FUNCTION_LIST *f;
1384 CK_SESSION_HANDLE session;
1385 CK_BBOOL true_val = CK_TRUE, false_val = CK_FALSE;
1386 CK_OBJECT_HANDLE pubKey, privKey;
1387 CK_MECHANISM mech = {
1388 CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
1389 };
1390 CK_ATTRIBUTE tpub[16], tpriv[16];
1391
1392 *err = 0;
1393
1394 for (i = 0; ec_curve_infos[i].name; i++) {
1395 if (ec_curve_infos[i].size == bits)
1396 break;
1397 }
1398 if (!ec_curve_infos[i].name) {
1399 error("%s: invalid key size %lu", __func__, bits);
1400 return NULL;
1401 }
1402 if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
1403 &ecparams_size) == -1) {
1404 error("%s: invalid oid", __func__);
1405 return NULL;
1406 }
1407
1408 FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1409 FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1410 FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1411 FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1412 FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1413 sizeof(false_val));
1414 FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1415 FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1416 FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
1417 FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1418
1419 FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
1420 FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
1421 FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
1422 FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
1423 FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
1424 FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
1425 FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
1426 sizeof(false_val));
1427 FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
1428 FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
1429 FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1430
1431 f = p->function_list;
1432 si = &p->slotinfo[slotidx];
1433 session = si->session;
1434
1435 if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1436 &pubKey, &privKey)) != CKR_OK) {
1437 error("%s: key generation failed: error 0x%lx", __func__, rv);
1438 *err = rv;
1439 return NULL;
1440 }
1441
1442 return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
1443}
1444#endif /* WITH_PKCS11_KEYGEN */
1445
1446/*
1447 * register a new provider, fails if provider already exists. if
1448 * keyp is provided, fetch keys.
1449 */
1450static int
1451pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1452 struct pkcs11_provider **providerp, CK_ULONG user)
594{ 1453{
595 int nkeys, need_finalize = 0; 1454 int nkeys, need_finalize = 0;
1455 int ret = -1;
596 struct pkcs11_provider *p = NULL; 1456 struct pkcs11_provider *p = NULL;
597 void *handle = NULL; 1457 void *handle = NULL;
598 CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); 1458 CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
@@ -601,13 +1461,19 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
601 CK_TOKEN_INFO *token; 1461 CK_TOKEN_INFO *token;
602 CK_ULONG i; 1462 CK_ULONG i;
603 1463
604 *keyp = NULL; 1464 if (providerp == NULL)
1465 goto fail;
1466 *providerp = NULL;
1467
1468 if (keyp != NULL)
1469 *keyp = NULL;
1470
605 if (pkcs11_provider_lookup(provider_id) != NULL) { 1471 if (pkcs11_provider_lookup(provider_id) != NULL) {
606 debug("%s: provider already registered: %s", 1472 debug("%s: provider already registered: %s",
607 __func__, provider_id); 1473 __func__, provider_id);
608 goto fail; 1474 goto fail;
609 } 1475 }
610 /* open shared pkcs11-libarary */ 1476 /* open shared pkcs11-library */
611 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { 1477 if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
612 error("dlopen %s failed: %s", provider_id, dlerror()); 1478 error("dlopen %s failed: %s", provider_id, dlerror());
613 goto fail; 1479 goto fail;
@@ -653,8 +1519,9 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
653 goto fail; 1519 goto fail;
654 } 1520 }
655 if (p->nslots == 0) { 1521 if (p->nslots == 0) {
656 debug("%s: provider %s returned no slots", __func__, 1522 error("%s: provider %s returned no slots", __func__,
657 provider_id); 1523 provider_id);
1524 ret = -SSH_PKCS11_ERR_NO_SLOTS;
658 goto fail; 1525 goto fail;
659 } 1526 }
660 p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); 1527 p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
@@ -690,43 +1557,251 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
690 provider_id, (unsigned long)i, 1557 provider_id, (unsigned long)i,
691 token->label, token->manufacturerID, token->model, 1558 token->label, token->manufacturerID, token->model,
692 token->serialNumber, token->flags); 1559 token->serialNumber, token->flags);
693 /* open session, login with pin and retrieve public keys */ 1560 /*
694 if (pkcs11_open_session(p, i, pin) == 0) 1561 * open session, login with pin and retrieve public
1562 * keys (if keyp is provided)
1563 */
1564 if ((ret = pkcs11_open_session(p, i, pin, user)) == 0) {
1565 if (keyp == NULL)
1566 continue;
695 pkcs11_fetch_keys(p, i, keyp, &nkeys); 1567 pkcs11_fetch_keys(p, i, keyp, &nkeys);
1568 pkcs11_fetch_certs(p, i, keyp, &nkeys);
1569 }
696 } 1570 }
697 if (nkeys > 0) { 1571
698 TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); 1572 /* now owned by caller */
699 p->refcount++; /* add to provider list */ 1573 *providerp = p;
700 return (nkeys); 1574
701 } 1575 TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
702 debug("%s: provider %s returned no keys", __func__, provider_id); 1576 p->refcount++; /* add to provider list */
703 /* don't add the provider, since it does not have any keys */ 1577
1578 return (nkeys);
704fail: 1579fail:
705 if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) 1580 if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
706 error("C_Finalize for provider %s failed: %lu", 1581 error("C_Finalize for provider %s failed: %lu",
707 provider_id, rv); 1582 provider_id, rv);
708 if (p) { 1583 if (p) {
1584 free(p->name);
709 free(p->slotlist); 1585 free(p->slotlist);
710 free(p->slotinfo); 1586 free(p->slotinfo);
711 free(p); 1587 free(p);
712 } 1588 }
713 if (handle) 1589 if (handle)
714 dlclose(handle); 1590 dlclose(handle);
715 return (-1); 1591 return (ret);
1592}
1593
1594/*
1595 * register a new provider and get number of keys hold by the token,
1596 * fails if provider already exists
1597 */
1598int
1599pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
1600{
1601 struct pkcs11_provider *p = NULL;
1602 int nkeys;
1603
1604 nkeys = pkcs11_register_provider(provider_id, pin, keyp, &p, CKU_USER);
1605
1606 /* no keys found or some other error, de-register provider */
1607 if (nkeys <= 0 && p != NULL) {
1608 TAILQ_REMOVE(&pkcs11_providers, p, next);
1609 pkcs11_provider_finalize(p);
1610 pkcs11_provider_unref(p);
1611 }
1612 if (nkeys == 0)
1613 debug("%s: provider %s returned no keys", __func__,
1614 provider_id);
1615
1616 return (nkeys);
716} 1617}
717 1618
718#else 1619#ifdef WITH_PKCS11_KEYGEN
1620struct sshkey *
1621pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
1622 unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err)
1623{
1624 struct pkcs11_provider *p = NULL;
1625 struct pkcs11_slotinfo *si;
1626 CK_FUNCTION_LIST *f;
1627 CK_SESSION_HANDLE session;
1628 struct sshkey *k = NULL;
1629 int ret = -1, reset_pin = 0, reset_provider = 0;
1630 CK_RV rv;
1631
1632 *err = 0;
719 1633
1634 if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
1635 debug("%s: provider \"%s\" available", __func__, provider_id);
1636 else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, &p,
1637 CKU_SO)) < 0) {
1638 debug("%s: could not register provider %s", __func__,
1639 provider_id);
1640 goto out;
1641 } else
1642 reset_provider = 1;
1643
1644 f = p->function_list;
1645 si = &p->slotinfo[slotidx];
1646 session = si->session;
1647
1648 if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1649 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1650 debug("%s: could not supply SO pin: %lu", __func__, rv);
1651 reset_pin = 0;
1652 } else
1653 reset_pin = 1;
1654
1655 switch (type) {
1656 case KEY_RSA:
1657 if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
1658 bits, keyid, err)) == NULL) {
1659 debug("%s: failed to generate RSA key", __func__);
1660 goto out;
1661 }
1662 break;
1663 case KEY_ECDSA:
1664 if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
1665 bits, keyid, err)) == NULL) {
1666 debug("%s: failed to generate ECDSA key", __func__);
1667 goto out;
1668 }
1669 break;
1670 default:
1671 *err = SSH_PKCS11_ERR_GENERIC;
1672 debug("%s: unknown type %d", __func__, type);
1673 goto out;
1674 }
1675
1676out:
1677 if (reset_pin)
1678 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1679 CK_INVALID_HANDLE);
1680
1681 if (reset_provider)
1682 pkcs11_del_provider(provider_id);
1683
1684 return (k);
1685}
1686
1687struct sshkey *
1688pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1689 unsigned char keyid, u_int32_t *err)
1690{
1691 struct pkcs11_provider *p = NULL;
1692 struct pkcs11_slotinfo *si;
1693 struct sshkey *k = NULL;
1694 int reset_pin = 0, reset_provider = 0;
1695 CK_ULONG nattrs;
1696 CK_FUNCTION_LIST *f;
1697 CK_SESSION_HANDLE session;
1698 CK_ATTRIBUTE attrs[16];
1699 CK_OBJECT_CLASS key_class;
1700 CK_KEY_TYPE key_type;
1701 CK_OBJECT_HANDLE obj = CK_INVALID_HANDLE;
1702 CK_RV rv;
1703
1704 *err = 0;
1705
1706 if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
1707 debug("%s: using provider \"%s\"", __func__, provider_id);
1708 } else if (pkcs11_register_provider(provider_id, pin, NULL, &p,
1709 CKU_SO) < 0) {
1710 debug("%s: could not register provider %s", __func__,
1711 provider_id);
1712 goto out;
1713 } else
1714 reset_provider = 1;
1715
1716 f = p->function_list;
1717 si = &p->slotinfo[slotidx];
1718 session = si->session;
1719
1720 if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1721 CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1722 debug("%s: could not supply SO pin: %lu", __func__, rv);
1723 reset_pin = 0;
1724 } else
1725 reset_pin = 1;
1726
1727 /* private key */
1728 nattrs = 0;
1729 key_class = CKO_PRIVATE_KEY;
1730 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1731 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1732
1733 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1734 obj != CK_INVALID_HANDLE) {
1735 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1736 debug("%s: could not destroy private key 0x%hhx",
1737 __func__, keyid);
1738 *err = rv;
1739 goto out;
1740 }
1741 }
1742
1743 /* public key */
1744 nattrs = 0;
1745 key_class = CKO_PUBLIC_KEY;
1746 FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1747 FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1748
1749 if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1750 obj != CK_INVALID_HANDLE) {
1751
1752 /* get key type */
1753 nattrs = 0;
1754 FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
1755 sizeof(key_type));
1756 rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
1757 if (rv != CKR_OK) {
1758 debug("%s: could not get key type of public key 0x%hhx",
1759 __func__, keyid);
1760 *err = rv;
1761 key_type = -1;
1762 }
1763 if (key_type == CKK_RSA)
1764 k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1765 else if (key_type == CKK_ECDSA)
1766 k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1767
1768 if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1769 debug("%s: could not destroy public key 0x%hhx",
1770 __func__, keyid);
1771 *err = rv;
1772 goto out;
1773 }
1774 }
1775
1776out:
1777 if (reset_pin)
1778 f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1779 CK_INVALID_HANDLE);
1780
1781 if (reset_provider)
1782 pkcs11_del_provider(provider_id);
1783
1784 return (k);
1785}
1786#endif /* WITH_PKCS11_KEYGEN */
1787#else /* ENABLE_PKCS11 */
720int 1788int
721pkcs11_init(int interactive) 1789pkcs11_init(int interactive)
722{ 1790{
723 return (0); 1791 error("%s: dlopen() not supported", __func__);
1792 return (-1);
1793}
1794
1795int
1796pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
1797{
1798 error("%s: dlopen() not supported", __func__);
1799 return (-1);
724} 1800}
725 1801
726void 1802void
727pkcs11_terminate(void) 1803pkcs11_terminate(void)
728{ 1804{
729 return; 1805 error("%s: dlopen() not supported", __func__);
730} 1806}
731
732#endif /* ENABLE_PKCS11 */ 1807#endif /* ENABLE_PKCS11 */