Bug Summary

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