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' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | |
42 | struct pkcs11_slotinfo { |
43 | CK_TOKEN_INFO token; |
44 | CK_SESSION_HANDLE session; |
45 | int logged_in; |
46 | }; |
47 | |
48 | struct 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 | |
61 | TAILQ_HEAD(, pkcs11_provider)struct { struct pkcs11_provider *tqh_first; struct pkcs11_provider **tqh_last; } pkcs11_providers; |
62 | |
63 | struct pkcs11_key { |
64 | struct pkcs11_provider *provider; |
65 | CK_ULONG slotidx; |
66 | char *keyid; |
67 | int keyid_len; |
68 | }; |
69 | |
70 | int pkcs11_interactive = 0; |
71 | |
72 | #ifdef HAVE_DLOPEN1 |
73 | static void |
74 | ossl_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 | |
84 | int |
85 | pkcs11_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 | */ |
98 | static void |
99 | pkcs11_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 | */ |
127 | static void |
128 | pkcs11_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 */ |
142 | void |
143 | pkcs11_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 */ |
155 | static struct pkcs11_provider * |
156 | pkcs11_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 */ |
169 | int |
170 | pkcs11_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 |
184 | static RSA_METHOD *rsa_method; |
185 | static int rsa_idx = 0; |
186 | static EC_KEY_METHOD *ec_key_method; |
187 | static int ec_key_idx = 0; |
188 | |
189 | /* release a wrapped object */ |
190 | static void |
191 | pkcs11_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 */ |
206 | static int |
207 | pkcs11_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 | |
233 | static int |
234 | pkcs11_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 | |
288 | static int |
289 | pkcs11_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 | |
301 | static int |
302 | pkcs11_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 | |
336 | static int |
337 | pkcs11_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 */ |
412 | static int |
413 | pkcs11_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 | |
447 | static int |
448 | pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, |
449 | int padding) |
450 | { |
451 | return (-1); |
452 | } |
453 | |
454 | static int |
455 | pkcs11_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 */ |
476 | static int |
477 | pkcs11_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 */ |
502 | static ECDSA_SIG * |
503 | ecdsa_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 | |
569 | static int |
570 | pkcs11_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 | |
589 | static int |
590 | pkcs11_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 */ |
615 | static void |
616 | rmspace(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 | */ |
633 | static int |
634 | pkcs11_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 | |
676 | static int |
677 | pkcs11_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 | |
687 | static struct sshkey * |
688 | pkcs11_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 | |
797 | fail: |
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 | |
810 | static struct sshkey * |
811 | pkcs11_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 | |
891 | fail: |
892 | for (i = 0; i < 3; i++) |
893 | free(key_attr[i].pValue); |
894 | RSA_free(rsa); |
895 | |
896 | return (key); |
897 | } |
898 | |
899 | static int |
900 | pkcs11_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 |
1052 | static int |
1053 | have_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 | |
1062 | static void |
1063 | note_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 | */ |
1083 | static int |
1084 | pkcs11_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; |
1173 | fail: |
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 | */ |
1188 | static int |
1189 | pkcs11_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; |
1285 | fail: |
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 | |
1299 | static struct sshkey * |
1300 | pkcs11_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 | |
1360 | static int |
1361 | pkcs11_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 | |
1392 | static 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 | |
1404 | static struct sshkey * |
1405 | pkcs11_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 | */ |
1482 | static int |
1483 | pkcs11_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); |
1624 | fail: |
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 | */ |
1645 | int |
1646 | pkcs11_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 |
1668 | struct sshkey * |
1669 | pkcs11_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 | |
1723 | out: |
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 | |
1734 | struct sshkey * |
1735 | pkcs11_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 | |
1822 | out: |
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 |
1834 | int |
1835 | pkcs11_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 */ |