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