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