1178825Sdfr/* 2233294Sstas * Copyright (c) 2004 - 2008 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr#ifdef HAVE_DLFCN_H 36178825Sdfr#include <dlfcn.h> 37178825Sdfr#endif 38178825Sdfr 39178825Sdfr#ifdef HAVE_DLOPEN 40178825Sdfr 41178825Sdfr#include "pkcs11.h" 42178825Sdfr 43178825Sdfrstruct p11_slot { 44178825Sdfr int flags; 45178825Sdfr#define P11_SESSION 1 46178825Sdfr#define P11_SESSION_IN_USE 2 47178825Sdfr#define P11_LOGIN_REQ 4 48178825Sdfr#define P11_LOGIN_DONE 8 49178825Sdfr#define P11_TOKEN_PRESENT 16 50178825Sdfr CK_SESSION_HANDLE session; 51178825Sdfr CK_SLOT_ID id; 52178825Sdfr CK_BBOOL token; 53178825Sdfr char *name; 54178825Sdfr hx509_certs certs; 55178825Sdfr char *pin; 56178825Sdfr struct { 57178825Sdfr CK_MECHANISM_TYPE_PTR list; 58178825Sdfr CK_ULONG num; 59178825Sdfr CK_MECHANISM_INFO_PTR *infos; 60178825Sdfr } mechs; 61178825Sdfr}; 62178825Sdfr 63178825Sdfrstruct p11_module { 64178825Sdfr void *dl_handle; 65178825Sdfr CK_FUNCTION_LIST_PTR funcs; 66178825Sdfr CK_ULONG num_slots; 67233294Sstas unsigned int ref; 68178825Sdfr struct p11_slot *slot; 69178825Sdfr}; 70178825Sdfr 71178825Sdfr#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args 72178825Sdfr 73178825Sdfrstatic int p11_get_session(hx509_context, 74178825Sdfr struct p11_module *, 75178825Sdfr struct p11_slot *, 76178825Sdfr hx509_lock, 77178825Sdfr CK_SESSION_HANDLE *); 78178825Sdfrstatic int p11_put_session(struct p11_module *, 79178825Sdfr struct p11_slot *, 80178825Sdfr CK_SESSION_HANDLE); 81178825Sdfrstatic void p11_release_module(struct p11_module *); 82178825Sdfr 83178825Sdfrstatic int p11_list_keys(hx509_context, 84178825Sdfr struct p11_module *, 85233294Sstas struct p11_slot *, 86178825Sdfr CK_SESSION_HANDLE, 87178825Sdfr hx509_lock, 88178825Sdfr hx509_certs *); 89178825Sdfr 90178825Sdfr/* 91178825Sdfr * 92178825Sdfr */ 93178825Sdfr 94178825Sdfrstruct p11_rsa { 95178825Sdfr struct p11_module *p; 96178825Sdfr struct p11_slot *slot; 97178825Sdfr CK_OBJECT_HANDLE private_key; 98178825Sdfr CK_OBJECT_HANDLE public_key; 99178825Sdfr}; 100178825Sdfr 101178825Sdfrstatic int 102178825Sdfrp11_rsa_public_encrypt(int flen, 103178825Sdfr const unsigned char *from, 104178825Sdfr unsigned char *to, 105178825Sdfr RSA *rsa, 106178825Sdfr int padding) 107178825Sdfr{ 108178825Sdfr return -1; 109178825Sdfr} 110178825Sdfr 111178825Sdfrstatic int 112178825Sdfrp11_rsa_public_decrypt(int flen, 113178825Sdfr const unsigned char *from, 114178825Sdfr unsigned char *to, 115178825Sdfr RSA *rsa, 116178825Sdfr int padding) 117178825Sdfr{ 118178825Sdfr return -1; 119178825Sdfr} 120178825Sdfr 121178825Sdfr 122178825Sdfrstatic int 123233294Sstasp11_rsa_private_encrypt(int flen, 124178825Sdfr const unsigned char *from, 125178825Sdfr unsigned char *to, 126178825Sdfr RSA *rsa, 127178825Sdfr int padding) 128178825Sdfr{ 129178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 130178825Sdfr CK_OBJECT_HANDLE key = p11rsa->private_key; 131178825Sdfr CK_SESSION_HANDLE session; 132178825Sdfr CK_MECHANISM mechanism; 133178825Sdfr CK_ULONG ck_sigsize; 134178825Sdfr int ret; 135178825Sdfr 136178825Sdfr if (padding != RSA_PKCS1_PADDING) 137178825Sdfr return -1; 138178825Sdfr 139178825Sdfr memset(&mechanism, 0, sizeof(mechanism)); 140178825Sdfr mechanism.mechanism = CKM_RSA_PKCS; 141178825Sdfr 142178825Sdfr ck_sigsize = RSA_size(rsa); 143178825Sdfr 144178825Sdfr ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); 145178825Sdfr if (ret) 146178825Sdfr return -1; 147178825Sdfr 148178825Sdfr ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key)); 149178825Sdfr if (ret != CKR_OK) { 150178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 151178825Sdfr return -1; 152178825Sdfr } 153178825Sdfr 154233294Sstas ret = P11FUNC(p11rsa->p, Sign, 155233294Sstas (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); 156178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 157178825Sdfr if (ret != CKR_OK) 158178825Sdfr return -1; 159178825Sdfr 160178825Sdfr return ck_sigsize; 161178825Sdfr} 162178825Sdfr 163178825Sdfrstatic int 164178825Sdfrp11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, 165178825Sdfr RSA * rsa, int padding) 166178825Sdfr{ 167178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 168178825Sdfr CK_OBJECT_HANDLE key = p11rsa->private_key; 169178825Sdfr CK_SESSION_HANDLE session; 170178825Sdfr CK_MECHANISM mechanism; 171178825Sdfr CK_ULONG ck_sigsize; 172178825Sdfr int ret; 173178825Sdfr 174178825Sdfr if (padding != RSA_PKCS1_PADDING) 175178825Sdfr return -1; 176178825Sdfr 177178825Sdfr memset(&mechanism, 0, sizeof(mechanism)); 178178825Sdfr mechanism.mechanism = CKM_RSA_PKCS; 179178825Sdfr 180178825Sdfr ck_sigsize = RSA_size(rsa); 181178825Sdfr 182178825Sdfr ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); 183178825Sdfr if (ret) 184178825Sdfr return -1; 185178825Sdfr 186178825Sdfr ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key)); 187178825Sdfr if (ret != CKR_OK) { 188178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 189178825Sdfr return -1; 190178825Sdfr } 191178825Sdfr 192233294Sstas ret = P11FUNC(p11rsa->p, Decrypt, 193233294Sstas (session, (CK_BYTE *)(intptr_t)from, flen, to, &ck_sigsize)); 194178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 195178825Sdfr if (ret != CKR_OK) 196178825Sdfr return -1; 197178825Sdfr 198178825Sdfr return ck_sigsize; 199178825Sdfr} 200178825Sdfr 201233294Sstasstatic int 202178825Sdfrp11_rsa_init(RSA *rsa) 203178825Sdfr{ 204178825Sdfr return 1; 205178825Sdfr} 206178825Sdfr 207178825Sdfrstatic int 208178825Sdfrp11_rsa_finish(RSA *rsa) 209178825Sdfr{ 210178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 211178825Sdfr p11_release_module(p11rsa->p); 212178825Sdfr free(p11rsa); 213178825Sdfr return 1; 214178825Sdfr} 215178825Sdfr 216178825Sdfrstatic const RSA_METHOD p11_rsa_pkcs1_method = { 217178825Sdfr "hx509 PKCS11 PKCS#1 RSA", 218178825Sdfr p11_rsa_public_encrypt, 219178825Sdfr p11_rsa_public_decrypt, 220178825Sdfr p11_rsa_private_encrypt, 221178825Sdfr p11_rsa_private_decrypt, 222178825Sdfr NULL, 223178825Sdfr NULL, 224178825Sdfr p11_rsa_init, 225178825Sdfr p11_rsa_finish, 226178825Sdfr 0, 227178825Sdfr NULL, 228178825Sdfr NULL, 229178825Sdfr NULL 230178825Sdfr}; 231178825Sdfr 232178825Sdfr/* 233178825Sdfr * 234178825Sdfr */ 235178825Sdfr 236178825Sdfrstatic int 237178825Sdfrp11_mech_info(hx509_context context, 238178825Sdfr struct p11_module *p, 239178825Sdfr struct p11_slot *slot, 240178825Sdfr int num) 241178825Sdfr{ 242178825Sdfr CK_ULONG i; 243178825Sdfr int ret; 244178825Sdfr 245178825Sdfr ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i)); 246178825Sdfr if (ret) { 247178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 248178825Sdfr "Failed to get mech list count for slot %d", 249178825Sdfr num); 250178825Sdfr return HX509_PKCS11_NO_MECH; 251178825Sdfr } 252178825Sdfr if (i == 0) { 253178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 254178825Sdfr "no mech supported for slot %d", num); 255178825Sdfr return HX509_PKCS11_NO_MECH; 256178825Sdfr } 257178825Sdfr slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0])); 258178825Sdfr if (slot->mechs.list == NULL) { 259178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 260178825Sdfr "out of memory"); 261178825Sdfr return ENOMEM; 262178825Sdfr } 263178825Sdfr slot->mechs.num = i; 264178825Sdfr ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i)); 265178825Sdfr if (ret) { 266178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 267178825Sdfr "Failed to get mech list for slot %d", 268178825Sdfr num); 269178825Sdfr return HX509_PKCS11_NO_MECH; 270178825Sdfr } 271178825Sdfr assert(i == slot->mechs.num); 272178825Sdfr 273178825Sdfr slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos)); 274178825Sdfr if (slot->mechs.list == NULL) { 275178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 276178825Sdfr "out of memory"); 277178825Sdfr return ENOMEM; 278178825Sdfr } 279178825Sdfr 280178825Sdfr for (i = 0; i < slot->mechs.num; i++) { 281178825Sdfr slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0]))); 282178825Sdfr if (slot->mechs.infos[i] == NULL) { 283178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 284178825Sdfr "out of memory"); 285178825Sdfr return ENOMEM; 286178825Sdfr } 287178825Sdfr ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i], 288178825Sdfr slot->mechs.infos[i])); 289178825Sdfr if (ret) { 290178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 291178825Sdfr "Failed to get mech info for slot %d", 292178825Sdfr num); 293178825Sdfr return HX509_PKCS11_NO_MECH; 294178825Sdfr } 295178825Sdfr } 296178825Sdfr 297178825Sdfr return 0; 298178825Sdfr} 299178825Sdfr 300178825Sdfrstatic int 301233294Sstasp11_init_slot(hx509_context context, 302178825Sdfr struct p11_module *p, 303178825Sdfr hx509_lock lock, 304178825Sdfr CK_SLOT_ID id, 305178825Sdfr int num, 306178825Sdfr struct p11_slot *slot) 307178825Sdfr{ 308178825Sdfr CK_SESSION_HANDLE session; 309178825Sdfr CK_SLOT_INFO slot_info; 310178825Sdfr CK_TOKEN_INFO token_info; 311233294Sstas size_t i; 312233294Sstas int ret; 313178825Sdfr 314178825Sdfr slot->certs = NULL; 315178825Sdfr slot->id = id; 316178825Sdfr 317178825Sdfr ret = P11FUNC(p, GetSlotInfo, (slot->id, &slot_info)); 318178825Sdfr if (ret) { 319178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, 320178825Sdfr "Failed to init PKCS11 slot %d", 321178825Sdfr num); 322178825Sdfr return HX509_PKCS11_TOKEN_CONFUSED; 323178825Sdfr } 324178825Sdfr 325178825Sdfr for (i = sizeof(slot_info.slotDescription) - 1; i > 0; i--) { 326178825Sdfr char c = slot_info.slotDescription[i]; 327178825Sdfr if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\0') 328178825Sdfr continue; 329178825Sdfr i++; 330178825Sdfr break; 331178825Sdfr } 332178825Sdfr 333178825Sdfr asprintf(&slot->name, "%.*s", 334233294Sstas (int)i, slot_info.slotDescription); 335178825Sdfr 336178825Sdfr if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0) 337178825Sdfr return 0; 338178825Sdfr 339178825Sdfr ret = P11FUNC(p, GetTokenInfo, (slot->id, &token_info)); 340178825Sdfr if (ret) { 341178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_TOKEN, 342178825Sdfr "Failed to init PKCS11 slot %d " 343178825Sdfr "with error 0x08x", 344178825Sdfr num, ret); 345178825Sdfr return HX509_PKCS11_NO_TOKEN; 346178825Sdfr } 347178825Sdfr slot->flags |= P11_TOKEN_PRESENT; 348178825Sdfr 349178825Sdfr if (token_info.flags & CKF_LOGIN_REQUIRED) 350178825Sdfr slot->flags |= P11_LOGIN_REQ; 351178825Sdfr 352178825Sdfr ret = p11_get_session(context, p, slot, lock, &session); 353178825Sdfr if (ret) 354178825Sdfr return ret; 355178825Sdfr 356178825Sdfr ret = p11_mech_info(context, p, slot, num); 357178825Sdfr if (ret) 358178825Sdfr goto out; 359178825Sdfr 360178825Sdfr ret = p11_list_keys(context, p, slot, session, lock, &slot->certs); 361178825Sdfr out: 362178825Sdfr p11_put_session(p, slot, session); 363178825Sdfr 364178825Sdfr return ret; 365178825Sdfr} 366178825Sdfr 367178825Sdfrstatic int 368178825Sdfrp11_get_session(hx509_context context, 369178825Sdfr struct p11_module *p, 370178825Sdfr struct p11_slot *slot, 371178825Sdfr hx509_lock lock, 372178825Sdfr CK_SESSION_HANDLE *psession) 373178825Sdfr{ 374178825Sdfr CK_RV ret; 375178825Sdfr 376178825Sdfr if (slot->flags & P11_SESSION_IN_USE) 377178825Sdfr _hx509_abort("slot already in session"); 378233294Sstas 379178825Sdfr if (slot->flags & P11_SESSION) { 380178825Sdfr slot->flags |= P11_SESSION_IN_USE; 381178825Sdfr *psession = slot->session; 382178825Sdfr return 0; 383178825Sdfr } 384178825Sdfr 385233294Sstas ret = P11FUNC(p, OpenSession, (slot->id, 386178825Sdfr CKF_SERIAL_SESSION, 387178825Sdfr NULL, 388178825Sdfr NULL, 389178825Sdfr &slot->session)); 390178825Sdfr if (ret != CKR_OK) { 391178825Sdfr if (context) 392178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_OPEN_SESSION, 393178825Sdfr "Failed to OpenSession for slot id %d " 394178825Sdfr "with error: 0x%08x", 395178825Sdfr (int)slot->id, ret); 396178825Sdfr return HX509_PKCS11_OPEN_SESSION; 397178825Sdfr } 398233294Sstas 399178825Sdfr slot->flags |= P11_SESSION; 400233294Sstas 401233294Sstas /* 402178825Sdfr * If we have have to login, and haven't tried before and have a 403178825Sdfr * prompter or known to work pin code. 404178825Sdfr * 405178825Sdfr * This code is very conversative and only uses the prompter in 406178825Sdfr * the hx509_lock, the reason is that it's bad to try many 407178825Sdfr * passwords on a pkcs11 token, it might lock up and have to be 408178825Sdfr * unlocked by a administrator. 409178825Sdfr * 410178825Sdfr * XXX try harder to not use pin several times on the same card. 411178825Sdfr */ 412178825Sdfr 413178825Sdfr if ( (slot->flags & P11_LOGIN_REQ) 414178825Sdfr && (slot->flags & P11_LOGIN_DONE) == 0 415178825Sdfr && (lock || slot->pin)) 416178825Sdfr { 417178825Sdfr hx509_prompt prompt; 418178825Sdfr char pin[20]; 419178825Sdfr char *str; 420178825Sdfr 421178825Sdfr if (slot->pin == NULL) { 422178825Sdfr 423178825Sdfr memset(&prompt, 0, sizeof(prompt)); 424178825Sdfr 425178825Sdfr asprintf(&str, "PIN code for %s: ", slot->name); 426178825Sdfr prompt.prompt = str; 427178825Sdfr prompt.type = HX509_PROMPT_TYPE_PASSWORD; 428178825Sdfr prompt.reply.data = pin; 429178825Sdfr prompt.reply.length = sizeof(pin); 430233294Sstas 431178825Sdfr ret = hx509_lock_prompt(lock, &prompt); 432178825Sdfr if (ret) { 433178825Sdfr free(str); 434178825Sdfr if (context) 435178825Sdfr hx509_set_error_string(context, 0, ret, 436178825Sdfr "Failed to get pin code for slot " 437178825Sdfr "id %d with error: %d", 438178825Sdfr (int)slot->id, ret); 439178825Sdfr return ret; 440178825Sdfr } 441178825Sdfr free(str); 442178825Sdfr } else { 443178825Sdfr strlcpy(pin, slot->pin, sizeof(pin)); 444178825Sdfr } 445178825Sdfr 446178825Sdfr ret = P11FUNC(p, Login, (slot->session, CKU_USER, 447178825Sdfr (unsigned char*)pin, strlen(pin))); 448178825Sdfr if (ret != CKR_OK) { 449178825Sdfr if (context) 450178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN, 451178825Sdfr "Failed to login on slot id %d " 452178825Sdfr "with error: 0x%08x", 453178825Sdfr (int)slot->id, ret); 454178825Sdfr return HX509_PKCS11_LOGIN; 455233294Sstas } else 456233294Sstas slot->flags |= P11_LOGIN_DONE; 457233294Sstas 458178825Sdfr if (slot->pin == NULL) { 459178825Sdfr slot->pin = strdup(pin); 460178825Sdfr if (slot->pin == NULL) { 461178825Sdfr if (context) 462178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 463178825Sdfr "out of memory"); 464178825Sdfr return ENOMEM; 465178825Sdfr } 466178825Sdfr } 467178825Sdfr } else 468178825Sdfr slot->flags |= P11_LOGIN_DONE; 469178825Sdfr 470178825Sdfr slot->flags |= P11_SESSION_IN_USE; 471178825Sdfr 472178825Sdfr *psession = slot->session; 473178825Sdfr 474178825Sdfr return 0; 475178825Sdfr} 476178825Sdfr 477178825Sdfrstatic int 478178825Sdfrp11_put_session(struct p11_module *p, 479233294Sstas struct p11_slot *slot, 480178825Sdfr CK_SESSION_HANDLE session) 481178825Sdfr{ 482178825Sdfr if ((slot->flags & P11_SESSION_IN_USE) == 0) 483178825Sdfr _hx509_abort("slot not in session"); 484178825Sdfr slot->flags &= ~P11_SESSION_IN_USE; 485178825Sdfr 486178825Sdfr return 0; 487178825Sdfr} 488178825Sdfr 489178825Sdfrstatic int 490178825Sdfriterate_entries(hx509_context context, 491178825Sdfr struct p11_module *p, struct p11_slot *slot, 492178825Sdfr CK_SESSION_HANDLE session, 493178825Sdfr CK_ATTRIBUTE *search_data, int num_search_data, 494178825Sdfr CK_ATTRIBUTE *query, int num_query, 495178825Sdfr int (*func)(hx509_context, 496178825Sdfr struct p11_module *, struct p11_slot *, 497178825Sdfr CK_SESSION_HANDLE session, 498178825Sdfr CK_OBJECT_HANDLE object, 499178825Sdfr void *, CK_ATTRIBUTE *, int), void *ptr) 500178825Sdfr{ 501178825Sdfr CK_OBJECT_HANDLE object; 502178825Sdfr CK_ULONG object_count; 503233294Sstas int ret, ret2, i; 504178825Sdfr 505178825Sdfr ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); 506178825Sdfr if (ret != CKR_OK) { 507178825Sdfr return -1; 508178825Sdfr } 509178825Sdfr while (1) { 510178825Sdfr ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); 511178825Sdfr if (ret != CKR_OK) { 512178825Sdfr return -1; 513178825Sdfr } 514178825Sdfr if (object_count == 0) 515178825Sdfr break; 516233294Sstas 517178825Sdfr for (i = 0; i < num_query; i++) 518178825Sdfr query[i].pValue = NULL; 519178825Sdfr 520233294Sstas ret = P11FUNC(p, GetAttributeValue, 521178825Sdfr (session, object, query, num_query)); 522178825Sdfr if (ret != CKR_OK) { 523178825Sdfr return -1; 524178825Sdfr } 525178825Sdfr for (i = 0; i < num_query; i++) { 526178825Sdfr query[i].pValue = malloc(query[i].ulValueLen); 527178825Sdfr if (query[i].pValue == NULL) { 528178825Sdfr ret = ENOMEM; 529178825Sdfr goto out; 530178825Sdfr } 531178825Sdfr } 532178825Sdfr ret = P11FUNC(p, GetAttributeValue, 533178825Sdfr (session, object, query, num_query)); 534178825Sdfr if (ret != CKR_OK) { 535178825Sdfr ret = -1; 536178825Sdfr goto out; 537178825Sdfr } 538233294Sstas 539178825Sdfr ret = (*func)(context, p, slot, session, object, ptr, query, num_query); 540178825Sdfr if (ret) 541178825Sdfr goto out; 542178825Sdfr 543178825Sdfr for (i = 0; i < num_query; i++) { 544178825Sdfr if (query[i].pValue) 545178825Sdfr free(query[i].pValue); 546178825Sdfr query[i].pValue = NULL; 547178825Sdfr } 548178825Sdfr } 549178825Sdfr out: 550178825Sdfr 551178825Sdfr for (i = 0; i < num_query; i++) { 552178825Sdfr if (query[i].pValue) 553178825Sdfr free(query[i].pValue); 554178825Sdfr query[i].pValue = NULL; 555178825Sdfr } 556178825Sdfr 557233294Sstas ret2 = P11FUNC(p, FindObjectsFinal, (session)); 558233294Sstas if (ret2 != CKR_OK) { 559233294Sstas return ret2; 560178825Sdfr } 561178825Sdfr 562233294Sstas return ret; 563233294Sstas} 564178825Sdfr 565178825Sdfrstatic BIGNUM * 566178825Sdfrgetattr_bn(struct p11_module *p, 567178825Sdfr struct p11_slot *slot, 568178825Sdfr CK_SESSION_HANDLE session, 569233294Sstas CK_OBJECT_HANDLE object, 570178825Sdfr unsigned int type) 571178825Sdfr{ 572178825Sdfr CK_ATTRIBUTE query; 573178825Sdfr BIGNUM *bn; 574178825Sdfr int ret; 575178825Sdfr 576178825Sdfr query.type = type; 577178825Sdfr query.pValue = NULL; 578178825Sdfr query.ulValueLen = 0; 579178825Sdfr 580233294Sstas ret = P11FUNC(p, GetAttributeValue, 581178825Sdfr (session, object, &query, 1)); 582178825Sdfr if (ret != CKR_OK) 583178825Sdfr return NULL; 584178825Sdfr 585178825Sdfr query.pValue = malloc(query.ulValueLen); 586178825Sdfr 587233294Sstas ret = P11FUNC(p, GetAttributeValue, 588178825Sdfr (session, object, &query, 1)); 589178825Sdfr if (ret != CKR_OK) { 590178825Sdfr free(query.pValue); 591178825Sdfr return NULL; 592178825Sdfr } 593178825Sdfr bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL); 594178825Sdfr free(query.pValue); 595178825Sdfr 596178825Sdfr return bn; 597178825Sdfr} 598178825Sdfr 599178825Sdfrstatic int 600178825Sdfrcollect_private_key(hx509_context context, 601178825Sdfr struct p11_module *p, struct p11_slot *slot, 602178825Sdfr CK_SESSION_HANDLE session, 603178825Sdfr CK_OBJECT_HANDLE object, 604178825Sdfr void *ptr, CK_ATTRIBUTE *query, int num_query) 605178825Sdfr{ 606178825Sdfr struct hx509_collector *collector = ptr; 607178825Sdfr hx509_private_key key; 608178825Sdfr heim_octet_string localKeyId; 609178825Sdfr int ret; 610178825Sdfr RSA *rsa; 611178825Sdfr struct p11_rsa *p11rsa; 612178825Sdfr 613178825Sdfr localKeyId.data = query[0].pValue; 614178825Sdfr localKeyId.length = query[0].ulValueLen; 615178825Sdfr 616233294Sstas ret = hx509_private_key_init(&key, NULL, NULL); 617178825Sdfr if (ret) 618178825Sdfr return ret; 619178825Sdfr 620178825Sdfr rsa = RSA_new(); 621178825Sdfr if (rsa == NULL) 622178825Sdfr _hx509_abort("out of memory"); 623178825Sdfr 624233294Sstas /* 625178825Sdfr * The exponent and modulus should always be present according to 626178825Sdfr * the pkcs11 specification, but some smartcards leaves it out, 627178825Sdfr * let ignore any failure to fetch it. 628178825Sdfr */ 629178825Sdfr rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS); 630178825Sdfr rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT); 631178825Sdfr 632178825Sdfr p11rsa = calloc(1, sizeof(*p11rsa)); 633178825Sdfr if (p11rsa == NULL) 634178825Sdfr _hx509_abort("out of memory"); 635178825Sdfr 636178825Sdfr p11rsa->p = p; 637178825Sdfr p11rsa->slot = slot; 638178825Sdfr p11rsa->private_key = object; 639178825Sdfr 640233294Sstas if (p->ref == 0) 641233294Sstas _hx509_abort("pkcs11 ref == 0 on alloc"); 642233294Sstas p->ref++; 643233294Sstas if (p->ref == UINT_MAX) 644233294Sstas _hx509_abort("pkcs11 ref == UINT_MAX on alloc"); 645233294Sstas 646178825Sdfr RSA_set_method(rsa, &p11_rsa_pkcs1_method); 647178825Sdfr ret = RSA_set_app_data(rsa, p11rsa); 648178825Sdfr if (ret != 1) 649178825Sdfr _hx509_abort("RSA_set_app_data"); 650178825Sdfr 651233294Sstas hx509_private_key_assign_rsa(key, rsa); 652178825Sdfr 653178825Sdfr ret = _hx509_collector_private_key_add(context, 654178825Sdfr collector, 655178825Sdfr hx509_signature_rsa(), 656178825Sdfr key, 657178825Sdfr NULL, 658178825Sdfr &localKeyId); 659178825Sdfr 660178825Sdfr if (ret) { 661233294Sstas hx509_private_key_free(&key); 662178825Sdfr return ret; 663178825Sdfr } 664178825Sdfr return 0; 665178825Sdfr} 666178825Sdfr 667178825Sdfrstatic void 668178825Sdfrp11_cert_release(hx509_cert cert, void *ctx) 669178825Sdfr{ 670178825Sdfr struct p11_module *p = ctx; 671178825Sdfr p11_release_module(p); 672178825Sdfr} 673178825Sdfr 674178825Sdfr 675178825Sdfrstatic int 676233294Sstascollect_cert(hx509_context context, 677178825Sdfr struct p11_module *p, struct p11_slot *slot, 678178825Sdfr CK_SESSION_HANDLE session, 679178825Sdfr CK_OBJECT_HANDLE object, 680178825Sdfr void *ptr, CK_ATTRIBUTE *query, int num_query) 681178825Sdfr{ 682178825Sdfr struct hx509_collector *collector = ptr; 683178825Sdfr hx509_cert cert; 684178825Sdfr int ret; 685178825Sdfr 686178825Sdfr if ((CK_LONG)query[0].ulValueLen == -1 || 687233294Sstas (CK_LONG)query[1].ulValueLen == -1) 688178825Sdfr { 689178825Sdfr return 0; 690178825Sdfr } 691178825Sdfr 692233294Sstas ret = hx509_cert_init_data(context, query[1].pValue, 693178825Sdfr query[1].ulValueLen, &cert); 694178825Sdfr if (ret) 695178825Sdfr return ret; 696178825Sdfr 697233294Sstas if (p->ref == 0) 698233294Sstas _hx509_abort("pkcs11 ref == 0 on alloc"); 699233294Sstas p->ref++; 700233294Sstas if (p->ref == UINT_MAX) 701233294Sstas _hx509_abort("pkcs11 ref to high"); 702178825Sdfr 703178825Sdfr _hx509_cert_set_release(cert, p11_cert_release, p); 704178825Sdfr 705178825Sdfr { 706178825Sdfr heim_octet_string data; 707233294Sstas 708178825Sdfr data.data = query[0].pValue; 709178825Sdfr data.length = query[0].ulValueLen; 710233294Sstas 711178825Sdfr _hx509_set_cert_attribute(context, 712178825Sdfr cert, 713233294Sstas &asn1_oid_id_pkcs_9_at_localKeyId, 714178825Sdfr &data); 715178825Sdfr } 716178825Sdfr 717178825Sdfr if ((CK_LONG)query[2].ulValueLen != -1) { 718178825Sdfr char *str; 719178825Sdfr 720178825Sdfr asprintf(&str, "%.*s", 721178825Sdfr (int)query[2].ulValueLen, (char *)query[2].pValue); 722178825Sdfr if (str) { 723178825Sdfr hx509_cert_set_friendly_name(cert, str); 724178825Sdfr free(str); 725178825Sdfr } 726178825Sdfr } 727178825Sdfr 728178825Sdfr ret = _hx509_collector_certs_add(context, collector, cert); 729178825Sdfr hx509_cert_free(cert); 730178825Sdfr 731178825Sdfr return ret; 732178825Sdfr} 733178825Sdfr 734178825Sdfr 735178825Sdfrstatic int 736178825Sdfrp11_list_keys(hx509_context context, 737178825Sdfr struct p11_module *p, 738233294Sstas struct p11_slot *slot, 739178825Sdfr CK_SESSION_HANDLE session, 740178825Sdfr hx509_lock lock, 741178825Sdfr hx509_certs *certs) 742178825Sdfr{ 743178825Sdfr struct hx509_collector *collector; 744178825Sdfr CK_OBJECT_CLASS key_class; 745178825Sdfr CK_ATTRIBUTE search_data[] = { 746178825Sdfr {CKA_CLASS, NULL, 0}, 747178825Sdfr }; 748178825Sdfr CK_ATTRIBUTE query_data[3] = { 749178825Sdfr {CKA_ID, NULL, 0}, 750178825Sdfr {CKA_VALUE, NULL, 0}, 751178825Sdfr {CKA_LABEL, NULL, 0} 752178825Sdfr }; 753178825Sdfr int ret; 754178825Sdfr 755178825Sdfr search_data[0].pValue = &key_class; 756178825Sdfr search_data[0].ulValueLen = sizeof(key_class); 757178825Sdfr 758178825Sdfr if (lock == NULL) 759178825Sdfr lock = _hx509_empty_lock; 760178825Sdfr 761178825Sdfr ret = _hx509_collector_alloc(context, lock, &collector); 762178825Sdfr if (ret) 763178825Sdfr return ret; 764178825Sdfr 765178825Sdfr key_class = CKO_PRIVATE_KEY; 766178825Sdfr ret = iterate_entries(context, p, slot, session, 767178825Sdfr search_data, 1, 768178825Sdfr query_data, 1, 769178825Sdfr collect_private_key, collector); 770178825Sdfr if (ret) 771178825Sdfr goto out; 772178825Sdfr 773178825Sdfr key_class = CKO_CERTIFICATE; 774178825Sdfr ret = iterate_entries(context, p, slot, session, 775178825Sdfr search_data, 1, 776178825Sdfr query_data, 3, 777178825Sdfr collect_cert, collector); 778178825Sdfr if (ret) 779178825Sdfr goto out; 780178825Sdfr 781178825Sdfr ret = _hx509_collector_collect_certs(context, collector, &slot->certs); 782178825Sdfr 783178825Sdfrout: 784178825Sdfr _hx509_collector_free(collector); 785178825Sdfr 786178825Sdfr return ret; 787178825Sdfr} 788178825Sdfr 789178825Sdfr 790178825Sdfrstatic int 791178825Sdfrp11_init(hx509_context context, 792233294Sstas hx509_certs certs, void **data, int flags, 793178825Sdfr const char *residue, hx509_lock lock) 794178825Sdfr{ 795178825Sdfr CK_C_GetFunctionList getFuncs; 796178825Sdfr struct p11_module *p; 797178825Sdfr char *list, *str; 798178825Sdfr int ret; 799178825Sdfr 800178825Sdfr *data = NULL; 801178825Sdfr 802178825Sdfr list = strdup(residue); 803178825Sdfr if (list == NULL) 804178825Sdfr return ENOMEM; 805178825Sdfr 806178825Sdfr p = calloc(1, sizeof(*p)); 807178825Sdfr if (p == NULL) { 808178825Sdfr free(list); 809178825Sdfr return ENOMEM; 810178825Sdfr } 811178825Sdfr 812233294Sstas p->ref = 1; 813178825Sdfr 814178825Sdfr str = strchr(list, ','); 815178825Sdfr if (str) 816178825Sdfr *str++ = '\0'; 817178825Sdfr while (str) { 818178825Sdfr char *strnext; 819178825Sdfr strnext = strchr(str, ','); 820178825Sdfr if (strnext) 821178825Sdfr *strnext++ = '\0'; 822178825Sdfr#if 0 823178825Sdfr if (strncasecmp(str, "slot=", 5) == 0) 824178825Sdfr p->selected_slot = atoi(str + 5); 825178825Sdfr#endif 826178825Sdfr str = strnext; 827178825Sdfr } 828178825Sdfr 829178825Sdfr p->dl_handle = dlopen(list, RTLD_NOW); 830178825Sdfr free(list); 831178825Sdfr if (p->dl_handle == NULL) { 832178825Sdfr ret = HX509_PKCS11_LOAD; 833178825Sdfr hx509_set_error_string(context, 0, ret, 834178825Sdfr "Failed to open %s: %s", list, dlerror()); 835178825Sdfr goto out; 836178825Sdfr } 837178825Sdfr 838233294Sstas getFuncs = (CK_C_GetFunctionList) dlsym(p->dl_handle, "C_GetFunctionList"); 839178825Sdfr if (getFuncs == NULL) { 840178825Sdfr ret = HX509_PKCS11_LOAD; 841178825Sdfr hx509_set_error_string(context, 0, ret, 842233294Sstas "C_GetFunctionList missing in %s: %s", 843178825Sdfr list, dlerror()); 844178825Sdfr goto out; 845178825Sdfr } 846178825Sdfr 847178825Sdfr ret = (*getFuncs)(&p->funcs); 848178825Sdfr if (ret) { 849178825Sdfr ret = HX509_PKCS11_LOAD; 850178825Sdfr hx509_set_error_string(context, 0, ret, 851178825Sdfr "C_GetFunctionList failed in %s", list); 852178825Sdfr goto out; 853178825Sdfr } 854178825Sdfr 855178825Sdfr ret = P11FUNC(p, Initialize, (NULL_PTR)); 856178825Sdfr if (ret != CKR_OK) { 857178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 858178825Sdfr hx509_set_error_string(context, 0, ret, 859178825Sdfr "Failed initialize the PKCS11 module"); 860178825Sdfr goto out; 861178825Sdfr } 862178825Sdfr 863178825Sdfr ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots)); 864178825Sdfr if (ret) { 865178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 866178825Sdfr hx509_set_error_string(context, 0, ret, 867178825Sdfr "Failed to get number of PKCS11 slots"); 868178825Sdfr goto out; 869178825Sdfr } 870178825Sdfr 871178825Sdfr if (p->num_slots == 0) { 872178825Sdfr ret = HX509_PKCS11_NO_SLOT; 873178825Sdfr hx509_set_error_string(context, 0, ret, 874178825Sdfr "Selected PKCS11 module have no slots"); 875178825Sdfr goto out; 876178825Sdfr } 877178825Sdfr 878178825Sdfr 879178825Sdfr { 880178825Sdfr CK_SLOT_ID_PTR slot_ids; 881233294Sstas int num_tokens = 0; 882233294Sstas size_t i; 883178825Sdfr 884178825Sdfr slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); 885178825Sdfr if (slot_ids == NULL) { 886178825Sdfr hx509_clear_error_string(context); 887178825Sdfr ret = ENOMEM; 888178825Sdfr goto out; 889178825Sdfr } 890178825Sdfr 891178825Sdfr ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); 892178825Sdfr if (ret) { 893178825Sdfr free(slot_ids); 894178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, 895178825Sdfr "Failed getting slot-list from " 896178825Sdfr "PKCS11 module"); 897178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 898178825Sdfr goto out; 899178825Sdfr } 900178825Sdfr 901178825Sdfr p->slot = calloc(p->num_slots, sizeof(p->slot[0])); 902178825Sdfr if (p->slot == NULL) { 903178825Sdfr free(slot_ids); 904178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 905178825Sdfr "Failed to get memory for slot-list"); 906178825Sdfr ret = ENOMEM; 907178825Sdfr goto out; 908178825Sdfr } 909233294Sstas 910178825Sdfr for (i = 0; i < p->num_slots; i++) { 911178825Sdfr ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); 912178825Sdfr if (ret) 913178825Sdfr break; 914178825Sdfr if (p->slot[i].flags & P11_TOKEN_PRESENT) 915178825Sdfr num_tokens++; 916178825Sdfr } 917178825Sdfr free(slot_ids); 918178825Sdfr if (ret) 919178825Sdfr goto out; 920178825Sdfr if (num_tokens == 0) { 921178825Sdfr ret = HX509_PKCS11_NO_TOKEN; 922178825Sdfr goto out; 923178825Sdfr } 924178825Sdfr } 925178825Sdfr 926178825Sdfr *data = p; 927178825Sdfr 928178825Sdfr return 0; 929233294Sstas out: 930178825Sdfr p11_release_module(p); 931178825Sdfr return ret; 932178825Sdfr} 933178825Sdfr 934178825Sdfrstatic void 935178825Sdfrp11_release_module(struct p11_module *p) 936178825Sdfr{ 937233294Sstas size_t i; 938178825Sdfr 939233294Sstas if (p->ref == 0) 940233294Sstas _hx509_abort("pkcs11 ref to low"); 941233294Sstas if (--p->ref > 0) 942178825Sdfr return; 943178825Sdfr 944178825Sdfr for (i = 0; i < p->num_slots; i++) { 945178825Sdfr if (p->slot[i].flags & P11_SESSION_IN_USE) 946178825Sdfr _hx509_abort("pkcs11 module release while session in use"); 947178825Sdfr if (p->slot[i].flags & P11_SESSION) { 948233294Sstas P11FUNC(p, CloseSession, (p->slot[i].session)); 949178825Sdfr } 950178825Sdfr 951178825Sdfr if (p->slot[i].name) 952178825Sdfr free(p->slot[i].name); 953178825Sdfr if (p->slot[i].pin) { 954178825Sdfr memset(p->slot[i].pin, 0, strlen(p->slot[i].pin)); 955178825Sdfr free(p->slot[i].pin); 956178825Sdfr } 957178825Sdfr if (p->slot[i].mechs.num) { 958178825Sdfr free(p->slot[i].mechs.list); 959178825Sdfr 960178825Sdfr if (p->slot[i].mechs.infos) { 961233294Sstas size_t j; 962178825Sdfr 963178825Sdfr for (j = 0 ; j < p->slot[i].mechs.num ; j++) 964178825Sdfr free(p->slot[i].mechs.infos[j]); 965178825Sdfr free(p->slot[i].mechs.infos); 966178825Sdfr } 967178825Sdfr } 968178825Sdfr } 969178825Sdfr free(p->slot); 970178825Sdfr 971178825Sdfr if (p->funcs) 972178825Sdfr P11FUNC(p, Finalize, (NULL)); 973178825Sdfr 974178825Sdfr if (p->dl_handle) 975178825Sdfr dlclose(p->dl_handle); 976178825Sdfr 977178825Sdfr memset(p, 0, sizeof(*p)); 978178825Sdfr free(p); 979178825Sdfr} 980178825Sdfr 981178825Sdfrstatic int 982178825Sdfrp11_free(hx509_certs certs, void *data) 983178825Sdfr{ 984178825Sdfr struct p11_module *p = data; 985233294Sstas size_t i; 986178825Sdfr 987178825Sdfr for (i = 0; i < p->num_slots; i++) { 988178825Sdfr if (p->slot[i].certs) 989178825Sdfr hx509_certs_free(&p->slot[i].certs); 990178825Sdfr } 991178825Sdfr p11_release_module(p); 992178825Sdfr return 0; 993178825Sdfr} 994178825Sdfr 995178825Sdfrstruct p11_cursor { 996178825Sdfr hx509_certs certs; 997178825Sdfr void *cursor; 998178825Sdfr}; 999178825Sdfr 1000233294Sstasstatic int 1001178825Sdfrp11_iter_start(hx509_context context, 1002178825Sdfr hx509_certs certs, void *data, void **cursor) 1003178825Sdfr{ 1004178825Sdfr struct p11_module *p = data; 1005178825Sdfr struct p11_cursor *c; 1006233294Sstas int ret; 1007233294Sstas size_t i; 1008178825Sdfr 1009178825Sdfr c = malloc(sizeof(*c)); 1010178825Sdfr if (c == NULL) { 1011178825Sdfr hx509_clear_error_string(context); 1012178825Sdfr return ENOMEM; 1013178825Sdfr } 1014178825Sdfr ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs); 1015178825Sdfr if (ret) { 1016178825Sdfr free(c); 1017178825Sdfr return ret; 1018178825Sdfr } 1019178825Sdfr 1020178825Sdfr for (i = 0 ; i < p->num_slots; i++) { 1021178825Sdfr if (p->slot[i].certs == NULL) 1022178825Sdfr continue; 1023178825Sdfr ret = hx509_certs_merge(context, c->certs, p->slot[i].certs); 1024178825Sdfr if (ret) { 1025178825Sdfr hx509_certs_free(&c->certs); 1026178825Sdfr free(c); 1027178825Sdfr return ret; 1028178825Sdfr } 1029178825Sdfr } 1030178825Sdfr 1031178825Sdfr ret = hx509_certs_start_seq(context, c->certs, &c->cursor); 1032178825Sdfr if (ret) { 1033178825Sdfr hx509_certs_free(&c->certs); 1034178825Sdfr free(c); 1035178825Sdfr return 0; 1036178825Sdfr } 1037178825Sdfr *cursor = c; 1038178825Sdfr 1039178825Sdfr return 0; 1040178825Sdfr} 1041178825Sdfr 1042178825Sdfrstatic int 1043178825Sdfrp11_iter(hx509_context context, 1044178825Sdfr hx509_certs certs, void *data, void *cursor, hx509_cert *cert) 1045178825Sdfr{ 1046178825Sdfr struct p11_cursor *c = cursor; 1047178825Sdfr return hx509_certs_next_cert(context, c->certs, c->cursor, cert); 1048178825Sdfr} 1049178825Sdfr 1050178825Sdfrstatic int 1051178825Sdfrp11_iter_end(hx509_context context, 1052178825Sdfr hx509_certs certs, void *data, void *cursor) 1053178825Sdfr{ 1054178825Sdfr struct p11_cursor *c = cursor; 1055178825Sdfr int ret; 1056178825Sdfr ret = hx509_certs_end_seq(context, c->certs, c->cursor); 1057178825Sdfr hx509_certs_free(&c->certs); 1058178825Sdfr free(c); 1059178825Sdfr return ret; 1060178825Sdfr} 1061178825Sdfr 1062178825Sdfr#define MECHFLAG(x) { "unknown-flag-" #x, x } 1063178825Sdfrstatic struct units mechflags[] = { 1064178825Sdfr MECHFLAG(0x80000000), 1065178825Sdfr MECHFLAG(0x40000000), 1066178825Sdfr MECHFLAG(0x20000000), 1067178825Sdfr MECHFLAG(0x10000000), 1068178825Sdfr MECHFLAG(0x08000000), 1069178825Sdfr MECHFLAG(0x04000000), 1070178825Sdfr {"ec-compress", 0x2000000 }, 1071178825Sdfr {"ec-uncompress", 0x1000000 }, 1072178825Sdfr {"ec-namedcurve", 0x0800000 }, 1073178825Sdfr {"ec-ecparameters", 0x0400000 }, 1074178825Sdfr {"ec-f-2m", 0x0200000 }, 1075178825Sdfr {"ec-f-p", 0x0100000 }, 1076178825Sdfr {"derive", 0x0080000 }, 1077178825Sdfr {"unwrap", 0x0040000 }, 1078178825Sdfr {"wrap", 0x0020000 }, 1079178825Sdfr {"genereate-key-pair", 0x0010000 }, 1080178825Sdfr {"generate", 0x0008000 }, 1081178825Sdfr {"verify-recover", 0x0004000 }, 1082178825Sdfr {"verify", 0x0002000 }, 1083178825Sdfr {"sign-recover", 0x0001000 }, 1084178825Sdfr {"sign", 0x0000800 }, 1085178825Sdfr {"digest", 0x0000400 }, 1086178825Sdfr {"decrypt", 0x0000200 }, 1087178825Sdfr {"encrypt", 0x0000100 }, 1088178825Sdfr MECHFLAG(0x00080), 1089178825Sdfr MECHFLAG(0x00040), 1090178825Sdfr MECHFLAG(0x00020), 1091178825Sdfr MECHFLAG(0x00010), 1092178825Sdfr MECHFLAG(0x00008), 1093178825Sdfr MECHFLAG(0x00004), 1094178825Sdfr MECHFLAG(0x00002), 1095178825Sdfr {"hw", 0x0000001 }, 1096178825Sdfr { NULL, 0x0000000 } 1097178825Sdfr}; 1098178825Sdfr#undef MECHFLAG 1099178825Sdfr 1100178825Sdfrstatic int 1101233294Sstasp11_printinfo(hx509_context context, 1102233294Sstas hx509_certs certs, 1103178825Sdfr void *data, 1104178825Sdfr int (*func)(void *, const char *), 1105178825Sdfr void *ctx) 1106178825Sdfr{ 1107178825Sdfr struct p11_module *p = data; 1108233294Sstas size_t i, j; 1109233294Sstas 1110233294Sstas _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s", 1111178825Sdfr p->num_slots, p->num_slots > 1 ? "s" : ""); 1112178825Sdfr 1113178825Sdfr for (i = 0; i < p->num_slots; i++) { 1114178825Sdfr struct p11_slot *s = &p->slot[i]; 1115178825Sdfr 1116178825Sdfr _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x", 1117178825Sdfr i, (int)s->id, s->name, s->flags); 1118178825Sdfr 1119233294Sstas _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu", 1120178825Sdfr (unsigned long)s->mechs.num); 1121178825Sdfr for (j = 0; j < s->mechs.num; j++) { 1122178825Sdfr const char *mechname = "unknown"; 1123178825Sdfr char flags[256], unknownname[40]; 1124178825Sdfr#define MECHNAME(s,n) case s: mechname = n; break 1125178825Sdfr switch(s->mechs.list[j]) { 1126178825Sdfr MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen"); 1127178825Sdfr MECHNAME(CKM_RSA_PKCS, "rsa-pkcs"); 1128178825Sdfr MECHNAME(CKM_RSA_X_509, "rsa-x-509"); 1129178825Sdfr MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs"); 1130178825Sdfr MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs"); 1131178825Sdfr MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs"); 1132178825Sdfr MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs"); 1133178825Sdfr MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs"); 1134178825Sdfr MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs"); 1135178825Sdfr MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep"); 1136178825Sdfr MECHNAME(CKM_SHA512_HMAC, "sha512-hmac"); 1137178825Sdfr MECHNAME(CKM_SHA512, "sha512"); 1138178825Sdfr MECHNAME(CKM_SHA384_HMAC, "sha384-hmac"); 1139178825Sdfr MECHNAME(CKM_SHA384, "sha384"); 1140178825Sdfr MECHNAME(CKM_SHA256_HMAC, "sha256-hmac"); 1141178825Sdfr MECHNAME(CKM_SHA256, "sha256"); 1142178825Sdfr MECHNAME(CKM_SHA_1, "sha1"); 1143178825Sdfr MECHNAME(CKM_MD5, "md5"); 1144178825Sdfr MECHNAME(CKM_RIPEMD160, "ripemd-160"); 1145178825Sdfr MECHNAME(CKM_DES_ECB, "des-ecb"); 1146178825Sdfr MECHNAME(CKM_DES_CBC, "des-cbc"); 1147178825Sdfr MECHNAME(CKM_AES_ECB, "aes-ecb"); 1148178825Sdfr MECHNAME(CKM_AES_CBC, "aes-cbc"); 1149178825Sdfr MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen"); 1150178825Sdfr default: 1151178825Sdfr snprintf(unknownname, sizeof(unknownname), 1152233294Sstas "unknown-mech-%lu", 1153178825Sdfr (unsigned long)s->mechs.list[j]); 1154178825Sdfr mechname = unknownname; 1155178825Sdfr break; 1156178825Sdfr } 1157178825Sdfr#undef MECHNAME 1158233294Sstas unparse_flags(s->mechs.infos[j]->flags, mechflags, 1159178825Sdfr flags, sizeof(flags)); 1160178825Sdfr 1161178825Sdfr _hx509_pi_printf(func, ctx, " %s: %s", mechname, flags); 1162178825Sdfr } 1163178825Sdfr } 1164178825Sdfr 1165178825Sdfr return 0; 1166178825Sdfr} 1167178825Sdfr 1168178825Sdfrstatic struct hx509_keyset_ops keyset_pkcs11 = { 1169178825Sdfr "PKCS11", 1170178825Sdfr 0, 1171178825Sdfr p11_init, 1172178825Sdfr NULL, 1173178825Sdfr p11_free, 1174178825Sdfr NULL, 1175178825Sdfr NULL, 1176178825Sdfr p11_iter_start, 1177178825Sdfr p11_iter, 1178178825Sdfr p11_iter_end, 1179178825Sdfr p11_printinfo 1180178825Sdfr}; 1181178825Sdfr 1182178825Sdfr#endif /* HAVE_DLOPEN */ 1183178825Sdfr 1184178825Sdfrvoid 1185178825Sdfr_hx509_ks_pkcs11_register(hx509_context context) 1186178825Sdfr{ 1187178825Sdfr#ifdef HAVE_DLOPEN 1188178825Sdfr _hx509_ks_register(context, &keyset_pkcs11); 1189178825Sdfr#endif 1190178825Sdfr} 1191