xref: /freebsd/crypto/heimdal/lib/hx509/ks_p11.c (revision c19800e8cd5640693f36f2040db4ab5e8d738146)
1c19800e8SDoug Rabson /*
2c19800e8SDoug Rabson  * Copyright (c) 2004 - 2006 Kungliga Tekniska H�gskolan
3c19800e8SDoug Rabson  * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson  * All rights reserved.
5c19800e8SDoug Rabson  *
6c19800e8SDoug Rabson  * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson  * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson  * are met:
9c19800e8SDoug Rabson  *
10c19800e8SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson  *
13c19800e8SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson  *    documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson  *
17c19800e8SDoug Rabson  * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson  *    may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson  *    without specific prior written permission.
20c19800e8SDoug Rabson  *
21c19800e8SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson  * SUCH DAMAGE.
32c19800e8SDoug Rabson  */
33c19800e8SDoug Rabson 
34c19800e8SDoug Rabson #include "hx_locl.h"
35c19800e8SDoug Rabson RCSID("$Id: ks_p11.c 22071 2007-11-14 20:04:50Z lha $");
36c19800e8SDoug Rabson #ifdef HAVE_DLFCN_H
37c19800e8SDoug Rabson #include <dlfcn.h>
38c19800e8SDoug Rabson #endif
39c19800e8SDoug Rabson 
40c19800e8SDoug Rabson #ifdef HAVE_DLOPEN
41c19800e8SDoug Rabson 
42c19800e8SDoug Rabson #include "pkcs11.h"
43c19800e8SDoug Rabson 
44c19800e8SDoug Rabson struct p11_slot {
45c19800e8SDoug Rabson     int flags;
46c19800e8SDoug Rabson #define P11_SESSION		1
47c19800e8SDoug Rabson #define P11_SESSION_IN_USE	2
48c19800e8SDoug Rabson #define P11_LOGIN_REQ		4
49c19800e8SDoug Rabson #define P11_LOGIN_DONE		8
50c19800e8SDoug Rabson #define P11_TOKEN_PRESENT	16
51c19800e8SDoug Rabson     CK_SESSION_HANDLE session;
52c19800e8SDoug Rabson     CK_SLOT_ID id;
53c19800e8SDoug Rabson     CK_BBOOL token;
54c19800e8SDoug Rabson     char *name;
55c19800e8SDoug Rabson     hx509_certs certs;
56c19800e8SDoug Rabson     char *pin;
57c19800e8SDoug Rabson     struct {
58c19800e8SDoug Rabson 	CK_MECHANISM_TYPE_PTR list;
59c19800e8SDoug Rabson 	CK_ULONG num;
60c19800e8SDoug Rabson 	CK_MECHANISM_INFO_PTR *infos;
61c19800e8SDoug Rabson     } mechs;
62c19800e8SDoug Rabson };
63c19800e8SDoug Rabson 
64c19800e8SDoug Rabson struct p11_module {
65c19800e8SDoug Rabson     void *dl_handle;
66c19800e8SDoug Rabson     CK_FUNCTION_LIST_PTR funcs;
67c19800e8SDoug Rabson     CK_ULONG num_slots;
68c19800e8SDoug Rabson     unsigned int refcount;
69c19800e8SDoug Rabson     struct p11_slot *slot;
70c19800e8SDoug Rabson };
71c19800e8SDoug Rabson 
72c19800e8SDoug Rabson #define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args
73c19800e8SDoug Rabson 
74c19800e8SDoug Rabson static int p11_get_session(hx509_context,
75c19800e8SDoug Rabson 			   struct p11_module *,
76c19800e8SDoug Rabson 			   struct p11_slot *,
77c19800e8SDoug Rabson 			   hx509_lock,
78c19800e8SDoug Rabson 			   CK_SESSION_HANDLE *);
79c19800e8SDoug Rabson static int p11_put_session(struct p11_module *,
80c19800e8SDoug Rabson 			   struct p11_slot *,
81c19800e8SDoug Rabson 			   CK_SESSION_HANDLE);
82c19800e8SDoug Rabson static void p11_release_module(struct p11_module *);
83c19800e8SDoug Rabson 
84c19800e8SDoug Rabson static int p11_list_keys(hx509_context,
85c19800e8SDoug Rabson 			 struct p11_module *,
86c19800e8SDoug Rabson 			 struct p11_slot *,
87c19800e8SDoug Rabson 			 CK_SESSION_HANDLE,
88c19800e8SDoug Rabson 			 hx509_lock,
89c19800e8SDoug Rabson 			 hx509_certs *);
90c19800e8SDoug Rabson 
91c19800e8SDoug Rabson /*
92c19800e8SDoug Rabson  *
93c19800e8SDoug Rabson  */
94c19800e8SDoug Rabson 
95c19800e8SDoug Rabson struct p11_rsa {
96c19800e8SDoug Rabson     struct p11_module *p;
97c19800e8SDoug Rabson     struct p11_slot *slot;
98c19800e8SDoug Rabson     CK_OBJECT_HANDLE private_key;
99c19800e8SDoug Rabson     CK_OBJECT_HANDLE public_key;
100c19800e8SDoug Rabson };
101c19800e8SDoug Rabson 
102c19800e8SDoug Rabson static int
103c19800e8SDoug Rabson p11_rsa_public_encrypt(int flen,
104c19800e8SDoug Rabson 		       const unsigned char *from,
105c19800e8SDoug Rabson 		       unsigned char *to,
106c19800e8SDoug Rabson 		       RSA *rsa,
107c19800e8SDoug Rabson 		       int padding)
108c19800e8SDoug Rabson {
109c19800e8SDoug Rabson     return -1;
110c19800e8SDoug Rabson }
111c19800e8SDoug Rabson 
112c19800e8SDoug Rabson static int
113c19800e8SDoug Rabson p11_rsa_public_decrypt(int flen,
114c19800e8SDoug Rabson 		       const unsigned char *from,
115c19800e8SDoug Rabson 		       unsigned char *to,
116c19800e8SDoug Rabson 		       RSA *rsa,
117c19800e8SDoug Rabson 		       int padding)
118c19800e8SDoug Rabson {
119c19800e8SDoug Rabson     return -1;
120c19800e8SDoug Rabson }
121c19800e8SDoug Rabson 
122c19800e8SDoug Rabson 
123c19800e8SDoug Rabson static int
124c19800e8SDoug Rabson p11_rsa_private_encrypt(int flen,
125c19800e8SDoug Rabson 			const unsigned char *from,
126c19800e8SDoug Rabson 			unsigned char *to,
127c19800e8SDoug Rabson 			RSA *rsa,
128c19800e8SDoug Rabson 			int padding)
129c19800e8SDoug Rabson {
130c19800e8SDoug Rabson     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
131c19800e8SDoug Rabson     CK_OBJECT_HANDLE key = p11rsa->private_key;
132c19800e8SDoug Rabson     CK_SESSION_HANDLE session;
133c19800e8SDoug Rabson     CK_MECHANISM mechanism;
134c19800e8SDoug Rabson     CK_ULONG ck_sigsize;
135c19800e8SDoug Rabson     int ret;
136c19800e8SDoug Rabson 
137c19800e8SDoug Rabson     if (padding != RSA_PKCS1_PADDING)
138c19800e8SDoug Rabson 	return -1;
139c19800e8SDoug Rabson 
140c19800e8SDoug Rabson     memset(&mechanism, 0, sizeof(mechanism));
141c19800e8SDoug Rabson     mechanism.mechanism = CKM_RSA_PKCS;
142c19800e8SDoug Rabson 
143c19800e8SDoug Rabson     ck_sigsize = RSA_size(rsa);
144c19800e8SDoug Rabson 
145c19800e8SDoug Rabson     ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);
146c19800e8SDoug Rabson     if (ret)
147c19800e8SDoug Rabson 	return -1;
148c19800e8SDoug Rabson 
149c19800e8SDoug Rabson     ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key));
150c19800e8SDoug Rabson     if (ret != CKR_OK) {
151c19800e8SDoug Rabson 	p11_put_session(p11rsa->p, p11rsa->slot, session);
152c19800e8SDoug Rabson 	return -1;
153c19800e8SDoug Rabson     }
154c19800e8SDoug Rabson 
155c19800e8SDoug Rabson     ret = P11FUNC(p11rsa->p, Sign,
156c19800e8SDoug Rabson 		  (session, (CK_BYTE *)from, flen, to, &ck_sigsize));
157c19800e8SDoug Rabson     p11_put_session(p11rsa->p, p11rsa->slot, session);
158c19800e8SDoug Rabson     if (ret != CKR_OK)
159c19800e8SDoug Rabson 	return -1;
160c19800e8SDoug Rabson 
161c19800e8SDoug Rabson     return ck_sigsize;
162c19800e8SDoug Rabson }
163c19800e8SDoug Rabson 
164c19800e8SDoug Rabson static int
165c19800e8SDoug Rabson p11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
166c19800e8SDoug Rabson 			RSA * rsa, int padding)
167c19800e8SDoug Rabson {
168c19800e8SDoug Rabson     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
169c19800e8SDoug Rabson     CK_OBJECT_HANDLE key = p11rsa->private_key;
170c19800e8SDoug Rabson     CK_SESSION_HANDLE session;
171c19800e8SDoug Rabson     CK_MECHANISM mechanism;
172c19800e8SDoug Rabson     CK_ULONG ck_sigsize;
173c19800e8SDoug Rabson     int ret;
174c19800e8SDoug Rabson 
175c19800e8SDoug Rabson     if (padding != RSA_PKCS1_PADDING)
176c19800e8SDoug Rabson 	return -1;
177c19800e8SDoug Rabson 
178c19800e8SDoug Rabson     memset(&mechanism, 0, sizeof(mechanism));
179c19800e8SDoug Rabson     mechanism.mechanism = CKM_RSA_PKCS;
180c19800e8SDoug Rabson 
181c19800e8SDoug Rabson     ck_sigsize = RSA_size(rsa);
182c19800e8SDoug Rabson 
183c19800e8SDoug Rabson     ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session);
184c19800e8SDoug Rabson     if (ret)
185c19800e8SDoug Rabson 	return -1;
186c19800e8SDoug Rabson 
187c19800e8SDoug Rabson     ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key));
188c19800e8SDoug Rabson     if (ret != CKR_OK) {
189c19800e8SDoug Rabson 	p11_put_session(p11rsa->p, p11rsa->slot, session);
190c19800e8SDoug Rabson 	return -1;
191c19800e8SDoug Rabson     }
192c19800e8SDoug Rabson 
193c19800e8SDoug Rabson     ret = P11FUNC(p11rsa->p, Decrypt,
194c19800e8SDoug Rabson 		  (session, (CK_BYTE *)from, flen, to, &ck_sigsize));
195c19800e8SDoug Rabson     p11_put_session(p11rsa->p, p11rsa->slot, session);
196c19800e8SDoug Rabson     if (ret != CKR_OK)
197c19800e8SDoug Rabson 	return -1;
198c19800e8SDoug Rabson 
199c19800e8SDoug Rabson     return ck_sigsize;
200c19800e8SDoug Rabson }
201c19800e8SDoug Rabson 
202c19800e8SDoug Rabson static int
203c19800e8SDoug Rabson p11_rsa_init(RSA *rsa)
204c19800e8SDoug Rabson {
205c19800e8SDoug Rabson     return 1;
206c19800e8SDoug Rabson }
207c19800e8SDoug Rabson 
208c19800e8SDoug Rabson static int
209c19800e8SDoug Rabson p11_rsa_finish(RSA *rsa)
210c19800e8SDoug Rabson {
211c19800e8SDoug Rabson     struct p11_rsa *p11rsa = RSA_get_app_data(rsa);
212c19800e8SDoug Rabson     p11_release_module(p11rsa->p);
213c19800e8SDoug Rabson     free(p11rsa);
214c19800e8SDoug Rabson     return 1;
215c19800e8SDoug Rabson }
216c19800e8SDoug Rabson 
217c19800e8SDoug Rabson static const RSA_METHOD p11_rsa_pkcs1_method = {
218c19800e8SDoug Rabson     "hx509 PKCS11 PKCS#1 RSA",
219c19800e8SDoug Rabson     p11_rsa_public_encrypt,
220c19800e8SDoug Rabson     p11_rsa_public_decrypt,
221c19800e8SDoug Rabson     p11_rsa_private_encrypt,
222c19800e8SDoug Rabson     p11_rsa_private_decrypt,
223c19800e8SDoug Rabson     NULL,
224c19800e8SDoug Rabson     NULL,
225c19800e8SDoug Rabson     p11_rsa_init,
226c19800e8SDoug Rabson     p11_rsa_finish,
227c19800e8SDoug Rabson     0,
228c19800e8SDoug Rabson     NULL,
229c19800e8SDoug Rabson     NULL,
230c19800e8SDoug Rabson     NULL
231c19800e8SDoug Rabson };
232c19800e8SDoug Rabson 
233c19800e8SDoug Rabson /*
234c19800e8SDoug Rabson  *
235c19800e8SDoug Rabson  */
236c19800e8SDoug Rabson 
237c19800e8SDoug Rabson static int
238c19800e8SDoug Rabson p11_mech_info(hx509_context context,
239c19800e8SDoug Rabson 	      struct p11_module *p,
240c19800e8SDoug Rabson 	      struct p11_slot *slot,
241c19800e8SDoug Rabson 	      int num)
242c19800e8SDoug Rabson {
243c19800e8SDoug Rabson     CK_ULONG i;
244c19800e8SDoug Rabson     int ret;
245c19800e8SDoug Rabson 
246c19800e8SDoug Rabson     ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i));
247c19800e8SDoug Rabson     if (ret) {
248c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
249c19800e8SDoug Rabson 			       "Failed to get mech list count for slot %d",
250c19800e8SDoug Rabson 			       num);
251c19800e8SDoug Rabson 	return HX509_PKCS11_NO_MECH;
252c19800e8SDoug Rabson     }
253c19800e8SDoug Rabson     if (i == 0) {
254c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
255c19800e8SDoug Rabson 			       "no mech supported for slot %d", num);
256c19800e8SDoug Rabson 	return HX509_PKCS11_NO_MECH;
257c19800e8SDoug Rabson     }
258c19800e8SDoug Rabson     slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0]));
259c19800e8SDoug Rabson     if (slot->mechs.list == NULL) {
260c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM,
261c19800e8SDoug Rabson 			       "out of memory");
262c19800e8SDoug Rabson 	return ENOMEM;
263c19800e8SDoug Rabson     }
264c19800e8SDoug Rabson     slot->mechs.num = i;
265c19800e8SDoug Rabson     ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i));
266c19800e8SDoug Rabson     if (ret) {
267c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
268c19800e8SDoug Rabson 			       "Failed to get mech list for slot %d",
269c19800e8SDoug Rabson 			       num);
270c19800e8SDoug Rabson 	return HX509_PKCS11_NO_MECH;
271c19800e8SDoug Rabson     }
272c19800e8SDoug Rabson     assert(i == slot->mechs.num);
273c19800e8SDoug Rabson 
274c19800e8SDoug Rabson     slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos));
275c19800e8SDoug Rabson     if (slot->mechs.list == NULL) {
276c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM,
277c19800e8SDoug Rabson 			       "out of memory");
278c19800e8SDoug Rabson 	return ENOMEM;
279c19800e8SDoug Rabson     }
280c19800e8SDoug Rabson 
281c19800e8SDoug Rabson     for (i = 0; i < slot->mechs.num; i++) {
282c19800e8SDoug Rabson 	slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0])));
283c19800e8SDoug Rabson 	if (slot->mechs.infos[i] == NULL) {
284c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ENOMEM,
285c19800e8SDoug Rabson 				   "out of memory");
286c19800e8SDoug Rabson 	    return ENOMEM;
287c19800e8SDoug Rabson 	}
288c19800e8SDoug Rabson 	ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i],
289c19800e8SDoug Rabson 					    slot->mechs.infos[i]));
290c19800e8SDoug Rabson 	if (ret) {
291c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH,
292c19800e8SDoug Rabson 				   "Failed to get mech info for slot %d",
293c19800e8SDoug Rabson 				   num);
294c19800e8SDoug Rabson 	    return HX509_PKCS11_NO_MECH;
295c19800e8SDoug Rabson 	}
296c19800e8SDoug Rabson     }
297c19800e8SDoug Rabson 
298c19800e8SDoug Rabson     return 0;
299c19800e8SDoug Rabson }
300c19800e8SDoug Rabson 
301c19800e8SDoug Rabson static int
302c19800e8SDoug Rabson p11_init_slot(hx509_context context,
303c19800e8SDoug Rabson 	      struct p11_module *p,
304c19800e8SDoug Rabson 	      hx509_lock lock,
305c19800e8SDoug Rabson 	      CK_SLOT_ID id,
306c19800e8SDoug Rabson 	      int num,
307c19800e8SDoug Rabson 	      struct p11_slot *slot)
308c19800e8SDoug Rabson {
309c19800e8SDoug Rabson     CK_SESSION_HANDLE session;
310c19800e8SDoug Rabson     CK_SLOT_INFO slot_info;
311c19800e8SDoug Rabson     CK_TOKEN_INFO token_info;
312c19800e8SDoug Rabson     int ret, i;
313c19800e8SDoug Rabson 
314c19800e8SDoug Rabson     slot->certs = NULL;
315c19800e8SDoug Rabson     slot->id = id;
316c19800e8SDoug Rabson 
317c19800e8SDoug Rabson     ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info));
318c19800e8SDoug Rabson     if (ret) {
319c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED,
320c19800e8SDoug Rabson 			       "Failed to init PKCS11 slot %d",
321c19800e8SDoug Rabson 			       num);
322c19800e8SDoug Rabson 	return HX509_PKCS11_TOKEN_CONFUSED;
323c19800e8SDoug Rabson     }
324c19800e8SDoug Rabson 
325c19800e8SDoug Rabson     for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) {
326c19800e8SDoug Rabson 	char c = slot_info.slotDescription[i];
327c19800e8SDoug Rabson 	if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0')
328c19800e8SDoug Rabson 	    continue;
329c19800e8SDoug Rabson 	i++;
330c19800e8SDoug Rabson 	break;
331c19800e8SDoug Rabson     }
332c19800e8SDoug Rabson 
333c19800e8SDoug Rabson     asprintf(&slot->name, "%.*s",
334c19800e8SDoug Rabson 	     i, slot_info.slotDescription);
335c19800e8SDoug Rabson 
336c19800e8SDoug Rabson     if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)
337c19800e8SDoug Rabson 	return 0;
338c19800e8SDoug Rabson 
339c19800e8SDoug Rabson     ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info));
340c19800e8SDoug Rabson     if (ret) {
341c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN,
342c19800e8SDoug Rabson 			       "Failed to init PKCS11 slot %d "
343c19800e8SDoug Rabson 			       "with error 0x08x",
344c19800e8SDoug Rabson 			       num, ret);
345c19800e8SDoug Rabson 	return HX509_PKCS11_NO_TOKEN;
346c19800e8SDoug Rabson     }
347c19800e8SDoug Rabson     slot->flags |= P11_TOKEN_PRESENT;
348c19800e8SDoug Rabson 
349c19800e8SDoug Rabson     if (token_info.flags & CKF_LOGIN_REQUIRED)
350c19800e8SDoug Rabson 	slot->flags |= P11_LOGIN_REQ;
351c19800e8SDoug Rabson 
352c19800e8SDoug Rabson     ret = p11_get_session(context, p, slot, lock, &session);
353c19800e8SDoug Rabson     if (ret)
354c19800e8SDoug Rabson 	return ret;
355c19800e8SDoug Rabson 
356c19800e8SDoug Rabson     ret = p11_mech_info(context, p, slot, num);
357c19800e8SDoug Rabson     if (ret)
358c19800e8SDoug Rabson 	goto out;
359c19800e8SDoug Rabson 
360c19800e8SDoug Rabson     ret = p11_list_keys(context, p, slot, session, lock, &slot->certs);
361c19800e8SDoug Rabson  out:
362c19800e8SDoug Rabson     p11_put_session(p, slot, session);
363c19800e8SDoug Rabson 
364c19800e8SDoug Rabson     return ret;
365c19800e8SDoug Rabson }
366c19800e8SDoug Rabson 
367c19800e8SDoug Rabson static int
368c19800e8SDoug Rabson p11_get_session(hx509_context context,
369c19800e8SDoug Rabson 		struct p11_module *p,
370c19800e8SDoug Rabson 		struct p11_slot *slot,
371c19800e8SDoug Rabson 		hx509_lock lock,
372c19800e8SDoug Rabson 		CK_SESSION_HANDLE *psession)
373c19800e8SDoug Rabson {
374c19800e8SDoug Rabson     CK_RV ret;
375c19800e8SDoug Rabson 
376c19800e8SDoug Rabson     if (slot->flags & P11_SESSION_IN_USE)
377c19800e8SDoug Rabson 	_hx509_abort("slot already in session");
378c19800e8SDoug Rabson 
379c19800e8SDoug Rabson     if (slot->flags & P11_SESSION) {
380c19800e8SDoug Rabson 	slot->flags |= P11_SESSION_IN_USE;
381c19800e8SDoug Rabson 	*psession = slot->session;
382c19800e8SDoug Rabson 	return 0;
383c19800e8SDoug Rabson     }
384c19800e8SDoug Rabson 
385c19800e8SDoug Rabson     ret = P11FUNC(p, OpenSession, (slot->id,
386c19800e8SDoug Rabson 				   CKF_SERIAL_SESSION,
387c19800e8SDoug Rabson 				   NULL,
388c19800e8SDoug Rabson 				   NULL,
389c19800e8SDoug Rabson 				   &slot->session));
390c19800e8SDoug Rabson     if (ret != CKR_OK) {
391c19800e8SDoug Rabson 	if (context)
392c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION,
393c19800e8SDoug Rabson 				   "Failed to OpenSession for slot id %d "
394c19800e8SDoug Rabson 				   "with error: 0x%08x",
395c19800e8SDoug Rabson 				   (int)slot->id, ret);
396c19800e8SDoug Rabson 	return HX509_PKCS11_OPEN_SESSION;
397c19800e8SDoug Rabson     }
398c19800e8SDoug Rabson 
399c19800e8SDoug Rabson     slot->flags |= P11_SESSION;
400c19800e8SDoug Rabson 
401c19800e8SDoug Rabson     /*
402c19800e8SDoug Rabson      * If we have have to login, and haven't tried before and have a
403c19800e8SDoug Rabson      * prompter or known to work pin code.
404c19800e8SDoug Rabson      *
405c19800e8SDoug Rabson      * This code is very conversative and only uses the prompter in
406c19800e8SDoug Rabson      * the hx509_lock, the reason is that it's bad to try many
407c19800e8SDoug Rabson      * passwords on a pkcs11 token, it might lock up and have to be
408c19800e8SDoug Rabson      * unlocked by a administrator.
409c19800e8SDoug Rabson      *
410c19800e8SDoug Rabson      * XXX try harder to not use pin several times on the same card.
411c19800e8SDoug Rabson      */
412c19800e8SDoug Rabson 
413c19800e8SDoug Rabson     if (   (slot->flags & P11_LOGIN_REQ)
414c19800e8SDoug Rabson 	&& (slot->flags & P11_LOGIN_DONE) == 0
415c19800e8SDoug Rabson 	&& (lock || slot->pin))
416c19800e8SDoug Rabson     {
417c19800e8SDoug Rabson 	hx509_prompt prompt;
418c19800e8SDoug Rabson 	char pin[20];
419c19800e8SDoug Rabson 	char *str;
420c19800e8SDoug Rabson 
421c19800e8SDoug Rabson 	slot->flags |= P11_LOGIN_DONE;
422c19800e8SDoug Rabson 
423c19800e8SDoug Rabson 	if (slot->pin == NULL) {
424c19800e8SDoug Rabson 
425c19800e8SDoug Rabson 	    memset(&prompt, 0, sizeof(prompt));
426c19800e8SDoug Rabson 
427c19800e8SDoug Rabson 	    asprintf(&str, "PIN code for %s: ", slot->name);
428c19800e8SDoug Rabson 	    prompt.prompt = str;
429c19800e8SDoug Rabson 	    prompt.type = HX509_PROMPT_TYPE_PASSWORD;
430c19800e8SDoug Rabson 	    prompt.reply.data = pin;
431c19800e8SDoug Rabson 	    prompt.reply.length = sizeof(pin);
432c19800e8SDoug Rabson 
433c19800e8SDoug Rabson 	    ret = hx509_lock_prompt(lock, &prompt);
434c19800e8SDoug Rabson 	    if (ret) {
435c19800e8SDoug Rabson 		free(str);
436c19800e8SDoug Rabson 		if (context)
437c19800e8SDoug Rabson 		    hx509_set_error_string(context, 0, ret,
438c19800e8SDoug Rabson 					   "Failed to get pin code for slot "
439c19800e8SDoug Rabson 					   "id %d with error: %d",
440c19800e8SDoug Rabson 					   (int)slot->id, ret);
441c19800e8SDoug Rabson 		return ret;
442c19800e8SDoug Rabson 	    }
443c19800e8SDoug Rabson 	    free(str);
444c19800e8SDoug Rabson 	} else {
445c19800e8SDoug Rabson 	    strlcpy(pin, slot->pin, sizeof(pin));
446c19800e8SDoug Rabson 	}
447c19800e8SDoug Rabson 
448c19800e8SDoug Rabson 	ret = P11FUNC(p, Login, (slot->session, CKU_USER,
449c19800e8SDoug Rabson 				 (unsigned char*)pin, strlen(pin)));
450c19800e8SDoug Rabson 	if (ret != CKR_OK) {
451c19800e8SDoug Rabson 	    if (context)
452c19800e8SDoug Rabson 		hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN,
453c19800e8SDoug Rabson 				       "Failed to login on slot id %d "
454c19800e8SDoug Rabson 				       "with error: 0x%08x",
455c19800e8SDoug Rabson 				       (int)slot->id, ret);
456c19800e8SDoug Rabson 	    p11_put_session(p, slot, slot->session);
457c19800e8SDoug Rabson 	    return HX509_PKCS11_LOGIN;
458c19800e8SDoug Rabson 	}
459c19800e8SDoug Rabson 	if (slot->pin == NULL) {
460c19800e8SDoug Rabson 	    slot->pin = strdup(pin);
461c19800e8SDoug Rabson 	    if (slot->pin == NULL) {
462c19800e8SDoug Rabson 		if (context)
463c19800e8SDoug Rabson 		    hx509_set_error_string(context, 0, ENOMEM,
464c19800e8SDoug Rabson 					   "out of memory");
465c19800e8SDoug Rabson 		p11_put_session(p, slot, slot->session);
466c19800e8SDoug Rabson 		return ENOMEM;
467c19800e8SDoug Rabson 	    }
468c19800e8SDoug Rabson 	}
469c19800e8SDoug Rabson     } else
470c19800e8SDoug Rabson 	slot->flags |= P11_LOGIN_DONE;
471c19800e8SDoug Rabson 
472c19800e8SDoug Rabson     slot->flags |= P11_SESSION_IN_USE;
473c19800e8SDoug Rabson 
474c19800e8SDoug Rabson     *psession = slot->session;
475c19800e8SDoug Rabson 
476c19800e8SDoug Rabson     return 0;
477c19800e8SDoug Rabson }
478c19800e8SDoug Rabson 
479c19800e8SDoug Rabson static int
480c19800e8SDoug Rabson p11_put_session(struct p11_module *p,
481c19800e8SDoug Rabson 		struct p11_slot *slot,
482c19800e8SDoug Rabson 		CK_SESSION_HANDLE session)
483c19800e8SDoug Rabson {
484c19800e8SDoug Rabson     if ((slot->flags & P11_SESSION_IN_USE) == 0)
485c19800e8SDoug Rabson 	_hx509_abort("slot not in session");
486c19800e8SDoug Rabson     slot->flags &= ~P11_SESSION_IN_USE;
487c19800e8SDoug Rabson 
488c19800e8SDoug Rabson     return 0;
489c19800e8SDoug Rabson }
490c19800e8SDoug Rabson 
491c19800e8SDoug Rabson static int
492c19800e8SDoug Rabson iterate_entries(hx509_context context,
493c19800e8SDoug Rabson 		struct p11_module *p, struct p11_slot *slot,
494c19800e8SDoug Rabson 		CK_SESSION_HANDLE session,
495c19800e8SDoug Rabson 		CK_ATTRIBUTE *search_data, int num_search_data,
496c19800e8SDoug Rabson 		CK_ATTRIBUTE *query, int num_query,
497c19800e8SDoug Rabson 		int (*func)(hx509_context,
498c19800e8SDoug Rabson 			    struct p11_module *, struct p11_slot *,
499c19800e8SDoug Rabson 			    CK_SESSION_HANDLE session,
500c19800e8SDoug Rabson 			    CK_OBJECT_HANDLE object,
501c19800e8SDoug Rabson 			    void *, CK_ATTRIBUTE *, int), void *ptr)
502c19800e8SDoug Rabson {
503c19800e8SDoug Rabson     CK_OBJECT_HANDLE object;
504c19800e8SDoug Rabson     CK_ULONG object_count;
505c19800e8SDoug Rabson     int ret, i;
506c19800e8SDoug Rabson 
507c19800e8SDoug Rabson     ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data));
508c19800e8SDoug Rabson     if (ret != CKR_OK) {
509c19800e8SDoug Rabson 	return -1;
510c19800e8SDoug Rabson     }
511c19800e8SDoug Rabson     while (1) {
512c19800e8SDoug Rabson 	ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count));
513c19800e8SDoug Rabson 	if (ret != CKR_OK) {
514c19800e8SDoug Rabson 	    return -1;
515c19800e8SDoug Rabson 	}
516c19800e8SDoug Rabson 	if (object_count == 0)
517c19800e8SDoug Rabson 	    break;
518c19800e8SDoug Rabson 
519c19800e8SDoug Rabson 	for (i = 0; i < num_query; i++)
520c19800e8SDoug Rabson 	    query[i].pValue = NULL;
521c19800e8SDoug Rabson 
522c19800e8SDoug Rabson 	ret = P11FUNC(p, GetAttributeValue,
523c19800e8SDoug Rabson 		      (session, object, query, num_query));
524c19800e8SDoug Rabson 	if (ret != CKR_OK) {
525c19800e8SDoug Rabson 	    return -1;
526c19800e8SDoug Rabson 	}
527c19800e8SDoug Rabson 	for (i = 0; i < num_query; i++) {
528c19800e8SDoug Rabson 	    query[i].pValue = malloc(query[i].ulValueLen);
529c19800e8SDoug Rabson 	    if (query[i].pValue == NULL) {
530c19800e8SDoug Rabson 		ret = ENOMEM;
531c19800e8SDoug Rabson 		goto out;
532c19800e8SDoug Rabson 	    }
533c19800e8SDoug Rabson 	}
534c19800e8SDoug Rabson 	ret = P11FUNC(p, GetAttributeValue,
535c19800e8SDoug Rabson 		      (session, object, query, num_query));
536c19800e8SDoug Rabson 	if (ret != CKR_OK) {
537c19800e8SDoug Rabson 	    ret = -1;
538c19800e8SDoug Rabson 	    goto out;
539c19800e8SDoug Rabson 	}
540c19800e8SDoug Rabson 
541c19800e8SDoug Rabson 	ret = (*func)(context, p, slot, session, object, ptr, query, num_query);
542c19800e8SDoug Rabson 	if (ret)
543c19800e8SDoug Rabson 	    goto out;
544c19800e8SDoug Rabson 
545c19800e8SDoug Rabson 	for (i = 0; i < num_query; i++) {
546c19800e8SDoug Rabson 	    if (query[i].pValue)
547c19800e8SDoug Rabson 		free(query[i].pValue);
548c19800e8SDoug Rabson 	    query[i].pValue = NULL;
549c19800e8SDoug Rabson 	}
550c19800e8SDoug Rabson     }
551c19800e8SDoug Rabson  out:
552c19800e8SDoug Rabson 
553c19800e8SDoug Rabson     for (i = 0; i < num_query; i++) {
554c19800e8SDoug Rabson 	if (query[i].pValue)
555c19800e8SDoug Rabson 	    free(query[i].pValue);
556c19800e8SDoug Rabson 	query[i].pValue = NULL;
557c19800e8SDoug Rabson     }
558c19800e8SDoug Rabson 
559c19800e8SDoug Rabson     ret = P11FUNC(p, FindObjectsFinal, (session));
560c19800e8SDoug Rabson     if (ret != CKR_OK) {
561c19800e8SDoug Rabson 	return -2;
562c19800e8SDoug Rabson     }
563c19800e8SDoug Rabson 
564c19800e8SDoug Rabson 
565c19800e8SDoug Rabson     return 0;
566c19800e8SDoug Rabson }
567c19800e8SDoug Rabson 
568c19800e8SDoug Rabson static BIGNUM *
569c19800e8SDoug Rabson getattr_bn(struct p11_module *p,
570c19800e8SDoug Rabson 	   struct p11_slot *slot,
571c19800e8SDoug Rabson 	   CK_SESSION_HANDLE session,
572c19800e8SDoug Rabson 	   CK_OBJECT_HANDLE object,
573c19800e8SDoug Rabson 	   unsigned int type)
574c19800e8SDoug Rabson {
575c19800e8SDoug Rabson     CK_ATTRIBUTE query;
576c19800e8SDoug Rabson     BIGNUM *bn;
577c19800e8SDoug Rabson     int ret;
578c19800e8SDoug Rabson 
579c19800e8SDoug Rabson     query.type = type;
580c19800e8SDoug Rabson     query.pValue = NULL;
581c19800e8SDoug Rabson     query.ulValueLen = 0;
582c19800e8SDoug Rabson 
583c19800e8SDoug Rabson     ret = P11FUNC(p, GetAttributeValue,
584c19800e8SDoug Rabson 		  (session, object, &query, 1));
585c19800e8SDoug Rabson     if (ret != CKR_OK)
586c19800e8SDoug Rabson 	return NULL;
587c19800e8SDoug Rabson 
588c19800e8SDoug Rabson     query.pValue = malloc(query.ulValueLen);
589c19800e8SDoug Rabson 
590c19800e8SDoug Rabson     ret = P11FUNC(p, GetAttributeValue,
591c19800e8SDoug Rabson 		  (session, object, &query, 1));
592c19800e8SDoug Rabson     if (ret != CKR_OK) {
593c19800e8SDoug Rabson 	free(query.pValue);
594c19800e8SDoug Rabson 	return NULL;
595c19800e8SDoug Rabson     }
596c19800e8SDoug Rabson     bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL);
597c19800e8SDoug Rabson     free(query.pValue);
598c19800e8SDoug Rabson 
599c19800e8SDoug Rabson     return bn;
600c19800e8SDoug Rabson }
601c19800e8SDoug Rabson 
602c19800e8SDoug Rabson static int
603c19800e8SDoug Rabson collect_private_key(hx509_context context,
604c19800e8SDoug Rabson 		    struct p11_module *p, struct p11_slot *slot,
605c19800e8SDoug Rabson 		    CK_SESSION_HANDLE session,
606c19800e8SDoug Rabson 		    CK_OBJECT_HANDLE object,
607c19800e8SDoug Rabson 		    void *ptr, CK_ATTRIBUTE *query, int num_query)
608c19800e8SDoug Rabson {
609c19800e8SDoug Rabson     struct hx509_collector *collector = ptr;
610c19800e8SDoug Rabson     hx509_private_key key;
611c19800e8SDoug Rabson     heim_octet_string localKeyId;
612c19800e8SDoug Rabson     int ret;
613c19800e8SDoug Rabson     RSA *rsa;
614c19800e8SDoug Rabson     struct p11_rsa *p11rsa;
615c19800e8SDoug Rabson 
616c19800e8SDoug Rabson     localKeyId.data = query[0].pValue;
617c19800e8SDoug Rabson     localKeyId.length = query[0].ulValueLen;
618c19800e8SDoug Rabson 
619c19800e8SDoug Rabson     ret = _hx509_private_key_init(&key, NULL, NULL);
620c19800e8SDoug Rabson     if (ret)
621c19800e8SDoug Rabson 	return ret;
622c19800e8SDoug Rabson 
623c19800e8SDoug Rabson     rsa = RSA_new();
624c19800e8SDoug Rabson     if (rsa == NULL)
625c19800e8SDoug Rabson 	_hx509_abort("out of memory");
626c19800e8SDoug Rabson 
627c19800e8SDoug Rabson     /*
628c19800e8SDoug Rabson      * The exponent and modulus should always be present according to
629c19800e8SDoug Rabson      * the pkcs11 specification, but some smartcards leaves it out,
630c19800e8SDoug Rabson      * let ignore any failure to fetch it.
631c19800e8SDoug Rabson      */
632c19800e8SDoug Rabson     rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS);
633c19800e8SDoug Rabson     rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT);
634c19800e8SDoug Rabson 
635c19800e8SDoug Rabson     p11rsa = calloc(1, sizeof(*p11rsa));
636c19800e8SDoug Rabson     if (p11rsa == NULL)
637c19800e8SDoug Rabson 	_hx509_abort("out of memory");
638c19800e8SDoug Rabson 
639c19800e8SDoug Rabson     p11rsa->p = p;
640c19800e8SDoug Rabson     p11rsa->slot = slot;
641c19800e8SDoug Rabson     p11rsa->private_key = object;
642c19800e8SDoug Rabson 
643c19800e8SDoug Rabson     p->refcount++;
644c19800e8SDoug Rabson     if (p->refcount == 0)
645c19800e8SDoug Rabson 	_hx509_abort("pkcs11 refcount to high");
646c19800e8SDoug Rabson 
647c19800e8SDoug Rabson     RSA_set_method(rsa, &p11_rsa_pkcs1_method);
648c19800e8SDoug Rabson     ret = RSA_set_app_data(rsa, p11rsa);
649c19800e8SDoug Rabson     if (ret != 1)
650c19800e8SDoug Rabson 	_hx509_abort("RSA_set_app_data");
651c19800e8SDoug Rabson 
652c19800e8SDoug Rabson     _hx509_private_key_assign_rsa(key, rsa);
653c19800e8SDoug Rabson 
654c19800e8SDoug Rabson     ret = _hx509_collector_private_key_add(context,
655c19800e8SDoug Rabson 					   collector,
656c19800e8SDoug Rabson 					   hx509_signature_rsa(),
657c19800e8SDoug Rabson 					   key,
658c19800e8SDoug Rabson 					   NULL,
659c19800e8SDoug Rabson 					   &localKeyId);
660c19800e8SDoug Rabson 
661c19800e8SDoug Rabson     if (ret) {
662c19800e8SDoug Rabson 	_hx509_private_key_free(&key);
663c19800e8SDoug Rabson 	return ret;
664c19800e8SDoug Rabson     }
665c19800e8SDoug Rabson     return 0;
666c19800e8SDoug Rabson }
667c19800e8SDoug Rabson 
668c19800e8SDoug Rabson static void
669c19800e8SDoug Rabson p11_cert_release(hx509_cert cert, void *ctx)
670c19800e8SDoug Rabson {
671c19800e8SDoug Rabson     struct p11_module *p = ctx;
672c19800e8SDoug Rabson     p11_release_module(p);
673c19800e8SDoug Rabson }
674c19800e8SDoug Rabson 
675c19800e8SDoug Rabson 
676c19800e8SDoug Rabson static int
677c19800e8SDoug Rabson collect_cert(hx509_context context,
678c19800e8SDoug Rabson 	     struct p11_module *p, struct p11_slot *slot,
679c19800e8SDoug Rabson 	     CK_SESSION_HANDLE session,
680c19800e8SDoug Rabson 	     CK_OBJECT_HANDLE object,
681c19800e8SDoug Rabson 	     void *ptr, CK_ATTRIBUTE *query, int num_query)
682c19800e8SDoug Rabson {
683c19800e8SDoug Rabson     struct hx509_collector *collector = ptr;
684c19800e8SDoug Rabson     hx509_cert cert;
685c19800e8SDoug Rabson     int ret;
686c19800e8SDoug Rabson 
687c19800e8SDoug Rabson     if ((CK_LONG)query[0].ulValueLen == -1 ||
688c19800e8SDoug Rabson 	(CK_LONG)query[1].ulValueLen == -1)
689c19800e8SDoug Rabson     {
690c19800e8SDoug Rabson 	return 0;
691c19800e8SDoug Rabson     }
692c19800e8SDoug Rabson 
693c19800e8SDoug Rabson     ret = hx509_cert_init_data(context, query[1].pValue,
694c19800e8SDoug Rabson 			       query[1].ulValueLen, &cert);
695c19800e8SDoug Rabson     if (ret)
696c19800e8SDoug Rabson 	return ret;
697c19800e8SDoug Rabson 
698c19800e8SDoug Rabson     p->refcount++;
699c19800e8SDoug Rabson     if (p->refcount == 0)
700c19800e8SDoug Rabson 	_hx509_abort("pkcs11 refcount to high");
701c19800e8SDoug Rabson 
702c19800e8SDoug Rabson     _hx509_cert_set_release(cert, p11_cert_release, p);
703c19800e8SDoug Rabson 
704c19800e8SDoug Rabson     {
705c19800e8SDoug Rabson 	heim_octet_string data;
706c19800e8SDoug Rabson 
707c19800e8SDoug Rabson 	data.data = query[0].pValue;
708c19800e8SDoug Rabson 	data.length = query[0].ulValueLen;
709c19800e8SDoug Rabson 
710c19800e8SDoug Rabson 	_hx509_set_cert_attribute(context,
711c19800e8SDoug Rabson 				  cert,
712c19800e8SDoug Rabson 				  oid_id_pkcs_9_at_localKeyId(),
713c19800e8SDoug Rabson 				  &data);
714c19800e8SDoug Rabson     }
715c19800e8SDoug Rabson 
716c19800e8SDoug Rabson     if ((CK_LONG)query[2].ulValueLen != -1) {
717c19800e8SDoug Rabson 	char *str;
718c19800e8SDoug Rabson 
719c19800e8SDoug Rabson 	asprintf(&str, "%.*s",
720c19800e8SDoug Rabson 		 (int)query[2].ulValueLen, (char *)query[2].pValue);
721c19800e8SDoug Rabson 	if (str) {
722c19800e8SDoug Rabson 	    hx509_cert_set_friendly_name(cert, str);
723c19800e8SDoug Rabson 	    free(str);
724c19800e8SDoug Rabson 	}
725c19800e8SDoug Rabson     }
726c19800e8SDoug Rabson 
727c19800e8SDoug Rabson     ret = _hx509_collector_certs_add(context, collector, cert);
728c19800e8SDoug Rabson     hx509_cert_free(cert);
729c19800e8SDoug Rabson 
730c19800e8SDoug Rabson     return ret;
731c19800e8SDoug Rabson }
732c19800e8SDoug Rabson 
733c19800e8SDoug Rabson 
734c19800e8SDoug Rabson static int
735c19800e8SDoug Rabson p11_list_keys(hx509_context context,
736c19800e8SDoug Rabson 	      struct p11_module *p,
737c19800e8SDoug Rabson 	      struct p11_slot *slot,
738c19800e8SDoug Rabson 	      CK_SESSION_HANDLE session,
739c19800e8SDoug Rabson 	      hx509_lock lock,
740c19800e8SDoug Rabson 	      hx509_certs *certs)
741c19800e8SDoug Rabson {
742c19800e8SDoug Rabson     struct hx509_collector *collector;
743c19800e8SDoug Rabson     CK_OBJECT_CLASS key_class;
744c19800e8SDoug Rabson     CK_ATTRIBUTE search_data[] = {
745c19800e8SDoug Rabson 	{CKA_CLASS, NULL, 0},
746c19800e8SDoug Rabson     };
747c19800e8SDoug Rabson     CK_ATTRIBUTE query_data[3] = {
748c19800e8SDoug Rabson 	{CKA_ID, NULL, 0},
749c19800e8SDoug Rabson 	{CKA_VALUE, NULL, 0},
750c19800e8SDoug Rabson 	{CKA_LABEL, NULL, 0}
751c19800e8SDoug Rabson     };
752c19800e8SDoug Rabson     int ret;
753c19800e8SDoug Rabson 
754c19800e8SDoug Rabson     search_data[0].pValue = &key_class;
755c19800e8SDoug Rabson     search_data[0].ulValueLen = sizeof(key_class);
756c19800e8SDoug Rabson 
757c19800e8SDoug Rabson     if (lock == NULL)
758c19800e8SDoug Rabson 	lock = _hx509_empty_lock;
759c19800e8SDoug Rabson 
760c19800e8SDoug Rabson     ret = _hx509_collector_alloc(context, lock, &collector);
761c19800e8SDoug Rabson     if (ret)
762c19800e8SDoug Rabson 	return ret;
763c19800e8SDoug Rabson 
764c19800e8SDoug Rabson     key_class = CKO_PRIVATE_KEY;
765c19800e8SDoug Rabson     ret = iterate_entries(context, p, slot, session,
766c19800e8SDoug Rabson 			  search_data, 1,
767c19800e8SDoug Rabson 			  query_data, 1,
768c19800e8SDoug Rabson 			  collect_private_key, collector);
769c19800e8SDoug Rabson     if (ret)
770c19800e8SDoug Rabson 	goto out;
771c19800e8SDoug Rabson 
772c19800e8SDoug Rabson     key_class = CKO_CERTIFICATE;
773c19800e8SDoug Rabson     ret = iterate_entries(context, p, slot, session,
774c19800e8SDoug Rabson 			  search_data, 1,
775c19800e8SDoug Rabson 			  query_data, 3,
776c19800e8SDoug Rabson 			  collect_cert, collector);
777c19800e8SDoug Rabson     if (ret)
778c19800e8SDoug Rabson 	goto out;
779c19800e8SDoug Rabson 
780c19800e8SDoug Rabson     ret = _hx509_collector_collect_certs(context, collector, &slot->certs);
781c19800e8SDoug Rabson 
782c19800e8SDoug Rabson out:
783c19800e8SDoug Rabson     _hx509_collector_free(collector);
784c19800e8SDoug Rabson 
785c19800e8SDoug Rabson     return ret;
786c19800e8SDoug Rabson }
787c19800e8SDoug Rabson 
788c19800e8SDoug Rabson 
789c19800e8SDoug Rabson static int
790c19800e8SDoug Rabson p11_init(hx509_context context,
791c19800e8SDoug Rabson 	 hx509_certs certs, void **data, int flags,
792c19800e8SDoug Rabson 	 const char *residue, hx509_lock lock)
793c19800e8SDoug Rabson {
794c19800e8SDoug Rabson     CK_C_GetFunctionList getFuncs;
795c19800e8SDoug Rabson     struct p11_module *p;
796c19800e8SDoug Rabson     char *list, *str;
797c19800e8SDoug Rabson     int ret;
798c19800e8SDoug Rabson 
799c19800e8SDoug Rabson     *data = NULL;
800c19800e8SDoug Rabson 
801c19800e8SDoug Rabson     list = strdup(residue);
802c19800e8SDoug Rabson     if (list == NULL)
803c19800e8SDoug Rabson 	return ENOMEM;
804c19800e8SDoug Rabson 
805c19800e8SDoug Rabson     p = calloc(1, sizeof(*p));
806c19800e8SDoug Rabson     if (p == NULL) {
807c19800e8SDoug Rabson 	free(list);
808c19800e8SDoug Rabson 	return ENOMEM;
809c19800e8SDoug Rabson     }
810c19800e8SDoug Rabson 
811c19800e8SDoug Rabson     p->refcount = 1;
812c19800e8SDoug Rabson 
813c19800e8SDoug Rabson     str = strchr(list, ',');
814c19800e8SDoug Rabson     if (str)
815c19800e8SDoug Rabson 	*str++ = '\0';
816c19800e8SDoug Rabson     while (str) {
817c19800e8SDoug Rabson 	char *strnext;
818c19800e8SDoug Rabson 	strnext = strchr(str, ',');
819c19800e8SDoug Rabson 	if (strnext)
820c19800e8SDoug Rabson 	    *strnext++ = '\0';
821c19800e8SDoug Rabson #if 0
822c19800e8SDoug Rabson 	if (strncasecmp(str, "slot=", 5) == 0)
823c19800e8SDoug Rabson 	    p->selected_slot = atoi(str + 5);
824c19800e8SDoug Rabson #endif
825c19800e8SDoug Rabson 	str = strnext;
826c19800e8SDoug Rabson     }
827c19800e8SDoug Rabson 
828c19800e8SDoug Rabson     p->dl_handle = dlopen(list, RTLD_NOW);
829c19800e8SDoug Rabson     free(list);
830c19800e8SDoug Rabson     if (p->dl_handle == NULL) {
831c19800e8SDoug Rabson 	ret = HX509_PKCS11_LOAD;
832c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
833c19800e8SDoug Rabson 			       "Failed to open %s: %s", list, dlerror());
834c19800e8SDoug Rabson 	goto out;
835c19800e8SDoug Rabson     }
836c19800e8SDoug Rabson 
837c19800e8SDoug Rabson     getFuncs = dlsym(p->dl_handle, "C_GetFunctionList");
838c19800e8SDoug Rabson     if (getFuncs == NULL) {
839c19800e8SDoug Rabson 	ret = HX509_PKCS11_LOAD;
840c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
841c19800e8SDoug Rabson 			       "C_GetFunctionList missing in %s: %s",
842c19800e8SDoug Rabson 			       list, dlerror());
843c19800e8SDoug Rabson 	goto out;
844c19800e8SDoug Rabson     }
845c19800e8SDoug Rabson 
846c19800e8SDoug Rabson     ret = (*getFuncs)(&p->funcs);
847c19800e8SDoug Rabson     if (ret) {
848c19800e8SDoug Rabson 	ret = HX509_PKCS11_LOAD;
849c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
850c19800e8SDoug Rabson 			       "C_GetFunctionList failed in %s", list);
851c19800e8SDoug Rabson 	goto out;
852c19800e8SDoug Rabson     }
853c19800e8SDoug Rabson 
854c19800e8SDoug Rabson     ret = P11FUNC(p, Initialize, (NULL_PTR));
855c19800e8SDoug Rabson     if (ret != CKR_OK) {
856c19800e8SDoug Rabson 	ret = HX509_PKCS11_TOKEN_CONFUSED;
857c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
858c19800e8SDoug Rabson 			       "Failed initialize the PKCS11 module");
859c19800e8SDoug Rabson 	goto out;
860c19800e8SDoug Rabson     }
861c19800e8SDoug Rabson 
862c19800e8SDoug Rabson     ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots));
863c19800e8SDoug Rabson     if (ret) {
864c19800e8SDoug Rabson 	ret = HX509_PKCS11_TOKEN_CONFUSED;
865c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
866c19800e8SDoug Rabson 			       "Failed to get number of PKCS11 slots");
867c19800e8SDoug Rabson 	goto out;
868c19800e8SDoug Rabson     }
869c19800e8SDoug Rabson 
870c19800e8SDoug Rabson    if (p->num_slots == 0) {
871c19800e8SDoug Rabson 	ret = HX509_PKCS11_NO_SLOT;
872c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
873c19800e8SDoug Rabson 			       "Selected PKCS11 module have no slots");
874c19800e8SDoug Rabson 	goto out;
875c19800e8SDoug Rabson    }
876c19800e8SDoug Rabson 
877c19800e8SDoug Rabson 
878c19800e8SDoug Rabson     {
879c19800e8SDoug Rabson 	CK_SLOT_ID_PTR slot_ids;
880c19800e8SDoug Rabson 	int i, num_tokens = 0;
881c19800e8SDoug Rabson 
882c19800e8SDoug Rabson 	slot_ids = malloc(p->num_slots * sizeof(*slot_ids));
883c19800e8SDoug Rabson 	if (slot_ids == NULL) {
884c19800e8SDoug Rabson 	    hx509_clear_error_string(context);
885c19800e8SDoug Rabson 	    ret = ENOMEM;
886c19800e8SDoug Rabson 	    goto out;
887c19800e8SDoug Rabson 	}
888c19800e8SDoug Rabson 
889c19800e8SDoug Rabson 	ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots));
890c19800e8SDoug Rabson 	if (ret) {
891c19800e8SDoug Rabson 	    free(slot_ids);
892c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED,
893c19800e8SDoug Rabson 				   "Failed getting slot-list from "
894c19800e8SDoug Rabson 				   "PKCS11 module");
895c19800e8SDoug Rabson 	    ret = HX509_PKCS11_TOKEN_CONFUSED;
896c19800e8SDoug Rabson 	    goto out;
897c19800e8SDoug Rabson 	}
898c19800e8SDoug Rabson 
899c19800e8SDoug Rabson 	p->slot = calloc(p->num_slots, sizeof(p->slot[0]));
900c19800e8SDoug Rabson 	if (p->slot == NULL) {
901c19800e8SDoug Rabson 	    free(slot_ids);
902c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ENOMEM,
903c19800e8SDoug Rabson 				   "Failed to get memory for slot-list");
904c19800e8SDoug Rabson 	    ret = ENOMEM;
905c19800e8SDoug Rabson 	    goto out;
906c19800e8SDoug Rabson 	}
907c19800e8SDoug Rabson 
908c19800e8SDoug Rabson 	for (i = 0; i < p->num_slots; i++) {
909c19800e8SDoug Rabson 	    ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]);
910c19800e8SDoug Rabson 	    if (ret)
911c19800e8SDoug Rabson 		break;
912c19800e8SDoug Rabson 	    if (p->slot[i].flags & P11_TOKEN_PRESENT)
913c19800e8SDoug Rabson 		num_tokens++;
914c19800e8SDoug Rabson 	}
915c19800e8SDoug Rabson 	free(slot_ids);
916c19800e8SDoug Rabson 	if (ret)
917c19800e8SDoug Rabson 	    goto out;
918c19800e8SDoug Rabson 	if (num_tokens == 0) {
919c19800e8SDoug Rabson 	    ret = HX509_PKCS11_NO_TOKEN;
920c19800e8SDoug Rabson 	    goto out;
921c19800e8SDoug Rabson 	}
922c19800e8SDoug Rabson     }
923c19800e8SDoug Rabson 
924c19800e8SDoug Rabson     *data = p;
925c19800e8SDoug Rabson 
926c19800e8SDoug Rabson     return 0;
927c19800e8SDoug Rabson  out:
928c19800e8SDoug Rabson     p11_release_module(p);
929c19800e8SDoug Rabson     return ret;
930c19800e8SDoug Rabson }
931c19800e8SDoug Rabson 
932c19800e8SDoug Rabson static void
933c19800e8SDoug Rabson p11_release_module(struct p11_module *p)
934c19800e8SDoug Rabson {
935c19800e8SDoug Rabson     int i;
936c19800e8SDoug Rabson 
937c19800e8SDoug Rabson     if (p->refcount == 0)
938c19800e8SDoug Rabson 	_hx509_abort("pkcs11 refcount to low");
939c19800e8SDoug Rabson     if (--p->refcount > 0)
940c19800e8SDoug Rabson 	return;
941c19800e8SDoug Rabson 
942c19800e8SDoug Rabson     for (i = 0; i < p->num_slots; i++) {
943c19800e8SDoug Rabson 	if (p->slot[i].flags & P11_SESSION_IN_USE)
944c19800e8SDoug Rabson 	    _hx509_abort("pkcs11 module release while session in use");
945c19800e8SDoug Rabson 	if (p->slot[i].flags & P11_SESSION) {
946c19800e8SDoug Rabson 	    int ret;
947c19800e8SDoug Rabson 
948c19800e8SDoug Rabson 	    ret = P11FUNC(p, CloseSession, (p->slot[i].session));
949c19800e8SDoug Rabson 	    if (ret != CKR_OK)
950c19800e8SDoug Rabson 		;
951c19800e8SDoug Rabson 	}
952c19800e8SDoug Rabson 
953c19800e8SDoug Rabson 	if (p->slot[i].name)
954c19800e8SDoug Rabson 	    free(p->slot[i].name);
955c19800e8SDoug Rabson 	if (p->slot[i].pin) {
956c19800e8SDoug Rabson 	    memset(p->slot[i].pin, 0, strlen(p->slot[i].pin));
957c19800e8SDoug Rabson 	    free(p->slot[i].pin);
958c19800e8SDoug Rabson 	}
959c19800e8SDoug Rabson 	if (p->slot[i].mechs.num) {
960c19800e8SDoug Rabson 	    free(p->slot[i].mechs.list);
961c19800e8SDoug Rabson 
962c19800e8SDoug Rabson 	    if (p->slot[i].mechs.infos) {
963c19800e8SDoug Rabson 		int j;
964c19800e8SDoug Rabson 
965c19800e8SDoug Rabson 		for (j = 0 ; j < p->slot[i].mechs.num ; j++)
966c19800e8SDoug Rabson 		    free(p->slot[i].mechs.infos[j]);
967c19800e8SDoug Rabson 		free(p->slot[i].mechs.infos);
968c19800e8SDoug Rabson 	    }
969c19800e8SDoug Rabson 	}
970c19800e8SDoug Rabson     }
971c19800e8SDoug Rabson     free(p->slot);
972c19800e8SDoug Rabson 
973c19800e8SDoug Rabson     if (p->funcs)
974c19800e8SDoug Rabson 	P11FUNC(p, Finalize, (NULL));
975c19800e8SDoug Rabson 
976c19800e8SDoug Rabson     if (p->dl_handle)
977c19800e8SDoug Rabson 	dlclose(p->dl_handle);
978c19800e8SDoug Rabson 
979c19800e8SDoug Rabson     memset(p, 0, sizeof(*p));
980c19800e8SDoug Rabson     free(p);
981c19800e8SDoug Rabson }
982c19800e8SDoug Rabson 
983c19800e8SDoug Rabson static int
984c19800e8SDoug Rabson p11_free(hx509_certs certs, void *data)
985c19800e8SDoug Rabson {
986c19800e8SDoug Rabson     struct p11_module *p = data;
987c19800e8SDoug Rabson     int i;
988c19800e8SDoug Rabson 
989c19800e8SDoug Rabson     for (i = 0; i < p->num_slots; i++) {
990c19800e8SDoug Rabson 	if (p->slot[i].certs)
991c19800e8SDoug Rabson 	    hx509_certs_free(&p->slot[i].certs);
992c19800e8SDoug Rabson     }
993c19800e8SDoug Rabson     p11_release_module(p);
994c19800e8SDoug Rabson     return 0;
995c19800e8SDoug Rabson }
996c19800e8SDoug Rabson 
997c19800e8SDoug Rabson struct p11_cursor {
998c19800e8SDoug Rabson     hx509_certs certs;
999c19800e8SDoug Rabson     void *cursor;
1000c19800e8SDoug Rabson };
1001c19800e8SDoug Rabson 
1002c19800e8SDoug Rabson static int
1003c19800e8SDoug Rabson p11_iter_start(hx509_context context,
1004c19800e8SDoug Rabson 	       hx509_certs certs, void *data, void **cursor)
1005c19800e8SDoug Rabson {
1006c19800e8SDoug Rabson     struct p11_module *p = data;
1007c19800e8SDoug Rabson     struct p11_cursor *c;
1008c19800e8SDoug Rabson     int ret, i;
1009c19800e8SDoug Rabson 
1010c19800e8SDoug Rabson     c = malloc(sizeof(*c));
1011c19800e8SDoug Rabson     if (c == NULL) {
1012c19800e8SDoug Rabson 	hx509_clear_error_string(context);
1013c19800e8SDoug Rabson 	return ENOMEM;
1014c19800e8SDoug Rabson     }
1015c19800e8SDoug Rabson     ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs);
1016c19800e8SDoug Rabson     if (ret) {
1017c19800e8SDoug Rabson 	free(c);
1018c19800e8SDoug Rabson 	return ret;
1019c19800e8SDoug Rabson     }
1020c19800e8SDoug Rabson 
1021c19800e8SDoug Rabson     for (i = 0 ; i < p->num_slots; i++) {
1022c19800e8SDoug Rabson 	if (p->slot[i].certs == NULL)
1023c19800e8SDoug Rabson 	    continue;
1024c19800e8SDoug Rabson 	ret = hx509_certs_merge(context, c->certs, p->slot[i].certs);
1025c19800e8SDoug Rabson 	if (ret) {
1026c19800e8SDoug Rabson 	    hx509_certs_free(&c->certs);
1027c19800e8SDoug Rabson 	    free(c);
1028c19800e8SDoug Rabson 	    return ret;
1029c19800e8SDoug Rabson 	}
1030c19800e8SDoug Rabson     }
1031c19800e8SDoug Rabson 
1032c19800e8SDoug Rabson     ret = hx509_certs_start_seq(context, c->certs, &c->cursor);
1033c19800e8SDoug Rabson     if (ret) {
1034c19800e8SDoug Rabson 	hx509_certs_free(&c->certs);
1035c19800e8SDoug Rabson 	free(c);
1036c19800e8SDoug Rabson 	return 0;
1037c19800e8SDoug Rabson     }
1038c19800e8SDoug Rabson     *cursor = c;
1039c19800e8SDoug Rabson 
1040c19800e8SDoug Rabson     return 0;
1041c19800e8SDoug Rabson }
1042c19800e8SDoug Rabson 
1043c19800e8SDoug Rabson static int
1044c19800e8SDoug Rabson p11_iter(hx509_context context,
1045c19800e8SDoug Rabson 	 hx509_certs certs, void *data, void *cursor, hx509_cert *cert)
1046c19800e8SDoug Rabson {
1047c19800e8SDoug Rabson     struct p11_cursor *c = cursor;
1048c19800e8SDoug Rabson     return hx509_certs_next_cert(context, c->certs, c->cursor, cert);
1049c19800e8SDoug Rabson }
1050c19800e8SDoug Rabson 
1051c19800e8SDoug Rabson static int
1052c19800e8SDoug Rabson p11_iter_end(hx509_context context,
1053c19800e8SDoug Rabson 	     hx509_certs certs, void *data, void *cursor)
1054c19800e8SDoug Rabson {
1055c19800e8SDoug Rabson     struct p11_cursor *c = cursor;
1056c19800e8SDoug Rabson     int ret;
1057c19800e8SDoug Rabson     ret = hx509_certs_end_seq(context, c->certs, c->cursor);
1058c19800e8SDoug Rabson     hx509_certs_free(&c->certs);
1059c19800e8SDoug Rabson     free(c);
1060c19800e8SDoug Rabson     return ret;
1061c19800e8SDoug Rabson }
1062c19800e8SDoug Rabson 
1063c19800e8SDoug Rabson #define MECHFLAG(x) { "unknown-flag-" #x, x }
1064c19800e8SDoug Rabson static struct units mechflags[] = {
1065c19800e8SDoug Rabson 	MECHFLAG(0x80000000),
1066c19800e8SDoug Rabson 	MECHFLAG(0x40000000),
1067c19800e8SDoug Rabson 	MECHFLAG(0x20000000),
1068c19800e8SDoug Rabson 	MECHFLAG(0x10000000),
1069c19800e8SDoug Rabson 	MECHFLAG(0x08000000),
1070c19800e8SDoug Rabson 	MECHFLAG(0x04000000),
1071c19800e8SDoug Rabson 	{"ec-compress",		0x2000000 },
1072c19800e8SDoug Rabson 	{"ec-uncompress",	0x1000000 },
1073c19800e8SDoug Rabson 	{"ec-namedcurve",	0x0800000 },
1074c19800e8SDoug Rabson 	{"ec-ecparameters",	0x0400000 },
1075c19800e8SDoug Rabson 	{"ec-f-2m",		0x0200000 },
1076c19800e8SDoug Rabson 	{"ec-f-p",		0x0100000 },
1077c19800e8SDoug Rabson 	{"derive",		0x0080000 },
1078c19800e8SDoug Rabson 	{"unwrap",		0x0040000 },
1079c19800e8SDoug Rabson 	{"wrap",		0x0020000 },
1080c19800e8SDoug Rabson 	{"genereate-key-pair",	0x0010000 },
1081c19800e8SDoug Rabson 	{"generate",		0x0008000 },
1082c19800e8SDoug Rabson 	{"verify-recover",	0x0004000 },
1083c19800e8SDoug Rabson 	{"verify",		0x0002000 },
1084c19800e8SDoug Rabson 	{"sign-recover",	0x0001000 },
1085c19800e8SDoug Rabson 	{"sign",		0x0000800 },
1086c19800e8SDoug Rabson 	{"digest",		0x0000400 },
1087c19800e8SDoug Rabson 	{"decrypt",		0x0000200 },
1088c19800e8SDoug Rabson 	{"encrypt",		0x0000100 },
1089c19800e8SDoug Rabson 	MECHFLAG(0x00080),
1090c19800e8SDoug Rabson 	MECHFLAG(0x00040),
1091c19800e8SDoug Rabson 	MECHFLAG(0x00020),
1092c19800e8SDoug Rabson 	MECHFLAG(0x00010),
1093c19800e8SDoug Rabson 	MECHFLAG(0x00008),
1094c19800e8SDoug Rabson 	MECHFLAG(0x00004),
1095c19800e8SDoug Rabson 	MECHFLAG(0x00002),
1096c19800e8SDoug Rabson 	{"hw",			0x0000001 },
1097c19800e8SDoug Rabson 	{ NULL,			0x0000000 }
1098c19800e8SDoug Rabson };
1099c19800e8SDoug Rabson #undef MECHFLAG
1100c19800e8SDoug Rabson 
1101c19800e8SDoug Rabson static int
1102c19800e8SDoug Rabson p11_printinfo(hx509_context context,
1103c19800e8SDoug Rabson 	      hx509_certs certs,
1104c19800e8SDoug Rabson 	      void *data,
1105c19800e8SDoug Rabson 	      int (*func)(void *, const char *),
1106c19800e8SDoug Rabson 	      void *ctx)
1107c19800e8SDoug Rabson {
1108c19800e8SDoug Rabson     struct p11_module *p = data;
1109c19800e8SDoug Rabson     int i, j;
1110c19800e8SDoug Rabson 
1111c19800e8SDoug Rabson     _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s",
1112c19800e8SDoug Rabson 		     p->num_slots, p->num_slots > 1 ? "s" : "");
1113c19800e8SDoug Rabson 
1114c19800e8SDoug Rabson     for (i = 0; i < p->num_slots; i++) {
1115c19800e8SDoug Rabson 	struct p11_slot *s = &p->slot[i];
1116c19800e8SDoug Rabson 
1117c19800e8SDoug Rabson 	_hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x",
1118c19800e8SDoug Rabson 			 i, (int)s->id, s->name, s->flags);
1119c19800e8SDoug Rabson 
1120c19800e8SDoug Rabson 	_hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu",
1121c19800e8SDoug Rabson 			 (unsigned long)s->mechs.num);
1122c19800e8SDoug Rabson 	for (j = 0; j < s->mechs.num; j++) {
1123c19800e8SDoug Rabson 	    const char *mechname = "unknown";
1124c19800e8SDoug Rabson 	    char flags[256], unknownname[40];
1125c19800e8SDoug Rabson #define MECHNAME(s,n) case s: mechname = n; break
1126c19800e8SDoug Rabson 	    switch(s->mechs.list[j]) {
1127c19800e8SDoug Rabson 		MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen");
1128c19800e8SDoug Rabson 		MECHNAME(CKM_RSA_PKCS, "rsa-pkcs");
1129c19800e8SDoug Rabson 		MECHNAME(CKM_RSA_X_509, "rsa-x-509");
1130c19800e8SDoug Rabson 		MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs");
1131c19800e8SDoug Rabson 		MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs");
1132c19800e8SDoug Rabson 		MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs");
1133c19800e8SDoug Rabson 		MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs");
1134c19800e8SDoug Rabson 		MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs");
1135c19800e8SDoug Rabson 		MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs");
1136c19800e8SDoug Rabson 		MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep");
1137c19800e8SDoug Rabson 		MECHNAME(CKM_SHA512_HMAC, "sha512-hmac");
1138c19800e8SDoug Rabson 		MECHNAME(CKM_SHA512, "sha512");
1139c19800e8SDoug Rabson 		MECHNAME(CKM_SHA384_HMAC, "sha384-hmac");
1140c19800e8SDoug Rabson 		MECHNAME(CKM_SHA384, "sha384");
1141c19800e8SDoug Rabson 		MECHNAME(CKM_SHA256_HMAC, "sha256-hmac");
1142c19800e8SDoug Rabson 		MECHNAME(CKM_SHA256, "sha256");
1143c19800e8SDoug Rabson 		MECHNAME(CKM_SHA_1, "sha1");
1144c19800e8SDoug Rabson 		MECHNAME(CKM_MD5, "md5");
1145c19800e8SDoug Rabson 		MECHNAME(CKM_MD2, "md2");
1146c19800e8SDoug Rabson 		MECHNAME(CKM_RIPEMD160, "ripemd-160");
1147c19800e8SDoug Rabson 		MECHNAME(CKM_DES_ECB, "des-ecb");
1148c19800e8SDoug Rabson 		MECHNAME(CKM_DES_CBC, "des-cbc");
1149c19800e8SDoug Rabson 		MECHNAME(CKM_AES_ECB, "aes-ecb");
1150c19800e8SDoug Rabson 		MECHNAME(CKM_AES_CBC, "aes-cbc");
1151c19800e8SDoug Rabson 		MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen");
1152c19800e8SDoug Rabson 	    default:
1153c19800e8SDoug Rabson 		snprintf(unknownname, sizeof(unknownname),
1154c19800e8SDoug Rabson 			 "unknown-mech-%lu",
1155c19800e8SDoug Rabson 			 (unsigned long)s->mechs.list[j]);
1156c19800e8SDoug Rabson 		mechname = unknownname;
1157c19800e8SDoug Rabson 		break;
1158c19800e8SDoug Rabson 	    }
1159c19800e8SDoug Rabson #undef MECHNAME
1160c19800e8SDoug Rabson 	    unparse_flags(s->mechs.infos[j]->flags, mechflags,
1161c19800e8SDoug Rabson 			  flags, sizeof(flags));
1162c19800e8SDoug Rabson 
1163c19800e8SDoug Rabson 	    _hx509_pi_printf(func, ctx, "  %s: %s", mechname, flags);
1164c19800e8SDoug Rabson 	}
1165c19800e8SDoug Rabson     }
1166c19800e8SDoug Rabson 
1167c19800e8SDoug Rabson     return 0;
1168c19800e8SDoug Rabson }
1169c19800e8SDoug Rabson 
1170c19800e8SDoug Rabson static struct hx509_keyset_ops keyset_pkcs11 = {
1171c19800e8SDoug Rabson     "PKCS11",
1172c19800e8SDoug Rabson     0,
1173c19800e8SDoug Rabson     p11_init,
1174c19800e8SDoug Rabson     NULL,
1175c19800e8SDoug Rabson     p11_free,
1176c19800e8SDoug Rabson     NULL,
1177c19800e8SDoug Rabson     NULL,
1178c19800e8SDoug Rabson     p11_iter_start,
1179c19800e8SDoug Rabson     p11_iter,
1180c19800e8SDoug Rabson     p11_iter_end,
1181c19800e8SDoug Rabson     p11_printinfo
1182c19800e8SDoug Rabson };
1183c19800e8SDoug Rabson 
1184c19800e8SDoug Rabson #endif /* HAVE_DLOPEN */
1185c19800e8SDoug Rabson 
1186c19800e8SDoug Rabson void
1187c19800e8SDoug Rabson _hx509_ks_pkcs11_register(hx509_context context)
1188c19800e8SDoug Rabson {
1189c19800e8SDoug Rabson #ifdef HAVE_DLOPEN
1190c19800e8SDoug Rabson     _hx509_ks_register(context, &keyset_pkcs11);
1191c19800e8SDoug Rabson #endif
1192c19800e8SDoug Rabson }
1193