int aws_cryptosdk_priv_unwrap_keys()

in source/session_decrypt.c [125:186]


int aws_cryptosdk_priv_unwrap_keys(struct aws_cryptosdk_session *AWS_RESTRICT session) {
    struct aws_cryptosdk_dec_request request;
    struct aws_cryptosdk_dec_materials *materials = NULL;

    session->alg_props = aws_cryptosdk_alg_props(session->header.alg_id);

    if (!session->alg_props) {
        // Unknown algorithm
        return aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_CIPHERTEXT);
    }

    if (fill_request(&request, session)) return AWS_OP_ERR;
    int rv = AWS_OP_ERR;

    if (aws_cryptosdk_cmm_decrypt_materials(session->cmm, &materials, &request)) goto out;

    aws_cryptosdk_transfer_list(&session->keyring_trace, &materials->keyring_trace);
    session->cmm_success = true;

    const struct aws_cryptosdk_alg_properties *materials_alg_props = aws_cryptosdk_alg_props(materials->alg);
    if (!materials_alg_props) {
        aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_STATE);
        goto out;
    }
    // In AWS_CRYPTOSDK_DECRYPT_UNSIGNED mode, the operation must fail if the CMM
    // returns decryption materials with a signing algorithm suite
    if (session->mode == AWS_CRYPTOSDK_DECRYPT_UNSIGNED && materials_alg_props->signature_len) {
        aws_raise_error(AWS_CRYPTOSDK_ERR_DECRYPT_SIGNED_MESSAGE_NOT_ALLOWED);
        goto out;
    }

    if (derive_data_key(session, materials)) goto out;
    if (validate_header(session)) goto out;

    if (session->alg_props->signature_len) {
        if (!materials->signctx) {
            aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_CIPHERTEXT);
            goto out;
        }

        // Move ownership of the signature context out of the materials
        session->signctx   = materials->signctx;
        materials->signctx = NULL;

        // Backfill the context with the header
        if (aws_cryptosdk_sig_update(
                session->signctx, aws_byte_cursor_from_array(session->header_copy, session->header_size))) {
            goto out;
        }
    }

    session->frame_seqno = 1;
    session->frame_size  = session->header.frame_len;
    aws_cryptosdk_priv_session_change_state(session, ST_DECRYPT_BODY);

    rv = AWS_OP_SUCCESS;
out:
    if (materials) aws_cryptosdk_dec_materials_destroy(materials);
    aws_array_list_clean_up(&request.encrypted_data_keys);

    return rv;
}