Coverage Report

Created: 2024-06-18 06:24

/src/hpn-ssh/ssh-pkcs11.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: ssh-pkcs11.c,v 1.59 2023/07/27 22:26:49 djm 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
  RSA_set_method(rsa, rsa_method);
506
0
  RSA_set_ex_data(rsa, rsa_idx, k11);
507
0
  return (0);
508
0
}
509
510
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
511
/* openssl callback doing the actual signing operation */
512
static ECDSA_SIG *
513
ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
514
    const BIGNUM *rp, EC_KEY *ec)
515
0
{
516
0
  struct pkcs11_key *k11;
517
0
  struct pkcs11_slotinfo  *si;
518
0
  CK_FUNCTION_LIST  *f;
519
0
  CK_ULONG    siglen = 0, bnlen;
520
0
  CK_RV     rv;
521
0
  ECDSA_SIG   *ret = NULL;
522
0
  u_char      *sig;
523
0
  BIGNUM      *r = NULL, *s = NULL;
524
525
0
  if ((k11 = EC_KEY_get_ex_data(ec, ec_key_idx)) == NULL) {
526
0
    ossl_error("EC_KEY_get_ex_data failed for ec");
527
0
    return (NULL);
528
0
  }
529
530
0
  if (pkcs11_get_key(k11, CKM_ECDSA) == -1) {
531
0
    error("pkcs11_get_key failed");
532
0
    return (NULL);
533
0
  }
534
535
0
  f = k11->provider->function_list;
536
0
  si = &k11->provider->slotinfo[k11->slotidx];
537
538
0
  siglen = ECDSA_size(ec);
539
0
  sig = xmalloc(siglen);
540
541
  /* XXX handle CKR_BUFFER_TOO_SMALL */
542
0
  rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, sig, &siglen);
543
0
  if (rv != CKR_OK) {
544
0
    error("C_Sign failed: %lu", rv);
545
0
    goto done;
546
0
  }
547
0
  if (siglen < 64 || siglen > 132 || siglen % 2) {
548
0
    error_f("bad signature length: %lu", (u_long)siglen);
549
0
    goto done;
550
0
  }
551
0
  bnlen = siglen/2;
552
0
  if ((ret = ECDSA_SIG_new()) == NULL) {
553
0
    error("ECDSA_SIG_new failed");
554
0
    goto done;
555
0
  }
556
0
  if ((r = BN_bin2bn(sig, bnlen, NULL)) == NULL ||
557
0
      (s = BN_bin2bn(sig+bnlen, bnlen, NULL)) == NULL) {
558
0
    ossl_error("BN_bin2bn failed");
559
0
    ECDSA_SIG_free(ret);
560
0
    ret = NULL;
561
0
    goto done;
562
0
  }
563
0
  if (!ECDSA_SIG_set0(ret, r, s)) {
564
0
    error_f("ECDSA_SIG_set0 failed");
565
0
    ECDSA_SIG_free(ret);
566
0
    ret = NULL;
567
0
    goto done;
568
0
  }
569
0
  r = s = NULL; /* now owned by ret */
570
  /* success */
571
0
 done:
572
0
  BN_free(r);
573
0
  BN_free(s);
574
0
  free(sig);
575
576
0
  return (ret);
577
0
}
578
579
static int
580
pkcs11_ecdsa_start_wrapper(void)
581
0
{
582
0
  int (*orig_sign)(int, const unsigned char *, int, unsigned char *,
583
0
      unsigned int *, const BIGNUM *, const BIGNUM *, EC_KEY *) = NULL;
584
585
0
  if (ec_key_method != NULL)
586
0
    return (0);
587
0
  ec_key_idx = EC_KEY_get_ex_new_index(0, "ssh-pkcs11-ecdsa",
588
0
      NULL, NULL, pkcs11_k11_free);
589
0
  if (ec_key_idx == -1)
590
0
    return (-1);
591
0
  ec_key_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
592
0
  if (ec_key_method == NULL)
593
0
    return (-1);
594
0
  EC_KEY_METHOD_get_sign(ec_key_method, &orig_sign, NULL, NULL);
595
0
  EC_KEY_METHOD_set_sign(ec_key_method, orig_sign, NULL, ecdsa_do_sign);
596
0
  return (0);
597
0
}
598
599
static int
600
pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx,
601
    CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec)
602
0
{
603
0
  struct pkcs11_key *k11;
604
605
0
  if (pkcs11_ecdsa_start_wrapper() == -1)
606
0
    return (-1);
607
608
0
  k11 = xcalloc(1, sizeof(*k11));
609
0
  k11->provider = provider;
610
0
  provider->refcount++; /* provider referenced by ECDSA key */
611
0
  k11->slotidx = slotidx;
612
  /* identify key object on smartcard */
613
0
  k11->keyid_len = keyid_attrib->ulValueLen;
614
0
  if (k11->keyid_len > 0) {
615
0
    k11->keyid = xmalloc(k11->keyid_len);
616
0
    memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len);
617
0
  }
618
0
  EC_KEY_set_method(ec, ec_key_method);
619
0
  EC_KEY_set_ex_data(ec, ec_key_idx, k11);
620
621
0
  return (0);
622
0
}
623
#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
624
625
/* remove trailing spaces */
626
static char *
627
rmspace(u_char *buf, size_t len)
628
0
{
629
0
  size_t i;
630
631
0
  if (len == 0)
632
0
    return buf;
633
0
  for (i = len - 1; i > 0; i--)
634
0
    if (buf[i] == ' ')
635
0
      buf[i] = '\0';
636
0
    else
637
0
      break;
638
0
  return buf;
639
0
}
640
/* Used to printf fixed-width, space-padded, unterminated strings using %.*s */
641
#define RMSPACE(s) (int)sizeof(s), rmspace(s, sizeof(s))
642
643
/*
644
 * open a pkcs11 session and login if required.
645
 * if pin == NULL we delay login until key use
646
 */
647
static int
648
pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin,
649
    CK_ULONG user)
650
0
{
651
0
  struct pkcs11_slotinfo  *si;
652
0
  CK_FUNCTION_LIST  *f;
653
0
  CK_RV     rv;
654
0
  CK_SESSION_HANDLE session;
655
0
  int     login_required, ret;
656
657
0
  f = p->function_list;
658
0
  si = &p->slotinfo[slotidx];
659
660
0
  login_required = si->token.flags & CKF_LOGIN_REQUIRED;
661
662
  /* fail early before opening session */
663
0
  if (login_required && !pkcs11_interactive &&
664
0
      (pin == NULL || strlen(pin) == 0)) {
665
0
    error("pin required");
666
0
    return (-SSH_PKCS11_ERR_PIN_REQUIRED);
667
0
  }
668
0
  if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION|
669
0
      CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) {
670
0
    error("C_OpenSession failed: %lu", rv);
671
0
    return (-1);
672
0
  }
673
0
  if (login_required && pin != NULL && strlen(pin) != 0) {
674
0
    rv = f->C_Login(session, user, (u_char *)pin, strlen(pin));
675
0
    if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) {
676
0
      error("C_Login failed: %lu", rv);
677
0
      ret = (rv == CKR_PIN_LOCKED) ?
678
0
          -SSH_PKCS11_ERR_PIN_LOCKED :
679
0
          -SSH_PKCS11_ERR_LOGIN_FAIL;
680
0
      if ((rv = f->C_CloseSession(session)) != CKR_OK)
681
0
        error("C_CloseSession failed: %lu", rv);
682
0
      return (ret);
683
0
    }
684
0
    si->logged_in = 1;
685
0
  }
686
0
  si->session = session;
687
0
  return (0);
688
0
}
689
690
static int
691
pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
692
0
{
693
0
  int i;
694
695
0
  for (i = 0; i < *nkeys; i++)
696
0
    if (sshkey_equal(key, (*keysp)[i]))
697
0
      return (1);
698
0
  return (0);
699
0
}
700
701
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
702
static struct sshkey *
703
pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
704
    CK_OBJECT_HANDLE *obj)
705
0
{
706
0
  CK_ATTRIBUTE     key_attr[3];
707
0
  CK_SESSION_HANDLE  session;
708
0
  CK_FUNCTION_LIST  *f = NULL;
709
0
  CK_RV      rv;
710
0
  ASN1_OCTET_STRING *octet = NULL;
711
0
  EC_KEY      *ec = NULL;
712
0
  EC_GROUP    *group = NULL;
713
0
  struct sshkey   *key = NULL;
714
0
  const unsigned char *attrp = NULL;
715
0
  int      i;
716
0
  int      nid;
717
718
0
  memset(&key_attr, 0, sizeof(key_attr));
719
0
  key_attr[0].type = CKA_ID;
720
0
  key_attr[1].type = CKA_EC_POINT;
721
0
  key_attr[2].type = CKA_EC_PARAMS;
722
723
0
  session = p->slotinfo[slotidx].session;
724
0
  f = p->function_list;
725
726
  /* figure out size of the attributes */
727
0
  rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
728
0
  if (rv != CKR_OK) {
729
0
    error("C_GetAttributeValue failed: %lu", rv);
730
0
    return (NULL);
731
0
  }
732
733
  /*
734
   * Allow CKA_ID (always first attribute) to be empty, but
735
   * ensure that none of the others are zero length.
736
   * XXX assumes CKA_ID is always first.
737
   */
738
0
  if (key_attr[1].ulValueLen == 0 ||
739
0
      key_attr[2].ulValueLen == 0) {
740
0
    error("invalid attribute length");
741
0
    return (NULL);
742
0
  }
743
744
  /* allocate buffers for attributes */
745
0
  for (i = 0; i < 3; i++)
746
0
    if (key_attr[i].ulValueLen > 0)
747
0
      key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
748
749
  /* retrieve ID, public point and curve parameters of EC key */
750
0
  rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
751
0
  if (rv != CKR_OK) {
752
0
    error("C_GetAttributeValue failed: %lu", rv);
753
0
    goto fail;
754
0
  }
755
756
0
  ec = EC_KEY_new();
757
0
  if (ec == NULL) {
758
0
    error("EC_KEY_new failed");
759
0
    goto fail;
760
0
  }
761
762
0
  attrp = key_attr[2].pValue;
763
0
  group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen);
764
0
  if (group == NULL) {
765
0
    ossl_error("d2i_ECPKParameters failed");
766
0
    goto fail;
767
0
  }
768
769
0
  if (EC_KEY_set_group(ec, group) == 0) {
770
0
    ossl_error("EC_KEY_set_group failed");
771
0
    goto fail;
772
0
  }
773
774
0
  if (key_attr[1].ulValueLen <= 2) {
775
0
    error("CKA_EC_POINT too small");
776
0
    goto fail;
777
0
  }
778
779
0
  attrp = key_attr[1].pValue;
780
0
  octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen);
781
0
  if (octet == NULL) {
782
0
    ossl_error("d2i_ASN1_OCTET_STRING failed");
783
0
    goto fail;
784
0
  }
785
0
  attrp = octet->data;
786
0
  if (o2i_ECPublicKey(&ec, &attrp, octet->length) == NULL) {
787
0
    ossl_error("o2i_ECPublicKey failed");
788
0
    goto fail;
789
0
  }
790
791
0
  nid = sshkey_ecdsa_key_to_nid(ec);
792
0
  if (nid < 0) {
793
0
    error("couldn't get curve nid");
794
0
    goto fail;
795
0
  }
796
797
0
  if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec))
798
0
    goto fail;
799
800
0
  key = sshkey_new(KEY_UNSPEC);
801
0
  if (key == NULL) {
802
0
    error("sshkey_new failed");
803
0
    goto fail;
804
0
  }
805
806
0
  key->ecdsa = ec;
807
0
  key->ecdsa_nid = nid;
808
0
  key->type = KEY_ECDSA;
809
0
  key->flags |= SSHKEY_FLAG_EXT;
810
0
  ec = NULL;  /* now owned by key */
811
812
0
fail:
813
0
  for (i = 0; i < 3; i++)
814
0
    free(key_attr[i].pValue);
815
0
  if (ec)
816
0
    EC_KEY_free(ec);
817
0
  if (group)
818
0
    EC_GROUP_free(group);
819
0
  if (octet)
820
0
    ASN1_OCTET_STRING_free(octet);
821
822
0
  return (key);
823
0
}
824
#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
825
826
static struct sshkey *
827
pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
828
    CK_OBJECT_HANDLE *obj)
829
0
{
830
0
  CK_ATTRIBUTE     key_attr[3];
831
0
  CK_SESSION_HANDLE  session;
832
0
  CK_FUNCTION_LIST  *f = NULL;
833
0
  CK_RV      rv;
834
0
  RSA     *rsa = NULL;
835
0
  BIGNUM      *rsa_n, *rsa_e;
836
0
  struct sshkey   *key = NULL;
837
0
  int      i;
838
839
0
  memset(&key_attr, 0, sizeof(key_attr));
840
0
  key_attr[0].type = CKA_ID;
841
0
  key_attr[1].type = CKA_MODULUS;
842
0
  key_attr[2].type = CKA_PUBLIC_EXPONENT;
843
844
0
  session = p->slotinfo[slotidx].session;
845
0
  f = p->function_list;
846
847
  /* figure out size of the attributes */
848
0
  rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
849
0
  if (rv != CKR_OK) {
850
0
    error("C_GetAttributeValue failed: %lu", rv);
851
0
    return (NULL);
852
0
  }
853
854
  /*
855
   * Allow CKA_ID (always first attribute) to be empty, but
856
   * ensure that none of the others are zero length.
857
   * XXX assumes CKA_ID is always first.
858
   */
859
0
  if (key_attr[1].ulValueLen == 0 ||
860
0
      key_attr[2].ulValueLen == 0) {
861
0
    error("invalid attribute length");
862
0
    return (NULL);
863
0
  }
864
865
  /* allocate buffers for attributes */
866
0
  for (i = 0; i < 3; i++)
867
0
    if (key_attr[i].ulValueLen > 0)
868
0
      key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen);
869
870
  /* retrieve ID, modulus and public exponent of RSA key */
871
0
  rv = f->C_GetAttributeValue(session, *obj, key_attr, 3);
872
0
  if (rv != CKR_OK) {
873
0
    error("C_GetAttributeValue failed: %lu", rv);
874
0
    goto fail;
875
0
  }
876
877
0
  rsa = RSA_new();
878
0
  if (rsa == NULL) {
879
0
    error("RSA_new failed");
880
0
    goto fail;
881
0
  }
882
883
0
  rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL);
884
0
  rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL);
885
0
  if (rsa_n == NULL || rsa_e == NULL) {
886
0
    error("BN_bin2bn failed");
887
0
    goto fail;
888
0
  }
889
0
  if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
890
0
    fatal_f("set key");
891
0
  rsa_n = rsa_e = NULL; /* transferred */
892
893
0
  if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
894
0
    goto fail;
895
896
0
  key = sshkey_new(KEY_UNSPEC);
897
0
  if (key == NULL) {
898
0
    error("sshkey_new failed");
899
0
    goto fail;
900
0
  }
901
902
0
  key->rsa = rsa;
903
0
  key->type = KEY_RSA;
904
0
  key->flags |= SSHKEY_FLAG_EXT;
905
0
  rsa = NULL; /* now owned by key */
906
907
0
fail:
908
0
  for (i = 0; i < 3; i++)
909
0
    free(key_attr[i].pValue);
910
0
  RSA_free(rsa);
911
912
0
  return (key);
913
0
}
914
915
static int
916
pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
917
    CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp)
918
0
{
919
0
  CK_ATTRIBUTE     cert_attr[3];
920
0
  CK_SESSION_HANDLE  session;
921
0
  CK_FUNCTION_LIST  *f = NULL;
922
0
  CK_RV      rv;
923
0
  X509      *x509 = NULL;
924
0
  X509_NAME   *x509_name = NULL;
925
0
  EVP_PKEY    *evp;
926
0
  RSA     *rsa = NULL;
927
0
#ifdef OPENSSL_HAS_ECC
928
0
  EC_KEY      *ec = NULL;
929
0
#endif
930
0
  struct sshkey   *key = NULL;
931
0
  int      i;
932
0
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
933
0
  int      nid;
934
0
#endif
935
0
  const u_char    *cp;
936
0
  char      *subject = NULL;
937
938
0
  *keyp = NULL;
939
0
  *labelp = NULL;
940
941
0
  memset(&cert_attr, 0, sizeof(cert_attr));
942
0
  cert_attr[0].type = CKA_ID;
943
0
  cert_attr[1].type = CKA_SUBJECT;
944
0
  cert_attr[2].type = CKA_VALUE;
945
946
0
  session = p->slotinfo[slotidx].session;
947
0
  f = p->function_list;
948
949
  /* figure out size of the attributes */
950
0
  rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
951
0
  if (rv != CKR_OK) {
952
0
    error("C_GetAttributeValue failed: %lu", rv);
953
0
    return -1;
954
0
  }
955
956
  /*
957
   * Allow CKA_ID (always first attribute) to be empty, but
958
   * ensure that none of the others are zero length.
959
   * XXX assumes CKA_ID is always first.
960
   */
961
0
  if (cert_attr[1].ulValueLen == 0 ||
962
0
      cert_attr[2].ulValueLen == 0) {
963
0
    error("invalid attribute length");
964
0
    return -1;
965
0
  }
966
967
  /* allocate buffers for attributes */
968
0
  for (i = 0; i < 3; i++)
969
0
    if (cert_attr[i].ulValueLen > 0)
970
0
      cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen);
971
972
  /* retrieve ID, subject and value of certificate */
973
0
  rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3);
974
0
  if (rv != CKR_OK) {
975
0
    error("C_GetAttributeValue failed: %lu", rv);
976
0
    goto out;
977
0
  }
978
979
  /* Decode DER-encoded cert subject */
980
0
  cp = cert_attr[1].pValue;
981
0
  if ((x509_name = d2i_X509_NAME(NULL, &cp,
982
0
      cert_attr[1].ulValueLen)) == NULL ||
983
0
      (subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
984
0
    subject = xstrdup("invalid subject");
985
0
  X509_NAME_free(x509_name);
986
987
0
  cp = cert_attr[2].pValue;
988
0
  if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) {
989
0
    error("d2i_x509 failed");
990
0
    goto out;
991
0
  }
992
993
0
  if ((evp = X509_get_pubkey(x509)) == NULL) {
994
0
    error("X509_get_pubkey failed");
995
0
    goto out;
996
0
  }
997
998
0
  if (EVP_PKEY_base_id(evp) == EVP_PKEY_RSA) {
999
0
    if (EVP_PKEY_get0_RSA(evp) == NULL) {
1000
0
      error("invalid x509; no rsa key");
1001
0
      goto out;
1002
0
    }
1003
0
    if ((rsa = RSAPublicKey_dup(EVP_PKEY_get0_RSA(evp))) == NULL) {
1004
0
      error("RSAPublicKey_dup failed");
1005
0
      goto out;
1006
0
    }
1007
1008
0
    if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa))
1009
0
      goto out;
1010
1011
0
    key = sshkey_new(KEY_UNSPEC);
1012
0
    if (key == NULL) {
1013
0
      error("sshkey_new failed");
1014
0
      goto out;
1015
0
    }
1016
1017
0
    key->rsa = rsa;
1018
0
    key->type = KEY_RSA;
1019
0
    key->flags |= SSHKEY_FLAG_EXT;
1020
0
    rsa = NULL; /* now owned by key */
1021
0
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1022
0
  } else if (EVP_PKEY_base_id(evp) == EVP_PKEY_EC) {
1023
0
    if (EVP_PKEY_get0_EC_KEY(evp) == NULL) {
1024
0
      error("invalid x509; no ec key");
1025
0
      goto out;
1026
0
    }
1027
0
    if ((ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(evp))) == NULL) {
1028
0
      error("EC_KEY_dup failed");
1029
0
      goto out;
1030
0
    }
1031
1032
0
    nid = sshkey_ecdsa_key_to_nid(ec);
1033
0
    if (nid < 0) {
1034
0
      error("couldn't get curve nid");
1035
0
      goto out;
1036
0
    }
1037
1038
0
    if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec))
1039
0
      goto out;
1040
1041
0
    key = sshkey_new(KEY_UNSPEC);
1042
0
    if (key == NULL) {
1043
0
      error("sshkey_new failed");
1044
0
      goto out;
1045
0
    }
1046
1047
0
    key->ecdsa = ec;
1048
0
    key->ecdsa_nid = nid;
1049
0
    key->type = KEY_ECDSA;
1050
0
    key->flags |= SSHKEY_FLAG_EXT;
1051
0
    ec = NULL;  /* now owned by key */
1052
0
#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1053
0
  } else {
1054
0
    error("unknown certificate key type");
1055
0
    goto out;
1056
0
  }
1057
0
 out:
1058
0
  for (i = 0; i < 3; i++)
1059
0
    free(cert_attr[i].pValue);
1060
0
  X509_free(x509);
1061
0
  RSA_free(rsa);
1062
0
#ifdef OPENSSL_HAS_ECC
1063
0
  EC_KEY_free(ec);
1064
0
#endif
1065
0
  if (key == NULL) {
1066
0
    free(subject);
1067
0
    return -1;
1068
0
  }
1069
  /* success */
1070
0
  *keyp = key;
1071
0
  *labelp = subject;
1072
0
  return 0;
1073
0
}
1074
1075
#if 0
1076
static int
1077
have_rsa_key(const RSA *rsa)
1078
{
1079
  const BIGNUM *rsa_n, *rsa_e;
1080
1081
  RSA_get0_key(rsa, &rsa_n, &rsa_e, NULL);
1082
  return rsa_n != NULL && rsa_e != NULL;
1083
}
1084
#endif
1085
1086
static void
1087
note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context,
1088
    struct sshkey *key)
1089
0
{
1090
0
  char *fp;
1091
1092
0
  if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
1093
0
      SSH_FP_DEFAULT)) == NULL) {
1094
0
    error_f("sshkey_fingerprint failed");
1095
0
    return;
1096
0
  }
1097
0
  debug2("%s: provider %s slot %lu: %s %s", context, p->name,
1098
0
      (u_long)slotidx, sshkey_type(key), fp);
1099
0
  free(fp);
1100
0
}
1101
1102
/*
1103
 * lookup certificates for token in slot identified by slotidx,
1104
 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1105
 * keysp points to an (possibly empty) array with *nkeys keys.
1106
 */
1107
static int
1108
pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
1109
    struct sshkey ***keysp, char ***labelsp, int *nkeys)
1110
0
{
1111
0
  struct sshkey   *key = NULL;
1112
0
  CK_OBJECT_CLASS    key_class;
1113
0
  CK_ATTRIBUTE     key_attr[1];
1114
0
  CK_SESSION_HANDLE  session;
1115
0
  CK_FUNCTION_LIST  *f = NULL;
1116
0
  CK_RV      rv;
1117
0
  CK_OBJECT_HANDLE   obj;
1118
0
  CK_ULONG     n = 0;
1119
0
  int      ret = -1;
1120
0
  char      *label;
1121
1122
0
  memset(&key_attr, 0, sizeof(key_attr));
1123
0
  memset(&obj, 0, sizeof(obj));
1124
1125
0
  key_class = CKO_CERTIFICATE;
1126
0
  key_attr[0].type = CKA_CLASS;
1127
0
  key_attr[0].pValue = &key_class;
1128
0
  key_attr[0].ulValueLen = sizeof(key_class);
1129
1130
0
  session = p->slotinfo[slotidx].session;
1131
0
  f = p->function_list;
1132
1133
0
  rv = f->C_FindObjectsInit(session, key_attr, 1);
1134
0
  if (rv != CKR_OK) {
1135
0
    error("C_FindObjectsInit failed: %lu", rv);
1136
0
    goto fail;
1137
0
  }
1138
1139
0
  while (1) {
1140
0
    CK_CERTIFICATE_TYPE ck_cert_type;
1141
1142
0
    rv = f->C_FindObjects(session, &obj, 1, &n);
1143
0
    if (rv != CKR_OK) {
1144
0
      error("C_FindObjects failed: %lu", rv);
1145
0
      goto fail;
1146
0
    }
1147
0
    if (n == 0)
1148
0
      break;
1149
1150
0
    memset(&ck_cert_type, 0, sizeof(ck_cert_type));
1151
0
    memset(&key_attr, 0, sizeof(key_attr));
1152
0
    key_attr[0].type = CKA_CERTIFICATE_TYPE;
1153
0
    key_attr[0].pValue = &ck_cert_type;
1154
0
    key_attr[0].ulValueLen = sizeof(ck_cert_type);
1155
1156
0
    rv = f->C_GetAttributeValue(session, obj, key_attr, 1);
1157
0
    if (rv != CKR_OK) {
1158
0
      error("C_GetAttributeValue failed: %lu", rv);
1159
0
      goto fail;
1160
0
    }
1161
1162
0
    key = NULL;
1163
0
    label = NULL;
1164
0
    switch (ck_cert_type) {
1165
0
    case CKC_X_509:
1166
0
      if (pkcs11_fetch_x509_pubkey(p, slotidx, &obj,
1167
0
          &key, &label) != 0) {
1168
0
        error("failed to fetch key");
1169
0
        continue;
1170
0
      }
1171
0
      break;
1172
0
    default:
1173
0
      error("skipping unsupported certificate type %lu",
1174
0
          ck_cert_type);
1175
0
      continue;
1176
0
    }
1177
0
    note_key(p, slotidx, __func__, key);
1178
0
    if (pkcs11_key_included(keysp, nkeys, key)) {
1179
0
      debug2_f("key already included");;
1180
0
      sshkey_free(key);
1181
0
    } else {
1182
      /* expand key array and add key */
1183
0
      *keysp = xrecallocarray(*keysp, *nkeys,
1184
0
          *nkeys + 1, sizeof(struct sshkey *));
1185
0
      (*keysp)[*nkeys] = key;
1186
0
      if (labelsp != NULL) {
1187
0
        *labelsp = xrecallocarray(*labelsp, *nkeys,
1188
0
            *nkeys + 1, sizeof(char *));
1189
0
        (*labelsp)[*nkeys] = xstrdup((char *)label);
1190
0
      }
1191
0
      *nkeys = *nkeys + 1;
1192
0
      debug("have %d keys", *nkeys);
1193
0
    }
1194
0
  }
1195
1196
0
  ret = 0;
1197
0
fail:
1198
0
  rv = f->C_FindObjectsFinal(session);
1199
0
  if (rv != CKR_OK) {
1200
0
    error("C_FindObjectsFinal failed: %lu", rv);
1201
0
    ret = -1;
1202
0
  }
1203
1204
0
  return (ret);
1205
0
}
1206
1207
/*
1208
 * lookup public keys for token in slot identified by slotidx,
1209
 * add 'wrapped' public keys to the 'keysp' array and increment nkeys.
1210
 * keysp points to an (possibly empty) array with *nkeys keys.
1211
 */
1212
static int
1213
pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
1214
    struct sshkey ***keysp, char ***labelsp, int *nkeys)
1215
0
{
1216
0
  struct sshkey   *key = NULL;
1217
0
  CK_OBJECT_CLASS    key_class;
1218
0
  CK_ATTRIBUTE     key_attr[2];
1219
0
  CK_SESSION_HANDLE  session;
1220
0
  CK_FUNCTION_LIST  *f = NULL;
1221
0
  CK_RV      rv;
1222
0
  CK_OBJECT_HANDLE   obj;
1223
0
  CK_ULONG     n = 0;
1224
0
  int      ret = -1;
1225
1226
0
  memset(&key_attr, 0, sizeof(key_attr));
1227
0
  memset(&obj, 0, sizeof(obj));
1228
1229
0
  key_class = CKO_PUBLIC_KEY;
1230
0
  key_attr[0].type = CKA_CLASS;
1231
0
  key_attr[0].pValue = &key_class;
1232
0
  key_attr[0].ulValueLen = sizeof(key_class);
1233
1234
0
  session = p->slotinfo[slotidx].session;
1235
0
  f = p->function_list;
1236
1237
0
  rv = f->C_FindObjectsInit(session, key_attr, 1);
1238
0
  if (rv != CKR_OK) {
1239
0
    error("C_FindObjectsInit failed: %lu", rv);
1240
0
    goto fail;
1241
0
  }
1242
1243
0
  while (1) {
1244
0
    CK_KEY_TYPE ck_key_type;
1245
0
    CK_UTF8CHAR label[256];
1246
1247
0
    rv = f->C_FindObjects(session, &obj, 1, &n);
1248
0
    if (rv != CKR_OK) {
1249
0
      error("C_FindObjects failed: %lu", rv);
1250
0
      goto fail;
1251
0
    }
1252
0
    if (n == 0)
1253
0
      break;
1254
1255
0
    memset(&ck_key_type, 0, sizeof(ck_key_type));
1256
0
    memset(&key_attr, 0, sizeof(key_attr));
1257
0
    key_attr[0].type = CKA_KEY_TYPE;
1258
0
    key_attr[0].pValue = &ck_key_type;
1259
0
    key_attr[0].ulValueLen = sizeof(ck_key_type);
1260
0
    key_attr[1].type = CKA_LABEL;
1261
0
    key_attr[1].pValue = &label;
1262
0
    key_attr[1].ulValueLen = sizeof(label) - 1;
1263
1264
0
    rv = f->C_GetAttributeValue(session, obj, key_attr, 2);
1265
0
    if (rv != CKR_OK) {
1266
0
      error("C_GetAttributeValue failed: %lu", rv);
1267
0
      goto fail;
1268
0
    }
1269
1270
0
    label[key_attr[1].ulValueLen] = '\0';
1271
1272
0
    switch (ck_key_type) {
1273
0
    case CKK_RSA:
1274
0
      key = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1275
0
      break;
1276
0
#if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW)
1277
0
    case CKK_ECDSA:
1278
0
      key = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1279
0
      break;
1280
0
#endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */
1281
0
    default:
1282
      /* XXX print key type? */
1283
0
      key = NULL;
1284
0
      error("skipping unsupported key type");
1285
0
    }
1286
1287
0
    if (key == NULL) {
1288
0
      error("failed to fetch key");
1289
0
      continue;
1290
0
    }
1291
0
    note_key(p, slotidx, __func__, key);
1292
0
    if (pkcs11_key_included(keysp, nkeys, key)) {
1293
0
      debug2_f("key already included");;
1294
0
      sshkey_free(key);
1295
0
    } else {
1296
      /* expand key array and add key */
1297
0
      *keysp = xrecallocarray(*keysp, *nkeys,
1298
0
          *nkeys + 1, sizeof(struct sshkey *));
1299
0
      (*keysp)[*nkeys] = key;
1300
0
      if (labelsp != NULL) {
1301
0
        *labelsp = xrecallocarray(*labelsp, *nkeys,
1302
0
            *nkeys + 1, sizeof(char *));
1303
0
        (*labelsp)[*nkeys] = xstrdup((char *)label);
1304
0
      }
1305
0
      *nkeys = *nkeys + 1;
1306
0
      debug("have %d keys", *nkeys);
1307
0
    }
1308
0
  }
1309
1310
0
  ret = 0;
1311
0
fail:
1312
0
  rv = f->C_FindObjectsFinal(session);
1313
0
  if (rv != CKR_OK) {
1314
0
    error("C_FindObjectsFinal failed: %lu", rv);
1315
0
    ret = -1;
1316
0
  }
1317
1318
0
  return (ret);
1319
0
}
1320
1321
#ifdef WITH_PKCS11_KEYGEN
1322
#define FILL_ATTR(attr, idx, typ, val, len) \
1323
  { (attr[idx]).type=(typ); (attr[idx]).pValue=(val); (attr[idx]).ulValueLen=len; idx++; }
1324
1325
static struct sshkey *
1326
pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1327
    char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1328
{
1329
  struct pkcs11_slotinfo  *si;
1330
  char      *plabel = label ? label : "";
1331
  int      npub = 0, npriv = 0;
1332
  CK_RV      rv;
1333
  CK_FUNCTION_LIST  *f;
1334
  CK_SESSION_HANDLE  session;
1335
  CK_BBOOL     true_val = CK_TRUE, false_val = CK_FALSE;
1336
  CK_OBJECT_HANDLE   pubKey, privKey;
1337
  CK_ATTRIBUTE     tpub[16], tpriv[16];
1338
  CK_MECHANISM     mech = {
1339
      CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0
1340
  };
1341
  CK_BYTE      pubExponent[] = {
1342
      0x01, 0x00, 0x01 /* RSA_F4 in bytes */
1343
  };
1344
  pubkey_filter[0].pValue = &pubkey_class;
1345
  cert_filter[0].pValue = &cert_class;
1346
1347
  *err = 0;
1348
1349
  FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1350
  FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1351
  FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1352
  FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1353
  FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1354
      sizeof(false_val));
1355
  FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1356
  FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1357
  FILL_ATTR(tpub, npub, CKA_MODULUS_BITS, &bits, sizeof(bits));
1358
  FILL_ATTR(tpub, npub, CKA_PUBLIC_EXPONENT, pubExponent,
1359
      sizeof(pubExponent));
1360
  FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1361
1362
  FILL_ATTR(tpriv, npriv, CKA_TOKEN,  &true_val, sizeof(true_val));
1363
  FILL_ATTR(tpriv, npriv, CKA_LABEL,  plabel, strlen(plabel));
1364
  FILL_ATTR(tpriv, npriv, CKA_PRIVATE,  &true_val, sizeof(true_val));
1365
  FILL_ATTR(tpriv, npriv, CKA_SENSITIVE,  &true_val, sizeof(true_val));
1366
  FILL_ATTR(tpriv, npriv, CKA_DECRYPT,  &false_val, sizeof(false_val));
1367
  FILL_ATTR(tpriv, npriv, CKA_SIGN,  &true_val, sizeof(true_val));
1368
  FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER,  &false_val,
1369
      sizeof(false_val));
1370
  FILL_ATTR(tpriv, npriv, CKA_UNWRAP,  &false_val, sizeof(false_val));
1371
  FILL_ATTR(tpriv, npriv, CKA_DERIVE,  &false_val, sizeof(false_val));
1372
  FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1373
1374
  f = p->function_list;
1375
  si = &p->slotinfo[slotidx];
1376
  session = si->session;
1377
1378
  if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1379
      &pubKey, &privKey)) != CKR_OK) {
1380
    error_f("key generation failed: error 0x%lx", rv);
1381
    *err = rv;
1382
    return NULL;
1383
  }
1384
1385
  return pkcs11_fetch_rsa_pubkey(p, slotidx, &pubKey);
1386
}
1387
1388
static int
1389
pkcs11_decode_hex(const char *hex, unsigned char **dest, size_t *rlen)
1390
{
1391
  size_t  i, len;
1392
  char  ptr[3];
1393
1394
  if (dest)
1395
    *dest = NULL;
1396
  if (rlen)
1397
    *rlen = 0;
1398
1399
  if ((len = strlen(hex)) % 2)
1400
    return -1;
1401
  len /= 2;
1402
1403
  *dest = xmalloc(len);
1404
1405
  ptr[2] = '\0';
1406
  for (i = 0; i < len; i++) {
1407
    ptr[0] = hex[2 * i];
1408
    ptr[1] = hex[(2 * i) + 1];
1409
    if (!isxdigit(ptr[0]) || !isxdigit(ptr[1]))
1410
      return -1;
1411
    (*dest)[i] = (unsigned char)strtoul(ptr, NULL, 16);
1412
  }
1413
1414
  if (rlen)
1415
    *rlen = len;
1416
1417
  return 0;
1418
}
1419
1420
static struct ec_curve_info {
1421
  const char  *name;
1422
  const char  *oid;
1423
  const char  *oid_encoded;
1424
  size_t     size;
1425
} ec_curve_infos[] = {
1426
  {"prime256v1",  "1.2.840.10045.3.1.7",  "06082A8648CE3D030107", 256},
1427
  {"secp384r1", "1.3.132.0.34",   "06052B81040022", 384},
1428
  {"secp521r1", "1.3.132.0.35",   "06052B81040023", 521},
1429
  {NULL,    NULL,     NULL,     0},
1430
};
1431
1432
static struct sshkey *
1433
pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
1434
    char *label, CK_ULONG bits, CK_BYTE keyid, u_int32_t *err)
1435
{
1436
  struct pkcs11_slotinfo  *si;
1437
  char      *plabel = label ? label : "";
1438
  int      i;
1439
  size_t       ecparams_size;
1440
  unsigned char   *ecparams = NULL;
1441
  int      npub = 0, npriv = 0;
1442
  CK_RV      rv;
1443
  CK_FUNCTION_LIST  *f;
1444
  CK_SESSION_HANDLE  session;
1445
  CK_BBOOL     true_val = CK_TRUE, false_val = CK_FALSE;
1446
  CK_OBJECT_HANDLE   pubKey, privKey;
1447
  CK_MECHANISM     mech = {
1448
      CKM_EC_KEY_PAIR_GEN, NULL_PTR, 0
1449
  };
1450
  CK_ATTRIBUTE     tpub[16], tpriv[16];
1451
1452
  *err = 0;
1453
1454
  for (i = 0; ec_curve_infos[i].name; i++) {
1455
    if (ec_curve_infos[i].size == bits)
1456
      break;
1457
  }
1458
  if (!ec_curve_infos[i].name) {
1459
    error_f("invalid key size %lu", bits);
1460
    return NULL;
1461
  }
1462
  if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
1463
      &ecparams_size) == -1) {
1464
    error_f("invalid oid");
1465
    return NULL;
1466
  }
1467
1468
  FILL_ATTR(tpub, npub, CKA_TOKEN, &true_val, sizeof(true_val));
1469
  FILL_ATTR(tpub, npub, CKA_LABEL, plabel, strlen(plabel));
1470
  FILL_ATTR(tpub, npub, CKA_ENCRYPT, &false_val, sizeof(false_val));
1471
  FILL_ATTR(tpub, npub, CKA_VERIFY, &true_val, sizeof(true_val));
1472
  FILL_ATTR(tpub, npub, CKA_VERIFY_RECOVER, &false_val,
1473
      sizeof(false_val));
1474
  FILL_ATTR(tpub, npub, CKA_WRAP, &false_val, sizeof(false_val));
1475
  FILL_ATTR(tpub, npub, CKA_DERIVE, &false_val, sizeof(false_val));
1476
  FILL_ATTR(tpub, npub, CKA_EC_PARAMS, ecparams, ecparams_size);
1477
  FILL_ATTR(tpub, npub, CKA_ID, &keyid, sizeof(keyid));
1478
1479
  FILL_ATTR(tpriv, npriv, CKA_TOKEN, &true_val, sizeof(true_val));
1480
  FILL_ATTR(tpriv, npriv, CKA_LABEL, plabel, strlen(plabel));
1481
  FILL_ATTR(tpriv, npriv, CKA_PRIVATE, &true_val, sizeof(true_val));
1482
  FILL_ATTR(tpriv, npriv, CKA_SENSITIVE, &true_val, sizeof(true_val));
1483
  FILL_ATTR(tpriv, npriv, CKA_DECRYPT, &false_val, sizeof(false_val));
1484
  FILL_ATTR(tpriv, npriv, CKA_SIGN, &true_val, sizeof(true_val));
1485
  FILL_ATTR(tpriv, npriv, CKA_SIGN_RECOVER, &false_val,
1486
      sizeof(false_val));
1487
  FILL_ATTR(tpriv, npriv, CKA_UNWRAP, &false_val, sizeof(false_val));
1488
  FILL_ATTR(tpriv, npriv, CKA_DERIVE, &false_val, sizeof(false_val));
1489
  FILL_ATTR(tpriv, npriv, CKA_ID, &keyid, sizeof(keyid));
1490
1491
  f = p->function_list;
1492
  si = &p->slotinfo[slotidx];
1493
  session = si->session;
1494
1495
  if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
1496
      &pubKey, &privKey)) != CKR_OK) {
1497
    error_f("key generation failed: error 0x%lx", rv);
1498
    *err = rv;
1499
    return NULL;
1500
  }
1501
1502
  return pkcs11_fetch_ecdsa_pubkey(p, slotidx, &pubKey);
1503
}
1504
#endif /* WITH_PKCS11_KEYGEN */
1505
1506
/*
1507
 * register a new provider, fails if provider already exists. if
1508
 * keyp is provided, fetch keys.
1509
 */
1510
static int
1511
pkcs11_register_provider(char *provider_id, char *pin,
1512
    struct sshkey ***keyp, char ***labelsp,
1513
    struct pkcs11_provider **providerp, CK_ULONG user)
1514
0
{
1515
0
  int nkeys, need_finalize = 0;
1516
0
  int ret = -1;
1517
0
  struct pkcs11_provider *p = NULL;
1518
0
  void *handle = NULL;
1519
0
  CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **);
1520
0
  CK_RV rv;
1521
0
  CK_FUNCTION_LIST *f = NULL;
1522
0
  CK_TOKEN_INFO *token;
1523
0
  CK_ULONG i;
1524
1525
0
  if (providerp == NULL)
1526
0
    goto fail;
1527
0
  *providerp = NULL;
1528
1529
0
  if (keyp != NULL)
1530
0
    *keyp = NULL;
1531
0
  if (labelsp != NULL)
1532
0
    *labelsp = NULL;
1533
1534
0
  if (pkcs11_provider_lookup(provider_id) != NULL) {
1535
0
    debug_f("provider already registered: %s", provider_id);
1536
0
    goto fail;
1537
0
  }
1538
0
  if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) {
1539
0
    error("provider %s is not a PKCS11 library", provider_id);
1540
0
    goto fail;
1541
0
  }
1542
  /* open shared pkcs11-library */
1543
0
  if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) {
1544
0
    error("dlopen %s failed: %s", provider_id, dlerror());
1545
0
    goto fail;
1546
0
  }
1547
0
  if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL)
1548
0
    fatal("dlsym(C_GetFunctionList) failed: %s", dlerror());
1549
0
  p = xcalloc(1, sizeof(*p));
1550
0
  p->name = xstrdup(provider_id);
1551
0
  p->handle = handle;
1552
  /* setup the pkcs11 callbacks */
1553
0
  if ((rv = (*getfunctionlist)(&f)) != CKR_OK) {
1554
0
    error("C_GetFunctionList for provider %s failed: %lu",
1555
0
        provider_id, rv);
1556
0
    goto fail;
1557
0
  }
1558
0
  p->function_list = f;
1559
0
  if ((rv = f->C_Initialize(NULL)) != CKR_OK) {
1560
0
    error("C_Initialize for provider %s failed: %lu",
1561
0
        provider_id, rv);
1562
0
    goto fail;
1563
0
  }
1564
0
  need_finalize = 1;
1565
0
  if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) {
1566
0
    error("C_GetInfo for provider %s failed: %lu",
1567
0
        provider_id, rv);
1568
0
    goto fail;
1569
0
  }
1570
0
  debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d"
1571
0
      " libraryDescription <%.*s> libraryVersion %d.%d",
1572
0
      provider_id,
1573
0
      RMSPACE(p->info.manufacturerID),
1574
0
      p->info.cryptokiVersion.major,
1575
0
      p->info.cryptokiVersion.minor,
1576
0
      RMSPACE(p->info.libraryDescription),
1577
0
      p->info.libraryVersion.major,
1578
0
      p->info.libraryVersion.minor);
1579
0
  if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) {
1580
0
    error("C_GetSlotList failed: %lu", rv);
1581
0
    goto fail;
1582
0
  }
1583
0
  if (p->nslots == 0) {
1584
0
    debug_f("provider %s returned no slots", provider_id);
1585
0
    ret = -SSH_PKCS11_ERR_NO_SLOTS;
1586
0
    goto fail;
1587
0
  }
1588
0
  p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID));
1589
0
  if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots))
1590
0
      != CKR_OK) {
1591
0
    error("C_GetSlotList for provider %s failed: %lu",
1592
0
        provider_id, rv);
1593
0
    goto fail;
1594
0
  }
1595
0
  p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo));
1596
0
  p->valid = 1;
1597
0
  nkeys = 0;
1598
0
  for (i = 0; i < p->nslots; i++) {
1599
0
    token = &p->slotinfo[i].token;
1600
0
    if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
1601
0
        != CKR_OK) {
1602
0
      error("C_GetTokenInfo for provider %s slot %lu "
1603
0
          "failed: %lu", provider_id, (u_long)i, rv);
1604
0
      continue;
1605
0
    }
1606
0
    if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
1607
0
      debug2_f("ignoring uninitialised token in "
1608
0
          "provider %s slot %lu", provider_id, (u_long)i);
1609
0
      continue;
1610
0
    }
1611
0
    debug("provider %s slot %lu: label <%.*s> "
1612
0
        "manufacturerID <%.*s> model <%.*s> serial <%.*s> "
1613
0
        "flags 0x%lx",
1614
0
        provider_id, (unsigned long)i,
1615
0
        RMSPACE(token->label), RMSPACE(token->manufacturerID),
1616
0
        RMSPACE(token->model), RMSPACE(token->serialNumber),
1617
0
        token->flags);
1618
    /*
1619
     * open session, login with pin and retrieve public
1620
     * keys (if keyp is provided)
1621
     */
1622
0
    if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 ||
1623
0
        keyp == NULL)
1624
0
      continue;
1625
0
    pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1626
0
    pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1627
0
    if (nkeys == 0 && !p->slotinfo[i].logged_in &&
1628
0
        pkcs11_interactive) {
1629
      /*
1630
       * Some tokens require login before they will
1631
       * expose keys.
1632
       */
1633
0
      if (pkcs11_login_slot(p, &p->slotinfo[i],
1634
0
          CKU_USER) < 0) {
1635
0
        error("login failed");
1636
0
        continue;
1637
0
      }
1638
0
      pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys);
1639
0
      pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys);
1640
0
    }
1641
0
  }
1642
1643
  /* now owned by caller */
1644
0
  *providerp = p;
1645
1646
0
  TAILQ_INSERT_TAIL(&pkcs11_providers, p, next);
1647
0
  p->refcount++;  /* add to provider list */
1648
1649
0
  return (nkeys);
1650
0
fail:
1651
0
  if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK)
1652
0
    error("C_Finalize for provider %s failed: %lu",
1653
0
        provider_id, rv);
1654
0
  if (p) {
1655
0
    free(p->name);
1656
0
    free(p->slotlist);
1657
0
    free(p->slotinfo);
1658
0
    free(p);
1659
0
  }
1660
0
  if (handle)
1661
0
    dlclose(handle);
1662
0
  if (ret > 0)
1663
0
    ret = -1;
1664
0
  return (ret);
1665
0
}
1666
1667
/*
1668
 * register a new provider and get number of keys hold by the token,
1669
 * fails if provider already exists
1670
 */
1671
int
1672
pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1673
    char ***labelsp)
1674
0
{
1675
0
  struct pkcs11_provider *p = NULL;
1676
0
  int nkeys;
1677
1678
0
  nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp,
1679
0
      &p, CKU_USER);
1680
1681
  /* no keys found or some other error, de-register provider */
1682
0
  if (nkeys <= 0 && p != NULL) {
1683
0
    TAILQ_REMOVE(&pkcs11_providers, p, next);
1684
0
    pkcs11_provider_finalize(p);
1685
0
    pkcs11_provider_unref(p);
1686
0
  }
1687
0
  if (nkeys == 0)
1688
0
    debug_f("provider %s returned no keys", provider_id);
1689
1690
0
  return (nkeys);
1691
0
}
1692
1693
#ifdef WITH_PKCS11_KEYGEN
1694
struct sshkey *
1695
pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
1696
    unsigned int type, unsigned int bits, unsigned char keyid, u_int32_t *err)
1697
{
1698
  struct pkcs11_provider  *p = NULL;
1699
  struct pkcs11_slotinfo  *si;
1700
  CK_FUNCTION_LIST  *f;
1701
  CK_SESSION_HANDLE  session;
1702
  struct sshkey   *k = NULL;
1703
  int      ret = -1, reset_pin = 0, reset_provider = 0;
1704
  CK_RV      rv;
1705
1706
  *err = 0;
1707
1708
  if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
1709
    debug_f("provider \"%s\" available", provider_id);
1710
  else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
1711
      &p, CKU_SO)) < 0) {
1712
    debug_f("could not register provider %s", provider_id);
1713
    goto out;
1714
  } else
1715
    reset_provider = 1;
1716
1717
  f = p->function_list;
1718
  si = &p->slotinfo[slotidx];
1719
  session = si->session;
1720
1721
  if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1722
      CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1723
    debug_f("could not supply SO pin: %lu", rv);
1724
    reset_pin = 0;
1725
  } else
1726
    reset_pin = 1;
1727
1728
  switch (type) {
1729
  case KEY_RSA:
1730
    if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
1731
        bits, keyid, err)) == NULL) {
1732
      debug_f("failed to generate RSA key");
1733
      goto out;
1734
    }
1735
    break;
1736
  case KEY_ECDSA:
1737
    if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
1738
        bits, keyid, err)) == NULL) {
1739
      debug_f("failed to generate ECDSA key");
1740
      goto out;
1741
    }
1742
    break;
1743
  default:
1744
    *err = SSH_PKCS11_ERR_GENERIC;
1745
    debug_f("unknown type %d", type);
1746
    goto out;
1747
  }
1748
1749
out:
1750
  if (reset_pin)
1751
    f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1752
        CK_INVALID_HANDLE);
1753
1754
  if (reset_provider)
1755
    pkcs11_del_provider(provider_id);
1756
1757
  return (k);
1758
}
1759
1760
struct sshkey *
1761
pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
1762
    unsigned char keyid, u_int32_t *err)
1763
{
1764
  struct pkcs11_provider  *p = NULL;
1765
  struct pkcs11_slotinfo  *si;
1766
  struct sshkey   *k = NULL;
1767
  int      reset_pin = 0, reset_provider = 0;
1768
  CK_ULONG     nattrs;
1769
  CK_FUNCTION_LIST  *f;
1770
  CK_SESSION_HANDLE  session;
1771
  CK_ATTRIBUTE     attrs[16];
1772
  CK_OBJECT_CLASS    key_class;
1773
  CK_KEY_TYPE    key_type;
1774
  CK_OBJECT_HANDLE   obj = CK_INVALID_HANDLE;
1775
  CK_RV      rv;
1776
1777
  *err = 0;
1778
1779
  if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
1780
    debug_f("using provider \"%s\"", provider_id);
1781
  } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
1782
      CKU_SO) < 0) {
1783
    debug_f("could not register provider %s",
1784
        provider_id);
1785
    goto out;
1786
  } else
1787
    reset_provider = 1;
1788
1789
  f = p->function_list;
1790
  si = &p->slotinfo[slotidx];
1791
  session = si->session;
1792
1793
  if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
1794
      CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
1795
    debug_f("could not supply SO pin: %lu", rv);
1796
    reset_pin = 0;
1797
  } else
1798
    reset_pin = 1;
1799
1800
  /* private key */
1801
  nattrs = 0;
1802
  key_class = CKO_PRIVATE_KEY;
1803
  FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1804
  FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1805
1806
  if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1807
      obj != CK_INVALID_HANDLE) {
1808
    if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1809
      debug_f("could not destroy private key 0x%hhx",
1810
          keyid);
1811
      *err = rv;
1812
      goto out;
1813
    }
1814
  }
1815
1816
  /* public key */
1817
  nattrs = 0;
1818
  key_class = CKO_PUBLIC_KEY;
1819
  FILL_ATTR(attrs, nattrs, CKA_CLASS, &key_class, sizeof(key_class));
1820
  FILL_ATTR(attrs, nattrs, CKA_ID, &keyid, sizeof(keyid));
1821
1822
  if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
1823
      obj != CK_INVALID_HANDLE) {
1824
1825
    /* get key type */
1826
    nattrs = 0;
1827
    FILL_ATTR(attrs, nattrs, CKA_KEY_TYPE, &key_type,
1828
        sizeof(key_type));
1829
    rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
1830
    if (rv != CKR_OK) {
1831
      debug_f("could not get key type of public key 0x%hhx",
1832
          keyid);
1833
      *err = rv;
1834
      key_type = -1;
1835
    }
1836
    if (key_type == CKK_RSA)
1837
      k = pkcs11_fetch_rsa_pubkey(p, slotidx, &obj);
1838
    else if (key_type == CKK_ECDSA)
1839
      k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
1840
1841
    if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
1842
      debug_f("could not destroy public key 0x%hhx", keyid);
1843
      *err = rv;
1844
      goto out;
1845
    }
1846
  }
1847
1848
out:
1849
  if (reset_pin)
1850
    f->C_SetOperationState(session , NULL, 0, CK_INVALID_HANDLE,
1851
        CK_INVALID_HANDLE);
1852
1853
  if (reset_provider)
1854
    pkcs11_del_provider(provider_id);
1855
1856
  return (k);
1857
}
1858
#endif /* WITH_PKCS11_KEYGEN */
1859
#else /* ENABLE_PKCS11 */
1860
1861
#include <sys/types.h>
1862
#include <stdarg.h>
1863
#include <stdio.h>
1864
1865
#include "log.h"
1866
#include "sshkey.h"
1867
1868
int
1869
pkcs11_init(int interactive)
1870
{
1871
  error("%s: dlopen() not supported", __func__);
1872
  return (-1);
1873
}
1874
1875
int
1876
pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
1877
    char ***labelsp)
1878
{
1879
  error("%s: dlopen() not supported", __func__);
1880
  return (-1);
1881
}
1882
1883
void
1884
pkcs11_terminate(void)
1885
{
1886
  error("%s: dlopen() not supported", __func__);
1887
}
1888
#endif /* ENABLE_PKCS11 */