pk11.c revision 1.1 1 1.1 christos /* $NetBSD: pk11.c,v 1.1 2024/02/18 20:57:49 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.1 christos * SPDX-License-Identifier: MPL-2.0
7 1.1 christos *
8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 1.1 christos *
12 1.1 christos * See the COPYRIGHT file distributed with this work for additional
13 1.1 christos * information regarding copyright ownership.
14 1.1 christos */
15 1.1 christos
16 1.1 christos #include <errno.h>
17 1.1 christos #include <inttypes.h>
18 1.1 christos #include <stdbool.h>
19 1.1 christos #include <stdio.h>
20 1.1 christos #include <stdlib.h>
21 1.1 christos #include <string.h>
22 1.1 christos
23 1.1 christos #include <isc/log.h>
24 1.1 christos #include <isc/mem.h>
25 1.1 christos #include <isc/once.h>
26 1.1 christos #include <isc/platform.h>
27 1.1 christos #include <isc/print.h>
28 1.1 christos #include <isc/stdio.h>
29 1.1 christos #include <isc/strerr.h>
30 1.1 christos #include <isc/string.h>
31 1.1 christos #include <isc/thread.h>
32 1.1 christos #include <isc/util.h>
33 1.1 christos
34 1.1 christos #include <pk11/internal.h>
35 1.1 christos #include <pk11/pk11.h>
36 1.1 christos #include <pk11/result.h>
37 1.1 christos #include <pk11/site.h>
38 1.1 christos #include <pkcs11/pkcs11.h>
39 1.1 christos
40 1.1 christos #include <dst/result.h>
41 1.1 christos
42 1.1 christos /* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */
43 1.1 christos #ifndef PINLEN
44 1.1 christos #define PINLEN 256
45 1.1 christos #endif /* ifndef PINLEN */
46 1.1 christos
47 1.1 christos #ifndef PK11_NO_LOGERR
48 1.1 christos #define PK11_NO_LOGERR 1
49 1.1 christos #endif /* ifndef PK11_NO_LOGERR */
50 1.1 christos
51 1.1 christos LIBISC_EXTERNAL_DATA bool pk11_verbose_init = false;
52 1.1 christos
53 1.1 christos static isc_once_t once = ISC_ONCE_INIT;
54 1.1 christos static isc_mem_t *pk11_mctx = NULL;
55 1.1 christos static int32_t allocsize = 0;
56 1.1 christos static bool initialized = false;
57 1.1 christos
58 1.1 christos typedef struct pk11_session pk11_session_t;
59 1.1 christos typedef struct pk11_token pk11_token_t;
60 1.1 christos typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t;
61 1.1 christos
62 1.1 christos struct pk11_session {
63 1.1 christos unsigned int magic;
64 1.1 christos CK_SESSION_HANDLE session;
65 1.1 christos ISC_LINK(pk11_session_t) link;
66 1.1 christos pk11_token_t *token;
67 1.1 christos };
68 1.1 christos
69 1.1 christos struct pk11_token {
70 1.1 christos unsigned int magic;
71 1.1 christos unsigned int operations;
72 1.1 christos ISC_LINK(pk11_token_t) link;
73 1.1 christos CK_SLOT_ID slotid;
74 1.1 christos pk11_sessionlist_t sessions;
75 1.1 christos bool logged;
76 1.1 christos char name[32];
77 1.1 christos char manuf[32];
78 1.1 christos char model[16];
79 1.1 christos char serial[16];
80 1.1 christos char pin[PINLEN + 1];
81 1.1 christos };
82 1.1 christos static ISC_LIST(pk11_token_t) tokens;
83 1.1 christos
84 1.1 christos static pk11_token_t *best_rsa_token;
85 1.1 christos static pk11_token_t *best_ecdsa_token;
86 1.1 christos static pk11_token_t *best_eddsa_token;
87 1.1 christos
88 1.1 christos static isc_result_t
89 1.1 christos free_all_sessions(void);
90 1.1 christos static isc_result_t
91 1.1 christos free_session_list(pk11_sessionlist_t *slist);
92 1.1 christos static isc_result_t
93 1.1 christos setup_session(pk11_session_t *sp, pk11_token_t *token, bool rw);
94 1.1 christos static void
95 1.1 christos scan_slots(void);
96 1.1 christos static isc_result_t
97 1.1 christos token_login(pk11_session_t *sp);
98 1.1 christos static char *
99 1.1 christos percent_decode(char *x, size_t *len);
100 1.1 christos static bool
101 1.1 christos pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny);
102 1.1 christos static CK_ATTRIBUTE *
103 1.1 christos push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len);
104 1.1 christos
105 1.1 christos static isc_mutex_t alloclock;
106 1.1 christos static isc_mutex_t sessionlock;
107 1.1 christos
108 1.1 christos static pk11_sessionlist_t actives;
109 1.1 christos
110 1.1 christos static CK_C_INITIALIZE_ARGS pk11_init_args = {
111 1.1 christos NULL_PTR, /* CreateMutex */
112 1.1 christos NULL_PTR, /* DestroyMutex */
113 1.1 christos NULL_PTR, /* LockMutex */
114 1.1 christos NULL_PTR, /* UnlockMutex */
115 1.1 christos CKF_OS_LOCKING_OK, /* flags */
116 1.1 christos NULL_PTR, /* pReserved */
117 1.1 christos };
118 1.1 christos
119 1.1 christos #ifndef PK11_LIB_LOCATION
120 1.1 christos #define PK11_LIB_LOCATION "unknown_provider"
121 1.1 christos #endif /* ifndef PK11_LIB_LOCATION */
122 1.1 christos
123 1.1 christos #ifndef WIN32
124 1.1 christos static const char *lib_name = PK11_LIB_LOCATION;
125 1.1 christos #else /* ifndef WIN32 */
126 1.1 christos static const char *lib_name = PK11_LIB_LOCATION ".dll";
127 1.1 christos #endif /* ifndef WIN32 */
128 1.1 christos
129 1.1 christos void
130 1.1 christos pk11_set_lib_name(const char *name) {
131 1.1 christos lib_name = name;
132 1.1 christos }
133 1.1 christos
134 1.1 christos const char *
135 1.1 christos pk11_get_lib_name(void) {
136 1.1 christos return (lib_name);
137 1.1 christos }
138 1.1 christos
139 1.1 christos static void
140 1.1 christos initialize(void) {
141 1.1 christos char *pk11_provider;
142 1.1 christos
143 1.1 christos isc_mutex_init(&alloclock);
144 1.1 christos isc_mutex_init(&sessionlock);
145 1.1 christos
146 1.1 christos pk11_provider = getenv("PKCS11_PROVIDER");
147 1.1 christos if (pk11_provider != NULL) {
148 1.1 christos lib_name = pk11_provider;
149 1.1 christos }
150 1.1 christos }
151 1.1 christos
152 1.1 christos void *
153 1.1 christos pk11_mem_get(size_t size) {
154 1.1 christos void *ptr;
155 1.1 christos
156 1.1 christos LOCK(&alloclock);
157 1.1 christos if (pk11_mctx != NULL) {
158 1.1 christos ptr = isc_mem_get(pk11_mctx, size);
159 1.1 christos } else {
160 1.1 christos ptr = malloc(size);
161 1.1 christos if (ptr == NULL && size != 0) {
162 1.1 christos char strbuf[ISC_STRERRORSIZE];
163 1.1 christos strerror_r(errno, strbuf, sizeof(strbuf));
164 1.1 christos isc_error_fatal(__FILE__, __LINE__, "malloc failed: %s",
165 1.1 christos strbuf);
166 1.1 christos }
167 1.1 christos }
168 1.1 christos UNLOCK(&alloclock);
169 1.1 christos
170 1.1 christos if (ptr != NULL) {
171 1.1 christos memset(ptr, 0, size);
172 1.1 christos }
173 1.1 christos return (ptr);
174 1.1 christos }
175 1.1 christos
176 1.1 christos void
177 1.1 christos pk11_mem_put(void *ptr, size_t size) {
178 1.1 christos if (ptr != NULL) {
179 1.1 christos memset(ptr, 0, size);
180 1.1 christos }
181 1.1 christos LOCK(&alloclock);
182 1.1 christos if (pk11_mctx != NULL) {
183 1.1 christos isc_mem_put(pk11_mctx, ptr, size);
184 1.1 christos } else {
185 1.1 christos if (ptr != NULL) {
186 1.1 christos allocsize -= (int)size;
187 1.1 christos }
188 1.1 christos free(ptr);
189 1.1 christos }
190 1.1 christos UNLOCK(&alloclock);
191 1.1 christos }
192 1.1 christos
193 1.1 christos isc_result_t
194 1.1 christos pk11_initialize(isc_mem_t *mctx, const char *engine) {
195 1.1 christos isc_result_t result = ISC_R_SUCCESS;
196 1.1 christos CK_RV rv;
197 1.1 christos
198 1.1 christos RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
199 1.1 christos
200 1.1 christos LOCK(&sessionlock);
201 1.1 christos LOCK(&alloclock);
202 1.1 christos if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0)) {
203 1.1 christos isc_mem_attach(mctx, &pk11_mctx);
204 1.1 christos }
205 1.1 christos UNLOCK(&alloclock);
206 1.1 christos if (initialized) {
207 1.1 christos goto unlock;
208 1.1 christos } else {
209 1.1 christos initialized = true;
210 1.1 christos }
211 1.1 christos
212 1.1 christos ISC_LIST_INIT(tokens);
213 1.1 christos ISC_LIST_INIT(actives);
214 1.1 christos
215 1.1 christos if (engine != NULL) {
216 1.1 christos lib_name = engine;
217 1.1 christos }
218 1.1 christos
219 1.1 christos /* Initialize the CRYPTOKI library */
220 1.1 christos rv = pkcs_C_Initialize((CK_VOID_PTR)&pk11_init_args);
221 1.1 christos
222 1.1 christos if (rv == 0xfe) {
223 1.1 christos result = PK11_R_NOPROVIDER;
224 1.1 christos fprintf(stderr, "Can't load PKCS#11 provider: %s\n",
225 1.1 christos pk11_get_load_error_message());
226 1.1 christos goto unlock;
227 1.1 christos }
228 1.1 christos if (rv != CKR_OK) {
229 1.1 christos result = PK11_R_INITFAILED;
230 1.1 christos goto unlock;
231 1.1 christos }
232 1.1 christos
233 1.1 christos scan_slots();
234 1.1 christos unlock:
235 1.1 christos UNLOCK(&sessionlock);
236 1.1 christos return (result);
237 1.1 christos }
238 1.1 christos
239 1.1 christos isc_result_t
240 1.1 christos pk11_finalize(void) {
241 1.1 christos pk11_token_t *token, *next;
242 1.1 christos isc_result_t ret;
243 1.1 christos
244 1.1 christos ret = free_all_sessions();
245 1.1 christos (void)pkcs_C_Finalize(NULL_PTR);
246 1.1 christos token = ISC_LIST_HEAD(tokens);
247 1.1 christos while (token != NULL) {
248 1.1 christos next = ISC_LIST_NEXT(token, link);
249 1.1 christos ISC_LIST_UNLINK(tokens, token, link);
250 1.1 christos if (token == best_rsa_token) {
251 1.1 christos best_rsa_token = NULL;
252 1.1 christos }
253 1.1 christos if (token == best_ecdsa_token) {
254 1.1 christos best_ecdsa_token = NULL;
255 1.1 christos }
256 1.1 christos if (token == best_eddsa_token) {
257 1.1 christos best_eddsa_token = NULL;
258 1.1 christos }
259 1.1 christos pk11_mem_put(token, sizeof(*token));
260 1.1 christos token = next;
261 1.1 christos }
262 1.1 christos if (pk11_mctx != NULL) {
263 1.1 christos isc_mem_detach(&pk11_mctx);
264 1.1 christos }
265 1.1 christos initialized = false;
266 1.1 christos return (ret);
267 1.1 christos }
268 1.1 christos
269 1.1 christos isc_result_t
270 1.1 christos pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype, bool need_services,
271 1.1 christos bool rw, bool logon, const char *pin, CK_SLOT_ID slot) {
272 1.1 christos pk11_token_t *token = NULL;
273 1.1 christos pk11_sessionlist_t *freelist;
274 1.1 christos pk11_session_t *sp;
275 1.1 christos isc_result_t ret;
276 1.1 christos UNUSED(need_services);
277 1.1 christos
278 1.1 christos memset(ctx, 0, sizeof(pk11_context_t));
279 1.1 christos ctx->handle = NULL;
280 1.1 christos ctx->session = CK_INVALID_HANDLE;
281 1.1 christos
282 1.1 christos ret = pk11_initialize(NULL, NULL);
283 1.1 christos if (ret != ISC_R_SUCCESS) {
284 1.1 christos return (ret);
285 1.1 christos }
286 1.1 christos
287 1.1 christos LOCK(&sessionlock);
288 1.1 christos /* wait for initialization to finish */
289 1.1 christos UNLOCK(&sessionlock);
290 1.1 christos
291 1.1 christos switch (optype) {
292 1.1 christos case OP_ANY:
293 1.1 christos for (token = ISC_LIST_HEAD(tokens); token != NULL;
294 1.1 christos token = ISC_LIST_NEXT(token, link))
295 1.1 christos {
296 1.1 christos if (token->slotid == slot) {
297 1.1 christos break;
298 1.1 christos }
299 1.1 christos }
300 1.1 christos break;
301 1.1 christos default:
302 1.1 christos for (token = ISC_LIST_HEAD(tokens); token != NULL;
303 1.1 christos token = ISC_LIST_NEXT(token, link))
304 1.1 christos {
305 1.1 christos if (token->slotid == slot) {
306 1.1 christos break;
307 1.1 christos }
308 1.1 christos }
309 1.1 christos break;
310 1.1 christos }
311 1.1 christos if (token == NULL) {
312 1.1 christos return (ISC_R_NOTFOUND);
313 1.1 christos }
314 1.1 christos
315 1.1 christos /* Override the token's PIN */
316 1.1 christos if (logon && pin != NULL && *pin != '\0') {
317 1.1 christos if (strlen(pin) > PINLEN) {
318 1.1 christos return (ISC_R_RANGE);
319 1.1 christos }
320 1.1 christos /*
321 1.1 christos * We want to zero out the old pin before
322 1.1 christos * overwriting with a new one.
323 1.1 christos */
324 1.1 christos memset(token->pin, 0, sizeof(token->pin));
325 1.1 christos strlcpy(token->pin, pin, sizeof(token->pin));
326 1.1 christos }
327 1.1 christos
328 1.1 christos freelist = &token->sessions;
329 1.1 christos
330 1.1 christos LOCK(&sessionlock);
331 1.1 christos sp = ISC_LIST_HEAD(*freelist);
332 1.1 christos if (sp != NULL) {
333 1.1 christos ISC_LIST_UNLINK(*freelist, sp, link);
334 1.1 christos ISC_LIST_APPEND(actives, sp, link);
335 1.1 christos UNLOCK(&sessionlock);
336 1.1 christos if (logon) {
337 1.1 christos ret = token_login(sp);
338 1.1 christos }
339 1.1 christos ctx->handle = sp;
340 1.1 christos ctx->session = sp->session;
341 1.1 christos return (ret);
342 1.1 christos }
343 1.1 christos UNLOCK(&sessionlock);
344 1.1 christos
345 1.1 christos sp = pk11_mem_get(sizeof(*sp));
346 1.1 christos sp->magic = SES_MAGIC;
347 1.1 christos sp->token = token;
348 1.1 christos sp->session = CK_INVALID_HANDLE;
349 1.1 christos ISC_LINK_INIT(sp, link);
350 1.1 christos ret = setup_session(sp, token, rw);
351 1.1 christos if ((ret == ISC_R_SUCCESS) && logon) {
352 1.1 christos ret = token_login(sp);
353 1.1 christos }
354 1.1 christos LOCK(&sessionlock);
355 1.1 christos ISC_LIST_APPEND(actives, sp, link);
356 1.1 christos UNLOCK(&sessionlock);
357 1.1 christos ctx->handle = sp;
358 1.1 christos ctx->session = sp->session;
359 1.1 christos return (ret);
360 1.1 christos }
361 1.1 christos
362 1.1 christos void
363 1.1 christos pk11_return_session(pk11_context_t *ctx) {
364 1.1 christos pk11_session_t *sp = (pk11_session_t *)ctx->handle;
365 1.1 christos
366 1.1 christos if (sp == NULL) {
367 1.1 christos return;
368 1.1 christos }
369 1.1 christos ctx->handle = NULL;
370 1.1 christos ctx->session = CK_INVALID_HANDLE;
371 1.1 christos
372 1.1 christos LOCK(&sessionlock);
373 1.1 christos ISC_LIST_UNLINK(actives, sp, link);
374 1.1 christos UNLOCK(&sessionlock);
375 1.1 christos if (sp->session == CK_INVALID_HANDLE) {
376 1.1 christos pk11_mem_put(sp, sizeof(*sp));
377 1.1 christos return;
378 1.1 christos }
379 1.1 christos
380 1.1 christos LOCK(&sessionlock);
381 1.1 christos ISC_LIST_APPEND(sp->token->sessions, sp, link);
382 1.1 christos UNLOCK(&sessionlock);
383 1.1 christos }
384 1.1 christos
385 1.1 christos static isc_result_t
386 1.1 christos free_all_sessions(void) {
387 1.1 christos pk11_token_t *token;
388 1.1 christos isc_result_t ret = ISC_R_SUCCESS;
389 1.1 christos isc_result_t oret;
390 1.1 christos
391 1.1 christos for (token = ISC_LIST_HEAD(tokens); token != NULL;
392 1.1 christos token = ISC_LIST_NEXT(token, link))
393 1.1 christos {
394 1.1 christos oret = free_session_list(&token->sessions);
395 1.1 christos if (oret != ISC_R_SUCCESS) {
396 1.1 christos ret = oret;
397 1.1 christos }
398 1.1 christos }
399 1.1 christos if (!ISC_LIST_EMPTY(actives)) {
400 1.1 christos ret = ISC_R_ADDRINUSE;
401 1.1 christos oret = free_session_list(&actives);
402 1.1 christos if (oret != ISC_R_SUCCESS) {
403 1.1 christos ret = oret;
404 1.1 christos }
405 1.1 christos }
406 1.1 christos return (ret);
407 1.1 christos }
408 1.1 christos
409 1.1 christos static isc_result_t
410 1.1 christos free_session_list(pk11_sessionlist_t *slist) {
411 1.1 christos pk11_session_t *sp;
412 1.1 christos CK_RV rv;
413 1.1 christos isc_result_t ret;
414 1.1 christos
415 1.1 christos ret = ISC_R_SUCCESS;
416 1.1 christos LOCK(&sessionlock);
417 1.1 christos while (!ISC_LIST_EMPTY(*slist)) {
418 1.1 christos sp = ISC_LIST_HEAD(*slist);
419 1.1 christos ISC_LIST_UNLINK(*slist, sp, link);
420 1.1 christos UNLOCK(&sessionlock);
421 1.1 christos if (sp->session != CK_INVALID_HANDLE) {
422 1.1 christos rv = pkcs_C_CloseSession(sp->session);
423 1.1 christos if (rv != CKR_OK) {
424 1.1 christos ret = DST_R_CRYPTOFAILURE;
425 1.1 christos }
426 1.1 christos }
427 1.1 christos LOCK(&sessionlock);
428 1.1 christos pk11_mem_put(sp, sizeof(*sp));
429 1.1 christos }
430 1.1 christos UNLOCK(&sessionlock);
431 1.1 christos
432 1.1 christos return (ret);
433 1.1 christos }
434 1.1 christos
435 1.1 christos static isc_result_t
436 1.1 christos setup_session(pk11_session_t *sp, pk11_token_t *token, bool rw) {
437 1.1 christos CK_RV rv;
438 1.1 christos CK_FLAGS flags = CKF_SERIAL_SESSION;
439 1.1 christos
440 1.1 christos if (rw) {
441 1.1 christos flags += CKF_RW_SESSION;
442 1.1 christos }
443 1.1 christos
444 1.1 christos rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR, NULL_PTR,
445 1.1 christos &sp->session);
446 1.1 christos if (rv != CKR_OK) {
447 1.1 christos return (DST_R_CRYPTOFAILURE);
448 1.1 christos }
449 1.1 christos return (ISC_R_SUCCESS);
450 1.1 christos }
451 1.1 christos
452 1.1 christos static isc_result_t
453 1.1 christos token_login(pk11_session_t *sp) {
454 1.1 christos CK_RV rv;
455 1.1 christos pk11_token_t *token = sp->token;
456 1.1 christos isc_result_t ret = ISC_R_SUCCESS;
457 1.1 christos
458 1.1 christos LOCK(&sessionlock);
459 1.1 christos if (!token->logged) {
460 1.1 christos rv = pkcs_C_Login(sp->session, CKU_USER,
461 1.1 christos (CK_UTF8CHAR_PTR)token->pin,
462 1.1 christos (CK_ULONG)strlen(token->pin));
463 1.1 christos if (rv != CKR_OK) {
464 1.1 christos #if PK11_NO_LOGERR
465 1.1 christos pk11_error_fatalcheck(__FILE__, __LINE__,
466 1.1 christos "pkcs_C_Login", rv);
467 1.1 christos #else /* if PK11_NO_LOGERR */
468 1.1 christos ret = ISC_R_NOPERM;
469 1.1 christos #endif /* if PK11_NO_LOGERR */
470 1.1 christos } else {
471 1.1 christos token->logged = true;
472 1.1 christos }
473 1.1 christos }
474 1.1 christos UNLOCK(&sessionlock);
475 1.1 christos return (ret);
476 1.1 christos }
477 1.1 christos
478 1.1 christos #define PK11_TRACE(fmt) \
479 1.1 christos if (pk11_verbose_init) \
480 1.1 christos fprintf(stderr, fmt)
481 1.1 christos #define PK11_TRACE1(fmt, arg) \
482 1.1 christos if (pk11_verbose_init) \
483 1.1 christos fprintf(stderr, fmt, arg)
484 1.1 christos #define PK11_TRACE2(fmt, arg1, arg2) \
485 1.1 christos if (pk11_verbose_init) \
486 1.1 christos fprintf(stderr, fmt, arg1, arg2)
487 1.1 christos #define PK11_TRACEM(mech) \
488 1.1 christos if (pk11_verbose_init) \
489 1.1 christos fprintf(stderr, #mech ": 0x%lx\n", rv)
490 1.1 christos
491 1.1 christos static void
492 1.1 christos scan_slots(void) {
493 1.1 christos CK_MECHANISM_INFO mechInfo;
494 1.1 christos CK_TOKEN_INFO tokenInfo;
495 1.1 christos CK_RV rv;
496 1.1 christos CK_SLOT_ID slot;
497 1.1 christos CK_SLOT_ID_PTR slotList;
498 1.1 christos CK_ULONG slotCount;
499 1.1 christos pk11_token_t *token;
500 1.1 christos unsigned int i;
501 1.1 christos bool bad;
502 1.1 christos
503 1.1 christos slotCount = 0;
504 1.1 christos PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount));
505 1.1 christos PK11_TRACE1("slotCount=%lu\n", slotCount);
506 1.1 christos /* it's not an error if we didn't find any providers */
507 1.1 christos if (slotCount == 0) {
508 1.1 christos return;
509 1.1 christos }
510 1.1 christos slotList = pk11_mem_get(sizeof(CK_SLOT_ID) * slotCount);
511 1.1 christos PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount));
512 1.1 christos
513 1.1 christos for (i = 0; i < slotCount; i++) {
514 1.1 christos slot = slotList[i];
515 1.1 christos PK11_TRACE2("slot#%u=0x%lx\n", i, slot);
516 1.1 christos
517 1.1 christos rv = pkcs_C_GetTokenInfo(slot, &tokenInfo);
518 1.1 christos if (rv != CKR_OK) {
519 1.1 christos continue;
520 1.1 christos }
521 1.1 christos token = pk11_mem_get(sizeof(*token));
522 1.1 christos token->magic = TOK_MAGIC;
523 1.1 christos token->slotid = slot;
524 1.1 christos ISC_LINK_INIT(token, link);
525 1.1 christos ISC_LIST_INIT(token->sessions);
526 1.1 christos memmove(token->name, tokenInfo.label, 32);
527 1.1 christos memmove(token->manuf, tokenInfo.manufacturerID, 32);
528 1.1 christos memmove(token->model, tokenInfo.model, 16);
529 1.1 christos memmove(token->serial, tokenInfo.serialNumber, 16);
530 1.1 christos ISC_LIST_APPEND(tokens, token, link);
531 1.1 christos
532 1.1 christos /* Check for RSA support */
533 1.1 christos bad = false;
534 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
535 1.1 christos &mechInfo);
536 1.1 christos if ((rv != CKR_OK) ||
537 1.1 christos ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
538 1.1 christos {
539 1.1 christos bad = true;
540 1.1 christos PK11_TRACEM(CKM_RSA_PKCS_KEY_PAIR_GEN);
541 1.1 christos }
542 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS, &mechInfo);
543 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
544 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
545 1.1 christos {
546 1.1 christos bad = true;
547 1.1 christos PK11_TRACEM(CKM_MD5_RSA_PKCS);
548 1.1 christos }
549 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS,
550 1.1 christos &mechInfo);
551 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
552 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
553 1.1 christos {
554 1.1 christos bad = true;
555 1.1 christos PK11_TRACEM(CKM_SHA1_RSA_PKCS);
556 1.1 christos }
557 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS,
558 1.1 christos &mechInfo);
559 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
560 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
561 1.1 christos {
562 1.1 christos bad = true;
563 1.1 christos PK11_TRACEM(CKM_SHA256_RSA_PKCS);
564 1.1 christos }
565 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS,
566 1.1 christos &mechInfo);
567 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
568 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
569 1.1 christos {
570 1.1 christos bad = true;
571 1.1 christos PK11_TRACEM(CKM_SHA512_RSA_PKCS);
572 1.1 christos }
573 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS, &mechInfo);
574 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
575 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
576 1.1 christos {
577 1.1 christos bad = true;
578 1.1 christos PK11_TRACEM(CKM_RSA_PKCS);
579 1.1 christos }
580 1.1 christos if (!bad) {
581 1.1 christos token->operations |= 1 << OP_RSA;
582 1.1 christos if (best_rsa_token == NULL) {
583 1.1 christos best_rsa_token = token;
584 1.1 christos }
585 1.1 christos }
586 1.1 christos
587 1.1 christos /* Check for ECDSA support */
588 1.1 christos bad = false;
589 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN,
590 1.1 christos &mechInfo);
591 1.1 christos if ((rv != CKR_OK) ||
592 1.1 christos ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
593 1.1 christos {
594 1.1 christos bad = true;
595 1.1 christos PK11_TRACEM(CKM_EC_KEY_PAIR_GEN);
596 1.1 christos }
597 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo);
598 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
599 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
600 1.1 christos {
601 1.1 christos bad = true;
602 1.1 christos PK11_TRACEM(CKM_ECDSA);
603 1.1 christos }
604 1.1 christos if (!bad) {
605 1.1 christos token->operations |= 1 << OP_ECDSA;
606 1.1 christos if (best_ecdsa_token == NULL) {
607 1.1 christos best_ecdsa_token = token;
608 1.1 christos }
609 1.1 christos }
610 1.1 christos
611 1.1 christos /* Check for EDDSA support */
612 1.1 christos bad = false;
613 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_EDWARDS_KEY_PAIR_GEN,
614 1.1 christos &mechInfo);
615 1.1 christos if ((rv != CKR_OK) ||
616 1.1 christos ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
617 1.1 christos {
618 1.1 christos bad = true;
619 1.1 christos PK11_TRACEM(CKM_EC_EDWARDS_KEY_PAIR_GEN);
620 1.1 christos }
621 1.1 christos rv = pkcs_C_GetMechanismInfo(slot, CKM_EDDSA, &mechInfo);
622 1.1 christos if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0) ||
623 1.1 christos ((mechInfo.flags & CKF_VERIFY) == 0))
624 1.1 christos {
625 1.1 christos bad = true;
626 1.1 christos PK11_TRACEM(CKM_EDDSA);
627 1.1 christos }
628 1.1 christos if (!bad) {
629 1.1 christos token->operations |= 1 << OP_EDDSA;
630 1.1 christos if (best_eddsa_token == NULL) {
631 1.1 christos best_eddsa_token = token;
632 1.1 christos }
633 1.1 christos }
634 1.1 christos }
635 1.1 christos
636 1.1 christos if (slotList != NULL) {
637 1.1 christos pk11_mem_put(slotList, sizeof(CK_SLOT_ID) * slotCount);
638 1.1 christos }
639 1.1 christos }
640 1.1 christos
641 1.1 christos CK_SLOT_ID
642 1.1 christos pk11_get_best_token(pk11_optype_t optype) {
643 1.1 christos pk11_token_t *token = NULL;
644 1.1 christos
645 1.1 christos switch (optype) {
646 1.1 christos case OP_RSA:
647 1.1 christos token = best_rsa_token;
648 1.1 christos break;
649 1.1 christos case OP_ECDSA:
650 1.1 christos token = best_ecdsa_token;
651 1.1 christos break;
652 1.1 christos case OP_EDDSA:
653 1.1 christos token = best_eddsa_token;
654 1.1 christos break;
655 1.1 christos default:
656 1.1 christos break;
657 1.1 christos }
658 1.1 christos if (token == NULL) {
659 1.1 christos return (0);
660 1.1 christos }
661 1.1 christos return (token->slotid);
662 1.1 christos }
663 1.1 christos
664 1.1 christos isc_result_t
665 1.1 christos pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits) {
666 1.1 christos unsigned int bitcnt, i;
667 1.1 christos CK_BYTE top;
668 1.1 christos
669 1.1 christos if (bytecnt == 0) {
670 1.1 christos *bits = 0;
671 1.1 christos return (ISC_R_SUCCESS);
672 1.1 christos }
673 1.1 christos bitcnt = bytecnt * 8;
674 1.1 christos for (i = 0; i < bytecnt; i++) {
675 1.1 christos top = data[i];
676 1.1 christos if (top == 0) {
677 1.1 christos bitcnt -= 8;
678 1.1 christos continue;
679 1.1 christos }
680 1.1 christos if (top & 0x80) {
681 1.1 christos *bits = bitcnt;
682 1.1 christos return (ISC_R_SUCCESS);
683 1.1 christos }
684 1.1 christos if (top & 0x40) {
685 1.1 christos *bits = bitcnt - 1;
686 1.1 christos return (ISC_R_SUCCESS);
687 1.1 christos }
688 1.1 christos if (top & 0x20) {
689 1.1 christos *bits = bitcnt - 2;
690 1.1 christos return (ISC_R_SUCCESS);
691 1.1 christos }
692 1.1 christos if (top & 0x10) {
693 1.1 christos *bits = bitcnt - 3;
694 1.1 christos return (ISC_R_SUCCESS);
695 1.1 christos }
696 1.1 christos if (top & 0x08) {
697 1.1 christos *bits = bitcnt - 4;
698 1.1 christos return (ISC_R_SUCCESS);
699 1.1 christos }
700 1.1 christos if (top & 0x04) {
701 1.1 christos *bits = bitcnt - 5;
702 1.1 christos return (ISC_R_SUCCESS);
703 1.1 christos }
704 1.1 christos if (top & 0x02) {
705 1.1 christos *bits = bitcnt - 6;
706 1.1 christos return (ISC_R_SUCCESS);
707 1.1 christos }
708 1.1 christos if (top & 0x01) {
709 1.1 christos *bits = bitcnt - 7;
710 1.1 christos return (ISC_R_SUCCESS);
711 1.1 christos }
712 1.1 christos break;
713 1.1 christos }
714 1.1 christos return (ISC_R_RANGE);
715 1.1 christos }
716 1.1 christos
717 1.1 christos CK_ATTRIBUTE *
718 1.1 christos pk11_attribute_first(const pk11_object_t *obj) {
719 1.1 christos return (obj->repr);
720 1.1 christos }
721 1.1 christos
722 1.1 christos CK_ATTRIBUTE *
723 1.1 christos pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) {
724 1.1 christos CK_ATTRIBUTE *next;
725 1.1 christos
726 1.1 christos next = attr + 1;
727 1.1 christos if ((next - obj->repr) >= obj->attrcnt) {
728 1.1 christos return (NULL);
729 1.1 christos }
730 1.1 christos return (next);
731 1.1 christos }
732 1.1 christos
733 1.1 christos CK_ATTRIBUTE *
734 1.1 christos pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) {
735 1.1 christos CK_ATTRIBUTE *attr;
736 1.1 christos
737 1.1 christos for (attr = pk11_attribute_first(obj); attr != NULL;
738 1.1 christos attr = pk11_attribute_next(obj, attr))
739 1.1 christos {
740 1.1 christos if (attr->type == type) {
741 1.1 christos return (attr);
742 1.1 christos }
743 1.1 christos }
744 1.1 christos return (NULL);
745 1.1 christos }
746 1.1 christos
747 1.1 christos static char *
748 1.1 christos percent_decode(char *x, size_t *len) {
749 1.1 christos char *p, *c;
750 1.1 christos unsigned char v = 0;
751 1.1 christos
752 1.1 christos INSIST(len != NULL);
753 1.1 christos
754 1.1 christos for (p = c = x; p[0] != '\0'; p++, c++) {
755 1.1 christos switch (p[0]) {
756 1.1 christos case '%':
757 1.1 christos switch (p[1]) {
758 1.1 christos case '0':
759 1.1 christos case '1':
760 1.1 christos case '2':
761 1.1 christos case '3':
762 1.1 christos case '4':
763 1.1 christos case '5':
764 1.1 christos case '6':
765 1.1 christos case '7':
766 1.1 christos case '8':
767 1.1 christos case '9':
768 1.1 christos v = (p[1] - '0') << 4;
769 1.1 christos break;
770 1.1 christos case 'A':
771 1.1 christos case 'B':
772 1.1 christos case 'C':
773 1.1 christos case 'D':
774 1.1 christos case 'E':
775 1.1 christos case 'F':
776 1.1 christos v = (p[1] - 'A' + 10) << 4;
777 1.1 christos break;
778 1.1 christos case 'a':
779 1.1 christos case 'b':
780 1.1 christos case 'c':
781 1.1 christos case 'd':
782 1.1 christos case 'e':
783 1.1 christos case 'f':
784 1.1 christos v = (p[1] - 'a' + 10) << 4;
785 1.1 christos break;
786 1.1 christos default:
787 1.1 christos return (NULL);
788 1.1 christos }
789 1.1 christos switch (p[2]) {
790 1.1 christos case '0':
791 1.1 christos case '1':
792 1.1 christos case '2':
793 1.1 christos case '3':
794 1.1 christos case '4':
795 1.1 christos case '5':
796 1.1 christos case '6':
797 1.1 christos case '7':
798 1.1 christos case '8':
799 1.1 christos case '9':
800 1.1 christos v |= (p[2] - '0') & 0x0f;
801 1.1 christos break;
802 1.1 christos case 'A':
803 1.1 christos case 'B':
804 1.1 christos case 'C':
805 1.1 christos case 'D':
806 1.1 christos case 'E':
807 1.1 christos case 'F':
808 1.1 christos v = (p[2] - 'A' + 10) & 0x0f;
809 1.1 christos break;
810 1.1 christos case 'a':
811 1.1 christos case 'b':
812 1.1 christos case 'c':
813 1.1 christos case 'd':
814 1.1 christos case 'e':
815 1.1 christos case 'f':
816 1.1 christos v = (p[2] - 'a' + 10) & 0x0f;
817 1.1 christos break;
818 1.1 christos default:
819 1.1 christos return (NULL);
820 1.1 christos }
821 1.1 christos p += 2;
822 1.1 christos *c = (char)v;
823 1.1 christos (*len)++;
824 1.1 christos break;
825 1.1 christos default:
826 1.1 christos *c = *p;
827 1.1 christos (*len)++;
828 1.1 christos }
829 1.1 christos }
830 1.1 christos return (x);
831 1.1 christos }
832 1.1 christos
833 1.1 christos static bool
834 1.1 christos pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) {
835 1.1 christos char buf[32];
836 1.1 christos
837 1.1 christos INSIST((leny == 32) || (leny == 16));
838 1.1 christos
839 1.1 christos memset(buf, ' ', 32);
840 1.1 christos if (lenx > leny) {
841 1.1 christos lenx = leny;
842 1.1 christos }
843 1.1 christos memmove(buf, x, lenx);
844 1.1 christos return (memcmp(buf, y, leny) == 0);
845 1.1 christos }
846 1.1 christos
847 1.1 christos static CK_ATTRIBUTE *
848 1.1 christos push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) {
849 1.1 christos CK_ATTRIBUTE *old = obj->repr;
850 1.1 christos CK_ATTRIBUTE *attr;
851 1.1 christos CK_BYTE cnt = obj->attrcnt;
852 1.1 christos
853 1.1 christos REQUIRE(old != NULL || cnt == 0);
854 1.1 christos
855 1.1 christos obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr));
856 1.1 christos memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
857 1.1 christos if (old != NULL) {
858 1.1 christos memmove(obj->repr, old, cnt * sizeof(*attr));
859 1.1 christos }
860 1.1 christos attr = obj->repr + cnt;
861 1.1 christos attr->ulValueLen = (CK_ULONG)len;
862 1.1 christos attr->pValue = isc_mem_get(mctx, len);
863 1.1 christos memset(attr->pValue, 0, len);
864 1.1 christos if (old != NULL) {
865 1.1 christos memset(old, 0, cnt * sizeof(*attr));
866 1.1 christos isc_mem_put(mctx, old, cnt * sizeof(*attr));
867 1.1 christos }
868 1.1 christos obj->attrcnt++;
869 1.1 christos return (attr);
870 1.1 christos }
871 1.1 christos
872 1.1 christos #define DST_RET(a) \
873 1.1 christos { \
874 1.1 christos ret = a; \
875 1.1 christos goto err; \
876 1.1 christos }
877 1.1 christos
878 1.1 christos isc_result_t
879 1.1 christos pk11_parse_uri(pk11_object_t *obj, const char *label, isc_mem_t *mctx,
880 1.1 christos pk11_optype_t optype) {
881 1.1 christos CK_ATTRIBUTE *attr;
882 1.1 christos pk11_token_t *token = NULL;
883 1.1 christos char *uri, *p, *a, *na, *v;
884 1.1 christos size_t len, l;
885 1.1 christos FILE *stream = NULL;
886 1.1 christos char pin[PINLEN + 1];
887 1.1 christos bool gotpin = false;
888 1.1 christos isc_result_t ret;
889 1.1 christos
890 1.1 christos /* get values to work on */
891 1.1 christos len = strlen(label) + 1;
892 1.1 christos uri = isc_mem_get(mctx, len);
893 1.1 christos memmove(uri, label, len);
894 1.1 christos
895 1.1 christos /* get the URI scheme */
896 1.1 christos p = strchr(uri, ':');
897 1.1 christos if (p == NULL) {
898 1.1 christos DST_RET(PK11_R_NOPROVIDER);
899 1.1 christos }
900 1.1 christos *p++ = '\0';
901 1.1 christos if (strcmp(uri, "pkcs11") != 0) {
902 1.1 christos DST_RET(PK11_R_NOPROVIDER);
903 1.1 christos }
904 1.1 christos
905 1.1 christos /* get attributes */
906 1.1 christos for (na = p; na != NULL;) {
907 1.1 christos a = na;
908 1.1 christos p = strchr(a, ';');
909 1.1 christos if (p == NULL) {
910 1.1 christos /* last attribute */
911 1.1 christos na = NULL;
912 1.1 christos } else {
913 1.1 christos *p++ = '\0';
914 1.1 christos na = p;
915 1.1 christos }
916 1.1 christos p = strchr(a, '=');
917 1.1 christos if (p != NULL) {
918 1.1 christos *p++ = '\0';
919 1.1 christos v = p;
920 1.1 christos } else {
921 1.1 christos v = a;
922 1.1 christos }
923 1.1 christos l = 0;
924 1.1 christos v = percent_decode(v, &l);
925 1.1 christos if (v == NULL) {
926 1.1 christos DST_RET(PK11_R_NOPROVIDER);
927 1.1 christos }
928 1.1 christos if ((a == v) || (strcmp(a, "object") == 0)) {
929 1.1 christos /* object: CKA_LABEL */
930 1.1 christos attr = pk11_attribute_bytype(obj, CKA_LABEL);
931 1.1 christos if (attr != NULL) {
932 1.1 christos DST_RET(PK11_R_NOPROVIDER);
933 1.1 christos }
934 1.1 christos attr = push_attribute(obj, mctx, l);
935 1.1 christos if (attr == NULL) {
936 1.1 christos DST_RET(ISC_R_NOMEMORY);
937 1.1 christos }
938 1.1 christos attr->type = CKA_LABEL;
939 1.1 christos memmove(attr->pValue, v, l);
940 1.1 christos } else if (strcmp(a, "token") == 0) {
941 1.1 christos /* token: CK_TOKEN_INFO label */
942 1.1 christos if (token == NULL) {
943 1.1 christos for (token = ISC_LIST_HEAD(tokens);
944 1.1 christos token != NULL;
945 1.1 christos token = ISC_LIST_NEXT(token, link))
946 1.1 christos {
947 1.1 christos if (pk11strcmp(v, l, token->name, 32)) {
948 1.1 christos break;
949 1.1 christos }
950 1.1 christos }
951 1.1 christos }
952 1.1 christos } else if (strcmp(a, "manufacturer") == 0) {
953 1.1 christos /* manufacturer: CK_TOKEN_INFO manufacturerID */
954 1.1 christos if (token == NULL) {
955 1.1 christos for (token = ISC_LIST_HEAD(tokens);
956 1.1 christos token != NULL;
957 1.1 christos token = ISC_LIST_NEXT(token, link))
958 1.1 christos {
959 1.1 christos if (pk11strcmp(v, l, token->manuf, 32))
960 1.1 christos {
961 1.1 christos break;
962 1.1 christos }
963 1.1 christos }
964 1.1 christos }
965 1.1 christos } else if (strcmp(a, "serial") == 0) {
966 1.1 christos /* serial: CK_TOKEN_INFO serialNumber */
967 1.1 christos if (token == NULL) {
968 1.1 christos for (token = ISC_LIST_HEAD(tokens);
969 1.1 christos token != NULL;
970 1.1 christos token = ISC_LIST_NEXT(token, link))
971 1.1 christos {
972 1.1 christos if (pk11strcmp(v, l, token->serial, 16))
973 1.1 christos {
974 1.1 christos break;
975 1.1 christos }
976 1.1 christos }
977 1.1 christos }
978 1.1 christos } else if (strcmp(a, "model") == 0) {
979 1.1 christos /* model: CK_TOKEN_INFO model */
980 1.1 christos if (token == NULL) {
981 1.1 christos for (token = ISC_LIST_HEAD(tokens);
982 1.1 christos token != NULL;
983 1.1 christos token = ISC_LIST_NEXT(token, link))
984 1.1 christos {
985 1.1 christos if (pk11strcmp(v, l, token->model, 16))
986 1.1 christos {
987 1.1 christos break;
988 1.1 christos }
989 1.1 christos }
990 1.1 christos }
991 1.1 christos } else if (strcmp(a, "library-manufacturer") == 0) {
992 1.1 christos /* ignored */
993 1.1 christos } else if (strcmp(a, "library-description") == 0) {
994 1.1 christos /* ignored */
995 1.1 christos } else if (strcmp(a, "library-version") == 0) {
996 1.1 christos /* ignored */
997 1.1 christos } else if (strcmp(a, "object-type") == 0) {
998 1.1 christos /* object-type: CKA_CLASS */
999 1.1 christos /* only private makes sense */
1000 1.1 christos if (strcmp(v, "private") != 0) {
1001 1.1 christos DST_RET(PK11_R_NOPROVIDER);
1002 1.1 christos }
1003 1.1 christos } else if (strcmp(a, "id") == 0) {
1004 1.1 christos /* id: CKA_ID */
1005 1.1 christos attr = pk11_attribute_bytype(obj, CKA_ID);
1006 1.1 christos if (attr != NULL) {
1007 1.1 christos DST_RET(PK11_R_NOPROVIDER);
1008 1.1 christos }
1009 1.1 christos attr = push_attribute(obj, mctx, l);
1010 1.1 christos if (attr == NULL) {
1011 1.1 christos DST_RET(ISC_R_NOMEMORY);
1012 1.1 christos }
1013 1.1 christos attr->type = CKA_ID;
1014 1.1 christos memmove(attr->pValue, v, l);
1015 1.1 christos } else if (strcmp(a, "pin-source") == 0) {
1016 1.1 christos /* pin-source: PIN */
1017 1.1 christos ret = isc_stdio_open(v, "r", &stream);
1018 1.1 christos if (ret != ISC_R_SUCCESS) {
1019 1.1 christos goto err;
1020 1.1 christos }
1021 1.1 christos memset(pin, 0, PINLEN + 1);
1022 1.1 christos ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l);
1023 1.1 christos if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF)) {
1024 1.1 christos goto err;
1025 1.1 christos }
1026 1.1 christos if (l > PINLEN) {
1027 1.1 christos DST_RET(ISC_R_RANGE);
1028 1.1 christos }
1029 1.1 christos ret = isc_stdio_close(stream);
1030 1.1 christos stream = NULL;
1031 1.1 christos if (ret != ISC_R_SUCCESS) {
1032 1.1 christos goto err;
1033 1.1 christos }
1034 1.1 christos gotpin = true;
1035 1.1 christos } else {
1036 1.1 christos DST_RET(PK11_R_NOPROVIDER);
1037 1.1 christos }
1038 1.1 christos }
1039 1.1 christos
1040 1.1 christos if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
1041 1.1 christos (pk11_attribute_bytype(obj, CKA_ID) == NULL))
1042 1.1 christos {
1043 1.1 christos DST_RET(ISC_R_NOTFOUND);
1044 1.1 christos }
1045 1.1 christos
1046 1.1 christos if (token == NULL) {
1047 1.1 christos if (optype == OP_RSA) {
1048 1.1 christos token = best_rsa_token;
1049 1.1 christos } else if (optype == OP_ECDSA) {
1050 1.1 christos token = best_ecdsa_token;
1051 1.1 christos } else if (optype == OP_EDDSA) {
1052 1.1 christos token = best_eddsa_token;
1053 1.1 christos }
1054 1.1 christos }
1055 1.1 christos if (token == NULL) {
1056 1.1 christos DST_RET(ISC_R_NOTFOUND);
1057 1.1 christos }
1058 1.1 christos obj->slot = token->slotid;
1059 1.1 christos if (gotpin) {
1060 1.1 christos memmove(token->pin, pin, PINLEN + 1);
1061 1.1 christos obj->reqlogon = true;
1062 1.1 christos }
1063 1.1 christos
1064 1.1 christos ret = ISC_R_SUCCESS;
1065 1.1 christos
1066 1.1 christos err:
1067 1.1 christos if (stream != NULL) {
1068 1.1 christos (void)isc_stdio_close(stream);
1069 1.1 christos }
1070 1.1 christos isc_mem_put(mctx, uri, len);
1071 1.1 christos return (ret);
1072 1.1 christos }
1073 1.1 christos
1074 1.1 christos void
1075 1.1 christos pk11_error_fatalcheck(const char *file, int line, const char *funcname,
1076 1.1 christos CK_RV rv) {
1077 1.1 christos isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv);
1078 1.1 christos }
1079 1.1 christos
1080 1.1 christos void
1081 1.1 christos pk11_dump_tokens(void) {
1082 1.1 christos pk11_token_t *token;
1083 1.1 christos bool first;
1084 1.1 christos
1085 1.1 christos printf("DEFAULTS\n");
1086 1.1 christos printf("\tbest_rsa_token=%p\n", best_rsa_token);
1087 1.1 christos printf("\tbest_ecdsa_token=%p\n", best_ecdsa_token);
1088 1.1 christos printf("\tbest_eddsa_token=%p\n", best_eddsa_token);
1089 1.1 christos
1090 1.1 christos for (token = ISC_LIST_HEAD(tokens); token != NULL;
1091 1.1 christos token = ISC_LIST_NEXT(token, link))
1092 1.1 christos {
1093 1.1 christos printf("\nTOKEN\n");
1094 1.1 christos printf("\taddress=%p\n", token);
1095 1.1 christos printf("\tslotID=%lu\n", token->slotid);
1096 1.1 christos printf("\tlabel=%.32s\n", token->name);
1097 1.1 christos printf("\tmanufacturerID=%.32s\n", token->manuf);
1098 1.1 christos printf("\tmodel=%.16s\n", token->model);
1099 1.1 christos printf("\tserialNumber=%.16s\n", token->serial);
1100 1.1 christos printf("\tsupported operations=0x%x (", token->operations);
1101 1.1 christos first = true;
1102 1.1 christos if (token->operations & (1 << OP_RSA)) {
1103 1.1 christos first = false;
1104 1.1 christos printf("RSA");
1105 1.1 christos }
1106 1.1 christos if (token->operations & (1 << OP_ECDSA)) {
1107 1.1 christos if (!first) {
1108 1.1 christos printf(",");
1109 1.1 christos }
1110 1.1 christos printf("EC");
1111 1.1 christos }
1112 1.1 christos printf(")\n");
1113 1.1 christos }
1114 1.1 christos }
1115