in crypto/apr_crypto_openssl.c [777:952]
static apr_status_t crypto_key(apr_crypto_key_t **k,
const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p)
{
apr_crypto_key_t *key = *k;
apr_status_t rv;
if (!key) {
*k = key = apr_pcalloc(p, sizeof *key);
if (!key) {
return APR_ENOMEM;
}
apr_pool_cleanup_register(p, key, crypto_key_cleanup_helper,
apr_pool_cleanup_null);
}
else {
crypto_key_cleanup(key);
}
key->pool = p;
key->f = f;
key->provider = f->provider;
key->rec = rec;
switch (rec->ktype) {
case APR_CRYPTO_KTYPE_PASSPHRASE: {
/* decide on what cipher mechanism we will be using */
rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
if (APR_SUCCESS != rv) {
return rv;
}
/* generate the key */
if (PKCS5_PBKDF2_HMAC_SHA1(rec->k.passphrase.pass,
rec->k.passphrase.passLen,
(unsigned char *) rec->k.passphrase.salt,
rec->k.passphrase.saltLen, rec->k.passphrase.iterations,
key->keyLen, key->key) == 0) {
return APR_ENOKEY;
}
break;
}
case APR_CRYPTO_KTYPE_SECRET: {
/* decide on what cipher mechanism we will be using */
rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
if (APR_SUCCESS != rv) {
return rv;
}
/* sanity check - key correct size? */
if (rec->k.secret.secretLen != key->keyLen) {
return APR_EKEYLENGTH;
}
/* copy the key */
memcpy(key->key, rec->k.secret.secret, rec->k.secret.secretLen);
break;
}
case APR_CRYPTO_KTYPE_HASH: {
switch (rec->k.hash.digest) {
case APR_CRYPTO_DIGEST_MD5:
key->md = EVP_md5();
break;
case APR_CRYPTO_DIGEST_SHA1:
key->md = EVP_sha1();
break;
case APR_CRYPTO_DIGEST_SHA224:
key->md = EVP_sha224();
break;
case APR_CRYPTO_DIGEST_SHA256:
key->md = EVP_sha256();
break;
case APR_CRYPTO_DIGEST_SHA384:
key->md = EVP_sha384();
break;
case APR_CRYPTO_DIGEST_SHA512:
key->md = EVP_sha512();
break;
default:
return APR_ENODIGEST;
}
break;
}
case APR_CRYPTO_KTYPE_HMAC:
case APR_CRYPTO_KTYPE_CMAC: {
switch (rec->k.hmac.digest) {
case APR_CRYPTO_DIGEST_MD5:
key->md = EVP_md5();
break;
case APR_CRYPTO_DIGEST_SHA1:
key->md = EVP_sha1();
break;
case APR_CRYPTO_DIGEST_SHA224:
key->md = EVP_sha224();
break;
case APR_CRYPTO_DIGEST_SHA256:
key->md = EVP_sha256();
break;
case APR_CRYPTO_DIGEST_SHA384:
key->md = EVP_sha384();
break;
case APR_CRYPTO_DIGEST_SHA512:
key->md = EVP_sha512();
break;
default:
return APR_ENODIGEST;
}
/* create hmac key */
#if APR_USE_OPENSSL_PRE_3_0_API
if (rec->ktype == APR_CRYPTO_KTYPE_HMAC) {
apr_crypto_config_t *config = f->config;
key->pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
config->engine,
rec->k.hmac.secret,
rec->k.hmac.secretLen);
}
else {
#if !APR_USE_OPENSSL_PRE_1_1_1_API
apr_crypto_config_t *config = f->config;
/* decide on what cipher mechanism we will be using */
rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
if (APR_SUCCESS != rv) {
return rv;
}
key->pkey = EVP_PKEY_new_CMAC_key(config->engine,
rec->k.cmac.secret,
rec->k.cmac.secretLen,
key->cipher);
#else
return APR_ENOTIMPL;
#endif
}
if (!key->pkey) {
return APR_ENOKEY;
}
#else
if (rec->ktype == APR_CRYPTO_KTYPE_HMAC) {
key->mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
}
else {
key->mac = EVP_MAC_fetch(NULL, "CMAC", NULL);
}
if (!key->mac) {
return APR_ENOMEM;
}
#endif
break;
}
default: {
return APR_ENOKEY;
}
}
key->doPad = rec->pad;
/* note: openssl incorrectly returns non zero IV size values for ECB
* algorithms, so work around this by ignoring the IV size.
*/
if (APR_MODE_ECB != rec->mode && key->cipher) {
key->ivSize = EVP_CIPHER_iv_length(key->cipher);
}
return APR_SUCCESS;
}