1c19800e8SDoug Rabson /* 2*ae771770SStanislav 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; 67*ae771770SStanislav 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 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 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 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, 155*ae771770SStanislav 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 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, 193*ae771770SStanislav 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 202c19800e8SDoug Rabson p11_rsa_init(RSA *rsa) 203c19800e8SDoug Rabson { 204c19800e8SDoug Rabson return 1; 205c19800e8SDoug Rabson } 206c19800e8SDoug Rabson 207c19800e8SDoug Rabson static int 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 216c19800e8SDoug Rabson static const RSA_METHOD p11_rsa_pkcs1_method = { 217c19800e8SDoug Rabson "hx509 PKCS11 PKCS#1 RSA", 218c19800e8SDoug Rabson p11_rsa_public_encrypt, 219c19800e8SDoug Rabson p11_rsa_public_decrypt, 220c19800e8SDoug Rabson p11_rsa_private_encrypt, 221c19800e8SDoug Rabson p11_rsa_private_decrypt, 222c19800e8SDoug Rabson NULL, 223c19800e8SDoug Rabson NULL, 224c19800e8SDoug Rabson p11_rsa_init, 225c19800e8SDoug Rabson p11_rsa_finish, 226c19800e8SDoug Rabson 0, 227c19800e8SDoug Rabson NULL, 228c19800e8SDoug Rabson NULL, 229c19800e8SDoug Rabson NULL 230c19800e8SDoug Rabson }; 231c19800e8SDoug Rabson 232c19800e8SDoug Rabson /* 233c19800e8SDoug Rabson * 234c19800e8SDoug Rabson */ 235c19800e8SDoug Rabson 236c19800e8SDoug Rabson static int 237c19800e8SDoug Rabson p11_mech_info(hx509_context context, 238c19800e8SDoug Rabson struct p11_module *p, 239c19800e8SDoug Rabson struct p11_slot *slot, 240c19800e8SDoug Rabson int num) 241c19800e8SDoug Rabson { 242c19800e8SDoug Rabson CK_ULONG i; 243c19800e8SDoug Rabson int ret; 244c19800e8SDoug Rabson 245c19800e8SDoug Rabson ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i)); 246c19800e8SDoug Rabson if (ret) { 247c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 248c19800e8SDoug Rabson "Failed to get mech list count for slot %d", 249c19800e8SDoug Rabson num); 250c19800e8SDoug Rabson return HX509_PKCS11_NO_MECH; 251c19800e8SDoug Rabson } 252c19800e8SDoug Rabson if (i == 0) { 253c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 254c19800e8SDoug Rabson "no mech supported for slot %d", num); 255c19800e8SDoug Rabson return HX509_PKCS11_NO_MECH; 256c19800e8SDoug Rabson } 257c19800e8SDoug Rabson slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0])); 258c19800e8SDoug Rabson if (slot->mechs.list == NULL) { 259c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, 260c19800e8SDoug Rabson "out of memory"); 261c19800e8SDoug Rabson return ENOMEM; 262c19800e8SDoug Rabson } 263c19800e8SDoug Rabson slot->mechs.num = i; 264c19800e8SDoug Rabson ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i)); 265c19800e8SDoug Rabson if (ret) { 266c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 267c19800e8SDoug Rabson "Failed to get mech list for slot %d", 268c19800e8SDoug Rabson num); 269c19800e8SDoug Rabson return HX509_PKCS11_NO_MECH; 270c19800e8SDoug Rabson } 271c19800e8SDoug Rabson assert(i == slot->mechs.num); 272c19800e8SDoug Rabson 273c19800e8SDoug Rabson slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos)); 274c19800e8SDoug Rabson if (slot->mechs.list == NULL) { 275c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, 276c19800e8SDoug Rabson "out of memory"); 277c19800e8SDoug Rabson return ENOMEM; 278c19800e8SDoug Rabson } 279c19800e8SDoug Rabson 280c19800e8SDoug Rabson for (i = 0; i < slot->mechs.num; i++) { 281c19800e8SDoug Rabson slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0]))); 282c19800e8SDoug Rabson if (slot->mechs.infos[i] == NULL) { 283c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, 284c19800e8SDoug Rabson "out of memory"); 285c19800e8SDoug Rabson return ENOMEM; 286c19800e8SDoug Rabson } 287c19800e8SDoug Rabson ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i], 288c19800e8SDoug Rabson slot->mechs.infos[i])); 289c19800e8SDoug Rabson if (ret) { 290c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 291c19800e8SDoug Rabson "Failed to get mech info for slot %d", 292c19800e8SDoug Rabson num); 293c19800e8SDoug Rabson return HX509_PKCS11_NO_MECH; 294c19800e8SDoug Rabson } 295c19800e8SDoug Rabson } 296c19800e8SDoug Rabson 297c19800e8SDoug Rabson return 0; 298c19800e8SDoug Rabson } 299c19800e8SDoug Rabson 300c19800e8SDoug Rabson static int 301c19800e8SDoug Rabson p11_init_slot(hx509_context context, 302c19800e8SDoug Rabson struct p11_module *p, 303c19800e8SDoug Rabson hx509_lock lock, 304c19800e8SDoug Rabson CK_SLOT_ID id, 305c19800e8SDoug Rabson int num, 306c19800e8SDoug Rabson struct p11_slot *slot) 307c19800e8SDoug Rabson { 308c19800e8SDoug Rabson CK_SESSION_HANDLE session; 309c19800e8SDoug Rabson CK_SLOT_INFO slot_info; 310c19800e8SDoug Rabson CK_TOKEN_INFO token_info; 311*ae771770SStanislav Sedov size_t i; 312*ae771770SStanislav Sedov int ret; 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", 334*ae771770SStanislav Sedov (int)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 if (slot->pin == NULL) { 422c19800e8SDoug Rabson 423c19800e8SDoug Rabson memset(&prompt, 0, sizeof(prompt)); 424c19800e8SDoug Rabson 425c19800e8SDoug Rabson asprintf(&str, "PIN code for %s: ", slot->name); 426c19800e8SDoug Rabson prompt.prompt = str; 427c19800e8SDoug Rabson prompt.type = HX509_PROMPT_TYPE_PASSWORD; 428c19800e8SDoug Rabson prompt.reply.data = pin; 429c19800e8SDoug Rabson prompt.reply.length = sizeof(pin); 430c19800e8SDoug Rabson 431c19800e8SDoug Rabson ret = hx509_lock_prompt(lock, &prompt); 432c19800e8SDoug Rabson if (ret) { 433c19800e8SDoug Rabson free(str); 434c19800e8SDoug Rabson if (context) 435c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 436c19800e8SDoug Rabson "Failed to get pin code for slot " 437c19800e8SDoug Rabson "id %d with error: %d", 438c19800e8SDoug Rabson (int)slot->id, ret); 439c19800e8SDoug Rabson return ret; 440c19800e8SDoug Rabson } 441c19800e8SDoug Rabson free(str); 442c19800e8SDoug Rabson } else { 443c19800e8SDoug Rabson strlcpy(pin, slot->pin, sizeof(pin)); 444c19800e8SDoug Rabson } 445c19800e8SDoug Rabson 446c19800e8SDoug Rabson ret = P11FUNC(p, Login, (slot->session, CKU_USER, 447c19800e8SDoug Rabson (unsigned char*)pin, strlen(pin))); 448c19800e8SDoug Rabson if (ret != CKR_OK) { 449c19800e8SDoug Rabson if (context) 450c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN, 451c19800e8SDoug Rabson "Failed to login on slot id %d " 452c19800e8SDoug Rabson "with error: 0x%08x", 453c19800e8SDoug Rabson (int)slot->id, ret); 454c19800e8SDoug Rabson return HX509_PKCS11_LOGIN; 455*ae771770SStanislav Sedov } else 456*ae771770SStanislav Sedov slot->flags |= P11_LOGIN_DONE; 457*ae771770SStanislav Sedov 458c19800e8SDoug Rabson if (slot->pin == NULL) { 459c19800e8SDoug Rabson slot->pin = strdup(pin); 460c19800e8SDoug Rabson if (slot->pin == NULL) { 461c19800e8SDoug Rabson if (context) 462c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, 463c19800e8SDoug Rabson "out of memory"); 464c19800e8SDoug Rabson return ENOMEM; 465c19800e8SDoug Rabson } 466c19800e8SDoug Rabson } 467c19800e8SDoug Rabson } else 468c19800e8SDoug Rabson slot->flags |= P11_LOGIN_DONE; 469c19800e8SDoug Rabson 470c19800e8SDoug Rabson slot->flags |= P11_SESSION_IN_USE; 471c19800e8SDoug Rabson 472c19800e8SDoug Rabson *psession = slot->session; 473c19800e8SDoug Rabson 474c19800e8SDoug Rabson return 0; 475c19800e8SDoug Rabson } 476c19800e8SDoug Rabson 477c19800e8SDoug Rabson static int 478c19800e8SDoug Rabson p11_put_session(struct p11_module *p, 479c19800e8SDoug Rabson struct p11_slot *slot, 480c19800e8SDoug Rabson CK_SESSION_HANDLE session) 481c19800e8SDoug Rabson { 482c19800e8SDoug Rabson if ((slot->flags & P11_SESSION_IN_USE) == 0) 483c19800e8SDoug Rabson _hx509_abort("slot not in session"); 484c19800e8SDoug Rabson slot->flags &= ~P11_SESSION_IN_USE; 485c19800e8SDoug Rabson 486c19800e8SDoug Rabson return 0; 487c19800e8SDoug Rabson } 488c19800e8SDoug Rabson 489c19800e8SDoug Rabson static int 490c19800e8SDoug Rabson iterate_entries(hx509_context context, 491c19800e8SDoug Rabson struct p11_module *p, struct p11_slot *slot, 492c19800e8SDoug Rabson CK_SESSION_HANDLE session, 493c19800e8SDoug Rabson CK_ATTRIBUTE *search_data, int num_search_data, 494c19800e8SDoug Rabson CK_ATTRIBUTE *query, int num_query, 495c19800e8SDoug Rabson int (*func)(hx509_context, 496c19800e8SDoug Rabson struct p11_module *, struct p11_slot *, 497c19800e8SDoug Rabson CK_SESSION_HANDLE session, 498c19800e8SDoug Rabson CK_OBJECT_HANDLE object, 499c19800e8SDoug Rabson void *, CK_ATTRIBUTE *, int), void *ptr) 500c19800e8SDoug Rabson { 501c19800e8SDoug Rabson CK_OBJECT_HANDLE object; 502c19800e8SDoug Rabson CK_ULONG object_count; 503*ae771770SStanislav Sedov int ret, ret2, i; 504c19800e8SDoug Rabson 505c19800e8SDoug Rabson ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); 506c19800e8SDoug Rabson if (ret != CKR_OK) { 507c19800e8SDoug Rabson return -1; 508c19800e8SDoug Rabson } 509c19800e8SDoug Rabson while (1) { 510c19800e8SDoug Rabson ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); 511c19800e8SDoug Rabson if (ret != CKR_OK) { 512c19800e8SDoug Rabson return -1; 513c19800e8SDoug Rabson } 514c19800e8SDoug Rabson if (object_count == 0) 515c19800e8SDoug Rabson break; 516c19800e8SDoug Rabson 517c19800e8SDoug Rabson for (i = 0; i < num_query; i++) 518c19800e8SDoug Rabson query[i].pValue = NULL; 519c19800e8SDoug Rabson 520c19800e8SDoug Rabson ret = P11FUNC(p, GetAttributeValue, 521c19800e8SDoug Rabson (session, object, query, num_query)); 522c19800e8SDoug Rabson if (ret != CKR_OK) { 523c19800e8SDoug Rabson return -1; 524c19800e8SDoug Rabson } 525c19800e8SDoug Rabson for (i = 0; i < num_query; i++) { 526c19800e8SDoug Rabson query[i].pValue = malloc(query[i].ulValueLen); 527c19800e8SDoug Rabson if (query[i].pValue == NULL) { 528c19800e8SDoug Rabson ret = ENOMEM; 529c19800e8SDoug Rabson goto out; 530c19800e8SDoug Rabson } 531c19800e8SDoug Rabson } 532c19800e8SDoug Rabson ret = P11FUNC(p, GetAttributeValue, 533c19800e8SDoug Rabson (session, object, query, num_query)); 534c19800e8SDoug Rabson if (ret != CKR_OK) { 535c19800e8SDoug Rabson ret = -1; 536c19800e8SDoug Rabson goto out; 537c19800e8SDoug Rabson } 538c19800e8SDoug Rabson 539c19800e8SDoug Rabson ret = (*func)(context, p, slot, session, object, ptr, query, num_query); 540c19800e8SDoug Rabson if (ret) 541c19800e8SDoug Rabson goto out; 542c19800e8SDoug Rabson 543c19800e8SDoug Rabson for (i = 0; i < num_query; i++) { 544c19800e8SDoug Rabson if (query[i].pValue) 545c19800e8SDoug Rabson free(query[i].pValue); 546c19800e8SDoug Rabson query[i].pValue = NULL; 547c19800e8SDoug Rabson } 548c19800e8SDoug Rabson } 549c19800e8SDoug Rabson out: 550c19800e8SDoug Rabson 551c19800e8SDoug Rabson for (i = 0; i < num_query; i++) { 552c19800e8SDoug Rabson if (query[i].pValue) 553c19800e8SDoug Rabson free(query[i].pValue); 554c19800e8SDoug Rabson query[i].pValue = NULL; 555c19800e8SDoug Rabson } 556c19800e8SDoug Rabson 557*ae771770SStanislav Sedov ret2 = P11FUNC(p, FindObjectsFinal, (session)); 558*ae771770SStanislav Sedov if (ret2 != CKR_OK) { 559*ae771770SStanislav Sedov return ret2; 560c19800e8SDoug Rabson } 561c19800e8SDoug Rabson 562*ae771770SStanislav Sedov return ret; 563c19800e8SDoug Rabson } 564c19800e8SDoug Rabson 565c19800e8SDoug Rabson static BIGNUM * 566c19800e8SDoug Rabson getattr_bn(struct p11_module *p, 567c19800e8SDoug Rabson struct p11_slot *slot, 568c19800e8SDoug Rabson CK_SESSION_HANDLE session, 569c19800e8SDoug Rabson CK_OBJECT_HANDLE object, 570c19800e8SDoug Rabson unsigned int type) 571c19800e8SDoug Rabson { 572c19800e8SDoug Rabson CK_ATTRIBUTE query; 573c19800e8SDoug Rabson BIGNUM *bn; 574c19800e8SDoug Rabson int ret; 575c19800e8SDoug Rabson 576c19800e8SDoug Rabson query.type = type; 577c19800e8SDoug Rabson query.pValue = NULL; 578c19800e8SDoug Rabson query.ulValueLen = 0; 579c19800e8SDoug Rabson 580c19800e8SDoug Rabson ret = P11FUNC(p, GetAttributeValue, 581c19800e8SDoug Rabson (session, object, &query, 1)); 582c19800e8SDoug Rabson if (ret != CKR_OK) 583c19800e8SDoug Rabson return NULL; 584c19800e8SDoug Rabson 585c19800e8SDoug Rabson query.pValue = malloc(query.ulValueLen); 586c19800e8SDoug Rabson 587c19800e8SDoug Rabson ret = P11FUNC(p, GetAttributeValue, 588c19800e8SDoug Rabson (session, object, &query, 1)); 589c19800e8SDoug Rabson if (ret != CKR_OK) { 590c19800e8SDoug Rabson free(query.pValue); 591c19800e8SDoug Rabson return NULL; 592c19800e8SDoug Rabson } 593c19800e8SDoug Rabson bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL); 594c19800e8SDoug Rabson free(query.pValue); 595c19800e8SDoug Rabson 596c19800e8SDoug Rabson return bn; 597c19800e8SDoug Rabson } 598c19800e8SDoug Rabson 599c19800e8SDoug Rabson static int 600c19800e8SDoug Rabson collect_private_key(hx509_context context, 601c19800e8SDoug Rabson struct p11_module *p, struct p11_slot *slot, 602c19800e8SDoug Rabson CK_SESSION_HANDLE session, 603c19800e8SDoug Rabson CK_OBJECT_HANDLE object, 604c19800e8SDoug Rabson void *ptr, CK_ATTRIBUTE *query, int num_query) 605c19800e8SDoug Rabson { 606c19800e8SDoug Rabson struct hx509_collector *collector = ptr; 607c19800e8SDoug Rabson hx509_private_key key; 608c19800e8SDoug Rabson heim_octet_string localKeyId; 609c19800e8SDoug Rabson int ret; 610c19800e8SDoug Rabson RSA *rsa; 611c19800e8SDoug Rabson struct p11_rsa *p11rsa; 612c19800e8SDoug Rabson 613c19800e8SDoug Rabson localKeyId.data = query[0].pValue; 614c19800e8SDoug Rabson localKeyId.length = query[0].ulValueLen; 615c19800e8SDoug Rabson 616*ae771770SStanislav Sedov ret = hx509_private_key_init(&key, NULL, NULL); 617c19800e8SDoug Rabson if (ret) 618c19800e8SDoug Rabson return ret; 619c19800e8SDoug Rabson 620c19800e8SDoug Rabson rsa = RSA_new(); 621c19800e8SDoug Rabson if (rsa == NULL) 622c19800e8SDoug Rabson _hx509_abort("out of memory"); 623c19800e8SDoug Rabson 624c19800e8SDoug Rabson /* 625c19800e8SDoug Rabson * The exponent and modulus should always be present according to 626c19800e8SDoug Rabson * the pkcs11 specification, but some smartcards leaves it out, 627c19800e8SDoug Rabson * let ignore any failure to fetch it. 628c19800e8SDoug Rabson */ 629c19800e8SDoug Rabson rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS); 630c19800e8SDoug Rabson rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT); 631c19800e8SDoug Rabson 632c19800e8SDoug Rabson p11rsa = calloc(1, sizeof(*p11rsa)); 633c19800e8SDoug Rabson if (p11rsa == NULL) 634c19800e8SDoug Rabson _hx509_abort("out of memory"); 635c19800e8SDoug Rabson 636c19800e8SDoug Rabson p11rsa->p = p; 637c19800e8SDoug Rabson p11rsa->slot = slot; 638c19800e8SDoug Rabson p11rsa->private_key = object; 639c19800e8SDoug Rabson 640*ae771770SStanislav Sedov if (p->ref == 0) 641*ae771770SStanislav Sedov _hx509_abort("pkcs11 ref == 0 on alloc"); 642*ae771770SStanislav Sedov p->ref++; 643*ae771770SStanislav Sedov if (p->ref == UINT_MAX) 644*ae771770SStanislav Sedov _hx509_abort("pkcs11 ref == UINT_MAX on alloc"); 645c19800e8SDoug Rabson 646c19800e8SDoug Rabson RSA_set_method(rsa, &p11_rsa_pkcs1_method); 647c19800e8SDoug Rabson ret = RSA_set_app_data(rsa, p11rsa); 648c19800e8SDoug Rabson if (ret != 1) 649c19800e8SDoug Rabson _hx509_abort("RSA_set_app_data"); 650c19800e8SDoug Rabson 651*ae771770SStanislav Sedov hx509_private_key_assign_rsa(key, rsa); 652c19800e8SDoug Rabson 653c19800e8SDoug Rabson ret = _hx509_collector_private_key_add(context, 654c19800e8SDoug Rabson collector, 655c19800e8SDoug Rabson hx509_signature_rsa(), 656c19800e8SDoug Rabson key, 657c19800e8SDoug Rabson NULL, 658c19800e8SDoug Rabson &localKeyId); 659c19800e8SDoug Rabson 660c19800e8SDoug Rabson if (ret) { 661*ae771770SStanislav Sedov hx509_private_key_free(&key); 662c19800e8SDoug Rabson return ret; 663c19800e8SDoug Rabson } 664c19800e8SDoug Rabson return 0; 665c19800e8SDoug Rabson } 666c19800e8SDoug Rabson 667c19800e8SDoug Rabson static void 668c19800e8SDoug Rabson p11_cert_release(hx509_cert cert, void *ctx) 669c19800e8SDoug Rabson { 670c19800e8SDoug Rabson struct p11_module *p = ctx; 671c19800e8SDoug Rabson p11_release_module(p); 672c19800e8SDoug Rabson } 673c19800e8SDoug Rabson 674c19800e8SDoug Rabson 675c19800e8SDoug Rabson static int 676c19800e8SDoug Rabson collect_cert(hx509_context context, 677c19800e8SDoug Rabson struct p11_module *p, struct p11_slot *slot, 678c19800e8SDoug Rabson CK_SESSION_HANDLE session, 679c19800e8SDoug Rabson CK_OBJECT_HANDLE object, 680c19800e8SDoug Rabson void *ptr, CK_ATTRIBUTE *query, int num_query) 681c19800e8SDoug Rabson { 682c19800e8SDoug Rabson struct hx509_collector *collector = ptr; 683c19800e8SDoug Rabson hx509_cert cert; 684c19800e8SDoug Rabson int ret; 685c19800e8SDoug Rabson 686c19800e8SDoug Rabson if ((CK_LONG)query[0].ulValueLen == -1 || 687c19800e8SDoug Rabson (CK_LONG)query[1].ulValueLen == -1) 688c19800e8SDoug Rabson { 689c19800e8SDoug Rabson return 0; 690c19800e8SDoug Rabson } 691c19800e8SDoug Rabson 692c19800e8SDoug Rabson ret = hx509_cert_init_data(context, query[1].pValue, 693c19800e8SDoug Rabson query[1].ulValueLen, &cert); 694c19800e8SDoug Rabson if (ret) 695c19800e8SDoug Rabson return ret; 696c19800e8SDoug Rabson 697*ae771770SStanislav Sedov if (p->ref == 0) 698*ae771770SStanislav Sedov _hx509_abort("pkcs11 ref == 0 on alloc"); 699*ae771770SStanislav Sedov p->ref++; 700*ae771770SStanislav Sedov if (p->ref == UINT_MAX) 701*ae771770SStanislav Sedov _hx509_abort("pkcs11 ref to high"); 702c19800e8SDoug Rabson 703c19800e8SDoug Rabson _hx509_cert_set_release(cert, p11_cert_release, p); 704c19800e8SDoug Rabson 705c19800e8SDoug Rabson { 706c19800e8SDoug Rabson heim_octet_string data; 707c19800e8SDoug Rabson 708c19800e8SDoug Rabson data.data = query[0].pValue; 709c19800e8SDoug Rabson data.length = query[0].ulValueLen; 710c19800e8SDoug Rabson 711c19800e8SDoug Rabson _hx509_set_cert_attribute(context, 712c19800e8SDoug Rabson cert, 713*ae771770SStanislav Sedov &asn1_oid_id_pkcs_9_at_localKeyId, 714c19800e8SDoug Rabson &data); 715c19800e8SDoug Rabson } 716c19800e8SDoug Rabson 717c19800e8SDoug Rabson if ((CK_LONG)query[2].ulValueLen != -1) { 718c19800e8SDoug Rabson char *str; 719c19800e8SDoug Rabson 720c19800e8SDoug Rabson asprintf(&str, "%.*s", 721c19800e8SDoug Rabson (int)query[2].ulValueLen, (char *)query[2].pValue); 722c19800e8SDoug Rabson if (str) { 723c19800e8SDoug Rabson hx509_cert_set_friendly_name(cert, str); 724c19800e8SDoug Rabson free(str); 725c19800e8SDoug Rabson } 726c19800e8SDoug Rabson } 727c19800e8SDoug Rabson 728c19800e8SDoug Rabson ret = _hx509_collector_certs_add(context, collector, cert); 729c19800e8SDoug Rabson hx509_cert_free(cert); 730c19800e8SDoug Rabson 731c19800e8SDoug Rabson return ret; 732c19800e8SDoug Rabson } 733c19800e8SDoug Rabson 734c19800e8SDoug Rabson 735c19800e8SDoug Rabson static int 736c19800e8SDoug Rabson p11_list_keys(hx509_context context, 737c19800e8SDoug Rabson struct p11_module *p, 738c19800e8SDoug Rabson struct p11_slot *slot, 739c19800e8SDoug Rabson CK_SESSION_HANDLE session, 740c19800e8SDoug Rabson hx509_lock lock, 741c19800e8SDoug Rabson hx509_certs *certs) 742c19800e8SDoug Rabson { 743c19800e8SDoug Rabson struct hx509_collector *collector; 744c19800e8SDoug Rabson CK_OBJECT_CLASS key_class; 745c19800e8SDoug Rabson CK_ATTRIBUTE search_data[] = { 746c19800e8SDoug Rabson {CKA_CLASS, NULL, 0}, 747c19800e8SDoug Rabson }; 748c19800e8SDoug Rabson CK_ATTRIBUTE query_data[3] = { 749c19800e8SDoug Rabson {CKA_ID, NULL, 0}, 750c19800e8SDoug Rabson {CKA_VALUE, NULL, 0}, 751c19800e8SDoug Rabson {CKA_LABEL, NULL, 0} 752c19800e8SDoug Rabson }; 753c19800e8SDoug Rabson int ret; 754c19800e8SDoug Rabson 755c19800e8SDoug Rabson search_data[0].pValue = &key_class; 756c19800e8SDoug Rabson search_data[0].ulValueLen = sizeof(key_class); 757c19800e8SDoug Rabson 758c19800e8SDoug Rabson if (lock == NULL) 759c19800e8SDoug Rabson lock = _hx509_empty_lock; 760c19800e8SDoug Rabson 761c19800e8SDoug Rabson ret = _hx509_collector_alloc(context, lock, &collector); 762c19800e8SDoug Rabson if (ret) 763c19800e8SDoug Rabson return ret; 764c19800e8SDoug Rabson 765c19800e8SDoug Rabson key_class = CKO_PRIVATE_KEY; 766c19800e8SDoug Rabson ret = iterate_entries(context, p, slot, session, 767c19800e8SDoug Rabson search_data, 1, 768c19800e8SDoug Rabson query_data, 1, 769c19800e8SDoug Rabson collect_private_key, collector); 770c19800e8SDoug Rabson if (ret) 771c19800e8SDoug Rabson goto out; 772c19800e8SDoug Rabson 773c19800e8SDoug Rabson key_class = CKO_CERTIFICATE; 774c19800e8SDoug Rabson ret = iterate_entries(context, p, slot, session, 775c19800e8SDoug Rabson search_data, 1, 776c19800e8SDoug Rabson query_data, 3, 777c19800e8SDoug Rabson collect_cert, collector); 778c19800e8SDoug Rabson if (ret) 779c19800e8SDoug Rabson goto out; 780c19800e8SDoug Rabson 781c19800e8SDoug Rabson ret = _hx509_collector_collect_certs(context, collector, &slot->certs); 782c19800e8SDoug Rabson 783c19800e8SDoug Rabson out: 784c19800e8SDoug Rabson _hx509_collector_free(collector); 785c19800e8SDoug Rabson 786c19800e8SDoug Rabson return ret; 787c19800e8SDoug Rabson } 788c19800e8SDoug Rabson 789c19800e8SDoug Rabson 790c19800e8SDoug Rabson static int 791c19800e8SDoug Rabson p11_init(hx509_context context, 792c19800e8SDoug Rabson hx509_certs certs, void **data, int flags, 793c19800e8SDoug Rabson const char *residue, hx509_lock lock) 794c19800e8SDoug Rabson { 795c19800e8SDoug Rabson CK_C_GetFunctionList getFuncs; 796c19800e8SDoug Rabson struct p11_module *p; 797c19800e8SDoug Rabson char *list, *str; 798c19800e8SDoug Rabson int ret; 799c19800e8SDoug Rabson 800c19800e8SDoug Rabson *data = NULL; 801c19800e8SDoug Rabson 802c19800e8SDoug Rabson list = strdup(residue); 803c19800e8SDoug Rabson if (list == NULL) 804c19800e8SDoug Rabson return ENOMEM; 805c19800e8SDoug Rabson 806c19800e8SDoug Rabson p = calloc(1, sizeof(*p)); 807c19800e8SDoug Rabson if (p == NULL) { 808c19800e8SDoug Rabson free(list); 809c19800e8SDoug Rabson return ENOMEM; 810c19800e8SDoug Rabson } 811c19800e8SDoug Rabson 812*ae771770SStanislav Sedov p->ref = 1; 813c19800e8SDoug Rabson 814c19800e8SDoug Rabson str = strchr(list, ','); 815c19800e8SDoug Rabson if (str) 816c19800e8SDoug Rabson *str++ = '\0'; 817c19800e8SDoug Rabson while (str) { 818c19800e8SDoug Rabson char *strnext; 819c19800e8SDoug Rabson strnext = strchr(str, ','); 820c19800e8SDoug Rabson if (strnext) 821c19800e8SDoug Rabson *strnext++ = '\0'; 822c19800e8SDoug Rabson #if 0 823c19800e8SDoug Rabson if (strncasecmp(str, "slot=", 5) == 0) 824c19800e8SDoug Rabson p->selected_slot = atoi(str + 5); 825c19800e8SDoug Rabson #endif 826c19800e8SDoug Rabson str = strnext; 827c19800e8SDoug Rabson } 828c19800e8SDoug Rabson 829c19800e8SDoug Rabson p->dl_handle = dlopen(list, RTLD_NOW); 830c19800e8SDoug Rabson free(list); 831c19800e8SDoug Rabson if (p->dl_handle == NULL) { 832c19800e8SDoug Rabson ret = HX509_PKCS11_LOAD; 833c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 834c19800e8SDoug Rabson "Failed to open %s: %s", list, dlerror()); 835c19800e8SDoug Rabson goto out; 836c19800e8SDoug Rabson } 837c19800e8SDoug Rabson 838*ae771770SStanislav Sedov getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList"); 839c19800e8SDoug Rabson if (getFuncs == NULL) { 840c19800e8SDoug Rabson ret = HX509_PKCS11_LOAD; 841c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 842c19800e8SDoug Rabson "C_GetFunctionList missing in %s: %s", 843c19800e8SDoug Rabson list, dlerror()); 844c19800e8SDoug Rabson goto out; 845c19800e8SDoug Rabson } 846c19800e8SDoug Rabson 847c19800e8SDoug Rabson ret = (*getFuncs)(&p->funcs); 848c19800e8SDoug Rabson if (ret) { 849c19800e8SDoug Rabson ret = HX509_PKCS11_LOAD; 850c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 851c19800e8SDoug Rabson "C_GetFunctionList failed in %s", list); 852c19800e8SDoug Rabson goto out; 853c19800e8SDoug Rabson } 854c19800e8SDoug Rabson 855c19800e8SDoug Rabson ret = P11FUNC(p, Initialize, (NULL_PTR)); 856c19800e8SDoug Rabson if (ret != CKR_OK) { 857c19800e8SDoug Rabson ret = HX509_PKCS11_TOKEN_CONFUSED; 858c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 859c19800e8SDoug Rabson "Failed initialize the PKCS11 module"); 860c19800e8SDoug Rabson goto out; 861c19800e8SDoug Rabson } 862c19800e8SDoug Rabson 863c19800e8SDoug Rabson ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots)); 864c19800e8SDoug Rabson if (ret) { 865c19800e8SDoug Rabson ret = HX509_PKCS11_TOKEN_CONFUSED; 866c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 867c19800e8SDoug Rabson "Failed to get number of PKCS11 slots"); 868c19800e8SDoug Rabson goto out; 869c19800e8SDoug Rabson } 870c19800e8SDoug Rabson 871c19800e8SDoug Rabson if (p->num_slots == 0) { 872c19800e8SDoug Rabson ret = HX509_PKCS11_NO_SLOT; 873c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, 874c19800e8SDoug Rabson "Selected PKCS11 module have no slots"); 875c19800e8SDoug Rabson goto out; 876c19800e8SDoug Rabson } 877c19800e8SDoug Rabson 878c19800e8SDoug Rabson 879c19800e8SDoug Rabson { 880c19800e8SDoug Rabson CK_SLOT_ID_PTR slot_ids; 881*ae771770SStanislav Sedov int num_tokens = 0; 882*ae771770SStanislav Sedov size_t i; 883c19800e8SDoug Rabson 884c19800e8SDoug Rabson slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); 885c19800e8SDoug Rabson if (slot_ids == NULL) { 886c19800e8SDoug Rabson hx509_clear_error_string(context); 887c19800e8SDoug Rabson ret = ENOMEM; 888c19800e8SDoug Rabson goto out; 889c19800e8SDoug Rabson } 890c19800e8SDoug Rabson 891c19800e8SDoug Rabson ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); 892c19800e8SDoug Rabson if (ret) { 893c19800e8SDoug Rabson free(slot_ids); 894c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, 895c19800e8SDoug Rabson "Failed getting slot-list from " 896c19800e8SDoug Rabson "PKCS11 module"); 897c19800e8SDoug Rabson ret = HX509_PKCS11_TOKEN_CONFUSED; 898c19800e8SDoug Rabson goto out; 899c19800e8SDoug Rabson } 900c19800e8SDoug Rabson 901c19800e8SDoug Rabson p->slot = calloc(p->num_slots, sizeof(p->slot[0])); 902c19800e8SDoug Rabson if (p->slot == NULL) { 903c19800e8SDoug Rabson free(slot_ids); 904c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, 905c19800e8SDoug Rabson "Failed to get memory for slot-list"); 906c19800e8SDoug Rabson ret = ENOMEM; 907c19800e8SDoug Rabson goto out; 908c19800e8SDoug Rabson } 909c19800e8SDoug Rabson 910c19800e8SDoug Rabson for (i = 0; i < p->num_slots; i++) { 911c19800e8SDoug Rabson ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); 912c19800e8SDoug Rabson if (ret) 913c19800e8SDoug Rabson break; 914c19800e8SDoug Rabson if (p->slot[i].flags & P11_TOKEN_PRESENT) 915c19800e8SDoug Rabson num_tokens++; 916c19800e8SDoug Rabson } 917c19800e8SDoug Rabson free(slot_ids); 918c19800e8SDoug Rabson if (ret) 919c19800e8SDoug Rabson goto out; 920c19800e8SDoug Rabson if (num_tokens == 0) { 921c19800e8SDoug Rabson ret = HX509_PKCS11_NO_TOKEN; 922c19800e8SDoug Rabson goto out; 923c19800e8SDoug Rabson } 924c19800e8SDoug Rabson } 925c19800e8SDoug Rabson 926c19800e8SDoug Rabson *data = p; 927c19800e8SDoug Rabson 928c19800e8SDoug Rabson return 0; 929c19800e8SDoug Rabson out: 930c19800e8SDoug Rabson p11_release_module(p); 931c19800e8SDoug Rabson return ret; 932c19800e8SDoug Rabson } 933c19800e8SDoug Rabson 934c19800e8SDoug Rabson static void 935c19800e8SDoug Rabson p11_release_module(struct p11_module *p) 936c19800e8SDoug Rabson { 937*ae771770SStanislav Sedov size_t i; 938c19800e8SDoug Rabson 939*ae771770SStanislav Sedov if (p->ref == 0) 940*ae771770SStanislav Sedov _hx509_abort("pkcs11 ref to low"); 941*ae771770SStanislav Sedov if (--p->ref > 0) 942c19800e8SDoug Rabson return; 943c19800e8SDoug Rabson 944c19800e8SDoug Rabson for (i = 0; i < p->num_slots; i++) { 945c19800e8SDoug Rabson if (p->slot[i].flags & P11_SESSION_IN_USE) 946c19800e8SDoug Rabson _hx509_abort("pkcs11 module release while session in use"); 947c19800e8SDoug Rabson if (p->slot[i].flags & P11_SESSION) { 948*ae771770SStanislav Sedov P11FUNC(p, CloseSession, (p->slot[i].session)); 949c19800e8SDoug Rabson } 950c19800e8SDoug Rabson 951c19800e8SDoug Rabson if (p->slot[i].name) 952c19800e8SDoug Rabson free(p->slot[i].name); 953c19800e8SDoug Rabson if (p->slot[i].pin) { 954c19800e8SDoug Rabson memset(p->slot[i].pin, 0, strlen(p->slot[i].pin)); 955c19800e8SDoug Rabson free(p->slot[i].pin); 956c19800e8SDoug Rabson } 957c19800e8SDoug Rabson if (p->slot[i].mechs.num) { 958c19800e8SDoug Rabson free(p->slot[i].mechs.list); 959c19800e8SDoug Rabson 960c19800e8SDoug Rabson if (p->slot[i].mechs.infos) { 961*ae771770SStanislav Sedov size_t j; 962c19800e8SDoug Rabson 963c19800e8SDoug Rabson for (j = 0 ; j < p->slot[i].mechs.num ; j++) 964c19800e8SDoug Rabson free(p->slot[i].mechs.infos[j]); 965c19800e8SDoug Rabson free(p->slot[i].mechs.infos); 966c19800e8SDoug Rabson } 967c19800e8SDoug Rabson } 968c19800e8SDoug Rabson } 969c19800e8SDoug Rabson free(p->slot); 970c19800e8SDoug Rabson 971c19800e8SDoug Rabson if (p->funcs) 972c19800e8SDoug Rabson P11FUNC(p, Finalize, (NULL)); 973c19800e8SDoug Rabson 974c19800e8SDoug Rabson if (p->dl_handle) 975c19800e8SDoug Rabson dlclose(p->dl_handle); 976c19800e8SDoug Rabson 977c19800e8SDoug Rabson memset(p, 0, sizeof(*p)); 978c19800e8SDoug Rabson free(p); 979c19800e8SDoug Rabson } 980c19800e8SDoug Rabson 981c19800e8SDoug Rabson static int 982c19800e8SDoug Rabson p11_free(hx509_certs certs, void *data) 983c19800e8SDoug Rabson { 984c19800e8SDoug Rabson struct p11_module *p = data; 985*ae771770SStanislav Sedov size_t i; 986c19800e8SDoug Rabson 987c19800e8SDoug Rabson for (i = 0; i < p->num_slots; i++) { 988c19800e8SDoug Rabson if (p->slot[i].certs) 989c19800e8SDoug Rabson hx509_certs_free(&p->slot[i].certs); 990c19800e8SDoug Rabson } 991c19800e8SDoug Rabson p11_release_module(p); 992c19800e8SDoug Rabson return 0; 993c19800e8SDoug Rabson } 994c19800e8SDoug Rabson 995c19800e8SDoug Rabson struct p11_cursor { 996c19800e8SDoug Rabson hx509_certs certs; 997c19800e8SDoug Rabson void *cursor; 998c19800e8SDoug Rabson }; 999c19800e8SDoug Rabson 1000c19800e8SDoug Rabson static int 1001c19800e8SDoug Rabson p11_iter_start(hx509_context context, 1002c19800e8SDoug Rabson hx509_certs certs, void *data, void **cursor) 1003c19800e8SDoug Rabson { 1004c19800e8SDoug Rabson struct p11_module *p = data; 1005c19800e8SDoug Rabson struct p11_cursor *c; 1006*ae771770SStanislav Sedov int ret; 1007*ae771770SStanislav Sedov size_t i; 1008c19800e8SDoug Rabson 1009c19800e8SDoug Rabson c = malloc(sizeof(*c)); 1010c19800e8SDoug Rabson if (c == NULL) { 1011c19800e8SDoug Rabson hx509_clear_error_string(context); 1012c19800e8SDoug Rabson return ENOMEM; 1013c19800e8SDoug Rabson } 1014c19800e8SDoug Rabson ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs); 1015c19800e8SDoug Rabson if (ret) { 1016c19800e8SDoug Rabson free(c); 1017c19800e8SDoug Rabson return ret; 1018c19800e8SDoug Rabson } 1019c19800e8SDoug Rabson 1020c19800e8SDoug Rabson for (i = 0 ; i < p->num_slots; i++) { 1021c19800e8SDoug Rabson if (p->slot[i].certs == NULL) 1022c19800e8SDoug Rabson continue; 1023c19800e8SDoug Rabson ret = hx509_certs_merge(context, c->certs, p->slot[i].certs); 1024c19800e8SDoug Rabson if (ret) { 1025c19800e8SDoug Rabson hx509_certs_free(&c->certs); 1026c19800e8SDoug Rabson free(c); 1027c19800e8SDoug Rabson return ret; 1028c19800e8SDoug Rabson } 1029c19800e8SDoug Rabson } 1030c19800e8SDoug Rabson 1031c19800e8SDoug Rabson ret = hx509_certs_start_seq(context, c->certs, &c->cursor); 1032c19800e8SDoug Rabson if (ret) { 1033c19800e8SDoug Rabson hx509_certs_free(&c->certs); 1034c19800e8SDoug Rabson free(c); 1035c19800e8SDoug Rabson return 0; 1036c19800e8SDoug Rabson } 1037c19800e8SDoug Rabson *cursor = c; 1038c19800e8SDoug Rabson 1039c19800e8SDoug Rabson return 0; 1040c19800e8SDoug Rabson } 1041c19800e8SDoug Rabson 1042c19800e8SDoug Rabson static int 1043c19800e8SDoug Rabson p11_iter(hx509_context context, 1044c19800e8SDoug Rabson hx509_certs certs, void *data, void *cursor, hx509_cert *cert) 1045c19800e8SDoug Rabson { 1046c19800e8SDoug Rabson struct p11_cursor *c = cursor; 1047c19800e8SDoug Rabson return hx509_certs_next_cert(context, c->certs, c->cursor, cert); 1048c19800e8SDoug Rabson } 1049c19800e8SDoug Rabson 1050c19800e8SDoug Rabson static int 1051c19800e8SDoug Rabson p11_iter_end(hx509_context context, 1052c19800e8SDoug Rabson hx509_certs certs, void *data, void *cursor) 1053c19800e8SDoug Rabson { 1054c19800e8SDoug Rabson struct p11_cursor *c = cursor; 1055c19800e8SDoug Rabson int ret; 1056c19800e8SDoug Rabson ret = hx509_certs_end_seq(context, c->certs, c->cursor); 1057c19800e8SDoug Rabson hx509_certs_free(&c->certs); 1058c19800e8SDoug Rabson free(c); 1059c19800e8SDoug Rabson return ret; 1060c19800e8SDoug Rabson } 1061c19800e8SDoug Rabson 1062c19800e8SDoug Rabson #define MECHFLAG(x) { "unknown-flag-" #x, x } 1063c19800e8SDoug Rabson static struct units mechflags[] = { 1064c19800e8SDoug Rabson MECHFLAG(0x80000000), 1065c19800e8SDoug Rabson MECHFLAG(0x40000000), 1066c19800e8SDoug Rabson MECHFLAG(0x20000000), 1067c19800e8SDoug Rabson MECHFLAG(0x10000000), 1068c19800e8SDoug Rabson MECHFLAG(0x08000000), 1069c19800e8SDoug Rabson MECHFLAG(0x04000000), 1070c19800e8SDoug Rabson {"ec-compress", 0x2000000 }, 1071c19800e8SDoug Rabson {"ec-uncompress", 0x1000000 }, 1072c19800e8SDoug Rabson {"ec-namedcurve", 0x0800000 }, 1073c19800e8SDoug Rabson {"ec-ecparameters", 0x0400000 }, 1074c19800e8SDoug Rabson {"ec-f-2m", 0x0200000 }, 1075c19800e8SDoug Rabson {"ec-f-p", 0x0100000 }, 1076c19800e8SDoug Rabson {"derive", 0x0080000 }, 1077c19800e8SDoug Rabson {"unwrap", 0x0040000 }, 1078c19800e8SDoug Rabson {"wrap", 0x0020000 }, 1079c19800e8SDoug Rabson {"genereate-key-pair", 0x0010000 }, 1080c19800e8SDoug Rabson {"generate", 0x0008000 }, 1081c19800e8SDoug Rabson {"verify-recover", 0x0004000 }, 1082c19800e8SDoug Rabson {"verify", 0x0002000 }, 1083c19800e8SDoug Rabson {"sign-recover", 0x0001000 }, 1084c19800e8SDoug Rabson {"sign", 0x0000800 }, 1085c19800e8SDoug Rabson {"digest", 0x0000400 }, 1086c19800e8SDoug Rabson {"decrypt", 0x0000200 }, 1087c19800e8SDoug Rabson {"encrypt", 0x0000100 }, 1088c19800e8SDoug Rabson MECHFLAG(0x00080), 1089c19800e8SDoug Rabson MECHFLAG(0x00040), 1090c19800e8SDoug Rabson MECHFLAG(0x00020), 1091c19800e8SDoug Rabson MECHFLAG(0x00010), 1092c19800e8SDoug Rabson MECHFLAG(0x00008), 1093c19800e8SDoug Rabson MECHFLAG(0x00004), 1094c19800e8SDoug Rabson MECHFLAG(0x00002), 1095c19800e8SDoug Rabson {"hw", 0x0000001 }, 1096c19800e8SDoug Rabson { NULL, 0x0000000 } 1097c19800e8SDoug Rabson }; 1098c19800e8SDoug Rabson #undef MECHFLAG 1099c19800e8SDoug Rabson 1100c19800e8SDoug Rabson static int 1101c19800e8SDoug Rabson p11_printinfo(hx509_context context, 1102c19800e8SDoug Rabson hx509_certs certs, 1103c19800e8SDoug Rabson void *data, 1104c19800e8SDoug Rabson int (*func)(void *, const char *), 1105c19800e8SDoug Rabson void *ctx) 1106c19800e8SDoug Rabson { 1107c19800e8SDoug Rabson struct p11_module *p = data; 1108*ae771770SStanislav Sedov size_t i, j; 1109c19800e8SDoug Rabson 1110c19800e8SDoug Rabson _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s", 1111c19800e8SDoug Rabson p->num_slots, p->num_slots > 1 ? "s" : ""); 1112c19800e8SDoug Rabson 1113c19800e8SDoug Rabson for (i = 0; i < p->num_slots; i++) { 1114c19800e8SDoug Rabson struct p11_slot *s = &p->slot[i]; 1115c19800e8SDoug Rabson 1116c19800e8SDoug Rabson _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x", 1117c19800e8SDoug Rabson i, (int)s->id, s->name, s->flags); 1118c19800e8SDoug Rabson 1119c19800e8SDoug Rabson _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu", 1120c19800e8SDoug Rabson (unsigned long)s->mechs.num); 1121c19800e8SDoug Rabson for (j = 0; j < s->mechs.num; j++) { 1122c19800e8SDoug Rabson const char *mechname = "unknown"; 1123c19800e8SDoug Rabson char flags[256], unknownname[40]; 1124c19800e8SDoug Rabson #define MECHNAME(s,n) case s: mechname = n; break 1125c19800e8SDoug Rabson switch(s->mechs.list[j]) { 1126c19800e8SDoug Rabson MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen"); 1127c19800e8SDoug Rabson MECHNAME(CKM_RSA_PKCS, "rsa-pkcs"); 1128c19800e8SDoug Rabson MECHNAME(CKM_RSA_X_509, "rsa-x-509"); 1129c19800e8SDoug Rabson MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs"); 1130c19800e8SDoug Rabson MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs"); 1131c19800e8SDoug Rabson MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs"); 1132c19800e8SDoug Rabson MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs"); 1133c19800e8SDoug Rabson MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs"); 1134c19800e8SDoug Rabson MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs"); 1135c19800e8SDoug Rabson MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep"); 1136c19800e8SDoug Rabson MECHNAME(CKM_SHA512_HMAC, "sha512-hmac"); 1137c19800e8SDoug Rabson MECHNAME(CKM_SHA512, "sha512"); 1138c19800e8SDoug Rabson MECHNAME(CKM_SHA384_HMAC, "sha384-hmac"); 1139c19800e8SDoug Rabson MECHNAME(CKM_SHA384, "sha384"); 1140c19800e8SDoug Rabson MECHNAME(CKM_SHA256_HMAC, "sha256-hmac"); 1141c19800e8SDoug Rabson MECHNAME(CKM_SHA256, "sha256"); 1142c19800e8SDoug Rabson MECHNAME(CKM_SHA_1, "sha1"); 1143c19800e8SDoug Rabson MECHNAME(CKM_MD5, "md5"); 1144c19800e8SDoug Rabson MECHNAME(CKM_RIPEMD160, "ripemd-160"); 1145c19800e8SDoug Rabson MECHNAME(CKM_DES_ECB, "des-ecb"); 1146c19800e8SDoug Rabson MECHNAME(CKM_DES_CBC, "des-cbc"); 1147c19800e8SDoug Rabson MECHNAME(CKM_AES_ECB, "aes-ecb"); 1148c19800e8SDoug Rabson MECHNAME(CKM_AES_CBC, "aes-cbc"); 1149c19800e8SDoug Rabson MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen"); 1150c19800e8SDoug Rabson default: 1151c19800e8SDoug Rabson snprintf(unknownname, sizeof(unknownname), 1152c19800e8SDoug Rabson "unknown-mech-%lu", 1153c19800e8SDoug Rabson (unsigned long)s->mechs.list[j]); 1154c19800e8SDoug Rabson mechname = unknownname; 1155c19800e8SDoug Rabson break; 1156c19800e8SDoug Rabson } 1157c19800e8SDoug Rabson #undef MECHNAME 1158c19800e8SDoug Rabson unparse_flags(s->mechs.infos[j]->flags, mechflags, 1159c19800e8SDoug Rabson flags, sizeof(flags)); 1160c19800e8SDoug Rabson 1161c19800e8SDoug Rabson _hx509_pi_printf(func, ctx, " %s: %s", mechname, flags); 1162c19800e8SDoug Rabson } 1163c19800e8SDoug Rabson } 1164c19800e8SDoug Rabson 1165c19800e8SDoug Rabson return 0; 1166c19800e8SDoug Rabson } 1167c19800e8SDoug Rabson 1168c19800e8SDoug Rabson static struct hx509_keyset_ops keyset_pkcs11 = { 1169c19800e8SDoug Rabson "PKCS11", 1170c19800e8SDoug Rabson 0, 1171c19800e8SDoug Rabson p11_init, 1172c19800e8SDoug Rabson NULL, 1173c19800e8SDoug Rabson p11_free, 1174c19800e8SDoug Rabson NULL, 1175c19800e8SDoug Rabson NULL, 1176c19800e8SDoug Rabson p11_iter_start, 1177c19800e8SDoug Rabson p11_iter, 1178c19800e8SDoug Rabson p11_iter_end, 1179c19800e8SDoug Rabson p11_printinfo 1180c19800e8SDoug Rabson }; 1181c19800e8SDoug Rabson 1182c19800e8SDoug Rabson #endif /* HAVE_DLOPEN */ 1183c19800e8SDoug Rabson 1184c19800e8SDoug Rabson void 1185c19800e8SDoug Rabson _hx509_ks_pkcs11_register(hx509_context context) 1186c19800e8SDoug Rabson { 1187c19800e8SDoug Rabson #ifdef HAVE_DLOPEN 1188c19800e8SDoug Rabson _hx509_ks_register(context, &keyset_pkcs11); 1189c19800e8SDoug Rabson #endif 1190c19800e8SDoug Rabson } 1191