#include "amduat/pel/derivation_sid.h" #include "amduat/enc/asl1_core_codec.h" #include "amduat/hash/asl1.h" #include #include #include #include #include static bool amduat_derivation_sid_check_ref(amduat_reference_t ref) { const amduat_hash_asl1_desc_t *desc; size_t digest_len; if (ref.digest.len != 0 && ref.digest.data == NULL) { return false; } if (amduat_hash_asl1_is_reserved(ref.hash_id)) { return false; } desc = amduat_hash_asl1_desc_lookup(ref.hash_id); digest_len = ref.digest.len; if (desc != NULL && desc->digest_len != 0) { assert(desc->digest_len == digest_len); if (desc->digest_len != digest_len) { return false; } } return true; } bool amduat_pel_derivation_sid_compute( const amduat_pel_derivation_sid_input_t *in, amduat_octets_t *out_sid) { amduat_hash_asl1_stream_t stream; uint8_t marker; size_t i; if (out_sid == NULL) { return false; } out_sid->data = NULL; out_sid->len = 0; if (in == NULL) { return false; } if (in->input_refs_len != 0 && in->input_refs == NULL) { return false; } if (in->has_params_ref && !amduat_derivation_sid_check_ref(in->params_ref)) { return false; } if (!amduat_derivation_sid_check_ref(in->program_ref)) { return false; } for (i = 0; i < in->input_refs_len; ++i) { if (!amduat_derivation_sid_check_ref(in->input_refs[i])) { return false; } } if (!amduat_hash_asl1_stream_init(AMDUAT_HASH_ASL1_ID_SHA256, &stream)) { return false; } { amduat_octets_t ref_bytes = amduat_octets(NULL, 0u); bool ok; /* ReferenceBytes are self-delimiting because hash_id implies digest_len. */ ok = amduat_enc_asl1_core_encode_reference_v1(in->program_ref, &ref_bytes); if (!ok || !amduat_hash_asl1_stream_update(&stream, ref_bytes.data, ref_bytes.len)) { amduat_hash_asl1_stream_destroy(&stream); free((void *)ref_bytes.data); return false; } free((void *)ref_bytes.data); } for (i = 0; i < in->input_refs_len; ++i) { amduat_octets_t ref_bytes = amduat_octets(NULL, 0u); bool ok = amduat_enc_asl1_core_encode_reference_v1(in->input_refs[i], &ref_bytes); if (!ok || !amduat_hash_asl1_stream_update(&stream, ref_bytes.data, ref_bytes.len)) { amduat_hash_asl1_stream_destroy(&stream); free((void *)ref_bytes.data); return false; } free((void *)ref_bytes.data); } marker = in->has_params_ref ? 0x01u : 0x00u; if (!amduat_hash_asl1_stream_update(&stream, &marker, 1u)) { amduat_hash_asl1_stream_destroy(&stream); return false; } if (in->has_params_ref) { amduat_octets_t ref_bytes = amduat_octets(NULL, 0u); bool ok = amduat_enc_asl1_core_encode_reference_v1(in->params_ref, &ref_bytes); if (!ok || !amduat_hash_asl1_stream_update(&stream, ref_bytes.data, ref_bytes.len)) { amduat_hash_asl1_stream_destroy(&stream); free((void *)ref_bytes.data); return false; } free((void *)ref_bytes.data); } /* ExecProfile is currently absent; presence must be explicitly marked. */ marker = in->has_exec_profile ? 0x01u : 0x00u; if (!amduat_hash_asl1_stream_update(&stream, &marker, 1u)) { amduat_hash_asl1_stream_destroy(&stream); return false; } if (in->has_exec_profile) { if (in->exec_profile.len != 0 && in->exec_profile.data == NULL) { amduat_hash_asl1_stream_destroy(&stream); return false; } if (!amduat_hash_asl1_stream_update(&stream, in->exec_profile.data, in->exec_profile.len)) { amduat_hash_asl1_stream_destroy(&stream); return false; } } { const amduat_hash_asl1_desc_t *desc = amduat_hash_asl1_desc_lookup(AMDUAT_HASH_ASL1_ID_SHA256); uint8_t *digest; size_t digest_len; if (desc == NULL || desc->digest_len == 0u) { amduat_hash_asl1_stream_destroy(&stream); return false; } digest_len = desc->digest_len; digest = (uint8_t *)malloc(digest_len); if (digest == NULL) { amduat_hash_asl1_stream_destroy(&stream); return false; } if (!amduat_hash_asl1_stream_final(&stream, digest, digest_len)) { free(digest); amduat_hash_asl1_stream_destroy(&stream); return false; } amduat_hash_asl1_stream_destroy(&stream); *out_sid = amduat_octets(digest, digest_len); } return true; }