Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs11/pkcs11_library.c, revision 1.1.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>