Coverage Report

Created: 2025-07-01 07:01

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