xref: /minix/external/bsd/bind/dist/lib/isc/pk11.c (revision fb9c64b2)
1 /*	$NetBSD: pk11.c,v 1.1.1.5 2015/07/08 15:38:05 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /*
20  * Portions copyright (c) 2008 Nominet UK.  All rights reserved.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the above copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41  */
42 
43 /*
44  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
45  * Use is subject to license terms.
46  */
47 
48 /*
49  * This product includes software developed by the OpenSSL Project for
50  * use in the OpenSSL Toolkit (http://www.openssl.org/).
51  *
52  * This project also referenced hw_pkcs11-0.9.7b.patch written by
53  * Afchine Madjlessi.
54  */
55 /*
56  * ====================================================================
57  * Copyright (c) 2000-2001 The OpenSSL Project.  All rights reserved.
58  *
59  * Redistribution and use in source and binary forms, with or without
60  * modification, are permitted provided that the following conditions
61  * are met:
62  *
63  * 1. Redistributions of source code must retain the above copyright
64  *    notice, this list of conditions and the following disclaimer.
65  *
66  * 2. Redistributions in binary form must reproduce the above copyright
67  *    notice, this list of conditions and the following disclaimer in
68  *    the documentation and/or other materials provided with the
69  *    distribution.
70  *
71  * 3. All advertising materials mentioning features or use of this
72  *    software must display the following acknowledgment:
73  *    "This product includes software developed by the OpenSSL Project
74  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
75  *
76  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
77  *    endorse or promote products derived from this software without
78  *    prior written permission. For written permission, please contact
79  *    licensing@OpenSSL.org.
80  *
81  * 5. Products derived from this software may not be called "OpenSSL"
82  *    nor may "OpenSSL" appear in their names without prior written
83  *    permission of the OpenSSL Project.
84  *
85  * 6. Redistributions of any form whatsoever must retain the following
86  *    acknowledgment:
87  *    "This product includes software developed by the OpenSSL Project
88  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
89  *
90  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
91  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
93  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
94  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
95  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
96  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
97  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
99  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
100  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
101  * OF THE POSSIBILITY OF SUCH DAMAGE.
102  * ====================================================================
103  *
104  * This product includes cryptographic software written by Eric Young
105  * (eay@cryptsoft.com).  This product includes software written by Tim
106  * Hudson (tjh@cryptsoft.com).
107  *
108  */
109 
110 /* Id */
111 
112 #include <config.h>
113 
114 #include <stdio.h>
115 #include <stdlib.h>
116 #include <string.h>
117 
118 #include <isc/log.h>
119 #include <isc/mem.h>
120 #include <isc/once.h>
121 #include <isc/platform.h>
122 #include <isc/stdio.h>
123 #include <isc/thread.h>
124 #include <isc/util.h>
125 
126 #include <dst/result.h>
127 
128 #include <pk11/pk11.h>
129 #include <pk11/internal.h>
130 #include <pk11/result.h>
131 
132 #include <pkcs11/cryptoki.h>
133 #include <pkcs11/pkcs11.h>
134 
135 /* was 32 octets, Petr Spacek suggested 1024, SoftHSMv2 uses 256... */
136 #ifndef PINLEN
137 #define PINLEN	256
138 #endif
139 
140 #ifndef PK11_NO_LOGERR
141 #define PK11_NO_LOGERR 1
142 #endif
143 
144 static isc_once_t once = ISC_ONCE_INIT;
145 static isc_mem_t *pk11_mctx = NULL;
146 static isc_int32_t allocsize = 0;
147 static isc_boolean_t initialized = ISC_FALSE;
148 
149 typedef struct pk11_session pk11_session_t;
150 typedef struct pk11_token pk11_token_t;
151 typedef ISC_LIST(pk11_session_t) pk11_sessionlist_t;
152 
153 struct pk11_session {
154 	unsigned int		magic;
155 	CK_SESSION_HANDLE	session;
156 	ISC_LINK(pk11_session_t) link;
157 	pk11_token_t		*token;
158 };
159 
160 struct pk11_token {
161 	unsigned int		magic;
162 	unsigned int		operations;
163 	ISC_LINK(pk11_token_t)	link;
164 	CK_SLOT_ID		slotid;
165 	pk11_sessionlist_t	sessions;
166 	isc_boolean_t		logged;
167 	char			name[32];
168 	char			manuf[32];
169 	char			model[16];
170 	char			serial[16];
171 	char			pin[PINLEN + 1];
172 };
173 static ISC_LIST(pk11_token_t) tokens;
174 
175 static pk11_token_t *rand_token;
176 static pk11_token_t *best_rsa_token;
177 static pk11_token_t *best_dsa_token;
178 static pk11_token_t *best_dh_token;
179 static pk11_token_t *digest_token;
180 static pk11_token_t *best_ec_token;
181 static pk11_token_t *best_gost_token;
182 static pk11_token_t *aes_token;
183 
184 static isc_result_t free_all_sessions(void);
185 static isc_result_t free_session_list(pk11_sessionlist_t *slist);
186 static isc_result_t setup_session(pk11_session_t *sp,
187 				  pk11_token_t *token,
188 				  isc_boolean_t rw);
189 static void choose_slots(void);
190 static isc_result_t token_login(pk11_session_t *sp);
191 static char *percent_decode(char *x, size_t *len);
192 static isc_boolean_t pk11strcmp(const char *x, size_t lenx,
193 				const char *y, size_t leny);
194 static CK_ATTRIBUTE *push_attribute(pk11_object_t *obj,
195 				    isc_mem_t *mctx,
196 				    size_t len);
197 
198 static isc_mutex_t alloclock;
199 static isc_mutex_t sessionlock;
200 
201 static pk11_sessionlist_t actives;
202 
203 static CK_C_INITIALIZE_ARGS pk11_init_args = {
204 	NULL_PTR,               /* CreateMutex */
205 	NULL_PTR,               /* DestroyMutex */
206 	NULL_PTR,               /* LockMutex */
207 	NULL_PTR,               /* UnlockMutex */
208 	CKF_OS_LOCKING_OK,      /* flags */
209 	NULL_PTR,               /* pReserved */
210 };
211 
212 #ifndef PK11_LIB_LOCATION
213 #define PK11_LIB_LOCATION	"unknown_provider"
214 #endif
215 
216 #ifndef WIN32
217 static const char *lib_name = PK11_LIB_LOCATION;
218 #else
219 static const char *lib_name = PK11_LIB_LOCATION ".dll";
220 #endif
221 
222 void
223 pk11_set_lib_name(const char *name) {
224 	lib_name = name;
225 }
226 
227 const char *
228 pk11_get_lib_name(void) {
229 	return (lib_name);
230 }
231 
232 static void
233 initialize(void) {
234 	char *pk11_provider;
235 
236 	RUNTIME_CHECK(isc_mutex_init(&alloclock) == ISC_R_SUCCESS);
237 	RUNTIME_CHECK(isc_mutex_init(&sessionlock) == ISC_R_SUCCESS);
238 
239 	pk11_provider = getenv("PKCS11_PROVIDER");
240 	if (pk11_provider != NULL)
241 		lib_name = pk11_provider;
242 }
243 
244 void *
245 pk11_mem_get(size_t size) {
246 	void *ptr;
247 
248 	LOCK(&alloclock);
249 	if (pk11_mctx != NULL)
250 		ptr = isc_mem_get(pk11_mctx, size);
251 	else {
252 		ptr = malloc(size);
253 		if (ptr != NULL)
254 			allocsize += (int)size;
255 	}
256 	UNLOCK(&alloclock);
257 
258 	if (ptr != NULL)
259 		memset(ptr, 0, size);
260 	return (ptr);
261 }
262 
263 void
264 pk11_mem_put(void *ptr, size_t size) {
265 	if (ptr != NULL)
266 		memset(ptr, 0, size);
267 	LOCK(&alloclock);
268 	if (pk11_mctx != NULL)
269 		isc_mem_put(pk11_mctx, ptr, size);
270 	else {
271 		if (ptr != NULL)
272 			allocsize -= (int)size;
273 		free(ptr);
274 	}
275 	UNLOCK(&alloclock);
276 }
277 
278 isc_result_t
279 pk11_initialize(isc_mem_t *mctx, const char *engine) {
280 	isc_result_t result;
281 	CK_RV rv;
282 
283 	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
284 
285 	LOCK(&alloclock);
286 	if ((mctx != NULL) && (pk11_mctx == NULL) && (allocsize == 0))
287 		isc_mem_attach(mctx, &pk11_mctx);
288 	if (initialized) {
289 		UNLOCK(&alloclock);
290 		return (ISC_R_SUCCESS);
291 	} else {
292 		LOCK(&sessionlock);
293 		initialized = ISC_TRUE;
294 		UNLOCK(&alloclock);
295 	}
296 
297 	ISC_LIST_INIT(tokens);
298 	ISC_LIST_INIT(actives);
299 
300 	if (engine != NULL)
301 		lib_name = engine;
302 
303 	/* Initialize the CRYPTOKI library */
304 	rv = pkcs_C_Initialize((CK_VOID_PTR) &pk11_init_args);
305 
306 	if (rv == 0xfe) {
307 		result = PK11_R_NOPROVIDER;
308 		goto unlock;
309 	}
310 	if (rv != CKR_OK) {
311 		result = PK11_R_INITFAILED;
312 		goto unlock;
313 	}
314 
315 	choose_slots();
316 #ifdef PKCS11CRYPTO
317 	if (rand_token == NULL) {
318 		result = PK11_R_NORANDOMSERVICE;
319 		goto unlock;
320 	}
321 	if (digest_token == NULL) {
322 		result = PK11_R_NODIGESTSERVICE;
323 		goto unlock;
324 	}
325 #if defined(ISC_PLATFORM_USESIT) && defined(AES_SIT)
326 	if (aes_token == NULL) {
327 		result = PK11_R_NOAESSERVICE;
328 		goto unlock;
329 	}
330 #endif
331 #endif /* PKCS11CRYPTO */
332 	result = ISC_R_SUCCESS;
333  unlock:
334 	UNLOCK(&sessionlock);
335 	return (result);
336 }
337 
338 isc_result_t
339 pk11_finalize(void) {
340 	pk11_token_t *token, *next;
341 	isc_result_t ret;
342 
343 	ret = free_all_sessions();
344 	(void) pkcs_C_Finalize(NULL_PTR);
345 	token = ISC_LIST_HEAD(tokens);
346 	while (token != NULL) {
347 		next = ISC_LIST_NEXT(token, link);
348 		ISC_LIST_UNLINK(tokens, token, link);
349 		if (token == rand_token)
350 			rand_token = NULL;
351 		if (token == best_rsa_token)
352 			best_rsa_token = NULL;
353 		if (token == best_dsa_token)
354 			best_dsa_token = NULL;
355 		if (token == best_dh_token)
356 			best_dh_token = NULL;
357 		if (token == digest_token)
358 			digest_token = NULL;
359 		if (token == best_ec_token)
360 			best_ec_token = NULL;
361 		if (token == best_gost_token)
362 			best_gost_token = NULL;
363 		if (token == aes_token)
364 			aes_token = NULL;
365 		pk11_mem_put(token, sizeof(*token));
366 		token = next;
367 	}
368 	if (pk11_mctx != NULL)
369 		isc_mem_detach(&pk11_mctx);
370 	initialized = ISC_FALSE;
371 	return (ret);
372 }
373 
374 isc_result_t
375 pk11_rand_bytes(unsigned char *buf, int num) {
376 	isc_result_t ret;
377 	CK_RV rv;
378 	pk11_context_t ctx;
379 
380 	ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
381 			       ISC_FALSE, NULL, 0);
382 	if ((ret != ISC_R_SUCCESS) &&
383 	    (ret != PK11_R_NODIGESTSERVICE) &&
384 	    (ret != PK11_R_NOAESSERVICE))
385 		return (ret);
386 	RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
387 	rv = pkcs_C_GenerateRandom(ctx.session,
388 				   (CK_BYTE_PTR) buf, (CK_ULONG) num);
389 	pk11_return_session(&ctx);
390 	if (rv == CKR_OK)
391 		return (ISC_R_SUCCESS);
392 	else
393 		return (DST_R_CRYPTOFAILURE);
394 }
395 
396 #define SEEDSIZE	1024
397 
398 static CK_BYTE seed[SEEDSIZE];
399 
400 void
401 pk11_rand_seed_fromfile(const char *randomfile) {
402 	pk11_context_t ctx;
403 	FILE *stream = NULL;
404 	size_t cc = 0;
405 	isc_result_t ret;
406 
407 	ret = pk11_get_session(&ctx, OP_RAND, ISC_FALSE, ISC_FALSE,
408 			       ISC_FALSE, NULL, 0);
409 	if ((ret != ISC_R_SUCCESS) &&
410 	    (ret != PK11_R_NODIGESTSERVICE) &&
411 	    (ret != PK11_R_NOAESSERVICE))
412 		return;
413 	RUNTIME_CHECK(ctx.session != CK_INVALID_HANDLE);
414 	ret = isc_stdio_open(randomfile, "r", &stream);
415 	if (ret != ISC_R_SUCCESS)
416 		goto cleanup;
417 	ret = isc_stdio_read(seed, 1, SEEDSIZE, stream, &cc);
418 	if (ret!= ISC_R_SUCCESS)
419 		goto cleanup;
420 	ret = isc_stdio_close(stream);
421 	stream = NULL;
422 	if (ret!= ISC_R_SUCCESS)
423 		goto cleanup;
424 	(void) pkcs_C_SeedRandom(ctx.session, seed, (CK_ULONG) cc);
425 
426     cleanup:
427 	if (stream != NULL)
428 		(void) isc_stdio_close(stream);
429 	pk11_return_session(&ctx);
430 }
431 
432 isc_result_t
433 pk11_get_session(pk11_context_t *ctx, pk11_optype_t optype,
434 		 isc_boolean_t need_services, isc_boolean_t rw,
435 		 isc_boolean_t logon, const char *pin, CK_SLOT_ID slot)
436 {
437 	pk11_token_t *token = NULL;
438 	pk11_sessionlist_t *freelist;
439 	pk11_session_t *sp;
440 	isc_result_t ret;
441 #ifdef PKCS11CRYPTO
442 	isc_result_t service_ret = ISC_R_SUCCESS;
443 #else
444 	UNUSED(need_services);
445 #endif
446 
447 	memset(ctx, 0, sizeof(pk11_context_t));
448 	ctx->handle = NULL;
449 	ctx->session = CK_INVALID_HANDLE;
450 
451 	ret = pk11_initialize(NULL, NULL);
452 #ifdef PKCS11CRYPTO
453 	if (ret == PK11_R_NORANDOMSERVICE ||
454 	    ret == PK11_R_NODIGESTSERVICE ||
455 	    ret == PK11_R_NOAESSERVICE) {
456 		if (need_services)
457 			return (ret);
458 		service_ret = ret;
459 	}
460 	else
461 #endif /* PKCS11CRYPTO */
462 	if (ret != ISC_R_SUCCESS)
463 		return (ret);
464 
465 	LOCK(&sessionlock);
466 	/* wait for initialization to finish */
467 	UNLOCK(&sessionlock);
468 
469 	switch(optype) {
470 #ifdef PKCS11CRYPTO
471 	case OP_RAND:
472 		token = rand_token;
473 		break;
474 	case OP_DIGEST:
475 		token = digest_token;
476 		break;
477 	case OP_AES:
478 		token = aes_token;
479 		break;
480 	case OP_ANY:
481 		for (token = ISC_LIST_HEAD(tokens);
482 		     token != NULL;
483 		     token = ISC_LIST_NEXT(token, link))
484 			if (token->slotid == slot)
485 				break;
486 		break;
487 #endif
488 	default:
489 		for (token = ISC_LIST_HEAD(tokens);
490 		     token != NULL;
491 		     token = ISC_LIST_NEXT(token, link))
492 			if (token->slotid == slot)
493 				break;
494 #ifdef PKCS11CRYPTO
495 		if ((token == NULL) ||
496 		    ((token->operations & (1 << optype)) == 0))
497 			return (ISC_R_NOTFOUND);
498 #endif
499 		break;
500 	}
501 	if (token == NULL)
502 		return (ISC_R_NOTFOUND);
503 
504 	/* Override the token's PIN */
505 	if (logon && pin != NULL && *pin != '\0') {
506 		if (strlen(pin) > PINLEN)
507 			return ISC_R_RANGE;
508 		memset(token->pin, 0, PINLEN + 1);
509 		strncpy(token->pin, pin, PINLEN);
510 	}
511 
512 	freelist = &token->sessions;
513 
514 	LOCK(&sessionlock);
515 	sp = ISC_LIST_HEAD(*freelist);
516 	if (sp != NULL) {
517 		ISC_LIST_UNLINK(*freelist, sp, link);
518 		ISC_LIST_APPEND(actives, sp, link);
519 		UNLOCK(&sessionlock);
520 		if (logon)
521 			ret = token_login(sp);
522 		ctx->handle = sp;
523 		ctx->session = sp->session;
524 		return (ret);
525 	}
526 	UNLOCK(&sessionlock);
527 
528 	sp = pk11_mem_get(sizeof(*sp));
529 	if (sp == NULL)
530 		return (ISC_R_NOMEMORY);
531 	sp->magic = SES_MAGIC;
532 	sp->token = token;
533 	sp->session = CK_INVALID_HANDLE;
534 	ISC_LINK_INIT(sp, link);
535 	ret = setup_session(sp, token, rw);
536 	if ((ret == ISC_R_SUCCESS) && logon)
537 		ret = token_login(sp);
538 	LOCK(&sessionlock);
539 	ISC_LIST_APPEND(actives, sp, link);
540 	UNLOCK(&sessionlock);
541 	ctx->handle = sp;
542 	ctx->session = sp->session;
543 #ifdef PKCS11CRYPTO
544 	if (ret == ISC_R_SUCCESS)
545 		ret = service_ret;
546 #endif
547 	return (ret);
548 }
549 
550 void
551 pk11_return_session(pk11_context_t *ctx) {
552 	pk11_session_t *sp = (pk11_session_t *) ctx->handle;
553 
554 	if (sp == NULL)
555 		return;
556 	ctx->handle = NULL;
557 	ctx->session = CK_INVALID_HANDLE;
558 
559 	LOCK(&sessionlock);
560 	ISC_LIST_UNLINK(actives, sp, link);
561 	UNLOCK(&sessionlock);
562 	if (sp->session == CK_INVALID_HANDLE) {
563 		pk11_mem_put(sp, sizeof(*sp));
564 		return;
565 	}
566 
567 	LOCK(&sessionlock);
568 	ISC_LIST_APPEND(sp->token->sessions, sp, link);
569 	UNLOCK(&sessionlock);
570 }
571 
572 static isc_result_t
573 free_all_sessions(void) {
574 	pk11_token_t *token;
575 	isc_result_t ret = ISC_R_SUCCESS;
576 	isc_result_t oret;
577 
578 	for (token = ISC_LIST_HEAD(tokens);
579 	     token != NULL;
580 	     token = ISC_LIST_NEXT(token, link)) {
581 		oret = free_session_list(&token->sessions);
582 		if (oret != ISC_R_SUCCESS)
583 			ret = oret;
584 	}
585 	if (!ISC_LIST_EMPTY(actives)) {
586 		ret = ISC_R_ADDRINUSE;
587 		oret = free_session_list(&actives);
588 		if (oret != ISC_R_SUCCESS)
589 			ret = oret;
590 	}
591 	return (ret);
592 }
593 
594 static isc_result_t
595 free_session_list(pk11_sessionlist_t *slist) {
596 	pk11_session_t *sp;
597 	CK_RV rv;
598 	isc_result_t ret;
599 
600 	ret = ISC_R_SUCCESS;
601 	LOCK(&sessionlock);
602 	while (!ISC_LIST_EMPTY(*slist)) {
603 		sp = ISC_LIST_HEAD(*slist);
604 		UNLOCK(&sessionlock);
605 		if (sp->session != CK_INVALID_HANDLE) {
606 			rv = pkcs_C_CloseSession(sp->session);
607 			if (rv != CKR_OK)
608 				ret = DST_R_CRYPTOFAILURE;
609 		}
610 		LOCK(&sessionlock);
611 		ISC_LIST_UNLINK(*slist, sp, link);
612 		pk11_mem_put(sp, sizeof(*sp));
613 	}
614 	UNLOCK(&sessionlock);
615 
616 	return (ret);
617 }
618 
619 static isc_result_t
620 setup_session(pk11_session_t *sp, pk11_token_t *token,
621 	      isc_boolean_t rw)
622 {
623 	CK_RV rv;
624 	CK_FLAGS flags = CKF_SERIAL_SESSION;
625 
626 	if (rw)
627 		flags += CKF_RW_SESSION;
628 
629 	rv = pkcs_C_OpenSession(token->slotid, flags, NULL_PTR,
630 				NULL_PTR, &sp->session);
631 	if (rv != CKR_OK)
632 		return (DST_R_CRYPTOFAILURE);
633 	return (ISC_R_SUCCESS);
634 }
635 
636 static isc_result_t
637 token_login(pk11_session_t *sp) {
638 	CK_RV rv;
639 	pk11_token_t *token = sp->token;
640 	isc_result_t ret = ISC_R_SUCCESS;
641 
642 	LOCK(&sessionlock);
643 	if (!token->logged) {
644 		rv = pkcs_C_Login(sp->session, CKU_USER,
645 				  (CK_UTF8CHAR_PTR) token->pin,
646 				  (CK_ULONG) strlen(token->pin));
647 		if (rv != CKR_OK) {
648 			ret = ISC_R_NOPERM;
649 #if PK11_NO_LOGERR
650 			pk11_error_fatalcheck(__FILE__, __LINE__,
651 					      "pkcs_C_Login", rv);
652 #endif
653 		} else
654 			token->logged = ISC_TRUE;
655 	}
656 	UNLOCK(&sessionlock);
657 	return (ret);
658 }
659 
660 static void
661 choose_slots(void) {
662 	CK_MECHANISM_INFO mechInfo;
663 	CK_TOKEN_INFO tokenInfo;
664 	CK_RV rv;
665 	CK_SLOT_ID slot;
666 	CK_SLOT_ID_PTR slotList;
667 	CK_ULONG slotCount;
668 	pk11_token_t *token;
669 	unsigned int i;
670 
671 	slotCount = 0;
672 	PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, NULL_PTR, &slotCount));
673 	/* it's not an error if we didn't find any providers */
674 	if (slotCount == 0)
675 		return;
676 	slotList = pk11_mem_get(sizeof(CK_SLOT_ID_PTR) * slotCount);
677 	RUNTIME_CHECK(slotList != NULL);
678 	PK11_FATALCHECK(pkcs_C_GetSlotList, (CK_FALSE, slotList, &slotCount));
679 
680 	for (i = 0; i < slotCount; i++) {
681 		slot = slotList[i];
682 
683 		rv = pkcs_C_GetTokenInfo(slot, &tokenInfo);
684 		if (rv != CKR_OK)
685 			continue;
686 		token = pk11_mem_get(sizeof(*token));
687 		RUNTIME_CHECK(token != NULL);
688 		token->magic = TOK_MAGIC;
689 		token->slotid = slot;
690 		ISC_LINK_INIT(token, link);
691 		ISC_LIST_INIT(token->sessions);
692 		memmove(token->name, tokenInfo.label, 32);
693 		memmove(token->manuf, tokenInfo.manufacturerID, 32);
694 		memmove(token->model, tokenInfo.model, 16);
695 		memmove(token->serial, tokenInfo.serialNumber, 16);
696 		ISC_LIST_APPEND(tokens, token, link);
697 		if ((tokenInfo.flags & CKF_RNG) == 0)
698 			goto try_rsa;
699 		token->operations |= 1 << OP_RAND;
700 		if (rand_token == NULL)
701 			rand_token = token;
702 
703 	try_rsa:
704 		rv = pkcs_C_GetMechanismInfo(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
705 					     &mechInfo);
706 		if ((rv != CKR_OK) ||
707 		    ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
708 			goto try_dsa;
709 		rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_RSA_PKCS,
710 					     &mechInfo);
711 		if ((rv != CKR_OK) ||
712 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
713 		    ((mechInfo.flags & CKF_VERIFY) == 0))
714 			goto try_dsa;
715 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA1_RSA_PKCS,
716 					     &mechInfo);
717 		if ((rv != CKR_OK) ||
718 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
719 		    ((mechInfo.flags & CKF_VERIFY) == 0))
720 			goto try_dsa;
721 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_RSA_PKCS,
722 					     &mechInfo);
723 		if ((rv != CKR_OK) ||
724 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
725 		    ((mechInfo.flags & CKF_VERIFY) == 0))
726 			goto try_dsa;
727 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_RSA_PKCS,
728 					     &mechInfo);
729 		if ((rv != CKR_OK) ||
730 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
731 		    ((mechInfo.flags & CKF_VERIFY) == 0))
732 			goto try_dsa;
733 		token->operations |= 1 << OP_RSA;
734 		if (best_rsa_token == NULL)
735 			best_rsa_token = token;
736 
737 	try_dsa:
738 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_PARAMETER_GEN,
739 					     &mechInfo);
740 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
741 			goto try_dh;
742 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_KEY_PAIR_GEN,
743 					     &mechInfo);
744 		if ((rv != CKR_OK) ||
745 		    ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
746 			goto try_dh;
747 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DSA_SHA1, &mechInfo);
748 		if ((rv != CKR_OK) ||
749 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
750 		    ((mechInfo.flags & CKF_VERIFY) == 0))
751 			goto try_dh;
752 		token->operations |= 1 << OP_DSA;
753 		if (best_dsa_token == NULL)
754 			best_dsa_token = token;
755 
756 	try_dh:
757 #ifdef notdef
758 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_PARAMETER_GEN,
759 					     &mechInfo);
760 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_GENERATE) == 0))
761 			goto try_digest;
762 #endif
763 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_KEY_PAIR_GEN,
764 					     &mechInfo);
765 		if ((rv != CKR_OK) ||
766 		    ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
767 			goto try_digest;
768 		rv = pkcs_C_GetMechanismInfo(slot, CKM_DH_PKCS_DERIVE,
769 					     &mechInfo);
770 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DERIVE) == 0))
771 			goto try_digest;
772 		token->operations |= 1 << OP_DH;
773 		if (best_dh_token == NULL)
774 			best_dh_token = token;
775 
776 	try_digest:
777 		rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5, &mechInfo);
778 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
779 			continue;
780 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1, &mechInfo);
781 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
782 			continue;
783 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224, &mechInfo);
784 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
785 			continue;
786 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256, &mechInfo);
787 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
788 			continue;
789 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384, &mechInfo);
790 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
791 			continue;
792 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512, &mechInfo);
793 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
794 			continue;
795 #ifdef PKCS11CRYPTOWITHHMAC
796 		rv = pkcs_C_GetMechanismInfo(slot, CKM_MD5_HMAC, &mechInfo);
797 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
798 			continue;
799 #endif
800 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA_1_HMAC, &mechInfo);
801 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
802 			continue;
803 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA224_HMAC, &mechInfo);
804 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
805 			continue;
806 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA256_HMAC, &mechInfo);
807 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
808 			continue;
809 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA384_HMAC, &mechInfo);
810 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
811 			continue;
812 		rv = pkcs_C_GetMechanismInfo(slot, CKM_SHA512_HMAC, &mechInfo);
813 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_SIGN) == 0))
814 			continue;
815 		token->operations |= 1 << OP_DIGEST;
816 		if (digest_token == NULL)
817 			digest_token = token;
818 
819 		/* ECDSA requires digest */
820 		rv = pkcs_C_GetMechanismInfo(slot, CKM_EC_KEY_PAIR_GEN,
821 					     &mechInfo);
822 		if ((rv != CKR_OK) ||
823 		    ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
824 			goto try_gost;
825 		rv = pkcs_C_GetMechanismInfo(slot, CKM_ECDSA, &mechInfo);
826 		if ((rv != CKR_OK) ||
827 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
828 		    ((mechInfo.flags & CKF_VERIFY) == 0))
829 			goto try_gost;
830 		token->operations |= 1 << OP_EC;
831 		if (best_ec_token == NULL)
832 			best_ec_token = token;
833 
834 	try_gost:
835 		/* does GOST require digest too? */
836 		rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3411, &mechInfo);
837 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_DIGEST) == 0))
838 			goto try_aes;
839 		rv = pkcs_C_GetMechanismInfo(slot, CKM_GOSTR3410_KEY_PAIR_GEN,
840 					     &mechInfo);
841 		if ((rv != CKR_OK) ||
842 		    ((mechInfo.flags & CKF_GENERATE_KEY_PAIR) == 0))
843 			goto try_aes;
844 		rv = pkcs_C_GetMechanismInfo(slot,
845 					     CKM_GOSTR3410_WITH_GOSTR3411,
846 					     &mechInfo);
847 		if ((rv != CKR_OK) ||
848 		    ((mechInfo.flags & CKF_SIGN) == 0) ||
849 		    ((mechInfo.flags & CKF_VERIFY) == 0))
850 			goto try_aes;
851 		token->operations |= 1 << OP_GOST;
852 		if (best_gost_token == NULL)
853 			best_gost_token = token;
854 
855 	try_aes:
856 		rv = pkcs_C_GetMechanismInfo(slot, CKM_AES_ECB, &mechInfo);
857 		if ((rv != CKR_OK) || ((mechInfo.flags & CKF_ENCRYPT) == 0))
858 			continue;
859 		token->operations |= 1 << OP_AES;
860 		if (aes_token == NULL)
861 			aes_token = token;
862 	}
863 
864 	if (slotList != NULL)
865 		pk11_mem_put(slotList, sizeof(CK_SLOT_ID_PTR) * slotCount);
866 }
867 
868 CK_SLOT_ID
869 pk11_get_best_token(pk11_optype_t optype) {
870 	pk11_token_t *token = NULL;
871 
872 	switch (optype) {
873 	case OP_RAND:
874 		token = rand_token;
875 		break;
876 	case OP_RSA:
877 		token = best_rsa_token;
878 		break;
879 	case OP_DSA:
880 		token = best_dsa_token;
881 		break;
882 	case OP_DH:
883 		token = best_dh_token;
884 		break;
885 	case OP_DIGEST:
886 		token = digest_token;
887 		break;
888 	case OP_EC:
889 		token = best_ec_token;
890 		break;
891 	case OP_GOST:
892 		token = best_gost_token;
893 		break;
894 	case OP_AES:
895 		token = aes_token;
896 		break;
897 	default:
898 		break;
899 	}
900 	if (token == NULL)
901 		return (0);
902 	return (token->slotid);
903 }
904 
905 unsigned int
906 pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) {
907 	unsigned int bitcnt, i;
908 	CK_BYTE top;
909 
910 	if (bytecnt == 0)
911 		return (0);
912 	bitcnt = bytecnt * 8;
913 	for (i = 0; i < bytecnt; i++) {
914 		top = data[i];
915 		if (top == 0) {
916 			bitcnt -= 8;
917 			continue;
918 		}
919 		if (top & 0x80)
920 			return (bitcnt);
921 		if (top & 0x40)
922 			return (bitcnt - 1);
923 		if (top & 0x20)
924 			return (bitcnt - 2);
925 		if (top & 0x10)
926 			return (bitcnt - 3);
927 		if (top & 0x08)
928 			return (bitcnt - 4);
929 		if (top & 0x04)
930 			return (bitcnt - 5);
931 		if (top & 0x02)
932 			return (bitcnt - 6);
933 		if (top & 0x01)
934 			return (bitcnt - 7);
935 		break;
936 	}
937 	INSIST(0);
938 }
939 
940 CK_ATTRIBUTE *
941 pk11_attribute_first(const pk11_object_t *obj) {
942 	return (obj->repr);
943 }
944 
945 CK_ATTRIBUTE *
946 pk11_attribute_next(const pk11_object_t *obj, CK_ATTRIBUTE *attr) {
947 	CK_ATTRIBUTE *next;
948 
949 	next = attr + 1;
950 	if ((next - obj->repr) >= obj->attrcnt)
951 		return (NULL);
952 	return (next);
953 }
954 
955 CK_ATTRIBUTE *
956 pk11_attribute_bytype(const pk11_object_t *obj, CK_ATTRIBUTE_TYPE type) {
957 	CK_ATTRIBUTE *attr;
958 
959 	for(attr = pk11_attribute_first(obj);
960 	    attr != NULL;
961 	    attr = pk11_attribute_next(obj, attr))
962 		if (attr->type == type)
963 			return (attr);
964 	return (NULL);
965 }
966 
967 static char *
968 percent_decode(char *x, size_t *len) {
969 	char *p, *c;
970 	unsigned char v;
971 
972 	INSIST(len != NULL);
973 
974 	for (p = c = x; p[0] != '\0'; p++, c++) {
975 		switch (p[0]) {
976 		case '%':
977 			v = 0;
978 			switch (p[1]) {
979 			case '0':
980 			case '1':
981 			case '2':
982 			case '3':
983 			case '4':
984 			case '5':
985 			case '6':
986 			case '7':
987 			case '8':
988 			case '9':
989 				v = (p[1] - '0') << 4;
990 				break;
991 			case 'A':
992 			case 'B':
993 			case 'C':
994 			case 'D':
995 			case 'E':
996 			case 'F':
997 				v = (p[1] - 'A' + 10) << 4;
998 				break;
999 			case 'a':
1000 			case 'b':
1001 			case 'c':
1002 			case 'd':
1003 			case 'e':
1004 			case 'f':
1005 				v = (p[1] - 'a' + 10) << 4;
1006 				break;
1007 			default:
1008 				return (NULL);
1009 			}
1010 			switch (p[2]) {
1011 			case '0':
1012 			case '1':
1013 			case '2':
1014 			case '3':
1015 			case '4':
1016 			case '5':
1017 			case '6':
1018 			case '7':
1019 			case '8':
1020 			case '9':
1021 				v |= (p[2] - '0') & 0x0f;
1022 				break;
1023 			case 'A':
1024 			case 'B':
1025 			case 'C':
1026 			case 'D':
1027 			case 'E':
1028 			case 'F':
1029 				v = (p[2] - 'A' + 10) & 0x0f;
1030 				break;
1031 			case 'a':
1032 			case 'b':
1033 			case 'c':
1034 			case 'd':
1035 			case 'e':
1036 			case 'f':
1037 				v = (p[2] - 'a' + 10) & 0x0f;
1038 				break;
1039 			default:
1040 				return (NULL);
1041 			}
1042 			p += 2;
1043 			*c = (char) v;
1044 			(*len)++;
1045 			break;
1046 		default:
1047 			*c = *p;
1048 			(*len)++;
1049 		}
1050 	}
1051 	return (x);
1052 }
1053 
1054 static isc_boolean_t
1055 pk11strcmp(const char *x, size_t lenx, const char *y, size_t leny) {
1056 	char buf[32];
1057 
1058 	INSIST((leny == 32) || (leny == 16));
1059 
1060 	memset(buf, ' ', 32);
1061 	if (lenx > leny)
1062 		lenx = leny;
1063 	memmove(buf, x, lenx);
1064 	return (ISC_TF(memcmp(buf, y, leny) == 0));
1065 }
1066 
1067 static CK_ATTRIBUTE *
1068 push_attribute(pk11_object_t *obj, isc_mem_t *mctx, size_t len) {
1069 	CK_ATTRIBUTE *old = obj->repr;
1070 	CK_ATTRIBUTE *attr;
1071 	CK_BYTE cnt = obj->attrcnt;
1072 
1073 	obj->repr = isc_mem_get(mctx, (cnt + 1) * sizeof(*attr));
1074 	if (obj->repr == NULL) {
1075 		obj->repr = old;
1076 		return (NULL);
1077 	}
1078 	memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
1079 	memmove(obj->repr, old, cnt * sizeof(*attr));
1080 	attr = obj->repr + cnt;
1081 	attr->ulValueLen = (CK_ULONG) len;
1082 	attr->pValue = isc_mem_get(mctx, len);
1083 	if (attr->pValue == NULL) {
1084 		memset(obj->repr, 0, (cnt + 1) * sizeof(*attr));
1085 		isc_mem_put(mctx, obj->repr, (cnt + 1) * sizeof(*attr));
1086 		obj->repr = old;
1087 		return (NULL);
1088 	}
1089 	memset(attr->pValue, 0, len);
1090 	if (old != NULL) {
1091 		memset(old, 0, cnt * sizeof(*attr));
1092 		isc_mem_put(mctx, old, cnt * sizeof(*attr));
1093 	}
1094 	obj->attrcnt++;
1095 	return (attr);
1096 }
1097 
1098 #define DST_RET(a)	{ ret = a; goto err; }
1099 
1100 isc_result_t
1101 pk11_parse_uri(pk11_object_t *obj, const char *label,
1102 	       isc_mem_t *mctx, pk11_optype_t optype)
1103 {
1104 	CK_ATTRIBUTE *attr;
1105 	pk11_token_t *token = NULL;
1106 	char *uri, *p, *a, *na, *v;
1107 	size_t len, l;
1108 	FILE *stream = NULL;
1109 	char pin[PINLEN + 1];
1110 	isc_boolean_t gotpin = ISC_FALSE;
1111 	isc_result_t ret;
1112 
1113 	/* get values to work on */
1114 	len = strlen(label) + 1;
1115 	uri = isc_mem_get(mctx, len);
1116 	if (uri == NULL)
1117 		return (ISC_R_NOMEMORY);
1118 	memmove(uri, label, len);
1119 
1120 	/* get the URI scheme */
1121 	p = strchr(uri, ':');
1122 	if (p == NULL)
1123 		DST_RET(PK11_R_NOPROVIDER);
1124 	*p++ = '\0';
1125 	if (strcmp(uri, "pkcs11") != 0)
1126 		DST_RET(PK11_R_NOPROVIDER);
1127 
1128 	/* get attributes */
1129 	for (na = p; na != NULL;) {
1130 		a = na;
1131 		p = strchr(a, ';');
1132 		if (p == NULL) {
1133 			/* last attribute */
1134 			na = NULL;
1135 		} else {
1136 			*p++ = '\0';
1137 			na = p;
1138 		}
1139 		p = strchr(a, '=');
1140 		if (p != NULL) {
1141 			*p++ = '\0';
1142 			v = p;
1143 		} else
1144 			v = a;
1145 		l = 0;
1146 		v = percent_decode(v, &l);
1147 		if (v == NULL)
1148 			DST_RET(PK11_R_NOPROVIDER);
1149 		if ((a == v) || (strcmp(a, "object") == 0)) {
1150 			/* object: CKA_LABEL */
1151 			attr = pk11_attribute_bytype(obj, CKA_LABEL);
1152 			if (attr != NULL)
1153 				DST_RET(PK11_R_NOPROVIDER);
1154 			attr = push_attribute(obj, mctx, l);
1155 			if (attr == NULL)
1156 				DST_RET(ISC_R_NOMEMORY);
1157 			attr->type = CKA_LABEL;
1158 			memmove(attr->pValue, v, l);
1159 		} else if (strcmp(a, "token") == 0) {
1160 			/* token: CK_TOKEN_INFO label */
1161 			if (token == NULL)
1162 				for (token = ISC_LIST_HEAD(tokens);
1163 				     token != NULL;
1164 				     token = ISC_LIST_NEXT(token, link))
1165 					if (pk11strcmp(v, l, token->name, 32))
1166 						break;
1167 		} else if (strcmp(a, "manufacturer") == 0) {
1168 			/* manufacturer: CK_TOKEN_INFO manufacturerID */
1169 			if (token == NULL)
1170 				for (token = ISC_LIST_HEAD(tokens);
1171 				     token != NULL;
1172 				     token = ISC_LIST_NEXT(token, link))
1173 					if (pk11strcmp(v, l, token->manuf, 32))
1174 						break;
1175 		} else if (strcmp(a, "serial") == 0) {
1176 			/* serial: CK_TOKEN_INFO serialNumber */
1177 			if (token == NULL)
1178 				for (token = ISC_LIST_HEAD(tokens);
1179 				     token != NULL;
1180 				     token = ISC_LIST_NEXT(token, link))
1181 					if (pk11strcmp(v, l, token->serial, 16))
1182 						break;
1183 		} else if (strcmp(a, "model") == 0) {
1184 			/* model: CK_TOKEN_INFO model */
1185 			if (token == NULL)
1186 				for (token = ISC_LIST_HEAD(tokens);
1187 				     token != NULL;
1188 				     token = ISC_LIST_NEXT(token, link))
1189 					if (pk11strcmp(v, l, token->model, 16))
1190 						break;
1191 		} else if (strcmp(a, "library-manufacturer") == 0) {
1192 			/* ignored */
1193 		} else if (strcmp(a, "library-description") == 0) {
1194 			/* ignored */
1195 		} else if (strcmp(a, "library-version") == 0) {
1196 			/* ignored */
1197 		} else if (strcmp(a, "object-type") == 0) {
1198 			/* object-type: CKA_CLASS */
1199 			/* only private makes sense */
1200 			if (strcmp(v, "private") != 0)
1201 				DST_RET(PK11_R_NOPROVIDER);
1202 		} else if (strcmp(a, "id") == 0) {
1203 			/* id: CKA_ID */
1204 			attr = pk11_attribute_bytype(obj, CKA_ID);
1205 			if (attr != NULL)
1206 				DST_RET(PK11_R_NOPROVIDER);
1207 			attr = push_attribute(obj, mctx, l);
1208 			if (attr == NULL)
1209 				DST_RET(ISC_R_NOMEMORY);
1210 			attr->type = CKA_ID;
1211 			memmove(attr->pValue, v, l);
1212 		} else if (strcmp(a, "pin-source") == 0) {
1213 			/* pin-source: PIN */
1214 			ret = isc_stdio_open(v, "r", &stream);
1215 			if (ret != ISC_R_SUCCESS)
1216 				goto err;
1217 			memset(pin, 0, PINLEN + 1);
1218 			ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l);
1219 			if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF))
1220 				goto err;
1221 			if (l > PINLEN)
1222 				DST_RET(ISC_R_RANGE);
1223 			ret = isc_stdio_close(stream);
1224 			stream = NULL;
1225 			if (ret != ISC_R_SUCCESS)
1226 				goto err;
1227 			gotpin = ISC_TRUE;
1228 		} else
1229 			DST_RET(PK11_R_NOPROVIDER);
1230 	}
1231 
1232 	if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
1233 	    (pk11_attribute_bytype(obj, CKA_ID) == NULL))
1234 		DST_RET(ISC_R_NOTFOUND);
1235 
1236 	if (token == NULL) {
1237 		if (optype == OP_RSA)
1238 			token = best_rsa_token;
1239 		else if (optype == OP_DSA)
1240 			token = best_dsa_token;
1241 		else if (optype == OP_DH)
1242 			token = best_dh_token;
1243 		else if (optype == OP_EC)
1244 			token = best_ec_token;
1245 	}
1246 	if (token == NULL)
1247 		DST_RET(ISC_R_NOTFOUND);
1248 	obj->slot = token->slotid;
1249 	if (gotpin) {
1250 		memmove(token->pin, pin, PINLEN + 1);
1251 		obj->reqlogon = ISC_TRUE;
1252 	}
1253 
1254 	ret = ISC_R_SUCCESS;
1255 
1256   err:
1257 	if (stream != NULL)
1258 		(void) isc_stdio_close(stream);
1259 	isc_mem_put(mctx, uri, len);
1260 	return (ret);
1261 }
1262 
1263 void
1264 pk11_error_fatalcheck(const char *file, int line,
1265 		      const char *funcname, CK_RV rv)
1266 {
1267 	isc_error_fatal(file, line, "%s: Error = 0x%.8lX\n", funcname, rv);
1268 }
1269 
1270 void
1271 pk11_dump_tokens(void)
1272 {
1273 	pk11_token_t *token;
1274 	isc_boolean_t first;
1275 
1276 	printf("DEFAULTS\n");
1277 	printf("\trand_token=%p\n", rand_token);
1278 	printf("\tbest_rsa_token=%p\n", best_rsa_token);
1279 	printf("\tbest_dsa_token=%p\n", best_dsa_token);
1280 	printf("\tbest_dh_token=%p\n", best_dh_token);
1281 	printf("\tdigest_token=%p\n", digest_token);
1282 	printf("\tbest_ec_token=%p\n", best_ec_token);
1283 	printf("\tbest_gost_token=%p\n", best_gost_token);
1284 	printf("\taes_token=%p\n", aes_token);
1285 
1286 	for (token = ISC_LIST_HEAD(tokens);
1287 	     token != NULL;
1288 	     token = ISC_LIST_NEXT(token, link)) {
1289 		printf("\nTOKEN\n");
1290 		printf("\taddress=%p\n", token);
1291 		printf("\tslotID=%lu\n", token->slotid);
1292 		printf("\tlabel=%.32s\n", token->name);
1293 		printf("\tmanufacturerID=%.32s\n", token->manuf);
1294 		printf("\tmodel=%.16s\n", token->model);
1295 		printf("\tserialNumber=%.16s\n", token->serial);
1296 		printf("\tsupported operations=0x%x (", token->operations);
1297 		first = ISC_TRUE;
1298 		if (token->operations & (1 << OP_RAND)) {
1299 			if (!first)
1300 				printf(",");
1301 			first = ISC_FALSE;
1302 			printf("RAND");
1303 		}
1304 		if (token->operations & (1 << OP_RSA)) {
1305 			if (!first)
1306 				printf(",");
1307 			first = ISC_FALSE;
1308 			printf("RSA");
1309 		}
1310 		if (token->operations & (1 << OP_DSA)) {
1311 			if (!first)
1312 				printf(",");
1313 			first = ISC_FALSE;
1314 			printf("DSA");
1315 		}
1316 		if (token->operations & (1 << OP_DH)) {
1317 			if (!first)
1318 				printf(",");
1319 			first = ISC_FALSE;
1320 			printf("DH");
1321 		}
1322 		if (token->operations & (1 << OP_DIGEST)) {
1323 			if (!first)
1324 				printf(",");
1325 			first = ISC_FALSE;
1326 			printf("DIGEST");
1327 		}
1328 		if (token->operations & (1 << OP_EC)) {
1329 			if (!first)
1330 				printf(",");
1331 			first = ISC_FALSE;
1332 			printf("EC");
1333 		}
1334 		printf(")\n");
1335 	}
1336 }
1337