static int raw_aes_keyring_on_decrypt()

in source/raw_aes_keyring.c [185:258]


static int raw_aes_keyring_on_decrypt(
    struct aws_cryptosdk_keyring *kr,
    struct aws_allocator *request_alloc,
    struct aws_byte_buf *unencrypted_data_key,
    struct aws_array_list *keyring_trace,
    const struct aws_array_list *edks,
    const struct aws_hash_table *enc_ctx,
    enum aws_cryptosdk_alg_id alg) {
    struct raw_aes_keyring *self = (struct raw_aes_keyring *)kr;

    struct aws_byte_buf aad;
    if (serialize_aad_init(request_alloc, &aad, enc_ctx)) {
        return AWS_OP_ERR;
    }

    size_t num_edks = aws_array_list_length(edks);

    const struct aws_cryptosdk_alg_properties *props = aws_cryptosdk_alg_props(alg);
    size_t data_key_len                              = props->data_key_len;

    if (aws_byte_buf_init(unencrypted_data_key, request_alloc, props->data_key_len)) {
        aws_byte_buf_clean_up(&aad);
        return AWS_OP_ERR;
    }

    for (size_t edk_idx = 0; edk_idx < num_edks; ++edk_idx) {
        const struct aws_cryptosdk_edk *edk;
        if (aws_array_list_get_at_ptr(edks, (void **)&edk, edk_idx)) {
            aws_byte_buf_clean_up(&aad);
            return AWS_OP_ERR;
        }
        if (!edk->provider_id.len || !edk->provider_info.len || !edk->ciphertext.len) continue;

        if (!aws_string_eq_byte_buf(self->key_namespace, &edk->provider_id)) continue;

        struct aws_byte_buf iv;
        if (!aws_cryptosdk_parse_provider_info(kr, &iv, &edk->provider_info)) continue;

        const struct aws_byte_buf *edk_bytes = &edk->ciphertext;

        /* Using GCM, so encrypted and unencrypted data key have same length, i.e. data_key_len.
         * edk_bytes->buffer holds encrypted data key followed by GCM tag.
         */
        if (data_key_len + RAW_AES_KR_TAG_LEN != edk_bytes->len) continue;

        if (aws_cryptosdk_aes_gcm_decrypt(
                unencrypted_data_key,
                aws_byte_cursor_from_array(edk_bytes->buffer, data_key_len),
                aws_byte_cursor_from_array(edk_bytes->buffer + data_key_len, RAW_AES_KR_TAG_LEN),
                aws_byte_cursor_from_buf(&iv),
                aws_byte_cursor_from_buf(&aad),
                self->raw_key)) {
            /* We are here either because of a ciphertext/tag mismatch (e.g., wrong encryption
             * context) or because of an OpenSSL error. In either case, nothing better to do
             * than just moving on to next EDK, so clear the error code.
             */
            aws_reset_error();
        } else {
            aws_cryptosdk_keyring_trace_add_record(
                request_alloc,
                keyring_trace,
                self->key_namespace,
                self->key_name,
                AWS_CRYPTOSDK_WRAPPING_KEY_DECRYPTED_DATA_KEY | AWS_CRYPTOSDK_WRAPPING_KEY_VERIFIED_ENC_CTX);
            goto success;
        }
    }
    // None of the EDKs worked, clean up unencrypted data key buffer and return success per materials.h
    aws_byte_buf_clean_up(unencrypted_data_key);

success:
    aws_byte_buf_clean_up(&aad);
    return AWS_OP_SUCCESS;
}