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