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>