1178825Sdfr/* 2178825Sdfr * Copyright (c) 2004 - 2006 Kungliga Tekniska H�gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 5178825Sdfr * 6178825Sdfr * Redistribution and use in source and binary forms, with or without 7178825Sdfr * modification, are permitted provided that the following conditions 8178825Sdfr * are met: 9178825Sdfr * 10178825Sdfr * 1. Redistributions of source code must retain the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 18178825Sdfr * may be used to endorse or promote products derived from this software 19178825Sdfr * without specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178825Sdfr * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825SdfrRCSID("$Id: ks_p11.c 22071 2007-11-14 20:04:50Z lha $"); 36178825Sdfr#ifdef HAVE_DLFCN_H 37178825Sdfr#include <dlfcn.h> 38178825Sdfr#endif 39178825Sdfr 40178825Sdfr#ifdef HAVE_DLOPEN 41178825Sdfr 42178825Sdfr#include "pkcs11.h" 43178825Sdfr 44178825Sdfrstruct p11_slot { 45178825Sdfr int flags; 46178825Sdfr#define P11_SESSION 1 47178825Sdfr#define P11_SESSION_IN_USE 2 48178825Sdfr#define P11_LOGIN_REQ 4 49178825Sdfr#define P11_LOGIN_DONE 8 50178825Sdfr#define P11_TOKEN_PRESENT 16 51178825Sdfr CK_SESSION_HANDLE session; 52178825Sdfr CK_SLOT_ID id; 53178825Sdfr CK_BBOOL token; 54178825Sdfr char *name; 55178825Sdfr hx509_certs certs; 56178825Sdfr char *pin; 57178825Sdfr struct { 58178825Sdfr CK_MECHANISM_TYPE_PTR list; 59178825Sdfr CK_ULONG num; 60178825Sdfr CK_MECHANISM_INFO_PTR *infos; 61178825Sdfr } mechs; 62178825Sdfr}; 63178825Sdfr 64178825Sdfrstruct p11_module { 65178825Sdfr void *dl_handle; 66178825Sdfr CK_FUNCTION_LIST_PTR funcs; 67178825Sdfr CK_ULONG num_slots; 68178825Sdfr unsigned int refcount; 69178825Sdfr struct p11_slot *slot; 70178825Sdfr}; 71178825Sdfr 72178825Sdfr#define P11FUNC(module,f,args) (*(module)->funcs->C_##f)args 73178825Sdfr 74178825Sdfrstatic int p11_get_session(hx509_context, 75178825Sdfr struct p11_module *, 76178825Sdfr struct p11_slot *, 77178825Sdfr hx509_lock, 78178825Sdfr CK_SESSION_HANDLE *); 79178825Sdfrstatic int p11_put_session(struct p11_module *, 80178825Sdfr struct p11_slot *, 81178825Sdfr CK_SESSION_HANDLE); 82178825Sdfrstatic void p11_release_module(struct p11_module *); 83178825Sdfr 84178825Sdfrstatic int p11_list_keys(hx509_context, 85178825Sdfr struct p11_module *, 86178825Sdfr struct p11_slot *, 87178825Sdfr CK_SESSION_HANDLE, 88178825Sdfr hx509_lock, 89178825Sdfr hx509_certs *); 90178825Sdfr 91178825Sdfr/* 92178825Sdfr * 93178825Sdfr */ 94178825Sdfr 95178825Sdfrstruct p11_rsa { 96178825Sdfr struct p11_module *p; 97178825Sdfr struct p11_slot *slot; 98178825Sdfr CK_OBJECT_HANDLE private_key; 99178825Sdfr CK_OBJECT_HANDLE public_key; 100178825Sdfr}; 101178825Sdfr 102178825Sdfrstatic int 103178825Sdfrp11_rsa_public_encrypt(int flen, 104178825Sdfr const unsigned char *from, 105178825Sdfr unsigned char *to, 106178825Sdfr RSA *rsa, 107178825Sdfr int padding) 108178825Sdfr{ 109178825Sdfr return -1; 110178825Sdfr} 111178825Sdfr 112178825Sdfrstatic int 113178825Sdfrp11_rsa_public_decrypt(int flen, 114178825Sdfr const unsigned char *from, 115178825Sdfr unsigned char *to, 116178825Sdfr RSA *rsa, 117178825Sdfr int padding) 118178825Sdfr{ 119178825Sdfr return -1; 120178825Sdfr} 121178825Sdfr 122178825Sdfr 123178825Sdfrstatic int 124178825Sdfrp11_rsa_private_encrypt(int flen, 125178825Sdfr const unsigned char *from, 126178825Sdfr unsigned char *to, 127178825Sdfr RSA *rsa, 128178825Sdfr int padding) 129178825Sdfr{ 130178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 131178825Sdfr CK_OBJECT_HANDLE key = p11rsa->private_key; 132178825Sdfr CK_SESSION_HANDLE session; 133178825Sdfr CK_MECHANISM mechanism; 134178825Sdfr CK_ULONG ck_sigsize; 135178825Sdfr int ret; 136178825Sdfr 137178825Sdfr if (padding != RSA_PKCS1_PADDING) 138178825Sdfr return -1; 139178825Sdfr 140178825Sdfr memset(&mechanism, 0, sizeof(mechanism)); 141178825Sdfr mechanism.mechanism = CKM_RSA_PKCS; 142178825Sdfr 143178825Sdfr ck_sigsize = RSA_size(rsa); 144178825Sdfr 145178825Sdfr ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); 146178825Sdfr if (ret) 147178825Sdfr return -1; 148178825Sdfr 149178825Sdfr ret = P11FUNC(p11rsa->p, SignInit, (session, &mechanism, key)); 150178825Sdfr if (ret != CKR_OK) { 151178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 152178825Sdfr return -1; 153178825Sdfr } 154178825Sdfr 155178825Sdfr ret = P11FUNC(p11rsa->p, Sign, 156178825Sdfr (session, (CK_BYTE *)from, flen, to, &ck_sigsize)); 157178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 158178825Sdfr if (ret != CKR_OK) 159178825Sdfr return -1; 160178825Sdfr 161178825Sdfr return ck_sigsize; 162178825Sdfr} 163178825Sdfr 164178825Sdfrstatic int 165178825Sdfrp11_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to, 166178825Sdfr RSA * rsa, int padding) 167178825Sdfr{ 168178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 169178825Sdfr CK_OBJECT_HANDLE key = p11rsa->private_key; 170178825Sdfr CK_SESSION_HANDLE session; 171178825Sdfr CK_MECHANISM mechanism; 172178825Sdfr CK_ULONG ck_sigsize; 173178825Sdfr int ret; 174178825Sdfr 175178825Sdfr if (padding != RSA_PKCS1_PADDING) 176178825Sdfr return -1; 177178825Sdfr 178178825Sdfr memset(&mechanism, 0, sizeof(mechanism)); 179178825Sdfr mechanism.mechanism = CKM_RSA_PKCS; 180178825Sdfr 181178825Sdfr ck_sigsize = RSA_size(rsa); 182178825Sdfr 183178825Sdfr ret = p11_get_session(NULL, p11rsa->p, p11rsa->slot, NULL, &session); 184178825Sdfr if (ret) 185178825Sdfr return -1; 186178825Sdfr 187178825Sdfr ret = P11FUNC(p11rsa->p, DecryptInit, (session, &mechanism, key)); 188178825Sdfr if (ret != CKR_OK) { 189178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 190178825Sdfr return -1; 191178825Sdfr } 192178825Sdfr 193178825Sdfr ret = P11FUNC(p11rsa->p, Decrypt, 194178825Sdfr (session, (CK_BYTE *)from, flen, to, &ck_sigsize)); 195178825Sdfr p11_put_session(p11rsa->p, p11rsa->slot, session); 196178825Sdfr if (ret != CKR_OK) 197178825Sdfr return -1; 198178825Sdfr 199178825Sdfr return ck_sigsize; 200178825Sdfr} 201178825Sdfr 202178825Sdfrstatic int 203178825Sdfrp11_rsa_init(RSA *rsa) 204178825Sdfr{ 205178825Sdfr return 1; 206178825Sdfr} 207178825Sdfr 208178825Sdfrstatic int 209178825Sdfrp11_rsa_finish(RSA *rsa) 210178825Sdfr{ 211178825Sdfr struct p11_rsa *p11rsa = RSA_get_app_data(rsa); 212178825Sdfr p11_release_module(p11rsa->p); 213178825Sdfr free(p11rsa); 214178825Sdfr return 1; 215178825Sdfr} 216178825Sdfr 217178825Sdfrstatic const RSA_METHOD p11_rsa_pkcs1_method = { 218178825Sdfr "hx509 PKCS11 PKCS#1 RSA", 219178825Sdfr p11_rsa_public_encrypt, 220178825Sdfr p11_rsa_public_decrypt, 221178825Sdfr p11_rsa_private_encrypt, 222178825Sdfr p11_rsa_private_decrypt, 223178825Sdfr NULL, 224178825Sdfr NULL, 225178825Sdfr p11_rsa_init, 226178825Sdfr p11_rsa_finish, 227178825Sdfr 0, 228178825Sdfr NULL, 229178825Sdfr NULL, 230178825Sdfr NULL 231178825Sdfr}; 232178825Sdfr 233178825Sdfr/* 234178825Sdfr * 235178825Sdfr */ 236178825Sdfr 237178825Sdfrstatic int 238178825Sdfrp11_mech_info(hx509_context context, 239178825Sdfr struct p11_module *p, 240178825Sdfr struct p11_slot *slot, 241178825Sdfr int num) 242178825Sdfr{ 243178825Sdfr CK_ULONG i; 244178825Sdfr int ret; 245178825Sdfr 246178825Sdfr ret = P11FUNC(p, GetMechanismList, (slot->id, NULL_PTR, &i)); 247178825Sdfr if (ret) { 248178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 249178825Sdfr "Failed to get mech list count for slot %d", 250178825Sdfr num); 251178825Sdfr return HX509_PKCS11_NO_MECH; 252178825Sdfr } 253178825Sdfr if (i == 0) { 254178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 255178825Sdfr "no mech supported for slot %d", num); 256178825Sdfr return HX509_PKCS11_NO_MECH; 257178825Sdfr } 258178825Sdfr slot->mechs.list = calloc(i, sizeof(slot->mechs.list[0])); 259178825Sdfr if (slot->mechs.list == NULL) { 260178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 261178825Sdfr "out of memory"); 262178825Sdfr return ENOMEM; 263178825Sdfr } 264178825Sdfr slot->mechs.num = i; 265178825Sdfr ret = P11FUNC(p, GetMechanismList, (slot->id, slot->mechs.list, &i)); 266178825Sdfr if (ret) { 267178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 268178825Sdfr "Failed to get mech list for slot %d", 269178825Sdfr num); 270178825Sdfr return HX509_PKCS11_NO_MECH; 271178825Sdfr } 272178825Sdfr assert(i == slot->mechs.num); 273178825Sdfr 274178825Sdfr slot->mechs.infos = calloc(i, sizeof(*slot->mechs.infos)); 275178825Sdfr if (slot->mechs.list == NULL) { 276178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 277178825Sdfr "out of memory"); 278178825Sdfr return ENOMEM; 279178825Sdfr } 280178825Sdfr 281178825Sdfr for (i = 0; i < slot->mechs.num; i++) { 282178825Sdfr slot->mechs.infos[i] = calloc(1, sizeof(*(slot->mechs.infos[0]))); 283178825Sdfr if (slot->mechs.infos[i] == NULL) { 284178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 285178825Sdfr "out of memory"); 286178825Sdfr return ENOMEM; 287178825Sdfr } 288178825Sdfr ret = P11FUNC(p, GetMechanismInfo, (slot->id, slot->mechs.list[i], 289178825Sdfr slot->mechs.infos[i])); 290178825Sdfr if (ret) { 291178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_NO_MECH, 292178825Sdfr "Failed to get mech info for slot %d", 293178825Sdfr num); 294178825Sdfr return HX509_PKCS11_NO_MECH; 295178825Sdfr } 296178825Sdfr } 297178825Sdfr 298178825Sdfr return 0; 299178825Sdfr} 300178825Sdfr 301178825Sdfrstatic int 302178825Sdfrp11_init_slot(hx509_context context, 303178825Sdfr struct p11_module *p, 304178825Sdfr hx509_lock lock, 305178825Sdfr CK_SLOT_ID id, 306178825Sdfr int num, 307178825Sdfr struct p11_slot *slot) 308178825Sdfr{ 309178825Sdfr CK_SESSION_HANDLE session; 310178825Sdfr CK_SLOT_INFO slot_info; 311178825Sdfr CK_TOKEN_INFO token_info; 312178825Sdfr int ret, i; 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", 334178825Sdfr 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"); 378178825Sdfr 379178825Sdfr if (slot->flags & P11_SESSION) { 380178825Sdfr slot->flags |= P11_SESSION_IN_USE; 381178825Sdfr *psession = slot->session; 382178825Sdfr return 0; 383178825Sdfr } 384178825Sdfr 385178825Sdfr 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 } 398178825Sdfr 399178825Sdfr slot->flags |= P11_SESSION; 400178825Sdfr 401178825Sdfr /* 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 slot->flags |= P11_LOGIN_DONE; 422178825Sdfr 423178825Sdfr if (slot->pin == NULL) { 424178825Sdfr 425178825Sdfr memset(&prompt, 0, sizeof(prompt)); 426178825Sdfr 427178825Sdfr asprintf(&str, "PIN code for %s: ", slot->name); 428178825Sdfr prompt.prompt = str; 429178825Sdfr prompt.type = HX509_PROMPT_TYPE_PASSWORD; 430178825Sdfr prompt.reply.data = pin; 431178825Sdfr prompt.reply.length = sizeof(pin); 432178825Sdfr 433178825Sdfr ret = hx509_lock_prompt(lock, &prompt); 434178825Sdfr if (ret) { 435178825Sdfr free(str); 436178825Sdfr if (context) 437178825Sdfr hx509_set_error_string(context, 0, ret, 438178825Sdfr "Failed to get pin code for slot " 439178825Sdfr "id %d with error: %d", 440178825Sdfr (int)slot->id, ret); 441178825Sdfr return ret; 442178825Sdfr } 443178825Sdfr free(str); 444178825Sdfr } else { 445178825Sdfr strlcpy(pin, slot->pin, sizeof(pin)); 446178825Sdfr } 447178825Sdfr 448178825Sdfr ret = P11FUNC(p, Login, (slot->session, CKU_USER, 449178825Sdfr (unsigned char*)pin, strlen(pin))); 450178825Sdfr if (ret != CKR_OK) { 451178825Sdfr if (context) 452178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_LOGIN, 453178825Sdfr "Failed to login on slot id %d " 454178825Sdfr "with error: 0x%08x", 455178825Sdfr (int)slot->id, ret); 456178825Sdfr p11_put_session(p, slot, slot->session); 457178825Sdfr return HX509_PKCS11_LOGIN; 458178825Sdfr } 459178825Sdfr if (slot->pin == NULL) { 460178825Sdfr slot->pin = strdup(pin); 461178825Sdfr if (slot->pin == NULL) { 462178825Sdfr if (context) 463178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 464178825Sdfr "out of memory"); 465178825Sdfr p11_put_session(p, slot, slot->session); 466178825Sdfr return ENOMEM; 467178825Sdfr } 468178825Sdfr } 469178825Sdfr } else 470178825Sdfr slot->flags |= P11_LOGIN_DONE; 471178825Sdfr 472178825Sdfr slot->flags |= P11_SESSION_IN_USE; 473178825Sdfr 474178825Sdfr *psession = slot->session; 475178825Sdfr 476178825Sdfr return 0; 477178825Sdfr} 478178825Sdfr 479178825Sdfrstatic int 480178825Sdfrp11_put_session(struct p11_module *p, 481178825Sdfr struct p11_slot *slot, 482178825Sdfr CK_SESSION_HANDLE session) 483178825Sdfr{ 484178825Sdfr if ((slot->flags & P11_SESSION_IN_USE) == 0) 485178825Sdfr _hx509_abort("slot not in session"); 486178825Sdfr slot->flags &= ~P11_SESSION_IN_USE; 487178825Sdfr 488178825Sdfr return 0; 489178825Sdfr} 490178825Sdfr 491178825Sdfrstatic int 492178825Sdfriterate_entries(hx509_context context, 493178825Sdfr struct p11_module *p, struct p11_slot *slot, 494178825Sdfr CK_SESSION_HANDLE session, 495178825Sdfr CK_ATTRIBUTE *search_data, int num_search_data, 496178825Sdfr CK_ATTRIBUTE *query, int num_query, 497178825Sdfr int (*func)(hx509_context, 498178825Sdfr struct p11_module *, struct p11_slot *, 499178825Sdfr CK_SESSION_HANDLE session, 500178825Sdfr CK_OBJECT_HANDLE object, 501178825Sdfr void *, CK_ATTRIBUTE *, int), void *ptr) 502178825Sdfr{ 503178825Sdfr CK_OBJECT_HANDLE object; 504178825Sdfr CK_ULONG object_count; 505178825Sdfr int ret, i; 506178825Sdfr 507178825Sdfr ret = P11FUNC(p, FindObjectsInit, (session, search_data, num_search_data)); 508178825Sdfr if (ret != CKR_OK) { 509178825Sdfr return -1; 510178825Sdfr } 511178825Sdfr while (1) { 512178825Sdfr ret = P11FUNC(p, FindObjects, (session, &object, 1, &object_count)); 513178825Sdfr if (ret != CKR_OK) { 514178825Sdfr return -1; 515178825Sdfr } 516178825Sdfr if (object_count == 0) 517178825Sdfr break; 518178825Sdfr 519178825Sdfr for (i = 0; i < num_query; i++) 520178825Sdfr query[i].pValue = NULL; 521178825Sdfr 522178825Sdfr ret = P11FUNC(p, GetAttributeValue, 523178825Sdfr (session, object, query, num_query)); 524178825Sdfr if (ret != CKR_OK) { 525178825Sdfr return -1; 526178825Sdfr } 527178825Sdfr for (i = 0; i < num_query; i++) { 528178825Sdfr query[i].pValue = malloc(query[i].ulValueLen); 529178825Sdfr if (query[i].pValue == NULL) { 530178825Sdfr ret = ENOMEM; 531178825Sdfr goto out; 532178825Sdfr } 533178825Sdfr } 534178825Sdfr ret = P11FUNC(p, GetAttributeValue, 535178825Sdfr (session, object, query, num_query)); 536178825Sdfr if (ret != CKR_OK) { 537178825Sdfr ret = -1; 538178825Sdfr goto out; 539178825Sdfr } 540178825Sdfr 541178825Sdfr ret = (*func)(context, p, slot, session, object, ptr, query, num_query); 542178825Sdfr if (ret) 543178825Sdfr goto out; 544178825Sdfr 545178825Sdfr for (i = 0; i < num_query; i++) { 546178825Sdfr if (query[i].pValue) 547178825Sdfr free(query[i].pValue); 548178825Sdfr query[i].pValue = NULL; 549178825Sdfr } 550178825Sdfr } 551178825Sdfr out: 552178825Sdfr 553178825Sdfr for (i = 0; i < num_query; i++) { 554178825Sdfr if (query[i].pValue) 555178825Sdfr free(query[i].pValue); 556178825Sdfr query[i].pValue = NULL; 557178825Sdfr } 558178825Sdfr 559178825Sdfr ret = P11FUNC(p, FindObjectsFinal, (session)); 560178825Sdfr if (ret != CKR_OK) { 561178825Sdfr return -2; 562178825Sdfr } 563178825Sdfr 564178825Sdfr 565178825Sdfr return 0; 566178825Sdfr} 567178825Sdfr 568178825Sdfrstatic BIGNUM * 569178825Sdfrgetattr_bn(struct p11_module *p, 570178825Sdfr struct p11_slot *slot, 571178825Sdfr CK_SESSION_HANDLE session, 572178825Sdfr CK_OBJECT_HANDLE object, 573178825Sdfr unsigned int type) 574178825Sdfr{ 575178825Sdfr CK_ATTRIBUTE query; 576178825Sdfr BIGNUM *bn; 577178825Sdfr int ret; 578178825Sdfr 579178825Sdfr query.type = type; 580178825Sdfr query.pValue = NULL; 581178825Sdfr query.ulValueLen = 0; 582178825Sdfr 583178825Sdfr ret = P11FUNC(p, GetAttributeValue, 584178825Sdfr (session, object, &query, 1)); 585178825Sdfr if (ret != CKR_OK) 586178825Sdfr return NULL; 587178825Sdfr 588178825Sdfr query.pValue = malloc(query.ulValueLen); 589178825Sdfr 590178825Sdfr ret = P11FUNC(p, GetAttributeValue, 591178825Sdfr (session, object, &query, 1)); 592178825Sdfr if (ret != CKR_OK) { 593178825Sdfr free(query.pValue); 594178825Sdfr return NULL; 595178825Sdfr } 596178825Sdfr bn = BN_bin2bn(query.pValue, query.ulValueLen, NULL); 597178825Sdfr free(query.pValue); 598178825Sdfr 599178825Sdfr return bn; 600178825Sdfr} 601178825Sdfr 602178825Sdfrstatic int 603178825Sdfrcollect_private_key(hx509_context context, 604178825Sdfr struct p11_module *p, struct p11_slot *slot, 605178825Sdfr CK_SESSION_HANDLE session, 606178825Sdfr CK_OBJECT_HANDLE object, 607178825Sdfr void *ptr, CK_ATTRIBUTE *query, int num_query) 608178825Sdfr{ 609178825Sdfr struct hx509_collector *collector = ptr; 610178825Sdfr hx509_private_key key; 611178825Sdfr heim_octet_string localKeyId; 612178825Sdfr int ret; 613178825Sdfr RSA *rsa; 614178825Sdfr struct p11_rsa *p11rsa; 615178825Sdfr 616178825Sdfr localKeyId.data = query[0].pValue; 617178825Sdfr localKeyId.length = query[0].ulValueLen; 618178825Sdfr 619178825Sdfr ret = _hx509_private_key_init(&key, NULL, NULL); 620178825Sdfr if (ret) 621178825Sdfr return ret; 622178825Sdfr 623178825Sdfr rsa = RSA_new(); 624178825Sdfr if (rsa == NULL) 625178825Sdfr _hx509_abort("out of memory"); 626178825Sdfr 627178825Sdfr /* 628178825Sdfr * The exponent and modulus should always be present according to 629178825Sdfr * the pkcs11 specification, but some smartcards leaves it out, 630178825Sdfr * let ignore any failure to fetch it. 631178825Sdfr */ 632178825Sdfr rsa->n = getattr_bn(p, slot, session, object, CKA_MODULUS); 633178825Sdfr rsa->e = getattr_bn(p, slot, session, object, CKA_PUBLIC_EXPONENT); 634178825Sdfr 635178825Sdfr p11rsa = calloc(1, sizeof(*p11rsa)); 636178825Sdfr if (p11rsa == NULL) 637178825Sdfr _hx509_abort("out of memory"); 638178825Sdfr 639178825Sdfr p11rsa->p = p; 640178825Sdfr p11rsa->slot = slot; 641178825Sdfr p11rsa->private_key = object; 642178825Sdfr 643178825Sdfr p->refcount++; 644178825Sdfr if (p->refcount == 0) 645178825Sdfr _hx509_abort("pkcs11 refcount to high"); 646178825Sdfr 647178825Sdfr RSA_set_method(rsa, &p11_rsa_pkcs1_method); 648178825Sdfr ret = RSA_set_app_data(rsa, p11rsa); 649178825Sdfr if (ret != 1) 650178825Sdfr _hx509_abort("RSA_set_app_data"); 651178825Sdfr 652178825Sdfr _hx509_private_key_assign_rsa(key, rsa); 653178825Sdfr 654178825Sdfr ret = _hx509_collector_private_key_add(context, 655178825Sdfr collector, 656178825Sdfr hx509_signature_rsa(), 657178825Sdfr key, 658178825Sdfr NULL, 659178825Sdfr &localKeyId); 660178825Sdfr 661178825Sdfr if (ret) { 662178825Sdfr _hx509_private_key_free(&key); 663178825Sdfr return ret; 664178825Sdfr } 665178825Sdfr return 0; 666178825Sdfr} 667178825Sdfr 668178825Sdfrstatic void 669178825Sdfrp11_cert_release(hx509_cert cert, void *ctx) 670178825Sdfr{ 671178825Sdfr struct p11_module *p = ctx; 672178825Sdfr p11_release_module(p); 673178825Sdfr} 674178825Sdfr 675178825Sdfr 676178825Sdfrstatic int 677178825Sdfrcollect_cert(hx509_context context, 678178825Sdfr struct p11_module *p, struct p11_slot *slot, 679178825Sdfr CK_SESSION_HANDLE session, 680178825Sdfr CK_OBJECT_HANDLE object, 681178825Sdfr void *ptr, CK_ATTRIBUTE *query, int num_query) 682178825Sdfr{ 683178825Sdfr struct hx509_collector *collector = ptr; 684178825Sdfr hx509_cert cert; 685178825Sdfr int ret; 686178825Sdfr 687178825Sdfr if ((CK_LONG)query[0].ulValueLen == -1 || 688178825Sdfr (CK_LONG)query[1].ulValueLen == -1) 689178825Sdfr { 690178825Sdfr return 0; 691178825Sdfr } 692178825Sdfr 693178825Sdfr ret = hx509_cert_init_data(context, query[1].pValue, 694178825Sdfr query[1].ulValueLen, &cert); 695178825Sdfr if (ret) 696178825Sdfr return ret; 697178825Sdfr 698178825Sdfr p->refcount++; 699178825Sdfr if (p->refcount == 0) 700178825Sdfr _hx509_abort("pkcs11 refcount to high"); 701178825Sdfr 702178825Sdfr _hx509_cert_set_release(cert, p11_cert_release, p); 703178825Sdfr 704178825Sdfr { 705178825Sdfr heim_octet_string data; 706178825Sdfr 707178825Sdfr data.data = query[0].pValue; 708178825Sdfr data.length = query[0].ulValueLen; 709178825Sdfr 710178825Sdfr _hx509_set_cert_attribute(context, 711178825Sdfr cert, 712178825Sdfr oid_id_pkcs_9_at_localKeyId(), 713178825Sdfr &data); 714178825Sdfr } 715178825Sdfr 716178825Sdfr if ((CK_LONG)query[2].ulValueLen != -1) { 717178825Sdfr char *str; 718178825Sdfr 719178825Sdfr asprintf(&str, "%.*s", 720178825Sdfr (int)query[2].ulValueLen, (char *)query[2].pValue); 721178825Sdfr if (str) { 722178825Sdfr hx509_cert_set_friendly_name(cert, str); 723178825Sdfr free(str); 724178825Sdfr } 725178825Sdfr } 726178825Sdfr 727178825Sdfr ret = _hx509_collector_certs_add(context, collector, cert); 728178825Sdfr hx509_cert_free(cert); 729178825Sdfr 730178825Sdfr return ret; 731178825Sdfr} 732178825Sdfr 733178825Sdfr 734178825Sdfrstatic int 735178825Sdfrp11_list_keys(hx509_context context, 736178825Sdfr struct p11_module *p, 737178825Sdfr struct p11_slot *slot, 738178825Sdfr CK_SESSION_HANDLE session, 739178825Sdfr hx509_lock lock, 740178825Sdfr hx509_certs *certs) 741178825Sdfr{ 742178825Sdfr struct hx509_collector *collector; 743178825Sdfr CK_OBJECT_CLASS key_class; 744178825Sdfr CK_ATTRIBUTE search_data[] = { 745178825Sdfr {CKA_CLASS, NULL, 0}, 746178825Sdfr }; 747178825Sdfr CK_ATTRIBUTE query_data[3] = { 748178825Sdfr {CKA_ID, NULL, 0}, 749178825Sdfr {CKA_VALUE, NULL, 0}, 750178825Sdfr {CKA_LABEL, NULL, 0} 751178825Sdfr }; 752178825Sdfr int ret; 753178825Sdfr 754178825Sdfr search_data[0].pValue = &key_class; 755178825Sdfr search_data[0].ulValueLen = sizeof(key_class); 756178825Sdfr 757178825Sdfr if (lock == NULL) 758178825Sdfr lock = _hx509_empty_lock; 759178825Sdfr 760178825Sdfr ret = _hx509_collector_alloc(context, lock, &collector); 761178825Sdfr if (ret) 762178825Sdfr return ret; 763178825Sdfr 764178825Sdfr key_class = CKO_PRIVATE_KEY; 765178825Sdfr ret = iterate_entries(context, p, slot, session, 766178825Sdfr search_data, 1, 767178825Sdfr query_data, 1, 768178825Sdfr collect_private_key, collector); 769178825Sdfr if (ret) 770178825Sdfr goto out; 771178825Sdfr 772178825Sdfr key_class = CKO_CERTIFICATE; 773178825Sdfr ret = iterate_entries(context, p, slot, session, 774178825Sdfr search_data, 1, 775178825Sdfr query_data, 3, 776178825Sdfr collect_cert, collector); 777178825Sdfr if (ret) 778178825Sdfr goto out; 779178825Sdfr 780178825Sdfr ret = _hx509_collector_collect_certs(context, collector, &slot->certs); 781178825Sdfr 782178825Sdfrout: 783178825Sdfr _hx509_collector_free(collector); 784178825Sdfr 785178825Sdfr return ret; 786178825Sdfr} 787178825Sdfr 788178825Sdfr 789178825Sdfrstatic int 790178825Sdfrp11_init(hx509_context context, 791178825Sdfr hx509_certs certs, void **data, int flags, 792178825Sdfr const char *residue, hx509_lock lock) 793178825Sdfr{ 794178825Sdfr CK_C_GetFunctionList getFuncs; 795178825Sdfr struct p11_module *p; 796178825Sdfr char *list, *str; 797178825Sdfr int ret; 798178825Sdfr 799178825Sdfr *data = NULL; 800178825Sdfr 801178825Sdfr list = strdup(residue); 802178825Sdfr if (list == NULL) 803178825Sdfr return ENOMEM; 804178825Sdfr 805178825Sdfr p = calloc(1, sizeof(*p)); 806178825Sdfr if (p == NULL) { 807178825Sdfr free(list); 808178825Sdfr return ENOMEM; 809178825Sdfr } 810178825Sdfr 811178825Sdfr p->refcount = 1; 812178825Sdfr 813178825Sdfr str = strchr(list, ','); 814178825Sdfr if (str) 815178825Sdfr *str++ = '\0'; 816178825Sdfr while (str) { 817178825Sdfr char *strnext; 818178825Sdfr strnext = strchr(str, ','); 819178825Sdfr if (strnext) 820178825Sdfr *strnext++ = '\0'; 821178825Sdfr#if 0 822178825Sdfr if (strncasecmp(str, "slot=", 5) == 0) 823178825Sdfr p->selected_slot = atoi(str + 5); 824178825Sdfr#endif 825178825Sdfr str = strnext; 826178825Sdfr } 827178825Sdfr 828178825Sdfr p->dl_handle = dlopen(list, RTLD_NOW); 829178825Sdfr free(list); 830178825Sdfr if (p->dl_handle == NULL) { 831178825Sdfr ret = HX509_PKCS11_LOAD; 832178825Sdfr hx509_set_error_string(context, 0, ret, 833178825Sdfr "Failed to open %s: %s", list, dlerror()); 834178825Sdfr goto out; 835178825Sdfr } 836178825Sdfr 837178825Sdfr getFuncs = dlsym(p->dl_handle, "C_GetFunctionList"); 838178825Sdfr if (getFuncs == NULL) { 839178825Sdfr ret = HX509_PKCS11_LOAD; 840178825Sdfr hx509_set_error_string(context, 0, ret, 841178825Sdfr "C_GetFunctionList missing in %s: %s", 842178825Sdfr list, dlerror()); 843178825Sdfr goto out; 844178825Sdfr } 845178825Sdfr 846178825Sdfr ret = (*getFuncs)(&p->funcs); 847178825Sdfr if (ret) { 848178825Sdfr ret = HX509_PKCS11_LOAD; 849178825Sdfr hx509_set_error_string(context, 0, ret, 850178825Sdfr "C_GetFunctionList failed in %s", list); 851178825Sdfr goto out; 852178825Sdfr } 853178825Sdfr 854178825Sdfr ret = P11FUNC(p, Initialize, (NULL_PTR)); 855178825Sdfr if (ret != CKR_OK) { 856178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 857178825Sdfr hx509_set_error_string(context, 0, ret, 858178825Sdfr "Failed initialize the PKCS11 module"); 859178825Sdfr goto out; 860178825Sdfr } 861178825Sdfr 862178825Sdfr ret = P11FUNC(p, GetSlotList, (FALSE, NULL, &p->num_slots)); 863178825Sdfr if (ret) { 864178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 865178825Sdfr hx509_set_error_string(context, 0, ret, 866178825Sdfr "Failed to get number of PKCS11 slots"); 867178825Sdfr goto out; 868178825Sdfr } 869178825Sdfr 870178825Sdfr if (p->num_slots == 0) { 871178825Sdfr ret = HX509_PKCS11_NO_SLOT; 872178825Sdfr hx509_set_error_string(context, 0, ret, 873178825Sdfr "Selected PKCS11 module have no slots"); 874178825Sdfr goto out; 875178825Sdfr } 876178825Sdfr 877178825Sdfr 878178825Sdfr { 879178825Sdfr CK_SLOT_ID_PTR slot_ids; 880178825Sdfr int i, num_tokens = 0; 881178825Sdfr 882178825Sdfr slot_ids = malloc(p->num_slots * sizeof(*slot_ids)); 883178825Sdfr if (slot_ids == NULL) { 884178825Sdfr hx509_clear_error_string(context); 885178825Sdfr ret = ENOMEM; 886178825Sdfr goto out; 887178825Sdfr } 888178825Sdfr 889178825Sdfr ret = P11FUNC(p, GetSlotList, (FALSE, slot_ids, &p->num_slots)); 890178825Sdfr if (ret) { 891178825Sdfr free(slot_ids); 892178825Sdfr hx509_set_error_string(context, 0, HX509_PKCS11_TOKEN_CONFUSED, 893178825Sdfr "Failed getting slot-list from " 894178825Sdfr "PKCS11 module"); 895178825Sdfr ret = HX509_PKCS11_TOKEN_CONFUSED; 896178825Sdfr goto out; 897178825Sdfr } 898178825Sdfr 899178825Sdfr p->slot = calloc(p->num_slots, sizeof(p->slot[0])); 900178825Sdfr if (p->slot == NULL) { 901178825Sdfr free(slot_ids); 902178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 903178825Sdfr "Failed to get memory for slot-list"); 904178825Sdfr ret = ENOMEM; 905178825Sdfr goto out; 906178825Sdfr } 907178825Sdfr 908178825Sdfr for (i = 0; i < p->num_slots; i++) { 909178825Sdfr ret = p11_init_slot(context, p, lock, slot_ids[i], i, &p->slot[i]); 910178825Sdfr if (ret) 911178825Sdfr break; 912178825Sdfr if (p->slot[i].flags & P11_TOKEN_PRESENT) 913178825Sdfr num_tokens++; 914178825Sdfr } 915178825Sdfr free(slot_ids); 916178825Sdfr if (ret) 917178825Sdfr goto out; 918178825Sdfr if (num_tokens == 0) { 919178825Sdfr ret = HX509_PKCS11_NO_TOKEN; 920178825Sdfr goto out; 921178825Sdfr } 922178825Sdfr } 923178825Sdfr 924178825Sdfr *data = p; 925178825Sdfr 926178825Sdfr return 0; 927178825Sdfr out: 928178825Sdfr p11_release_module(p); 929178825Sdfr return ret; 930178825Sdfr} 931178825Sdfr 932178825Sdfrstatic void 933178825Sdfrp11_release_module(struct p11_module *p) 934178825Sdfr{ 935178825Sdfr int i; 936178825Sdfr 937178825Sdfr if (p->refcount == 0) 938178825Sdfr _hx509_abort("pkcs11 refcount to low"); 939178825Sdfr if (--p->refcount > 0) 940178825Sdfr return; 941178825Sdfr 942178825Sdfr for (i = 0; i < p->num_slots; i++) { 943178825Sdfr if (p->slot[i].flags & P11_SESSION_IN_USE) 944178825Sdfr _hx509_abort("pkcs11 module release while session in use"); 945178825Sdfr if (p->slot[i].flags & P11_SESSION) { 946178825Sdfr int ret; 947178825Sdfr 948178825Sdfr ret = P11FUNC(p, CloseSession, (p->slot[i].session)); 949178825Sdfr if (ret != CKR_OK) 950178825Sdfr ; 951178825Sdfr } 952178825Sdfr 953178825Sdfr if (p->slot[i].name) 954178825Sdfr free(p->slot[i].name); 955178825Sdfr if (p->slot[i].pin) { 956178825Sdfr memset(p->slot[i].pin, 0, strlen(p->slot[i].pin)); 957178825Sdfr free(p->slot[i].pin); 958178825Sdfr } 959178825Sdfr if (p->slot[i].mechs.num) { 960178825Sdfr free(p->slot[i].mechs.list); 961178825Sdfr 962178825Sdfr if (p->slot[i].mechs.infos) { 963178825Sdfr int j; 964178825Sdfr 965178825Sdfr for (j = 0 ; j < p->slot[i].mechs.num ; j++) 966178825Sdfr free(p->slot[i].mechs.infos[j]); 967178825Sdfr free(p->slot[i].mechs.infos); 968178825Sdfr } 969178825Sdfr } 970178825Sdfr } 971178825Sdfr free(p->slot); 972178825Sdfr 973178825Sdfr if (p->funcs) 974178825Sdfr P11FUNC(p, Finalize, (NULL)); 975178825Sdfr 976178825Sdfr if (p->dl_handle) 977178825Sdfr dlclose(p->dl_handle); 978178825Sdfr 979178825Sdfr memset(p, 0, sizeof(*p)); 980178825Sdfr free(p); 981178825Sdfr} 982178825Sdfr 983178825Sdfrstatic int 984178825Sdfrp11_free(hx509_certs certs, void *data) 985178825Sdfr{ 986178825Sdfr struct p11_module *p = data; 987178825Sdfr int i; 988178825Sdfr 989178825Sdfr for (i = 0; i < p->num_slots; i++) { 990178825Sdfr if (p->slot[i].certs) 991178825Sdfr hx509_certs_free(&p->slot[i].certs); 992178825Sdfr } 993178825Sdfr p11_release_module(p); 994178825Sdfr return 0; 995178825Sdfr} 996178825Sdfr 997178825Sdfrstruct p11_cursor { 998178825Sdfr hx509_certs certs; 999178825Sdfr void *cursor; 1000178825Sdfr}; 1001178825Sdfr 1002178825Sdfrstatic int 1003178825Sdfrp11_iter_start(hx509_context context, 1004178825Sdfr hx509_certs certs, void *data, void **cursor) 1005178825Sdfr{ 1006178825Sdfr struct p11_module *p = data; 1007178825Sdfr struct p11_cursor *c; 1008178825Sdfr int ret, i; 1009178825Sdfr 1010178825Sdfr c = malloc(sizeof(*c)); 1011178825Sdfr if (c == NULL) { 1012178825Sdfr hx509_clear_error_string(context); 1013178825Sdfr return ENOMEM; 1014178825Sdfr } 1015178825Sdfr ret = hx509_certs_init(context, "MEMORY:pkcs11-iter", 0, NULL, &c->certs); 1016178825Sdfr if (ret) { 1017178825Sdfr free(c); 1018178825Sdfr return ret; 1019178825Sdfr } 1020178825Sdfr 1021178825Sdfr for (i = 0 ; i < p->num_slots; i++) { 1022178825Sdfr if (p->slot[i].certs == NULL) 1023178825Sdfr continue; 1024178825Sdfr ret = hx509_certs_merge(context, c->certs, p->slot[i].certs); 1025178825Sdfr if (ret) { 1026178825Sdfr hx509_certs_free(&c->certs); 1027178825Sdfr free(c); 1028178825Sdfr return ret; 1029178825Sdfr } 1030178825Sdfr } 1031178825Sdfr 1032178825Sdfr ret = hx509_certs_start_seq(context, c->certs, &c->cursor); 1033178825Sdfr if (ret) { 1034178825Sdfr hx509_certs_free(&c->certs); 1035178825Sdfr free(c); 1036178825Sdfr return 0; 1037178825Sdfr } 1038178825Sdfr *cursor = c; 1039178825Sdfr 1040178825Sdfr return 0; 1041178825Sdfr} 1042178825Sdfr 1043178825Sdfrstatic int 1044178825Sdfrp11_iter(hx509_context context, 1045178825Sdfr hx509_certs certs, void *data, void *cursor, hx509_cert *cert) 1046178825Sdfr{ 1047178825Sdfr struct p11_cursor *c = cursor; 1048178825Sdfr return hx509_certs_next_cert(context, c->certs, c->cursor, cert); 1049178825Sdfr} 1050178825Sdfr 1051178825Sdfrstatic int 1052178825Sdfrp11_iter_end(hx509_context context, 1053178825Sdfr hx509_certs certs, void *data, void *cursor) 1054178825Sdfr{ 1055178825Sdfr struct p11_cursor *c = cursor; 1056178825Sdfr int ret; 1057178825Sdfr ret = hx509_certs_end_seq(context, c->certs, c->cursor); 1058178825Sdfr hx509_certs_free(&c->certs); 1059178825Sdfr free(c); 1060178825Sdfr return ret; 1061178825Sdfr} 1062178825Sdfr 1063178825Sdfr#define MECHFLAG(x) { "unknown-flag-" #x, x } 1064178825Sdfrstatic struct units mechflags[] = { 1065178825Sdfr MECHFLAG(0x80000000), 1066178825Sdfr MECHFLAG(0x40000000), 1067178825Sdfr MECHFLAG(0x20000000), 1068178825Sdfr MECHFLAG(0x10000000), 1069178825Sdfr MECHFLAG(0x08000000), 1070178825Sdfr MECHFLAG(0x04000000), 1071178825Sdfr {"ec-compress", 0x2000000 }, 1072178825Sdfr {"ec-uncompress", 0x1000000 }, 1073178825Sdfr {"ec-namedcurve", 0x0800000 }, 1074178825Sdfr {"ec-ecparameters", 0x0400000 }, 1075178825Sdfr {"ec-f-2m", 0x0200000 }, 1076178825Sdfr {"ec-f-p", 0x0100000 }, 1077178825Sdfr {"derive", 0x0080000 }, 1078178825Sdfr {"unwrap", 0x0040000 }, 1079178825Sdfr {"wrap", 0x0020000 }, 1080178825Sdfr {"genereate-key-pair", 0x0010000 }, 1081178825Sdfr {"generate", 0x0008000 }, 1082178825Sdfr {"verify-recover", 0x0004000 }, 1083178825Sdfr {"verify", 0x0002000 }, 1084178825Sdfr {"sign-recover", 0x0001000 }, 1085178825Sdfr {"sign", 0x0000800 }, 1086178825Sdfr {"digest", 0x0000400 }, 1087178825Sdfr {"decrypt", 0x0000200 }, 1088178825Sdfr {"encrypt", 0x0000100 }, 1089178825Sdfr MECHFLAG(0x00080), 1090178825Sdfr MECHFLAG(0x00040), 1091178825Sdfr MECHFLAG(0x00020), 1092178825Sdfr MECHFLAG(0x00010), 1093178825Sdfr MECHFLAG(0x00008), 1094178825Sdfr MECHFLAG(0x00004), 1095178825Sdfr MECHFLAG(0x00002), 1096178825Sdfr {"hw", 0x0000001 }, 1097178825Sdfr { NULL, 0x0000000 } 1098178825Sdfr}; 1099178825Sdfr#undef MECHFLAG 1100178825Sdfr 1101178825Sdfrstatic int 1102178825Sdfrp11_printinfo(hx509_context context, 1103178825Sdfr hx509_certs certs, 1104178825Sdfr void *data, 1105178825Sdfr int (*func)(void *, const char *), 1106178825Sdfr void *ctx) 1107178825Sdfr{ 1108178825Sdfr struct p11_module *p = data; 1109178825Sdfr int i, j; 1110178825Sdfr 1111178825Sdfr _hx509_pi_printf(func, ctx, "pkcs11 driver with %d slot%s", 1112178825Sdfr p->num_slots, p->num_slots > 1 ? "s" : ""); 1113178825Sdfr 1114178825Sdfr for (i = 0; i < p->num_slots; i++) { 1115178825Sdfr struct p11_slot *s = &p->slot[i]; 1116178825Sdfr 1117178825Sdfr _hx509_pi_printf(func, ctx, "slot %d: id: %d name: %s flags: %08x", 1118178825Sdfr i, (int)s->id, s->name, s->flags); 1119178825Sdfr 1120178825Sdfr _hx509_pi_printf(func, ctx, "number of supported mechanisms: %lu", 1121178825Sdfr (unsigned long)s->mechs.num); 1122178825Sdfr for (j = 0; j < s->mechs.num; j++) { 1123178825Sdfr const char *mechname = "unknown"; 1124178825Sdfr char flags[256], unknownname[40]; 1125178825Sdfr#define MECHNAME(s,n) case s: mechname = n; break 1126178825Sdfr switch(s->mechs.list[j]) { 1127178825Sdfr MECHNAME(CKM_RSA_PKCS_KEY_PAIR_GEN, "rsa-pkcs-key-pair-gen"); 1128178825Sdfr MECHNAME(CKM_RSA_PKCS, "rsa-pkcs"); 1129178825Sdfr MECHNAME(CKM_RSA_X_509, "rsa-x-509"); 1130178825Sdfr MECHNAME(CKM_MD5_RSA_PKCS, "md5-rsa-pkcs"); 1131178825Sdfr MECHNAME(CKM_SHA1_RSA_PKCS, "sha1-rsa-pkcs"); 1132178825Sdfr MECHNAME(CKM_SHA256_RSA_PKCS, "sha256-rsa-pkcs"); 1133178825Sdfr MECHNAME(CKM_SHA384_RSA_PKCS, "sha384-rsa-pkcs"); 1134178825Sdfr MECHNAME(CKM_SHA512_RSA_PKCS, "sha512-rsa-pkcs"); 1135178825Sdfr MECHNAME(CKM_RIPEMD160_RSA_PKCS, "ripemd160-rsa-pkcs"); 1136178825Sdfr MECHNAME(CKM_RSA_PKCS_OAEP, "rsa-pkcs-oaep"); 1137178825Sdfr MECHNAME(CKM_SHA512_HMAC, "sha512-hmac"); 1138178825Sdfr MECHNAME(CKM_SHA512, "sha512"); 1139178825Sdfr MECHNAME(CKM_SHA384_HMAC, "sha384-hmac"); 1140178825Sdfr MECHNAME(CKM_SHA384, "sha384"); 1141178825Sdfr MECHNAME(CKM_SHA256_HMAC, "sha256-hmac"); 1142178825Sdfr MECHNAME(CKM_SHA256, "sha256"); 1143178825Sdfr MECHNAME(CKM_SHA_1, "sha1"); 1144178825Sdfr MECHNAME(CKM_MD5, "md5"); 1145178825Sdfr MECHNAME(CKM_MD2, "md2"); 1146178825Sdfr MECHNAME(CKM_RIPEMD160, "ripemd-160"); 1147178825Sdfr MECHNAME(CKM_DES_ECB, "des-ecb"); 1148178825Sdfr MECHNAME(CKM_DES_CBC, "des-cbc"); 1149178825Sdfr MECHNAME(CKM_AES_ECB, "aes-ecb"); 1150178825Sdfr MECHNAME(CKM_AES_CBC, "aes-cbc"); 1151178825Sdfr MECHNAME(CKM_DH_PKCS_PARAMETER_GEN, "dh-pkcs-parameter-gen"); 1152178825Sdfr default: 1153178825Sdfr snprintf(unknownname, sizeof(unknownname), 1154178825Sdfr "unknown-mech-%lu", 1155178825Sdfr (unsigned long)s->mechs.list[j]); 1156178825Sdfr mechname = unknownname; 1157178825Sdfr break; 1158178825Sdfr } 1159178825Sdfr#undef MECHNAME 1160178825Sdfr unparse_flags(s->mechs.infos[j]->flags, mechflags, 1161178825Sdfr flags, sizeof(flags)); 1162178825Sdfr 1163178825Sdfr _hx509_pi_printf(func, ctx, " %s: %s", mechname, flags); 1164178825Sdfr } 1165178825Sdfr } 1166178825Sdfr 1167178825Sdfr return 0; 1168178825Sdfr} 1169178825Sdfr 1170178825Sdfrstatic struct hx509_keyset_ops keyset_pkcs11 = { 1171178825Sdfr "PKCS11", 1172178825Sdfr 0, 1173178825Sdfr p11_init, 1174178825Sdfr NULL, 1175178825Sdfr p11_free, 1176178825Sdfr NULL, 1177178825Sdfr NULL, 1178178825Sdfr p11_iter_start, 1179178825Sdfr p11_iter, 1180178825Sdfr p11_iter_end, 1181178825Sdfr p11_printinfo 1182178825Sdfr}; 1183178825Sdfr 1184178825Sdfr#endif /* HAVE_DLOPEN */ 1185178825Sdfr 1186178825Sdfrvoid 1187178825Sdfr_hx509_ks_pkcs11_register(hx509_context context) 1188178825Sdfr{ 1189178825Sdfr#ifdef HAVE_DLOPEN 1190178825Sdfr _hx509_ks_register(context, &keyset_pkcs11); 1191178825Sdfr#endif 1192178825Sdfr} 1193