static int decrypt_materials()

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;
}