Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs11/pkcs11_library.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011-2015 Tobias Brunner
! 3: * HSR Hochschule fuer Technik Rapperswil
! 4: *
! 5: * Copyright (C) 2010 Martin Willi
! 6: * Copyright (C) 2010 revosec AG
! 7: *
! 8: * This program is free software; you can redistribute it and/or modify it
! 9: * under the terms of the GNU General Public License as published by the
! 10: * Free Software Foundation; either version 2 of the License, or (at your
! 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 12: *
! 13: * This program is distributed in the hope that it will be useful, but
! 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 16: * for more details.
! 17: */
! 18:
! 19: #include "pkcs11_library.h"
! 20:
! 21: #include <dlfcn.h>
! 22:
! 23: #include <library.h>
! 24: #include <asn1/asn1.h>
! 25: #include <utils/debug.h>
! 26: #include <threading/mutex.h>
! 27: #include <collections/linked_list.h>
! 28:
! 29: typedef struct private_pkcs11_library_t private_pkcs11_library_t;
! 30:
! 31:
! 32: ENUM_BEGIN(ck_rv_names, CKR_OK, CKR_CANT_LOCK,
! 33: "OK",
! 34: "CANCEL",
! 35: "HOST_MEMORY",
! 36: "SLOT_ID_INVALID",
! 37: "(0x04)",
! 38: "GENERAL_ERROR",
! 39: "FUNCTION_FAILED",
! 40: "ARGUMENTS_BAD",
! 41: "NO_EVENT",
! 42: "NEED_TO_CREATE_THREADS",
! 43: "CANT_LOCK");
! 44: ENUM_NEXT(ck_rv_names, CKR_ATTRIBUTE_READ_ONLY, CKR_ATTRIBUTE_VALUE_INVALID,
! 45: CKR_CANT_LOCK,
! 46: "ATTRIBUTE_READ_ONLY",
! 47: "ATTRIBUTE_SENSITIVE",
! 48: "ATTRIBUTE_TYPE_INVALID",
! 49: "ATTRIBUTE_VALUE_INVALID");
! 50: ENUM_NEXT(ck_rv_names, CKR_DATA_INVALID, CKR_DATA_LEN_RANGE,
! 51: CKR_ATTRIBUTE_VALUE_INVALID,
! 52: "DATA_INVALID",
! 53: "DATA_LEN_RANGE");
! 54: ENUM_NEXT(ck_rv_names, CKR_DEVICE_ERROR, CKR_DEVICE_REMOVED,
! 55: CKR_DATA_LEN_RANGE,
! 56: "DEVICE_ERROR",
! 57: "DEVICE_MEMORY",
! 58: "DEVICE_REMOVED");
! 59: ENUM_NEXT(ck_rv_names, CKR_ENCRYPTED_DATA_INVALID, CKR_ENCRYPTED_DATA_LEN_RANGE,
! 60: CKR_DEVICE_REMOVED,
! 61: "ENCRYPTED_DATA_INVALID",
! 62: "ENCRYPTED_DATA_LEN_RANGE");
! 63: ENUM_NEXT(ck_rv_names, CKR_FUNCTION_CANCELED, CKR_FUNCTION_NOT_SUPPORTED,
! 64: CKR_ENCRYPTED_DATA_LEN_RANGE,
! 65: "FUNCTION_CANCELED",
! 66: "FUNCTION_NOT_PARALLEL",
! 67: "(0x52)",
! 68: "(0x53)",
! 69: "FUNCTION_NOT_SUPPORTED");
! 70: ENUM_NEXT(ck_rv_names, CKR_KEY_HANDLE_INVALID, CKR_KEY_UNEXTRACTABLE,
! 71: CKR_FUNCTION_NOT_SUPPORTED,
! 72: "KEY_HANDLE_INVALID",
! 73: "(0x61)",
! 74: "KEY_SIZE_RANGE",
! 75: "KEY_TYPE_INCONSISTENT",
! 76: "KEY_NOT_NEEDED",
! 77: "KEY_CHANGED",
! 78: "KEY_NEEDED",
! 79: "KEY_INDIGESTIBLE",
! 80: "KEY_FUNCTION_NOT_PERMITTED",
! 81: "KEY_NOT_WRAPPABLE",
! 82: "KEY_UNEXTRACTABLE");
! 83: ENUM_NEXT(ck_rv_names, CKR_MECHANISM_INVALID, CKR_MECHANISM_PARAM_INVALID,
! 84: CKR_KEY_UNEXTRACTABLE,
! 85: "MECHANISM_INVALID",
! 86: "MECHANISM_PARAM_INVALID");
! 87: ENUM_NEXT(ck_rv_names, CKR_OBJECT_HANDLE_INVALID, CKR_OBJECT_HANDLE_INVALID,
! 88: CKR_MECHANISM_PARAM_INVALID,
! 89: "OBJECT_HANDLE_INVALID");
! 90: ENUM_NEXT(ck_rv_names, CKR_OPERATION_ACTIVE, CKR_OPERATION_NOT_INITIALIZED,
! 91: CKR_OBJECT_HANDLE_INVALID,
! 92: "OPERATION_ACTIVE",
! 93: "OPERATION_NOT_INITIALIZED");
! 94: ENUM_NEXT(ck_rv_names, CKR_PIN_INCORRECT, CKR_PIN_LOCKED,
! 95: CKR_OPERATION_NOT_INITIALIZED,
! 96: "PIN_INCORRECT",
! 97: "PIN_INVALID",
! 98: "PIN_LEN_RANGE",
! 99: "PIN_EXPIRED",
! 100: "PIN_LOCKED");
! 101: ENUM_NEXT(ck_rv_names, CKR_SESSION_CLOSED, CKR_SESSION_READ_WRITE_SO_EXISTS,
! 102: CKR_PIN_LOCKED,
! 103: "SESSION_CLOSED",
! 104: "SESSION_COUNT",
! 105: "(0xb2)",
! 106: "SESSION_HANDLE_INVALID",
! 107: "SESSION_PARALLEL_NOT_SUPPORTED",
! 108: "SESSION_READ_ONLY",
! 109: "SESSION_EXISTS",
! 110: "SESSION_READ_ONLY_EXISTS",
! 111: "SESSION_READ_WRITE_SO_EXISTS");
! 112: ENUM_NEXT(ck_rv_names, CKR_SIGNATURE_INVALID, CKR_SIGNATURE_LEN_RANGE,
! 113: CKR_SESSION_READ_WRITE_SO_EXISTS,
! 114: "SIGNATURE_INVALID",
! 115: "SIGNATURE_LEN_RANGE");
! 116: ENUM_NEXT(ck_rv_names, CKR_TEMPLATE_INCOMPLETE, CKR_TEMPLATE_INCONSISTENT,
! 117: CKR_SIGNATURE_LEN_RANGE,
! 118: "TEMPLATE_INCOMPLETE",
! 119: "TEMPLATE_INCONSISTENT",
! 120: );
! 121: ENUM_NEXT(ck_rv_names, CKR_TOKEN_NOT_PRESENT, CKR_TOKEN_WRITE_PROTECTED,
! 122: CKR_TEMPLATE_INCONSISTENT,
! 123: "TOKEN_NOT_PRESENT",
! 124: "TOKEN_NOT_RECOGNIZED",
! 125: "TOKEN_WRITE_PROTECTED");
! 126: ENUM_NEXT(ck_rv_names, CKR_UNWRAPPING_KEY_HANDLE_INVALID, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
! 127: CKR_TOKEN_WRITE_PROTECTED,
! 128: "UNWRAPPING_KEY_HANDLE_INVALID",
! 129: "UNWRAPPING_KEY_SIZE_RANGE",
! 130: "UNWRAPPING_KEY_TYPE_INCONSISTENT");
! 131: ENUM_NEXT(ck_rv_names, CKR_USER_ALREADY_LOGGED_IN, CKR_USER_TOO_MANY_TYPES,
! 132: CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT,
! 133: "USER_ALREADY_LOGGED_IN",
! 134: "USER_NOT_LOGGED_IN",
! 135: "USER_PIN_NOT_INITIALIZED",
! 136: "USER_TYPE_INVALID",
! 137: "USER_ANOTHER_ALREADY_LOGGED_IN",
! 138: "USER_TOO_MANY_TYPES");
! 139: ENUM_NEXT(ck_rv_names, CKR_WRAPPED_KEY_INVALID, CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
! 140: CKR_USER_TOO_MANY_TYPES,
! 141: "WRAPPED_KEY_INVALID",
! 142: "(0x111)",
! 143: "WRAPPED_KEY_LEN_RANGE",
! 144: "WRAPPING_KEY_HANDLE_INVALID",
! 145: "WRAPPING_KEY_SIZE_RANGE",
! 146: "WRAPPING_KEY_TYPE_INCONSISTENT");
! 147: ENUM_NEXT(ck_rv_names, CKR_RANDOM_SEED_NOT_SUPPORTED, CKR_RANDOM_NO_RNG,
! 148: CKR_WRAPPING_KEY_TYPE_INCONSISTENT,
! 149: "RANDOM_SEED_NOT_SUPPORTED",
! 150: "RANDOM_NO_RNG");
! 151: ENUM_NEXT(ck_rv_names, CKR_DOMAIN_PARAMS_INVALID, CKR_DOMAIN_PARAMS_INVALID,
! 152: CKR_RANDOM_NO_RNG,
! 153: "DOMAIN_PARAMS_INVALID");
! 154: ENUM_NEXT(ck_rv_names, CKR_BUFFER_TOO_SMALL, CKR_BUFFER_TOO_SMALL,
! 155: CKR_DOMAIN_PARAMS_INVALID,
! 156: "BUFFER_TOO_SMALL");
! 157: ENUM_NEXT(ck_rv_names, CKR_SAVED_STATE_INVALID, CKR_SAVED_STATE_INVALID,
! 158: CKR_BUFFER_TOO_SMALL,
! 159: "SAVED_STATE_INVALID");
! 160: ENUM_NEXT(ck_rv_names, CKR_INFORMATION_SENSITIVE, CKR_INFORMATION_SENSITIVE,
! 161: CKR_SAVED_STATE_INVALID,
! 162: "INFORMATION_SENSITIVE");
! 163: ENUM_NEXT(ck_rv_names, CKR_STATE_UNSAVEABLE, CKR_STATE_UNSAVEABLE,
! 164: CKR_INFORMATION_SENSITIVE,
! 165: "STATE_UNSAVEABLE");
! 166: ENUM_NEXT(ck_rv_names, CKR_CRYPTOKI_NOT_INITIALIZED, CKR_CRYPTOKI_ALREADY_INITIALIZED,
! 167: CKR_STATE_UNSAVEABLE,
! 168: "CRYPTOKI_NOT_INITIALIZED",
! 169: "CRYPTOKI_ALREADY_INITIALIZED");
! 170: ENUM_NEXT(ck_rv_names, CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED,
! 171: CKR_CRYPTOKI_ALREADY_INITIALIZED,
! 172: "MUTEX_BAD",
! 173: "MUTEX_NOT_LOCKED");
! 174: ENUM_NEXT(ck_rv_names, CKR_FUNCTION_REJECTED, CKR_FUNCTION_REJECTED,
! 175: CKR_MUTEX_NOT_LOCKED,
! 176: "FUNCTION_REJECTED");
! 177: ENUM_END(ck_rv_names, CKR_FUNCTION_REJECTED);
! 178:
! 179:
! 180: ENUM_BEGIN(ck_mech_names, CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_DSA_SHA1,
! 181: "RSA_PKCS_KEY_PAIR_GEN",
! 182: "RSA_PKCS",
! 183: "RSA_9796",
! 184: "RSA_X_509",
! 185: "MD2_RSA_PKCS",
! 186: "MD5_RSA_PKCS",
! 187: "SHA1_RSA_PKCS",
! 188: "RIPEMD128_RSA_PKCS",
! 189: "RIPEMD160_RSA_PKCS",
! 190: "RSA_PKCS_OAEP",
! 191: "RSA_X9_31_KEY_PAIR_GEN",
! 192: "RSA_X9_31",
! 193: "SHA1_RSA_X9_31",
! 194: "RSA_PKCS_PSS",
! 195: "SHA1_RSA_PKCS_PSS",
! 196: "(0xf)",
! 197: "DSA_KEY_PAIR_GEN",
! 198: "DSA",
! 199: "DSA_SHA1");
! 200: ENUM_NEXT(ck_mech_names, CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE,
! 201: CKM_DSA_SHA1,
! 202: "DH_PKCS_KEY_PAIR_GEN",
! 203: "DH_PKCS_DERIVE");
! 204: ENUM_NEXT(ck_mech_names, CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_MQV_DERIVE,
! 205: CKM_DH_PKCS_DERIVE,
! 206: "X9_42_DH_KEY_PAIR_GEN",
! 207: "X9_42_DH_DERIVE",
! 208: "X9_42_DH_HYBRID_DERIVE",
! 209: "X9_42_MQV_DERIVE");
! 210: ENUM_NEXT(ck_mech_names, CKM_SHA256_RSA_PKCS, CKM_SHA512_RSA_PKCS_PSS,
! 211: CKM_X9_42_MQV_DERIVE,
! 212: "SHA256_RSA_PKCS",
! 213: "SHA384_RSA_PKCS",
! 214: "SHA512_RSA_PKCS",
! 215: "SHA256_RSA_PKCS_PSS",
! 216: "SHA384_RSA_PKCS_PSS",
! 217: "SHA512_RSA_PKCS_PSS");
! 218: ENUM_NEXT(ck_mech_names, CKM_RC2_KEY_GEN, CKM_RC2_CBC_PAD,
! 219: CKM_SHA512_RSA_PKCS_PSS,
! 220: "RC2_KEY_GEN",
! 221: "RC2_ECB",
! 222: "RC2_CBC",
! 223: "RC2_MAC",
! 224: "RC2_MAC_GENERAL",
! 225: "RC2_CBC_PAD");
! 226: ENUM_NEXT(ck_mech_names, CKM_RC4_KEY_GEN, CKM_RC4,
! 227: CKM_RC2_CBC_PAD,
! 228: "RC4_KEY_GEN",
! 229: "RC4");
! 230: ENUM_NEXT(ck_mech_names, CKM_DES_KEY_GEN, CKM_DES_CBC_PAD,
! 231: CKM_RC4,
! 232: "DES_KEY_GEN",
! 233: "DES_ECB",
! 234: "DES_CBC",
! 235: "DES_MAC",
! 236: "DES_MAC_GENERAL",
! 237: "DES_CBC_PAD");
! 238: ENUM_NEXT(ck_mech_names, CKM_DES2_KEY_GEN, CKM_DES3_CBC_PAD,
! 239: CKM_DES_CBC_PAD,
! 240: "DES2_KEY_GEN",
! 241: "DES3_KEY_GEN",
! 242: "DES3_ECB",
! 243: "DES3_CBC",
! 244: "DES3_MAC",
! 245: "DES3_MAC_GENERAL",
! 246: "DES3_CBC_PAD");
! 247: ENUM_NEXT(ck_mech_names, CKM_CDMF_KEY_GEN, CKM_CDMF_CBC_PAD,
! 248: CKM_DES3_CBC_PAD,
! 249: "CDMF_KEY_GEN",
! 250: "CDMF_ECB",
! 251: "CDMF_CBC",
! 252: "CDMF_MAC",
! 253: "CDMF_MAC_GENERAL",
! 254: "CDMF_CBC_PAD");
! 255: ENUM_NEXT(ck_mech_names, CKM_MD2, CKM_MD2_HMAC_GENERAL,
! 256: CKM_CDMF_CBC_PAD,
! 257: "MD2",
! 258: "MD2_HMAC",
! 259: "MD2_HMAC_GENERAL");
! 260: ENUM_NEXT(ck_mech_names, CKM_MD5, CKM_MD5_HMAC_GENERAL,
! 261: CKM_MD2_HMAC_GENERAL,
! 262: "MD5",
! 263: "MD5_HMAC",
! 264: "MD5_HMAC_GENERAL");
! 265: ENUM_NEXT(ck_mech_names, CKM_SHA_1, CKM_SHA_1_HMAC_GENERAL,
! 266: CKM_MD5_HMAC_GENERAL,
! 267: "SHA_1",
! 268: "SHA_1_HMAC",
! 269: "SHA_1_HMAC_GENERAL");
! 270: ENUM_NEXT(ck_mech_names, CKM_RIPEMD128, CKM_RIPEMD128_HMAC_GENERAL,
! 271: CKM_SHA_1_HMAC_GENERAL,
! 272: "RIPEMD128",
! 273: "RIPEMD128_HMAC",
! 274: "RIPEMD128_HMAC_GENERAL");
! 275: ENUM_NEXT(ck_mech_names, CKM_RIPEMD160, CKM_RIPEMD160_HMAC_GENERAL,
! 276: CKM_RIPEMD128_HMAC_GENERAL,
! 277: "RIPEMD160",
! 278: "RIPEMD160_HMAC",
! 279: "RIPEMD160_HMAC_GENERAL");
! 280: ENUM_NEXT(ck_mech_names, CKM_SHA256, CKM_SHA256_HMAC_GENERAL,
! 281: CKM_RIPEMD160_HMAC_GENERAL,
! 282: "SHA256",
! 283: "SHA256_HMAC",
! 284: "SHA256_HMAC_GENERAL");
! 285: ENUM_NEXT(ck_mech_names, CKM_SHA384, CKM_SHA384_HMAC_GENERAL,
! 286: CKM_SHA256_HMAC_GENERAL,
! 287: "SHA384",
! 288: "SHA384_HMAC",
! 289: "SHA384_HMAC_GENERAL");
! 290: ENUM_NEXT(ck_mech_names, CKM_SHA512, CKM_SHA512_HMAC_GENERAL,
! 291: CKM_SHA384_HMAC_GENERAL ,
! 292: "SHA512",
! 293: "SHA512_HMAC",
! 294: "SHA512_HMAC_GENERAL");
! 295: ENUM_NEXT(ck_mech_names, CKM_CAST_KEY_GEN, CKM_CAST_CBC_PAD,
! 296: CKM_SHA512_HMAC_GENERAL,
! 297: "CAST_KEY_GEN",
! 298: "CAST_ECB",
! 299: "CAST_CBC",
! 300: "CAST_MAC",
! 301: "CAST_MAC_GENERAL",
! 302: "CAST_CBC_PAD");
! 303: ENUM_NEXT(ck_mech_names, CKM_CAST3_KEY_GEN, CKM_CAST3_CBC_PAD,
! 304: CKM_CAST_CBC_PAD,
! 305: "CAST3_KEY_GEN",
! 306: "CAST3_ECB",
! 307: "CAST3_CBC",
! 308: "CAST3_MAC",
! 309: "CAST3_MAC_GENERAL",
! 310: "CAST3_CBC_PAD");
! 311: ENUM_NEXT(ck_mech_names, CKM_CAST128_KEY_GEN, CKM_CAST128_CBC_PAD,
! 312: CKM_CAST3_CBC_PAD,
! 313: "CAST128_KEY_GEN",
! 314: "CAST128_ECB",
! 315: "CAST128_CBC",
! 316: "CAST128_MAC",
! 317: "CAST128_MAC_GENERAL",
! 318: "CAST128_CBC_PAD");
! 319: ENUM_NEXT(ck_mech_names, CKM_RC5_KEY_GEN, CKM_RC5_CBC_PAD,
! 320: CKM_CAST128_CBC_PAD,
! 321: "RC5_KEY_GEN",
! 322: "RC5_ECB",
! 323: "RC5_CBC",
! 324: "RC5_MAC",
! 325: "RC5_MAC_GENERAL",
! 326: "RC5_CBC_PAD");
! 327: ENUM_NEXT(ck_mech_names, CKM_IDEA_KEY_GEN, CKM_IDEA_CBC_PAD,
! 328: CKM_RC5_CBC_PAD,
! 329: "IDEA_KEY_GEN",
! 330: "IDEA_ECB",
! 331: "IDEA_CBC",
! 332: "IDEA_MAC",
! 333: "IDEA_MAC_GENERAL",
! 334: "IDEA_CBC_PAD");
! 335: ENUM_NEXT(ck_mech_names, CKM_GENERIC_SECRET_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN,
! 336: CKM_IDEA_CBC_PAD,
! 337: "GENERIC_SECRET_KEY_GEN");
! 338: ENUM_NEXT(ck_mech_names, CKM_CONCATENATE_BASE_AND_KEY, CKM_EXTRACT_KEY_FROM_KEY,
! 339: CKM_GENERIC_SECRET_KEY_GEN,
! 340: "CONCATENATE_BASE_AND_KEY",
! 341: "(0x361)",
! 342: "CONCATENATE_BASE_AND_DATA",
! 343: "CONCATENATE_DATA_AND_BASE",
! 344: "XOR_BASE_AND_DATA",
! 345: "EXTRACT_KEY_FROM_KEY");
! 346: ENUM_NEXT(ck_mech_names, CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_MASTER_KEY_DERIVE_DH,
! 347: CKM_EXTRACT_KEY_FROM_KEY,
! 348: "SSL3_PRE_MASTER_KEY_GEN",
! 349: "SSL3_MASTER_KEY_DERIVE",
! 350: "SSL3_KEY_AND_MAC_DERIVE",
! 351: "SSL3_MASTER_KEY_DERIVE_DH",
! 352: "TLS_PRE_MASTER_KEY_GEN",
! 353: "TLS_MASTER_KEY_DERIVE",
! 354: "TLS_KEY_AND_MAC_DERIVE",
! 355: "TLS_MASTER_KEY_DERIVE_DH");
! 356: ENUM_NEXT(ck_mech_names, CKM_SSL3_MD5_MAC, CKM_SSL3_SHA1_MAC,
! 357: CKM_TLS_MASTER_KEY_DERIVE_DH,
! 358: "SSL3_MD5_MAC",
! 359: "SSL3_SHA1_MAC");
! 360: ENUM_NEXT(ck_mech_names, CKM_MD5_KEY_DERIVATION, CKM_SHA1_KEY_DERIVATION,
! 361: CKM_SSL3_SHA1_MAC,
! 362: "MD5_KEY_DERIVATION",
! 363: "MD2_KEY_DERIVATION",
! 364: "SHA1_KEY_DERIVATION");
! 365: ENUM_NEXT(ck_mech_names, CKM_PBE_MD2_DES_CBC, CKM_PBE_SHA1_RC2_40_CBC,
! 366: CKM_SHA1_KEY_DERIVATION,
! 367: "PBE_MD2_DES_CBC",
! 368: "PBE_MD5_DES_CBC",
! 369: "PBE_MD5_CAST_CBC",
! 370: "PBE_MD5_CAST3_CBC",
! 371: "PBE_MD5_CAST128_CBC",
! 372: "PBE_SHA1_CAST128_CBC",
! 373: "PBE_SHA1_RC4_128",
! 374: "PBE_SHA1_RC4_40",
! 375: "PBE_SHA1_DES3_EDE_CBC",
! 376: "PBE_SHA1_DES2_EDE_CBC",
! 377: "PBE_SHA1_RC2_128_CBC",
! 378: "PBE_SHA1_RC2_40_CBC");
! 379: ENUM_NEXT(ck_mech_names, CKM_PKCS5_PBKD2, CKM_PKCS5_PBKD2,
! 380: CKM_PBE_SHA1_RC2_40_CBC,
! 381: "PKCS5_PBKD2");
! 382: ENUM_NEXT(ck_mech_names, CKM_PBA_SHA1_WITH_SHA1_HMAC, CKM_PBA_SHA1_WITH_SHA1_HMAC,
! 383: CKM_PKCS5_PBKD2,
! 384: "PBA_SHA1_WITH_SHA1_HMAC");
! 385: ENUM_NEXT(ck_mech_names, CKM_KEY_WRAP_LYNKS, CKM_KEY_WRAP_SET_OAEP,
! 386: CKM_PBA_SHA1_WITH_SHA1_HMAC,
! 387: "KEY_WRAP_LYNKS",
! 388: "KEY_WRAP_SET_OAEP");
! 389: ENUM_NEXT(ck_mech_names, CKM_SKIPJACK_KEY_GEN, CKM_SKIPJACK_RELAYX,
! 390: CKM_KEY_WRAP_SET_OAEP,
! 391: "SKIPJACK_KEY_GEN",
! 392: "SKIPJACK_ECB64",
! 393: "SKIPJACK_CBC64",
! 394: "SKIPJACK_OFB64",
! 395: "SKIPJACK_CFB64",
! 396: "SKIPJACK_CFB32",
! 397: "SKIPJACK_CFB16",
! 398: "SKIPJACK_CFB8",
! 399: "SKIPJACK_WRAP",
! 400: "SKIPJACK_PRIVATE_WRAP",
! 401: "SKIPJACK_RELAYX");
! 402: ENUM_NEXT(ck_mech_names, CKM_KEA_KEY_PAIR_GEN, CKM_KEA_KEY_DERIVE,
! 403: CKM_SKIPJACK_RELAYX,
! 404: "KEA_KEY_PAIR_GEN",
! 405: "KEA_KEY_DERIVE");
! 406: ENUM_NEXT(ck_mech_names, CKM_FORTEZZA_TIMESTAMP, CKM_FORTEZZA_TIMESTAMP,
! 407: CKM_KEA_KEY_DERIVE,
! 408: "FORTEZZA_TIMESTAMP");
! 409: ENUM_NEXT(ck_mech_names, CKM_BATON_KEY_GEN, CKM_BATON_WRAP,
! 410: CKM_FORTEZZA_TIMESTAMP,
! 411: "BATON_KEY_GEN",
! 412: "BATON_ECB128",
! 413: "BATON_ECB96",
! 414: "BATON_CBC128",
! 415: "BATON_COUNTER",
! 416: "BATON_SHUFFLE",
! 417: "BATON_WRAP");
! 418: ENUM_NEXT(ck_mech_names, CKM_ECDSA_KEY_PAIR_GEN, CKM_ECDSA_SHA1,
! 419: CKM_BATON_WRAP,
! 420: "ECDSA_KEY_PAIR_GEN",
! 421: "ECDSA",
! 422: "ECDSA_SHA1");
! 423: ENUM_NEXT(ck_mech_names, CKM_ECDH1_DERIVE, CKM_ECMQV_DERIVE,
! 424: CKM_ECDSA_SHA1,
! 425: "ECDH1_DERIVE",
! 426: "ECDH1_COFACTOR_DERIVE",
! 427: "ECMQV_DERIVE");
! 428: ENUM_NEXT(ck_mech_names, CKM_JUNIPER_KEY_GEN, CKM_JUNIPER_WRAP,
! 429: CKM_ECMQV_DERIVE,
! 430: "JUNIPER_KEY_GEN",
! 431: "JUNIPER_ECB128",
! 432: "JUNIPER_CBC128",
! 433: "JUNIPER_COUNTER",
! 434: "JUNIPER_SHUFFLE",
! 435: "JUNIPER_WRAP");
! 436: ENUM_NEXT(ck_mech_names, CKM_FASTHASH, CKM_FASTHASH,
! 437: CKM_JUNIPER_WRAP,
! 438: "FASTHASH");
! 439: ENUM_NEXT(ck_mech_names, CKM_AES_KEY_GEN, CKM_AES_CBC_PAD,
! 440: CKM_FASTHASH,
! 441: "AES_KEY_GEN",
! 442: "AES_ECB",
! 443: "AES_CBC",
! 444: "AES_MAC",
! 445: "AES_MAC_GENERAL",
! 446: "AES_CBC_PAD");
! 447: ENUM_NEXT(ck_mech_names, CKM_DSA_PARAMETER_GEN, CKM_X9_42_DH_PARAMETER_GEN,
! 448: CKM_AES_CBC_PAD,
! 449: "DSA_PARAMETER_GEN",
! 450: "DH_PKCS_PARAMETER_GEN",
! 451: "X9_42_DH_PARAMETER_GEN");
! 452: ENUM_END(ck_mech_names, CKM_X9_42_DH_PARAMETER_GEN);
! 453:
! 454:
! 455: ENUM_BEGIN(ck_attr_names, CKA_CLASS, CKA_LABEL,
! 456: "CLASS",
! 457: "TOKEN",
! 458: "PRIVATE",
! 459: "LABEL");
! 460: ENUM_NEXT(ck_attr_names, CKA_APPLICATION, CKA_OBJECT_ID, CKA_LABEL,
! 461: "APPLICATION",
! 462: "VALUE",
! 463: "OBJECT_ID");
! 464: ENUM_NEXT(ck_attr_names, CKA_CERTIFICATE_TYPE, CKA_HASH_OF_ISSUER_PUBLIC_KEY,
! 465: CKA_OBJECT_ID,
! 466: "CERTIFICATE_TYPE",
! 467: "ISSUER",
! 468: "SERIAL_NUMBER",
! 469: "AC_ISSUER",
! 470: "OWNER",
! 471: "ATTR_TYPES",
! 472: "TRUSTED",
! 473: "CERTIFICATE_CATEGORY",
! 474: "JAVA_MIDP_SECURITY_DOMAIN",
! 475: "URL",
! 476: "HASH_OF_SUBJECT_PUBLIC_KEY",
! 477: "HASH_OF_ISSUER_PUBLIC_KEY");
! 478: ENUM_NEXT(ck_attr_names, CKA_CHECK_VALUE, CKA_CHECK_VALUE,
! 479: CKA_HASH_OF_ISSUER_PUBLIC_KEY,
! 480: "CHECK_VALUE");
! 481: ENUM_NEXT(ck_attr_names, CKA_KEY_TYPE, CKA_DERIVE, CKA_CHECK_VALUE,
! 482: "KEY_TYPE",
! 483: "SUBJECT",
! 484: "ID",
! 485: "SENSITIVE",
! 486: "ENCRYPT",
! 487: "DECRYPT",
! 488: "WRAP",
! 489: "UNWRAP",
! 490: "SIGN",
! 491: "SIGN_RECOVER",
! 492: "VERIFY",
! 493: "VERIFY_RECOVER",
! 494: "DERIVE");
! 495: ENUM_NEXT(ck_attr_names, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE,
! 496: "START_DATE",
! 497: "END_DATE");
! 498: ENUM_NEXT(ck_attr_names, CKA_MODULUS, CKA_COEFFICIENT, CKA_END_DATE,
! 499: "MODULUS",
! 500: "MODULUS_BITS",
! 501: "PUBLIC_EXPONENT",
! 502: "PRIVATE_EXPONENT",
! 503: "PRIME_1",
! 504: "PRIME_2",
! 505: "EXPONENT_1",
! 506: "EXPONENT_2",
! 507: "COEFFICIENT");
! 508: ENUM_NEXT(ck_attr_names, CKA_PRIME, CKA_SUB_PRIME_BITS, CKA_COEFFICIENT,
! 509: "PRIME",
! 510: "SUBPRIME",
! 511: "BASE",
! 512: "PRIME_BITS",
! 513: "SUB_PRIME_BITS");
! 514: ENUM_NEXT(ck_attr_names, CKA_VALUE_BITS, CKA_KEY_GEN_MECHANISM,
! 515: CKA_SUB_PRIME_BITS,
! 516: "VALUE_BITS",
! 517: "VALUE_LEN",
! 518: "EXTRACTABLE",
! 519: "LOCAL",
! 520: "NEVER_EXTRACTABLE",
! 521: "ALWAYS_SENSITIVE",
! 522: "KEY_GEN_MECHANISM");
! 523: ENUM_NEXT(ck_attr_names, CKA_MODIFIABLE, CKA_MODIFIABLE, CKA_KEY_GEN_MECHANISM,
! 524: "MODIFIABLE");
! 525: ENUM_NEXT(ck_attr_names, CKA_EC_PARAMS, CKA_EC_POINT, CKA_MODIFIABLE,
! 526: "EC_PARAMS",
! 527: "EC_POINT");
! 528: ENUM_NEXT(ck_attr_names, CKA_SECONDARY_AUTH, CKA_ALWAYS_AUTHENTICATE,
! 529: CKA_EC_POINT,
! 530: "SECONDARY_AUTH",
! 531: "AUTH_PIN_FLAGS",
! 532: "ALWAYS_AUTHENTICATE");
! 533: ENUM_NEXT(ck_attr_names, CKA_WRAP_WITH_TRUSTED, CKA_WRAP_WITH_TRUSTED,
! 534: CKA_ALWAYS_AUTHENTICATE,
! 535: "WRAP_WITH_TRUSTED");
! 536: ENUM_NEXT(ck_attr_names, CKA_HW_FEATURE_TYPE, CKA_HAS_RESET,
! 537: CKA_WRAP_WITH_TRUSTED,
! 538: "HW_FEATURE_TYPE",
! 539: "RESET_ON_INIT",
! 540: "HAS_RESET");
! 541: ENUM_NEXT(ck_attr_names, CKA_PIXEL_X, CKA_BITS_PER_PIXEL, CKA_HAS_RESET,
! 542: "PIXEL_X",
! 543: "PIXEL_Y",
! 544: "RESOLUTION",
! 545: "CHAR_ROWS",
! 546: "CHAR_COLUMNS",
! 547: "COLOR",
! 548: "BITS_PER_PIXEL");
! 549: ENUM_NEXT(ck_attr_names, CKA_CHAR_SETS, CKA_MIME_TYPES, CKA_BITS_PER_PIXEL,
! 550: "CHAR_SETS",
! 551: "ENCODING_METHODS",
! 552: "MIME_TYPES");
! 553: ENUM_NEXT(ck_attr_names, CKA_MECHANISM_TYPE, CKA_SUPPORTED_CMS_ATTRIBUTES,
! 554: CKA_MIME_TYPES,
! 555: "MECHANISM_TYPE",
! 556: "REQUIRED_CMS_ATTRIBUTES",
! 557: "DEFAULT_CMS_ATTRIBUTES",
! 558: "SUPPORTED_CMS_ATTRIBUTES");
! 559: ENUM_NEXT(ck_attr_names, CKA_WRAP_TEMPLATE, CKA_UNWRAP_TEMPLATE,
! 560: CKA_SUPPORTED_CMS_ATTRIBUTES,
! 561: "WRAP_TEMPLATE",
! 562: "UNWRAP_TEMPLATE");
! 563: ENUM_NEXT(ck_attr_names, CKA_ALLOWED_MECHANISMS, CKA_ALLOWED_MECHANISMS,
! 564: CKA_UNWRAP_TEMPLATE,
! 565: "ALLOWED_MECHANISMS");
! 566: ENUM_END(ck_attr_names, CKA_ALLOWED_MECHANISMS);
! 567: /* the values in an enum_name_t are stored as int, thus CKA_VENDOR_DEFINED
! 568: * will overflow and is thus not defined here */
! 569:
! 570:
! 571:
! 572: /**
! 573: * Private data of an pkcs11_library_t object.
! 574: */
! 575: struct private_pkcs11_library_t {
! 576:
! 577: /**
! 578: * Public pkcs11_library_t interface.
! 579: */
! 580: pkcs11_library_t public;
! 581:
! 582: /**
! 583: * dlopen() handle
! 584: */
! 585: void *handle;
! 586:
! 587: /**
! 588: * Name as passed to the constructor
! 589: */
! 590: char *name;
! 591:
! 592: /**
! 593: * Supported feature set
! 594: */
! 595: pkcs11_feature_t features;
! 596: };
! 597:
! 598: METHOD(pkcs11_library_t, get_name, char*,
! 599: private_pkcs11_library_t *this)
! 600: {
! 601: return this->name;
! 602: }
! 603:
! 604: METHOD(pkcs11_library_t, get_features, pkcs11_feature_t,
! 605: private_pkcs11_library_t *this)
! 606: {
! 607: return this->features;
! 608: }
! 609:
! 610: /**
! 611: * Object enumerator
! 612: */
! 613: typedef struct {
! 614: /* implements enumerator_t */
! 615: enumerator_t public;
! 616: /* session */
! 617: CK_SESSION_HANDLE session;
! 618: /* pkcs11 library */
! 619: pkcs11_library_t *lib;
! 620: /* attributes to retrieve */
! 621: CK_ATTRIBUTE_PTR attr;
! 622: /* number of attributes */
! 623: CK_ULONG count;
! 624: /* object handle in case of a single object */
! 625: CK_OBJECT_HANDLE object;
! 626: /* currently allocated attributes, to free */
! 627: linked_list_t *freelist;
! 628: } object_enumerator_t;
! 629:
! 630: /**
! 631: * Free contents of attributes in a list
! 632: */
! 633: static void free_attrs(object_enumerator_t *this)
! 634: {
! 635: CK_ATTRIBUTE_PTR attr;
! 636:
! 637: while (this->freelist->remove_last(this->freelist, (void**)&attr) == SUCCESS)
! 638: {
! 639: free(attr->pValue);
! 640: attr->pValue = NULL;
! 641: attr->ulValueLen = 0;
! 642: }
! 643: }
! 644:
! 645: /**
! 646: * CKA_EC_POINT is encoded as ASN.1 octet string, we can't handle that and
! 647: * some tokens actually return them even unwrapped.
! 648: *
! 649: * Because ASN1_OCTET_STRING is 0x04 and uncompressed EC_POINTs also begin with
! 650: * 0x04 (compressed ones with 0x02 or 0x03) there will be an attempt to parse
! 651: * unwrapped uncompressed EC_POINTs. This will fail in most cases as the length
! 652: * will not be correct, however, there is a small chance that the key's first
! 653: * byte denotes the correct length. Checking the first byte of the key should
! 654: * further reduce the risk of false positives, though.
! 655: *
! 656: * The original memory is freed if the value is unwrapped.
! 657: */
! 658: static void unwrap_ec_point(chunk_t *data)
! 659: {
! 660: chunk_t wrapped, unwrapped;
! 661:
! 662: wrapped = unwrapped = *data;
! 663: if (asn1_unwrap(&unwrapped, &unwrapped) == ASN1_OCTET_STRING &&
! 664: unwrapped.len && unwrapped.ptr[0] >= 0x02 && unwrapped.ptr[0] <= 0x04)
! 665: {
! 666: *data = chunk_clone(unwrapped);
! 667: free(wrapped.ptr);
! 668: }
! 669: }
! 670:
! 671: /**
! 672: * Get attributes for a given object during enumeration
! 673: */
! 674: static bool get_attributes(object_enumerator_t *this, CK_OBJECT_HANDLE object)
! 675: {
! 676: chunk_t data;
! 677: CK_RV rv;
! 678: int i;
! 679:
! 680: free_attrs(this);
! 681:
! 682: /* get length of objects first */
! 683: rv = this->lib->f->C_GetAttributeValue(this->session, object,
! 684: this->attr, this->count);
! 685: if (rv != CKR_OK)
! 686: {
! 687: DBG1(DBG_CFG, "C_GetAttributeValue(NULL) error: %N", ck_rv_names, rv);
! 688: return FALSE;
! 689: }
! 690: /* allocate required chunks */
! 691: for (i = 0; i < this->count; i++)
! 692: {
! 693: if (this->attr[i].pValue == NULL &&
! 694: this->attr[i].ulValueLen != 0 && this->attr[i].ulValueLen != -1)
! 695: {
! 696: this->attr[i].pValue = malloc(this->attr[i].ulValueLen);
! 697: this->freelist->insert_last(this->freelist, &this->attr[i]);
! 698: }
! 699: }
! 700: /* get the data */
! 701: rv = this->lib->f->C_GetAttributeValue(this->session, object,
! 702: this->attr, this->count);
! 703: if (rv != CKR_OK)
! 704: {
! 705: free_attrs(this);
! 706: DBG1(DBG_CFG, "C_GetAttributeValue() error: %N", ck_rv_names, rv);
! 707: return FALSE;
! 708: }
! 709: for (i = 0; i < this->count; i++)
! 710: {
! 711: if (this->attr[i].type == CKA_EC_POINT)
! 712: {
! 713: data = chunk_create(this->attr[i].pValue, this->attr[i].ulValueLen);
! 714: unwrap_ec_point(&data);
! 715: this->attr[i].pValue = data.ptr;
! 716: this->attr[i].ulValueLen = data.len;
! 717: }
! 718: }
! 719: return TRUE;
! 720: }
! 721:
! 722: METHOD(enumerator_t, object_enumerate, bool,
! 723: object_enumerator_t *this, va_list args)
! 724: {
! 725: CK_OBJECT_HANDLE object, *out;
! 726: CK_ULONG found;
! 727: CK_RV rv;
! 728:
! 729: VA_ARGS_VGET(args, out);
! 730:
! 731: if (!this->object)
! 732: {
! 733: rv = this->lib->f->C_FindObjects(this->session, &object, 1, &found);
! 734: if (rv != CKR_OK)
! 735: {
! 736: DBG1(DBG_CFG, "C_FindObjects() failed: %N", ck_rv_names, rv);
! 737: return FALSE;
! 738: }
! 739: }
! 740: else
! 741: {
! 742: object = this->object;
! 743: found = 1;
! 744: }
! 745: if (found)
! 746: {
! 747: if (this->attr)
! 748: {
! 749: if (!get_attributes(this, object))
! 750: {
! 751: return FALSE;
! 752: }
! 753: }
! 754: if (out)
! 755: {
! 756: *out = object;
! 757: }
! 758: return TRUE;
! 759: }
! 760: return FALSE;
! 761: }
! 762:
! 763: METHOD(enumerator_t, object_destroy, void,
! 764: object_enumerator_t *this)
! 765: {
! 766: if (!this->object)
! 767: {
! 768: this->lib->f->C_FindObjectsFinal(this->session);
! 769: }
! 770: free_attrs(this);
! 771: this->freelist->destroy(this->freelist);
! 772: free(this);
! 773: }
! 774:
! 775: METHOD(pkcs11_library_t, create_object_enumerator, enumerator_t*,
! 776: private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
! 777: CK_ATTRIBUTE_PTR tmpl, CK_ULONG tcount,
! 778: CK_ATTRIBUTE_PTR attr, CK_ULONG acount)
! 779: {
! 780: object_enumerator_t *enumerator;
! 781: CK_RV rv;
! 782:
! 783: rv = this->public.f->C_FindObjectsInit(session, tmpl, tcount);
! 784: if (rv != CKR_OK)
! 785: {
! 786: DBG1(DBG_CFG, "C_FindObjectsInit() failed: %N", ck_rv_names, rv);
! 787: return enumerator_create_empty();
! 788: }
! 789:
! 790: INIT(enumerator,
! 791: .public = {
! 792: .enumerate = enumerator_enumerate_default,
! 793: .venumerate = _object_enumerate,
! 794: .destroy = _object_destroy,
! 795: },
! 796: .session = session,
! 797: .lib = &this->public,
! 798: .attr = attr,
! 799: .count = acount,
! 800: .freelist = linked_list_create(),
! 801: );
! 802: return &enumerator->public;
! 803: }
! 804:
! 805: METHOD(pkcs11_library_t, create_object_attr_enumerator, enumerator_t*,
! 806: private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
! 807: CK_OBJECT_HANDLE object, CK_ATTRIBUTE_PTR attr, CK_ULONG count)
! 808: {
! 809: object_enumerator_t *enumerator;
! 810:
! 811: INIT(enumerator,
! 812: .public = {
! 813: .enumerate = enumerator_enumerate_default,
! 814: .venumerate = _object_enumerate,
! 815: .destroy = _object_destroy,
! 816: },
! 817: .session = session,
! 818: .lib = &this->public,
! 819: .attr = attr,
! 820: .count = count,
! 821: .object = object,
! 822: .freelist = linked_list_create(),
! 823: );
! 824: return &enumerator->public;
! 825: }
! 826:
! 827: /**
! 828: * Enumerator over mechanisms
! 829: */
! 830: typedef struct {
! 831: /* implements enumerator_t */
! 832: enumerator_t public;
! 833: /* PKCS#11 library */
! 834: pkcs11_library_t *lib;
! 835: /* slot of token */
! 836: CK_SLOT_ID slot;
! 837: /* mechanism type list */
! 838: CK_MECHANISM_TYPE_PTR mechs;
! 839: /* number of mechanism types */
! 840: CK_ULONG count;
! 841: /* current mechanism */
! 842: CK_ULONG current;
! 843: } mechanism_enumerator_t;
! 844:
! 845: METHOD(enumerator_t, enumerate_mech, bool,
! 846: mechanism_enumerator_t *this, va_list args)
! 847: {
! 848: CK_MECHANISM_INFO *info;
! 849: CK_MECHANISM_TYPE *type;
! 850: CK_RV rv;
! 851:
! 852: VA_ARGS_VGET(args, type, info);
! 853:
! 854: if (this->current >= this->count)
! 855: {
! 856: return FALSE;
! 857: }
! 858: if (info)
! 859: {
! 860: rv = this->lib->f->C_GetMechanismInfo(this->slot,
! 861: this->mechs[this->current], info);
! 862: if (rv != CKR_OK)
! 863: {
! 864: DBG1(DBG_CFG, "C_GetMechanismInfo() failed: %N", ck_rv_names, rv);
! 865: return FALSE;
! 866: }
! 867: }
! 868: *type = this->mechs[this->current++];
! 869: return TRUE;
! 870: }
! 871:
! 872: METHOD(enumerator_t, destroy_mech, void,
! 873: mechanism_enumerator_t *this)
! 874: {
! 875: free(this->mechs);
! 876: free(this);
! 877: }
! 878:
! 879: METHOD(pkcs11_library_t, create_mechanism_enumerator, enumerator_t*,
! 880: private_pkcs11_library_t *this, CK_SLOT_ID slot)
! 881: {
! 882: mechanism_enumerator_t *enumerator;
! 883: CK_RV rv;
! 884:
! 885: INIT(enumerator,
! 886: .public = {
! 887: .enumerate = enumerator_enumerate_default,
! 888: .venumerate = _enumerate_mech,
! 889: .destroy = _destroy_mech,
! 890: },
! 891: .lib = &this->public,
! 892: .slot = slot,
! 893: );
! 894:
! 895: rv = enumerator->lib->f->C_GetMechanismList(slot, NULL, &enumerator->count);
! 896: if (rv != CKR_OK)
! 897: {
! 898: DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv);
! 899: free(enumerator);
! 900: return enumerator_create_empty();
! 901: }
! 902: enumerator->mechs = malloc(sizeof(CK_MECHANISM_TYPE) * enumerator->count);
! 903: rv = enumerator->lib->f->C_GetMechanismList(slot, enumerator->mechs,
! 904: &enumerator->count);
! 905: if (rv != CKR_OK)
! 906: {
! 907: DBG1(DBG_CFG, "C_GetMechanismList() failed: %N", ck_rv_names, rv);
! 908: destroy_mech(enumerator);
! 909: return enumerator_create_empty();
! 910: }
! 911: return &enumerator->public;
! 912: }
! 913:
! 914: METHOD(pkcs11_library_t, get_ck_attribute, bool,
! 915: private_pkcs11_library_t *this, CK_SESSION_HANDLE session,
! 916: CK_OBJECT_HANDLE obj, CK_ATTRIBUTE_TYPE type, chunk_t *data)
! 917: {
! 918: CK_ATTRIBUTE attr = { type, NULL, 0 };
! 919: CK_RV rv;
! 920: rv = this->public.f->C_GetAttributeValue(session, obj, &attr, 1);
! 921: if (rv != CKR_OK)
! 922: {
! 923: DBG1(DBG_CFG, "C_GetAttributeValue(%N) error: %N", ck_attr_names, type,
! 924: ck_rv_names, rv);
! 925: return FALSE;
! 926: }
! 927: *data = chunk_alloc(attr.ulValueLen);
! 928: attr.pValue = data->ptr;
! 929: rv = this->public.f->C_GetAttributeValue(session, obj, &attr, 1);
! 930: if (rv != CKR_OK)
! 931: {
! 932: DBG1(DBG_CFG, "C_GetAttributeValue(%N) error: %N", ck_attr_names, type,
! 933: ck_rv_names, rv);
! 934: chunk_free(data);
! 935: return FALSE;
! 936: }
! 937: if (attr.type == CKA_EC_POINT)
! 938: {
! 939: unwrap_ec_point(data);
! 940: }
! 941: return TRUE;
! 942: }
! 943:
! 944: METHOD(pkcs11_library_t, destroy, void,
! 945: private_pkcs11_library_t *this)
! 946: {
! 947: this->public.f->C_Finalize(NULL);
! 948: dlclose(this->handle);
! 949: free(this->name);
! 950: free(this);
! 951: }
! 952:
! 953: /**
! 954: * See header
! 955: */
! 956: void pkcs11_library_trim(char *str, int len)
! 957: {
! 958: int i;
! 959:
! 960: str[len - 1] = '\0';
! 961: for (i = len - 2; i > 0; i--)
! 962: {
! 963: if (str[i] == ' ')
! 964: {
! 965: str[i] = '\0';
! 966: continue;
! 967: }
! 968: break;
! 969: }
! 970: }
! 971:
! 972: /**
! 973: * Mutex creation callback
! 974: */
! 975: static CK_RV CreateMutex(CK_VOID_PTR_PTR data)
! 976: {
! 977: *data = mutex_create(MUTEX_TYPE_RECURSIVE);
! 978: return CKR_OK;
! 979: }
! 980:
! 981: /**
! 982: * Mutex destruction callback
! 983: */
! 984: static CK_RV DestroyMutex(CK_VOID_PTR data)
! 985: {
! 986: mutex_t *mutex = (mutex_t*)data;
! 987:
! 988: mutex->destroy(mutex);
! 989: return CKR_OK;
! 990: }
! 991:
! 992: /**
! 993: * Mutex lock callback
! 994: */
! 995: static CK_RV LockMutex(CK_VOID_PTR data)
! 996: {
! 997: mutex_t *mutex = (mutex_t*)data;
! 998:
! 999: mutex->lock(mutex);
! 1000: return CKR_OK;
! 1001: }
! 1002:
! 1003: /**
! 1004: * Mutex unlock callback
! 1005: */
! 1006: static CK_RV UnlockMutex(CK_VOID_PTR data)
! 1007: {
! 1008: mutex_t *mutex = (mutex_t*)data;
! 1009:
! 1010: mutex->unlock(mutex);
! 1011: return CKR_OK;
! 1012: }
! 1013:
! 1014: /**
! 1015: * Check if the library has at least a given cryptoki version
! 1016: */
! 1017: static bool has_version(CK_INFO *info, int major, int minor)
! 1018: {
! 1019: return info->cryptokiVersion.major > major ||
! 1020: (info->cryptokiVersion.major == major &&
! 1021: info->cryptokiVersion.minor >= minor);
! 1022: }
! 1023:
! 1024: /**
! 1025: * Check for optional PKCS#11 library functionality
! 1026: */
! 1027: static void check_features(private_pkcs11_library_t *this, CK_INFO *info)
! 1028: {
! 1029: if (has_version(info, 2, 20))
! 1030: {
! 1031: this->features |= PKCS11_TRUSTED_CERTS;
! 1032: this->features |= PKCS11_ALWAYS_AUTH_KEYS;
! 1033: }
! 1034: }
! 1035:
! 1036: /**
! 1037: * Initialize a PKCS#11 library
! 1038: */
! 1039: static bool initialize(private_pkcs11_library_t *this, char *name, char *file,
! 1040: bool os_locking)
! 1041: {
! 1042: CK_C_GetFunctionList pC_GetFunctionList;
! 1043: CK_INFO info;
! 1044: CK_RV rv;
! 1045: static CK_C_INITIALIZE_ARGS args = {
! 1046: .CreateMutex = CreateMutex,
! 1047: .DestroyMutex = DestroyMutex,
! 1048: .LockMutex = LockMutex,
! 1049: .UnlockMutex = UnlockMutex,
! 1050: };
! 1051: static CK_C_INITIALIZE_ARGS args_os = {
! 1052: .flags = CKF_OS_LOCKING_OK,
! 1053: };
! 1054:
! 1055: pC_GetFunctionList = dlsym(this->handle, "C_GetFunctionList");
! 1056: if (!pC_GetFunctionList)
! 1057: {
! 1058: DBG1(DBG_CFG, "C_GetFunctionList not found for '%s': %s", name, dlerror());
! 1059: return FALSE;
! 1060: }
! 1061: rv = pC_GetFunctionList(&this->public.f);
! 1062: if (rv != CKR_OK)
! 1063: {
! 1064: DBG1(DBG_CFG, "C_GetFunctionList() error for '%s': %N",
! 1065: name, ck_rv_names, rv);
! 1066: return FALSE;
! 1067: }
! 1068: if (os_locking)
! 1069: {
! 1070: rv = CKR_CANT_LOCK;
! 1071: }
! 1072: else
! 1073: {
! 1074: rv = this->public.f->C_Initialize(&args);
! 1075: }
! 1076: if (rv == CKR_CANT_LOCK)
! 1077: { /* fallback to OS locking */
! 1078: os_locking = TRUE;
! 1079: rv = this->public.f->C_Initialize(&args_os);
! 1080: }
! 1081: if (rv != CKR_OK)
! 1082: {
! 1083: DBG1(DBG_CFG, "C_Initialize() error for '%s': %N",
! 1084: name, ck_rv_names, rv);
! 1085: return FALSE;
! 1086: }
! 1087: rv = this->public.f->C_GetInfo(&info);
! 1088: if (rv != CKR_OK)
! 1089: {
! 1090: DBG1(DBG_CFG, "C_GetInfo() error for '%s': %N",
! 1091: name, ck_rv_names, rv);
! 1092: this->public.f->C_Finalize(NULL);
! 1093: return FALSE;
! 1094: }
! 1095:
! 1096: pkcs11_library_trim(info.manufacturerID,
! 1097: strnlen(info.manufacturerID, sizeof(info.manufacturerID)));
! 1098: pkcs11_library_trim(info.libraryDescription,
! 1099: strnlen(info.libraryDescription, sizeof(info.libraryDescription)));
! 1100:
! 1101: DBG1(DBG_CFG, "loaded PKCS#11 v%d.%d library '%s' (%s)",
! 1102: info.cryptokiVersion.major, info.cryptokiVersion.minor, name, file);
! 1103: DBG1(DBG_CFG, " %s: %s v%d.%d",
! 1104: info.manufacturerID, info.libraryDescription,
! 1105: info.libraryVersion.major, info.libraryVersion.minor);
! 1106: if (os_locking)
! 1107: {
! 1108: DBG1(DBG_CFG, " uses OS locking functions");
! 1109: }
! 1110:
! 1111: check_features(this, &info);
! 1112: return TRUE;
! 1113: }
! 1114:
! 1115: /**
! 1116: * See header
! 1117: */
! 1118: pkcs11_library_t *pkcs11_library_create(char *name, char *file, bool os_locking)
! 1119: {
! 1120: private_pkcs11_library_t *this;
! 1121:
! 1122: INIT(this,
! 1123: .public = {
! 1124: .get_name = _get_name,
! 1125: .get_features = _get_features,
! 1126: .create_object_enumerator = _create_object_enumerator,
! 1127: .create_object_attr_enumerator = _create_object_attr_enumerator,
! 1128: .create_mechanism_enumerator = _create_mechanism_enumerator,
! 1129: .get_ck_attribute = _get_ck_attribute,
! 1130: .destroy = _destroy,
! 1131: },
! 1132: .name = strdup(name),
! 1133: .handle = dlopen(file, RTLD_LAZY),
! 1134: );
! 1135:
! 1136: if (!this->handle)
! 1137: {
! 1138: DBG1(DBG_CFG, "opening PKCS#11 library failed: %s", dlerror());
! 1139: free(this);
! 1140: return NULL;
! 1141: }
! 1142:
! 1143: if (!initialize(this, name, file, os_locking))
! 1144: {
! 1145: dlclose(this->handle);
! 1146: free(this);
! 1147: return NULL;
! 1148: }
! 1149:
! 1150: return &this->public;
! 1151: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>