/* This internal function is used by ENGINE_pkcs11() and possibly by the * "dynamic" ENGINE support too */ static int bind_helper(ENGINE *e) { if (!ENGINE_set_id(e, PKCS11_ENGINE_ID) || !ENGINE_set_destroy_function(e, engine_destroy) || !ENGINE_set_init_function(e, engine_init) || !ENGINE_set_finish_function(e, engine_finish) || !ENGINE_set_ctrl_function(e, engine_ctrl) || !ENGINE_set_cmd_defns(e, engine_cmd_defns) || !ENGINE_set_name(e, PKCS11_ENGINE_NAME) || #ifndef OPENSSL_NO_RSA !ENGINE_set_RSA(e, PKCS11_get_rsa_method()) || #endif #if OPENSSL_VERSION_NUMBER >= 0x10100002L #ifndef OPENSSL_NO_EC /* PKCS11_get_ec_key_method combines ECDSA and ECDH */ !ENGINE_set_EC(e, PKCS11_get_ec_key_method()) || #endif /* OPENSSL_NO_EC */ #else /* OPENSSL_VERSION_NUMBER */ #ifndef OPENSSL_NO_ECDSA !ENGINE_set_ECDSA(e, PKCS11_get_ecdsa_method()) || #endif #ifndef OPENSSL_NO_ECDH !ENGINE_set_ECDH(e, PKCS11_get_ecdh_method()) || #endif #endif /* OPENSSL_VERSION_NUMBER */ !ENGINE_set_load_pubkey_function(e, load_pubkey) || !ENGINE_set_load_privkey_function(e, load_privkey)) { return 0; } else { return 1; } }
/* * Get EC key material and stash pointer in ex_data * Note we get called twice, once for private key, and once for public * We need to get the EC_PARAMS and EC_POINT into both, * as lib11 dates from RSA only where all the pub key components * were also part of the private key. With EC the point * is not in the private key, and the params may or may not be. * */ static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY *key) { EVP_PKEY *pk; EC_KEY *ec; ec = pkcs11_get_ec(key); if (ec == NULL) return NULL; pk = EVP_PKEY_new(); if (pk == NULL) { EC_KEY_free(ec); return NULL; } EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */ if (key->isPrivate) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L EC_KEY_set_method(ec, PKCS11_get_ec_key_method()); #else ECDSA_set_method(ec, PKCS11_get_ecdsa_method()); ECDH_set_method(ec, PKCS11_get_ecdh_method()); #endif } /* TODO: Retrieve the ECDSA private key object attributes instead, * unless the key has the "sensitive" attribute set */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L EC_KEY_set_ex_data(ec, ec_ex_index, key); #else ECDSA_set_ex_data(ec, ec_ex_index, key); #endif EC_KEY_free(ec); /* Drops our reference to it */ return pk; }
static ENGINE* LoadEngine() { // This function creates an engine for PKCS#11 and inspired by // the "ENGINE_load_dynamic" function from OpenSSL, in file // "crypto/engine/eng_dyn.c" ENGINE* engine = ENGINE_new(); if (!engine) { LOG(ERROR) << "Cannot create an OpenSSL engine for PKCS#11"; throw OrthancException(ErrorCode_InternalError); } // Create a PKCS#11 context using libp11 context_ = pkcs11_new(); if (!context_) { LOG(ERROR) << "Cannot create a libp11 context for PKCS#11"; ENGINE_free(engine); throw OrthancException(ErrorCode_InternalError); } if (!ENGINE_set_id(engine, PKCS11_ENGINE_ID) || !ENGINE_set_name(engine, PKCS11_ENGINE_NAME) || !ENGINE_set_cmd_defns(engine, PKCS11_ENGINE_COMMANDS) || // Register the callback functions !ENGINE_set_init_function(engine, EngineInitialize) || !ENGINE_set_finish_function(engine, EngineFinalize) || !ENGINE_set_destroy_function(engine, EngineDestroy) || !ENGINE_set_ctrl_function(engine, EngineControl) || !ENGINE_set_load_pubkey_function(engine, EngineLoadPublicKey) || !ENGINE_set_load_privkey_function(engine, EngineLoadPrivateKey) || !ENGINE_set_RSA(engine, PKCS11_get_rsa_method()) || !ENGINE_set_ECDSA(engine, PKCS11_get_ecdsa_method()) || !ENGINE_set_ECDH(engine, PKCS11_get_ecdh_method()) || #if OPENSSL_VERSION_NUMBER >= 0x10100002L !ENGINE_set_EC(engine, PKCS11_get_ec_key_method()) || #endif // Make OpenSSL know about our PKCS#11 engine !ENGINE_add(engine)) { LOG(ERROR) << "Cannot initialize the OpenSSL engine for PKCS#11"; pkcs11_finish(context_); ENGINE_free(engine); throw OrthancException(ErrorCode_InternalError); } // If the "ENGINE_add" worked, it gets a structural // reference. We release our just-created reference. ENGINE_free(engine); return ENGINE_by_id(PKCS11_ENGINE_ID); }
/* * Get EC key material and stash pointer in ex_data * Note we get called twice, once for private key, and once for public * We need to get the EC_PARAMS and EC_POINT into both, * as lib11 dates from RSA only where all the pub key components * were also part of the private key. With EC the point * is not in the private key, and the params may or may not be. * */ static EVP_PKEY *pkcs11_get_evp_key_ec(PKCS11_KEY * key) { EVP_PKEY *pk; EC_KEY * ec = NULL; CK_RV ckrv; size_t ec_paramslen = 0; CK_BYTE * ec_params = NULL; size_t ec_pointlen = 0; CK_BYTE * ec_point = NULL; PKCS11_KEY * pubkey; ASN1_OCTET_STRING *os=NULL; pk = EVP_PKEY_new(); if (pk == NULL) return NULL; ec = EC_KEY_new(); if (ec == NULL) { EVP_PKEY_free(pk); return NULL; } EVP_PKEY_set1_EC_KEY(pk, ec); /* Also increments the ec ref count */ /* For Openssl req we need at least the * EC_KEY_get0_group(ec_key)) to return the group. * Even if it fails will continue as a sign only does not need * need this if the pkcs11 or card can figure this out. */ if (key_getattr_var(key, CKA_EC_PARAMS, NULL, &ec_paramslen) == CKR_OK && ec_paramslen > 0) { ec_params = OPENSSL_malloc(ec_paramslen); if (ec_params) { ckrv = key_getattr_var(key, CKA_EC_PARAMS, ec_params, &ec_paramslen); if (ckrv == CKR_OK) { const unsigned char * a = ec_params; /* convert to OpenSSL parmas */ d2i_ECParameters(&ec, &a, (long) ec_paramslen); } } } /* Now get the ec_point */ pubkey = key->isPrivate ? PKCS11_find_key_from_key(key) : key; if (pubkey) { ckrv = key_getattr_var(pubkey, CKA_EC_POINT, NULL, &ec_pointlen); if (ckrv == CKR_OK && ec_pointlen > 0) { ec_point = OPENSSL_malloc(ec_pointlen); if (ec_point) { ckrv = key_getattr_var(pubkey, CKA_EC_POINT, ec_point, &ec_pointlen); if (ckrv == CKR_OK) { /* PKCS#11 returns ASN1 octstring*/ const unsigned char * a; /* we have asn1 octet string, need to strip off 04 len */ a = ec_point; os = d2i_ASN1_OCTET_STRING(NULL, &a, (long) ec_pointlen); if (os) { a = os->data; o2i_ECPublicKey(&ec, &a, os->length); } /* EC_KEY_print_fp(stderr, ec, 5); */ } } } } /* If the key is not extractable, create a key object * that will use the card's functions to sign & decrypt */ if (os) ASN1_STRING_free(os); if (ec_point) OPENSSL_free(ec_point); if (ec_params) OPENSSL_free(ec_params); if (key->isPrivate) { #if OPENSSL_VERSION_NUMBER >= 0x10100000L EC_KEY_set_method(ec, PKCS11_get_ec_key_method()); #else ECDSA_set_method(ec, PKCS11_get_ecdsa_method()); /* TODO: Retrieve the ECDSA private key object attributes instead, * unless the key has the "sensitive" attribute set */ #endif } /* TODO: Extract the ECDSA private key instead, if the key * is marked as extractable (and not private?) */ #if OPENSSL_VERSION_NUMBER >= 0x10100002L EC_KEY_set_ex_data(ec,ec_key_ex_index, key); #else ECDSA_set_ex_data(ec, ecdsa_ex_index, key); #endif EC_KEY_free(ec); /* drops our reference to it */ return pk; }