in source/caching_cmm.c [583:647]
static int decrypt_materials(
struct aws_cryptosdk_cmm *generic_cmm,
struct aws_cryptosdk_dec_materials **output,
struct aws_cryptosdk_dec_request *request) {
struct caching_cmm *cmm = AWS_CONTAINER_OF(generic_cmm, struct caching_cmm, base);
bool is_encrypt;
struct aws_cryptosdk_materials_cache_entry *entry = NULL;
if (!can_cache_algorithm(request->alg)) {
/* The algorithm used for the ciphertext is not cachable, so bypass the cache entirely */
return aws_cryptosdk_cmm_decrypt_materials(cmm->upstream, output, request);
}
uint8_t hash_arr[AWS_CRYPTOSDK_MD_MAX_SIZE];
struct aws_byte_buf hash_buf = aws_byte_buf_from_array(hash_arr, sizeof(hash_arr));
if (hash_dec_request(cmm->partition_id, &hash_buf, request)) {
return AWS_OP_ERR;
}
if (aws_cryptosdk_materials_cache_find_entry(cmm->materials_cache, &entry, &is_encrypt, &hash_buf) || !entry ||
is_encrypt) {
/*
* If we got an encrypt entry, we'll invalidate it, since we're about to replace it anyway.
* (This is unlikely to happen anyway, unless our hash function is broken)
*/
goto cache_miss;
}
if (!check_ttl(cmm, entry)) {
goto cache_miss;
}
if (aws_cryptosdk_materials_cache_get_dec_materials(cmm->materials_cache, request->alloc, output, entry)) {
goto cache_miss;
}
aws_cryptosdk_materials_cache_entry_release(cmm->materials_cache, entry, false);
return AWS_OP_SUCCESS;
cache_miss:
if (entry) {
/*
* If we found the entry but then did a cache miss, it must have been unusable for some reason,
* and we should invalidate.
*/
aws_cryptosdk_materials_cache_entry_release(cmm->materials_cache, entry, true);
}
if (aws_cryptosdk_cmm_decrypt_materials(cmm->upstream, output, request)) {
return AWS_OP_ERR;
}
aws_cryptosdk_materials_cache_put_entry_for_decrypt(cmm->materials_cache, &entry, *output, &hash_buf);
set_ttl_on_miss(cmm, entry);
if (entry) {
aws_cryptosdk_materials_cache_entry_release(cmm->materials_cache, entry, false);
}
return AWS_OP_SUCCESS;
}