in crypto/apr_crypto_openssl.c [1581:1710]
static apr_status_t crypto_digest_final(apr_crypto_digest_t *digest)
{
apr_status_t status = APR_SUCCESS;
switch (digest->key->rec->ktype) {
case APR_CRYPTO_KTYPE_HASH: {
switch (digest->rec->dtype) {
case APR_CRYPTO_DTYPE_HASH: {
unsigned int len = EVP_MD_CTX_size(digest->mdCtx);
/* must we allocate the output buffer from a pool? */
if (!digest->rec->d.hash.s || digest->rec->d.hash.slen != len) {
digest->rec->d.hash.slen = len;
digest->rec->d.hash.s = apr_pcalloc(digest->pool, len);
if (!digest->rec->d.hash.s) {
return APR_ENOMEM;
}
}
/* then, determine the signature */
if (EVP_DigestFinal_ex(digest->mdCtx, digest->rec->d.hash.s, &len)
== 0) {
OPENSSL_cleanse(digest->rec->d.hash.s,
digest->rec->d.hash.slen);
status = APR_ECRYPT;
}
break;
}
default:
status = APR_ENODIGEST;
}
break;
}
case APR_CRYPTO_KTYPE_HMAC:
case APR_CRYPTO_KTYPE_CMAC: {
size_t len;
/* first, determine the signature length */
#if APR_USE_OPENSSL_PRE_3_0_API
if (!EVP_DigestSignFinal(digest->mdCtx, NULL, &len)) {
status = APR_ECRYPT;
}
#else
if (!EVP_MAC_final(digest->macCtx, NULL, &len, 0)) {
status = APR_ECRYPT;
}
#endif
if (status == APR_SUCCESS) {
switch (digest->rec->dtype) {
case APR_CRYPTO_DTYPE_SIGN: {
/* must we allocate the output buffer from a pool? */
if (!digest->rec->d.sign.s || digest->rec->d.sign.slen != len) {
digest->rec->d.sign.slen = len;
digest->rec->d.sign.s = apr_pcalloc(digest->pool, len);
if (!digest->rec->d.sign.s) {
return APR_ENOMEM;
}
}
/* then, determine the signature */
#if APR_USE_OPENSSL_PRE_3_0_API
if (!EVP_DigestSignFinal(digest->mdCtx,
digest->rec->d.sign.s, &len)) {
status = APR_ECRYPT;
}
#else
if (!EVP_MAC_final(digest->macCtx,
digest->rec->d.sign.s, &len, len)) {
status = APR_ECRYPT;
}
#endif
if (status != APR_SUCCESS) {
OPENSSL_cleanse(digest->rec->d.sign.s,
digest->rec->d.sign.slen);
}
break;
}
case APR_CRYPTO_DTYPE_VERIFY: {
/* must we allocate the output buffer from a pool? */
if (!digest->rec->d.verify.s
|| digest->rec->d.verify.slen != len) {
digest->rec->d.verify.slen = len;
digest->rec->d.verify.s = apr_pcalloc(digest->pool, len);
if (!digest->rec->d.verify.s) {
return APR_ENOMEM;
}
}
/* then, determine the signature */
#if APR_USE_OPENSSL_PRE_3_0_API
if (!EVP_DigestSignFinal(digest->mdCtx,
digest->rec->d.verify.s, &len)) {
status = APR_ECRYPT;
}
#else
if (!EVP_MAC_final(digest->macCtx,
digest->rec->d.verify.s, &len, len)) {
status = APR_ECRYPT;
}
#endif
if (status == APR_SUCCESS
&& (len != digest->rec->d.verify.vlen
|| CRYPTO_memcmp(digest->rec->d.verify.v,
digest->rec->d.verify.s, len))) {
status = APR_ENOVERIFY;
}
if (status != APR_SUCCESS) {
OPENSSL_cleanse(digest->rec->d.verify.s,
digest->rec->d.verify.slen);
}
break;
}
default:
status = APR_ENODIGEST;
}
}
break;
}
default:
status = APR_EINVAL;
}
return status;
}