Bug Summary

File:src/usr.bin/ssh/ssh-keygen/../ssh-pkcs11.c
Warning:line 1596, column 8
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'

Annotated Source Code

Press '?' to see keyboard shortcuts

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