const ECDSA_METHOD *ECDSA_get_default_method(void) { if (!default_ECDSA_method) { #ifdef OPENSSL_FIPS if (FIPS_mode()) return FIPS_ecdsa_openssl(); else return ECDSA_OpenSSL(); #else default_ECDSA_method = ECDSA_OpenSSL(); #endif } return default_ECDSA_method; }
const ECDSA_METHOD * ECDSA_get_default_method(void) { if (!default_ECDSA_method) { default_ECDSA_method = ECDSA_OpenSSL(); } return default_ECDSA_method; }
/** * ECDSA signing method (replaces ossl_ecdsa_sign_sig) * * @param dgst hash value to sign * @param dlen length of the hash value * @param kinv precomputed inverse k (from the sign_setup method) * @param rp precomputed rp (from the sign_setup method) * @param ec private EC signing key * @return pointer to a ECDSA_SIG structure or NULL if an error occurred */ static ECDSA_SIG *pkcs11_ecdsa_sign_sig(const unsigned char *dgst, int dlen, const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *ec) { unsigned char sigret[512]; /* HACK for now */ ECDSA_SIG *sig; PKCS11_KEY *key; unsigned int siglen; BIGNUM *r, *s, *order; (void)kinv; /* Precomputed values are not used for PKCS#11 */ (void)rp; /* Precomputed values are not used for PKCS#11 */ key = pkcs11_get_ex_data_ec(ec); if (check_key_fork(key) < 0) { sign_sig_fn orig_sign_sig; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) const EC_KEY_METHOD *meth = EC_KEY_OpenSSL(); EC_KEY_METHOD_get_sign((EC_KEY_METHOD *)meth, NULL, NULL, &orig_sign_sig); #else const ECDSA_METHOD *meth = ECDSA_OpenSSL(); orig_sign_sig = meth->ecdsa_do_sign; #endif return orig_sign_sig(dgst, dlen, kinv, rp, ec); } /* Truncate digest if its byte size is longer than needed */ order = BN_new(); if (order) { const EC_GROUP *group = EC_KEY_get0_group(ec); if (group && EC_GROUP_get_order(group, order, NULL)) { int klen = BN_num_bits(order); if (klen < 8*dlen) dlen = (klen+7)/8; } BN_free(order); } siglen = sizeof sigret; if (pkcs11_ecdsa_sign(dgst, dlen, sigret, &siglen, key) <= 0) return NULL; r = BN_bin2bn(sigret, siglen/2, NULL); s = BN_bin2bn(sigret + siglen/2, siglen/2, NULL); sig = ECDSA_SIG_new(); if (sig == NULL) return NULL; #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) ECDSA_SIG_set0(sig, r, s); #else BN_free(sig->r); sig->r = r; BN_free(sig->s); sig->s = s; #endif return sig; }
// Signing functions bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); if (lowerMechanism.compare("ecdsa")) { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); return false; } // Check if the private key is the right type if (!privateKey->isOfType(OSSLECPrivateKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey; EC_KEY* eckey = pk->getOSSLKey(); if (eckey == NULL) { ERROR_MSG("Could not get the OpenSSL private key"); return false; } // Use the OpenSSL implementation and not any engine ECDSA_set_method(eckey, ECDSA_OpenSSL()); // Perform the signature operation size_t len = pk->getOrderLength(); if (len == 0) { ERROR_MSG("Could not get the order length"); return false; } signature.resize(2 * len); memset(&signature[0], 0, 2 * len); ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey); if (sig == NULL) { ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error()); return false; } // Store the 2 values with padding BN_bn2bin(sig->r, &signature[len - BN_num_bytes(sig->r)]); BN_bn2bin(sig->s, &signature[2 * len - BN_num_bytes(sig->s)]); ECDSA_SIG_free(sig); return true; }
ECDSA_METHOD *PKCS11_get_ecdsa_method(void) { if (ops == NULL) { alloc_ecdsa_ex_index(); ops = ECDSA_METHOD_new((ECDSA_METHOD *)ECDSA_OpenSSL()); ECDSA_METHOD_set_sign(ops, pkcs11_ecdsa_do_sign); ECDSA_METHOD_set_sign_setup(ops, pkcs11_ecdsa_sign_setup); } return ops; }
/* This internal function is used by ENGINE_openssl() and possibly by the * "dynamic" ENGINE support too */ static int bind_helper(ENGINE *e) { if(!ENGINE_set_id(e, engine_openssl_id) || !ENGINE_set_name(e, engine_openssl_name) #ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS #ifndef OPENSSL_NO_RSA || !ENGINE_set_RSA(e, RSA_get_default_method()) #endif #ifndef OPENSSL_NO_DSA || !ENGINE_set_DSA(e, DSA_get_default_method()) #endif #ifndef OPENSSL_NO_ECDH || !ENGINE_set_ECDH(e, ECDH_OpenSSL()) #endif #ifndef OPENSSL_NO_ECDSA || !ENGINE_set_ECDSA(e, ECDSA_OpenSSL()) #endif #ifndef OPENSSL_NO_DH || !ENGINE_set_DH(e, DH_get_default_method()) #endif || !ENGINE_set_RAND(e, RAND_SSLeay()) #ifdef TEST_ENG_OPENSSL_RC4 || !ENGINE_set_ciphers(e, openssl_ciphers) #endif #ifdef TEST_ENG_OPENSSL_SHA || !ENGINE_set_digests(e, openssl_digests) #endif #endif //MS: #ifndef OPENSSL_NO_STDIO #ifdef TEST_ENG_OPENSSL_PKEY || !ENGINE_set_load_privkey_function(e, openssl_load_privkey) #endif #endif ) return 0; /* If we add errors to this ENGINE, ensure the error handling is setup here */ /* openssl_load_error_strings(); */ return 1; }
// Verification functions bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const std::string mechanism) { std::string lowerMechanism; lowerMechanism.resize(mechanism.size()); std::transform(mechanism.begin(), mechanism.end(), lowerMechanism.begin(), tolower); if (lowerMechanism.compare("ecdsa")) { ERROR_MSG("Invalid mechanism supplied (%s)", mechanism.c_str()); return false; } // Check if the private key is the right type if (!publicKey->isOfType(OSSLECPublicKey::type)) { ERROR_MSG("Invalid key type supplied"); return false; } OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey; EC_KEY* eckey = pk->getOSSLKey(); if (eckey == NULL) { ERROR_MSG("Could not get the OpenSSL public key"); return false; } // Use the OpenSSL implementation and not any engine ECDSA_set_method(eckey, ECDSA_OpenSSL()); // Perform the verify operation size_t len = pk->getOrderLength(); if (len == 0) { ERROR_MSG("Could not get the order length"); return false; } if (signature.size() != 2 * len) { ERROR_MSG("Invalid buffer length"); return false; } ECDSA_SIG* sig = ECDSA_SIG_new(); if (sig == NULL) { ERROR_MSG("Could not create an ECDSA_SIG object"); return false; } if (sig->r != NULL) BN_clear_free(sig->r); const unsigned char *s = signature.const_byte_str(); sig->r = BN_bin2bn(s, len, NULL); if (sig->s != NULL) BN_clear_free(sig->s); sig->s = BN_bin2bn(s + len, len, NULL); if (sig->r == NULL || sig->s == NULL) { ERROR_MSG("Could not add data to the ECDSA_SIG object"); ECDSA_SIG_free(sig); return false; } int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey); if (ret != 1) { if (ret < 0) ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error()); ECDSA_SIG_free(sig); return false; } ECDSA_SIG_free(sig); return true; }