int hash_enc_request()

in source/caching_cmm.c [251:323]


int hash_enc_request(
    struct aws_string *partition_id, struct aws_byte_buf *out, const struct aws_cryptosdk_enc_request *req) {
    /*
     * Here, we hash the relevant aspects of the request structure to use as a cache identifier.
     * The hash is intended to match Java and Python, but since we've not yet committed to maintaining
     * that parity indefinitely, we don't include this structure as part of the header API docs.
     * The structure, internally, is:
     *   [partition ID hash]
     *   [0x01 if the request alg id is set, otherwise 0x00]
     *   [request alg id, if set]
     *   [serialized encryption context]
     */
    struct aws_byte_buf context_buf              = { 0 };
    uint8_t digestbuf[AWS_CRYPTOSDK_MD_MAX_SIZE] = { 0 };

    if (out->capacity < AWS_CRYPTOSDK_MD_MAX_SIZE) {
        return aws_raise_error(AWS_ERROR_INVALID_BUFFER_SIZE);
    }

    struct aws_cryptosdk_md_context *md_context, *enc_ctx_md;
    if (aws_cryptosdk_md_init(req->alloc, &md_context, AWS_CRYPTOSDK_MD_SHA512)) {
        return AWS_OP_ERR;
    }

    if (aws_cryptosdk_md_init(req->alloc, &enc_ctx_md, AWS_CRYPTOSDK_MD_SHA512)) {
        return AWS_OP_ERR;
    }

    if (aws_cryptosdk_md_update(md_context, aws_string_bytes(partition_id), partition_id->len)) {
        goto md_err;
    }

    uint8_t requested_alg_present = req->requested_alg != 0;
    if (aws_cryptosdk_md_update(md_context, &requested_alg_present, 1)) {
        goto md_err;
    }

    if (requested_alg_present) {
        uint16_t alg_id = aws_hton16(req->requested_alg);
        if (aws_cryptosdk_md_update(md_context, &alg_id, sizeof(alg_id))) {
            goto md_err;
        }
    }

    size_t context_size;
    if (aws_cryptosdk_enc_ctx_size(&context_size, req->enc_ctx) ||
        aws_byte_buf_init(&context_buf, req->alloc, context_size) ||
        aws_cryptosdk_enc_ctx_serialize(req->alloc, &context_buf, req->enc_ctx) ||
        aws_cryptosdk_md_update(enc_ctx_md, context_buf.buffer, context_buf.len)) {
        goto md_err;
    }

    size_t enc_ctx_digest_len;
    if (aws_cryptosdk_md_finish(enc_ctx_md, digestbuf, &enc_ctx_digest_len)) {
        enc_ctx_md = NULL;
        goto md_err;
    }
    enc_ctx_md = NULL;

    if (aws_cryptosdk_md_update(md_context, digestbuf, enc_ctx_digest_len)) {
        goto md_err;
    }

    aws_byte_buf_clean_up(&context_buf);
    return aws_cryptosdk_md_finish(md_context, out->buffer, &out->len);

md_err:
    aws_byte_buf_clean_up(&context_buf);
    aws_cryptosdk_md_abort(md_context);
    aws_cryptosdk_md_abort(enc_ctx_md);

    return AWS_OP_ERR;
}