in crypto/apr_crypto_commoncrypto.c [1305:1427]
static apr_status_t crypto_digest_final(apr_crypto_digest_t *digest)
{
switch (digest->key->rec->ktype) {
case APR_CRYPTO_KTYPE_HASH: {
size_t len = digest->key->digestSize;
/* 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_palloc(digest->pool, len);
if (!digest->rec->d.hash.s) {
return APR_ENOMEM;
}
apr_crypto_clear(digest->pool, digest->rec->d.hash.s, len);
}
switch (digest->key->rec->k.hash.digest) {
case APR_CRYPTO_DIGEST_MD5:
CC_MD5_Final(digest->rec->d.hash.s, digest->hash);
break;
case APR_CRYPTO_DIGEST_SHA1:
CC_SHA1_Final(digest->rec->d.hash.s, digest->hash);
break;
case APR_CRYPTO_DIGEST_SHA224:
CC_SHA224_Final(digest->rec->d.hash.s, digest->hash);
break;
case APR_CRYPTO_DIGEST_SHA256:
CC_SHA256_Final(digest->rec->d.hash.s, digest->hash);
break;
case APR_CRYPTO_DIGEST_SHA384:
CC_SHA384_Final(digest->rec->d.hash.s, digest->hash);
break;
case APR_CRYPTO_DIGEST_SHA512:
CC_SHA512_Final(digest->rec->d.hash.s, digest->hash);
break;
default:
return APR_ENODIGEST;
}
break;
}
case APR_CRYPTO_KTYPE_HMAC: {
apr_status_t status = APR_SUCCESS;
size_t len = digest->key->digestSize;
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_palloc(digest->pool, len);
if (!digest->rec->d.sign.s) {
return APR_ENOMEM;
}
apr_crypto_clear(digest->pool, digest->rec->d.sign.s, len);
}
/* then, determine the signature */
CCHmacFinal(digest->hmac, digest->rec->d.sign.s);
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_palloc(digest->pool, len);
if (!digest->rec->d.verify.s) {
return APR_ENOMEM;
}
apr_crypto_clear(digest->pool, digest->rec->d.verify.s,
len);
}
/* then, determine the signature */
CCHmacFinal(digest->hmac, digest->rec->d.verify.s);
if (digest->rec->d.verify.slen
== digest->rec->d.verify.vlen) {
status =
apr_crypto_equals(digest->rec->d.verify.s,
digest->rec->d.verify.v,
digest->rec->d.verify.slen) ?
APR_SUCCESS : APR_ENOVERIFY;
} else {
status = APR_ENOVERIFY;
}
break;
}
default: {
status = APR_ENODIGEST;
break;
}
}
return status;
}
case APR_CRYPTO_KTYPE_CMAC: {
return APR_ENOTIMPL;
}
default: {
return APR_EINVAL;
}
}
return APR_SUCCESS;
}