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