diff --git a/attesters/sev-snp/collect_evidence.c b/attesters/sev-snp/collect_evidence.c index c56ea93..a415a75 100644 --- a/attesters/sev-snp/collect_evidence.c +++ b/attesters/sev-snp/collect_evidence.c @@ -107,7 +107,7 @@ rats_attester_err_t sev_snp_collect_evidence(rats_attester_ctx_t *ctx, snprintf(evidence->type, sizeof(evidence->type), "sev_snp"); rats_attester_err_t err = sev_snp_get_vcek_der(report.chip_id, sizeof(report.chip_id), - &report.platform_version, snp_report); + &report.current_tcb, snp_report); if (err != RATS_ATTESTER_ERR_NONE) { return err; } diff --git a/attesters/sev-snp/sev_snp.h b/attesters/sev-snp/sev_snp.h index 96c2fb3..187c34f 100644 --- a/attesters/sev-snp/sev_snp.h +++ b/attesters/sev-snp/sev_snp.h @@ -48,7 +48,7 @@ typedef struct snp_attestation_report { uint8_t image_id[16]; /* 0x020 */ uint32_t vmpl; /* 0x030 */ uint32_t signature_algo; /* 0x034 */ - snp_tcb_version_t platform_version; /* 0x038 */ + snp_tcb_version_t current_tcb; /* 0x038 */ uint64_t platform_info; /* 0x040 */ uint32_t flags; /* 0x048 */ uint32_t reserved0; /* 0x04C */ diff --git a/core/claim.c b/core/claim.c index 35b13d1..812f467 100644 --- a/core/claim.c +++ b/core/claim.c @@ -25,9 +25,9 @@ void free_claims_list(claim_t *claims, size_t claims_length) free(claims); } -int librats_add_claim(claim_t *claim, const void *name, size_t name_size, const void *value, - size_t value_size) +int librats_add_claim(claim_t *claim, const char *name, const void *value, size_t value_size) { + size_t name_size = strlen(name) + 1; claim->name = (char *)malloc(name_size); if (claim->name == NULL) return 1; diff --git a/crypto_wrappers/api/crypto_wrapper_verify_certificate_extension.c b/crypto_wrappers/api/crypto_wrapper_verify_certificate_extension.c index 1c1bf71..a34f45e 100644 --- a/crypto_wrappers/api/crypto_wrapper_verify_certificate_extension.c +++ b/crypto_wrappers/api/crypto_wrapper_verify_certificate_extension.c @@ -13,14 +13,6 @@ #include "internal/verifier.h" #include "internal/dice.h" -#include -// clang-format off -#ifdef SGX -#include "sgx_report.h" -#endif -#include "sgx_quote_3.h" -// clang-format on - crypto_wrapper_err_t crypto_wrapper_verify_evidence(crypto_wrapper_ctx_t *crypto_ctx, attestation_evidence_t *evidence, uint8_t *hash, uint32_t hash_len, diff --git a/include/librats/claim.h b/include/librats/claim.h index 9b69497..10611bd 100644 --- a/include/librats/claim.h +++ b/include/librats/claim.h @@ -12,6 +12,89 @@ #include #include +/* Common built-in claims */ +#define BUILT_IN_CLAIM_COMMON_QUOTE "common_quote" +#define BUILT_IN_CLAIM_COMMON_QUOTE_TYPE "common_quote_type" + +/* SGX built-in claims */ +/* Refer to: https://github.com/intel/linux-sgx/blob/a1eeccba5a72b3b9b342569d2cc469ece106d3e9/common/inc/sgx_report.h#L93-L111 */ +/* Security Version of the CPU */ +#define BUILT_IN_CLAIM_SGX_CPU_SVN "sgx_cpu_svn" +/* ISV assigned Extended Product ID */ +#define BUILT_IN_CLAIM_SGX_ISV_EXT_PROD_ID "sgx_isv_ext_prod_id" +/* Any special Capabilities the Enclave possess */ +#define BUILT_IN_CLAIM_SGX_ATTRIBUTES "sgx_attributes" +/* The value of the enclave's ENCLAVE measurement */ +#define BUILT_IN_CLAIM_SGX_MR_ENCLAVE "sgx_mr_enclave" +/* The value of the enclave's SIGNER measurement */ +#define BUILT_IN_CLAIM_SGX_MR_SIGNER "sgx_mr_signer" +/* CONFIGID */ +#define BUILT_IN_CLAIM_SGX_CONFIG_ID "sgx_config_id" +/* Product ID of the Enclave */ +#define BUILT_IN_CLAIM_SGX_ISV_PROD_ID "sgx_isv_prod_id" +/* Security Version of the Enclave */ +#define BUILT_IN_CLAIM_SGX_ISV_SVN "sgx_isv_svn" +/* CONFIGSVN */ +#define BUILT_IN_CLAIM_SGX_CONFIG_SVN "sgx_config_svn" +/* ISV assigned Family ID */ +#define BUILT_IN_CLAIM_SGX_ISV_FAMILY_ID "sgx_isv_family_id" + +/* TDX built-in claims */ +/* Refer to: https://github.com/intel/linux-sgx/blob/a1eeccba5a72b3b9b342569d2cc469ece106d3e9/common/inc/sgx_report.h#L93-L111 */ +/// TEE_TCB_SVN Array +#define BUILT_IN_CLAIM_TDX_TEE_TCB_SVN "tdx_tee_tcb_svn" +/// Measurement of the SEAM module +#define BUILT_IN_CLAIM_TDX_MR_SEAM "tdx_mr_seam" +/// Measurement of a 3rd party SEAM module’s signer (SHA384 hash). The value is 0’ed for Intel SEAM module +#define BUILT_IN_CLAIM_TDX_MRSIGNER_SEAM "tdx_mrsigner_seam" +/// MBZ: TDX 1.0 +#define BUILT_IN_CLAIM_TDX_SEAM_ATTRIBUTES "tdx_seam_attributes" +/// TD's attributes +#define BUILT_IN_CLAIM_TDX_TD_ATTRIBUTES "tdx_td_attributes" +/// TD's XFAM +#define BUILT_IN_CLAIM_TDX_XFAM "tdx_xfam" +/// Measurement of the initial contents of the TD +#define BUILT_IN_CLAIM_TDX_MR_TD "tdx_mr_td" +/// Software defined ID for non-owner-defined configuration on the guest TD. e.g., runtime or OS configuration +#define BUILT_IN_CLAIM_TDX_MR_CONFIG_ID "tdx_mr_config_id" +/// Software defined ID for the guest TD's owner +#define BUILT_IN_CLAIM_TDX_MR_OWNER "tdx_mr_owner" +/// Software defined ID for owner-defined configuration of the guest TD, e.g., specific to the workload rather than the runtime or OS +#define BUILT_IN_CLAIM_TDX_MR_OWNER_CONFIG "tdx_mr_owner_config" +/// Array of 4(TDX1: NUM_RTMRS is 4) runtime extendable measurement registers +#define BUILT_IN_CLAIM_TDX_RT_MR0 "tdx_rt_mr0" +#define BUILT_IN_CLAIM_TDX_RT_MR1 "tdx_rt_mr1" +#define BUILT_IN_CLAIM_TDX_RT_MR2 "tdx_rt_mr2" +#define BUILT_IN_CLAIM_TDX_RT_MR3 "tdx_rt_mr3" + +/* sev-snp built-in claims */ +#define BUILT_IN_CLAIM_SEV_SNP_GUEST_SVN "sev_snp_guest_svn" /* 0x004 */ +#define BUILT_IN_CLAIM_SEV_SNP_POLICY "sev_snp_policy" /* 0x008 */ +#define BUILT_IN_CLAIM_SEV_SNP_FAMILY_ID "sev_snp_family_id" /* 0x010 */ +#define BUILT_IN_CLAIM_SEV_SNP_IMAGE_ID "sev_snp_image_id" /* 0x020 */ +#define BUILT_IN_CLAIM_SEV_SNP_VMPL "sev_snp_vmpl" /* 0x030 */ +#define BUILT_IN_CLAIM_SEV_SNP_CURRENT_TCB "sev_snp_current_tcb" /* 0x038 */ +#define BUILT_IN_CLAIM_SEV_SNP_PLATFORM_INFO "sev_snp_platform_info" /* 0x040 */ +#define BUILT_IN_CLAIM_SEV_SNP_MEASUREMENT "sev_snp_measurement" /* 0x090 */ +#define BUILT_IN_CLAIM_SEV_SNP_HOST_DATA "sev_snp_host_data" /* 0x0C0 */ +#define BUILT_IN_CLAIM_SEV_SNP_ID_KEY_DIGEST "sev_snp_id_key_digest" /* 0x0E0 */ +#define BUILT_IN_CLAIM_SEV_SNP_REPORT_ID "sev_snp_report_id" /* 0x140 */ +#define BUILT_IN_CLAIM_SEV_SNP_REPORT_ID_MA "sev_snp_report_id_ma" /* 0x160 */ +#define BUILT_IN_CLAIM_SEV_SNP_REPORTED_TCB "sev_snp_reported_tcb" /* 0x180 */ +#define BUILT_IN_CLAIM_SEV_SNP_CHIP_ID "sev_snp_chip_id" /* 0x1A0 */ + +/* csv built-in claims */ +#define BUILT_IN_CLAIM_CSV_USER_PUBKEY_DIGEST "csv_user_pubkey_digest" +#define BUILT_IN_CLAIM_CSV_VM_ID "csv_vm_id" +#define BUILT_IN_CLAIM_CSV_VM_VERSION "csv_vm_version" +#define BUILT_IN_CLAIM_CSV_USER_DATA "csv_user_data" +#define BUILT_IN_CLAIM_CSV_MNONCE "csv_mnonce" +#define BUILT_IN_CLAIM_CSV_MEASURE "csv_measure" +#define BUILT_IN_CLAIM_CSV_POLICY "csv_policy" +#define BUILT_IN_CLAIM_CSV_SIG_USAGE "csv_sig_usage" +#define BUILT_IN_CLAIM_CSV_SIG_ALGO "csv_sig_algo" +#define BUILT_IN_CLAIM_CSV_CHIP_ID "csv_chip_id" + /** * Claims struct used for claims parameters. */ @@ -23,8 +106,7 @@ struct claim { } __attribute__((packed)); void free_claims_list(claim_t *claims, size_t claims_length); -int librats_add_claim(claim_t *claim, const void *name, size_t name_size, const void *value, - size_t value_size); +int librats_add_claim(claim_t *claim, const char *name, const void *value, size_t value_size); /* This macro checks whether the expression argument evaluates to RATS_ERR_NONE */ #define CLAIM_CHECK(EXPRESSION) \ diff --git a/samples/cert-app/common.c b/samples/cert-app/common.c index 263560e..24e6bcf 100644 --- a/samples/cert-app/common.c +++ b/samples/cert-app/common.c @@ -2,6 +2,7 @@ #include #include #include +#include int generate_key_pairs(uint8_t **private_key_out, size_t *private_key_size_out) { @@ -74,6 +75,25 @@ int generate_key_pairs(uint8_t **private_key_out, size_t *private_key_size_out) return ret; } +void print_claim_value(uint8_t *value, size_t value_size) +{ + bool hex = false; + for (size_t i = 0; i < value_size; ++i) { + if (!isprint(value[i])) { + hex = true; + break; + } + } + if (hex) { + printf("(hex)"); + for (size_t i = 0; i < value_size; ++i) { + printf("%02X", value[i]); + } + } else { + printf("'%.*s'", (int)value_size, value); + } +} + int verify_callback(claim_t *claims, size_t claims_size, void *args_in) { int ret = 0; @@ -81,9 +101,10 @@ int verify_callback(claim_t *claims, size_t claims_size, void *args_in) printf("verify_callback called, claims %p, claims_size %zu, args %p\n", claims, claims_size, args_in); for (size_t i = 0; i < claims_size; ++i) { - printf("claims[%zu] -> name: '%s' value_size: %zu value: '%.*s'\n", i, - claims[i].name, claims[i].value_size, (int)claims[i].value_size, - claims[i].value); + printf("claims[%zu] -> name: '%s' value_size: %zu value: ", i, claims[i].name, + claims[i].value_size); + print_claim_value(claims[i].value, claims[i].value_size); + printf("\n"); } /* Let's check all custom claims exits and unchanged */ @@ -110,10 +131,12 @@ int verify_callback(claim_t *claims, size_t claims_size, void *args_in) } if (memcmp(claim->value, claims[j].value, claim->value_size)) { - printf("different claim detected -> name: '%s' value_size: %zu expected value: '%.*s' got: '%.*s'\n", - claim->name, claim->value_size, - (int)claim->value_size, claim->value, - (int)claim->value_size, claims[j].value); + printf("different claim detected -> name: '%s' value_size: %zu expected value: ", + claim->name, claim->value_size); + print_claim_value(claim->value, claim->value_size); + printf(" got: "); + print_claim_value(claims[j].value, claim->value_size); + printf("\n"); ret = 1; break; } diff --git a/verifiers/csv/verify_evidence.c b/verifiers/csv/verify_evidence.c index 7a04ff1..93773b1 100644 --- a/verifiers/csv/verify_evidence.c +++ b/verifiers/csv/verify_evidence.c @@ -97,12 +97,79 @@ static rats_verifier_err_t verify_attestation_report(csv_attestation_report *rep return RATS_VERIFIER_ERR_NONE; } +rats_verifier_err_t convert_quote_to_claims(csv_attestation_report *report, uint32_t report_size, + claim_t **claims_out, size_t *claims_length_out) +{ + if (!claims_out || !claims_length_out) + return RATS_VERIFIER_ERR_NONE; + if (!report || !report_size) + return RATS_VERIFIER_ERR_INVALID_PARAMETER; + + claim_t *claims = NULL; + size_t claims_length = 0; + rats_verifier_err_t err = RATS_VERIFIER_ERR_UNKNOWN; + if (claims == NULL) + return RATS_VERIFIER_ERR_NO_MEM; + + claims_length = 2 + 10; /* 2 common claims + 10 csv claims */ + claims = malloc(sizeof(claim_t) * claims_length); + + size_t claims_index = 0; + + /* common claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE, report, + report_size)); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE_TYPE, + "csv", sizeof("csv"))); + + /* Clear nonce on the range from field `user_pubkey_digest` to field `anonce`, note that + pek_cert and chip_id have been retrieved in function verify_cert_chain(). */ + int cnt = (offsetof(csv_attestation_report, anonce) - + offsetof(csv_attestation_report, user_pubkey_digest)) / + sizeof(uint32_t); + for (int i = 0; i < cnt; i++) { + ((uint32_t *)report)[i] ^= report->anonce; + } + + /* csv claims */ + CLAIM_CHECK(librats_add_claim( + &claims[claims_index++], BUILT_IN_CLAIM_CSV_USER_PUBKEY_DIGEST, + (uint8_t *)&report->user_pubkey_digest, sizeof(report->user_pubkey_digest))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_VM_ID, + (uint8_t *)&report->vm_id, sizeof(report->vm_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_VM_VERSION, + (uint8_t *)&report->vm_version, sizeof(report->vm_version))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_USER_DATA, + (uint8_t *)&report->user_data, sizeof(report->user_data))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_MNONCE, + (uint8_t *)&report->mnonce, sizeof(report->mnonce))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_MEASURE, + (uint8_t *)&report->measure, sizeof(report->measure))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_POLICY, + (uint8_t *)&report->policy, sizeof(report->policy))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_SIG_USAGE, + (uint8_t *)&report->sig_usage, sizeof(report->sig_usage))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_SIG_ALGO, + (uint8_t *)&report->sig_algo, sizeof(report->sig_algo))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_CSV_CHIP_ID, + (uint8_t *)&report->chip_id, sizeof(report->chip_id))); + + *claims_out = claims; + *claims_length_out = claims_length; + claims = NULL; + + err = RATS_VERIFIER_ERR_NONE; +done: + if (claims) + free_claims_list(claims, claims_index); + return err; +} + rats_verifier_err_t csv_verify_evidence(rats_verifier_ctx_t *ctx, attestation_evidence_t *evidence, const uint8_t *hash, uint32_t hash_len, __attribute__((unused)) attestation_endorsement_t *endorsements, - __attribute__((unused)) claim_t **claims, - __attribute__((unused)) size_t *claims_length) + claim_t **claims, size_t *claims_length) { RATS_DEBUG("ctx %p, evidence %p, hash %p\n", ctx, evidence, hash); @@ -116,6 +183,7 @@ rats_verifier_err_t csv_verify_evidence(rats_verifier_ctx_t *ctx, attestation_ev }; int i; + /* add nonce on new user_data buffer */ for (i = 0; i < sizeof(user_data) / sizeof(uint32_t); i++) ((uint32_t *)user_data)[i] = ((uint32_t *)attestation_report->user_data)[i] ^ attestation_report->anonce; @@ -139,5 +207,13 @@ rats_verifier_err_t csv_verify_evidence(rats_verifier_ctx_t *ctx, attestation_ev if (err != RATS_VERIFIER_ERR_NONE) RATS_ERR("failed to verify csv attestation report\n"); + if (err == RATS_VERIFIER_ERR_NONE) { + err = convert_quote_to_claims(attestation_report, sizeof(*attestation_report), + claims, claims_length); + if (err != RATS_VERIFIER_ERR_NONE) + RATS_ERR( + "failed to convert csv attestation report to builtin claims: %#x\n", + err); + } return err; } diff --git a/verifiers/sev-snp/verify_evidence.c b/verifiers/sev-snp/verify_evidence.c index d6a2587..f536956 100644 --- a/verifiers/sev-snp/verify_evidence.c +++ b/verifiers/sev-snp/verify_evidence.c @@ -20,10 +20,84 @@ #include "crypto.h" #include "utils.h" -rats_verifier_err_t sev_snp_verify_evidence( - rats_verifier_ctx_t *ctx, attestation_evidence_t *evidence, const uint8_t *hash, - uint32_t hash_len, __attribute__((unused)) attestation_endorsement_t *endorsements, - __attribute__((unused)) claim_t **claims, __attribute__((unused)) size_t *claims_length) +rats_verifier_err_t convert_quote_to_claims(snp_attestation_report_t *report, uint32_t report_size, + claim_t **claims_out, size_t *claims_length_out) +{ + if (!claims_out || !claims_length_out) + return RATS_VERIFIER_ERR_NONE; + if (!report || !report_size) + return RATS_VERIFIER_ERR_INVALID_PARAMETER; + + claim_t *claims = NULL; + size_t claims_length = 0; + rats_verifier_err_t err = RATS_VERIFIER_ERR_UNKNOWN; + if (claims == NULL) + return RATS_VERIFIER_ERR_NO_MEM; + + claims_length = 2 + 14; /* 2 common claims + 14 sev_snp claims */ + claims = malloc(sizeof(claim_t) * claims_length); + + size_t claims_index = 0; + + /* common claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE, report, + report_size)); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE_TYPE, + "sev_snp", sizeof("sev_snp"))); + + /* sev_snp claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_GUEST_SVN, + (uint8_t *)&report->guest_svn, sizeof(report->guest_svn))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_POLICY, + (uint8_t *)&report->policy, sizeof(report->policy))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_FAMILY_ID, + (uint8_t *)&report->family_id, sizeof(report->family_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_IMAGE_ID, + (uint8_t *)&report->image_id, sizeof(report->image_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_VMPL, + (uint8_t *)&report->vmpl, sizeof(report->vmpl))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_CURRENT_TCB, + (uint8_t *)&report->current_tcb, + sizeof(report->current_tcb))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_PLATFORM_INFO, + (uint8_t *)&report->platform_info, + sizeof(report->platform_info))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_MEASUREMENT, + (uint8_t *)&report->measurement, + sizeof(report->measurement))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_HOST_DATA, + (uint8_t *)&report->host_data, sizeof(report->host_data))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_ID_KEY_DIGEST, + (uint8_t *)&report->id_key_digest, + sizeof(report->id_key_digest))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_REPORT_ID, + (uint8_t *)&report->report_id, sizeof(report->report_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_REPORT_ID_MA, + (uint8_t *)&report->report_id_ma, + sizeof(report->report_id_ma))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_REPORTED_TCB, + (uint8_t *)&report->reported_tcb, + sizeof(report->reported_tcb))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SEV_SNP_CHIP_ID, + (uint8_t *)&report->chip_id, sizeof(report->chip_id))); + + *claims_out = claims; + *claims_length_out = claims_length; + claims = NULL; + + err = RATS_VERIFIER_ERR_NONE; +done: + if (claims) + free_claims_list(claims, claims_index); + return err; +} + +rats_verifier_err_t sev_snp_verify_evidence(rats_verifier_ctx_t *ctx, + attestation_evidence_t *evidence, const uint8_t *hash, + uint32_t hash_len, + __attribute__((unused)) + attestation_endorsement_t *endorsements, + claim_t **claims, size_t *claims_length) { RATS_DEBUG("ctx %p, evidence %p, hash %p\n", ctx, evidence, hash); @@ -36,7 +110,7 @@ rats_verifier_err_t sev_snp_verify_evidence( #else memset(evidence->snp.vcek, 0, VECK_MAX_SIZE); err = sev_snp_get_vcek_der(report->chip_id, sizeof(report->chip_id), - &report->platform_version, &evidence->snp); + &report->current_tcb, &evidence->snp); if (err != RATS_ATTESTER_ERR_NONE) return err; #endif @@ -57,36 +131,36 @@ rats_verifier_err_t sev_snp_verify_evidence( bio_mem = BIO_new(BIO_s_mem()); if (!bio_mem) { - goto err; + goto errret; } BIO_puts(bio_mem, ask_pem); x509_ask = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL); if (!x509_ask) { - goto err; + goto errret; } BIO_reset(bio_mem); BIO_puts(bio_mem, ark_pem); x509_ark = PEM_read_bio_X509(bio_mem, NULL, NULL, NULL); if (!x509_ark) { - goto err; + goto errret; } uint8_t *vcek_ptr = evidence->snp.vcek; x509_vcek = d2i_X509(NULL, (const unsigned char **)&(vcek_ptr), evidence->snp.vcek_len); if (!x509_vcek) { - goto err; + goto errret; } /* Extract the VCEK public key */ vcek_pub_key = X509_get_pubkey(x509_vcek); if (!vcek_pub_key) - goto err; + goto errret; /* Verify the ARK self-signed the ARK */ ret = x509_validate_signature(x509_ark, NULL, x509_ark); if (!ret) { RATS_ERR("failed to validate signature of x509_ark cert\n"); err = RATS_VERIFIER_ERR_INVALID; - goto err; + goto errret; } /* Verify the ASK signed by ARK */ @@ -94,7 +168,7 @@ rats_verifier_err_t sev_snp_verify_evidence( if (!ret) { RATS_ERR("failed to validate signature of x509_ask cert\n"); err = RATS_VERIFIER_ERR_INVALID; - goto err; + goto errret; } /* Verify the VCEK signed by ASK */ @@ -102,7 +176,7 @@ rats_verifier_err_t sev_snp_verify_evidence( if (!ret) { RATS_ERR("failed to validate signature of x509_vcek cert\n"); err = RATS_VERIFIER_ERR_INVALID; - goto err; + goto errret; } /* Verify the attestation report signed by VCEK */ @@ -112,14 +186,19 @@ rats_verifier_err_t sev_snp_verify_evidence( if (!ret) { RATS_ERR("failed to verify snp guest report\n"); err = RATS_VERIFIER_ERR_INVALID; - goto err; + goto errret; } - err = RATS_VERIFIER_ERR_NONE; + err = convert_quote_to_claims(report, sizeof(*report), claims, claims_length); + if (err != RATS_VERIFIER_ERR_NONE) { + RATS_ERR("failed to convert sev_snp attestation report to builtin claims: %#x\n", + err); + goto errret; + } RATS_INFO("SEV-SNP attestation report validated successfully!\n"); -err: +errret: X509_free(x509_ark); X509_free(x509_ask); X509_free(x509_vcek); diff --git a/verifiers/sgx-ecdsa/verify_evidence.c b/verifiers/sgx-ecdsa/verify_evidence.c index 3c435cf..8abead0 100644 --- a/verifiers/sgx-ecdsa/verify_evidence.c +++ b/verifiers/sgx-ecdsa/verify_evidence.c @@ -299,12 +299,77 @@ rats_verifier_err_t ecdsa_verify_evidence(sgx_quote3_t *pquote, uint32_t quote_s } #endif +rats_verifier_err_t convert_quote_to_claims(sgx_quote3_t *quote, uint32_t quote_size, + claim_t **claims_out, size_t *claims_length_out) +{ + if (!claims_out || !claims_length_out) + return RATS_VERIFIER_ERR_NONE; + if (!quote || !quote_size) + return RATS_VERIFIER_ERR_INVALID_PARAMETER; + + claim_t *claims = NULL; + size_t claims_length = 0; + rats_verifier_err_t err = RATS_VERIFIER_ERR_UNKNOWN; + + claims_length = 2 + 10; /* 2 common claims + 10 sgx claims */ + claims = malloc(sizeof(claim_t) * claims_length); + + size_t claims_index = 0; + + /* common claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE, quote, + quote_size)); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE_TYPE, + "sgx_ecdsa", sizeof("sgx_ecdsa"))); + + /* sgx claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_CPU_SVN, + (uint8_t *)"e->report_body.cpu_svn, + sizeof(quote->report_body.cpu_svn))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_ISV_EXT_PROD_ID, + (uint8_t *)"e->report_body.isv_ext_prod_id, + sizeof(quote->report_body.isv_ext_prod_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_ATTRIBUTES, + (uint8_t *)"e->report_body.attributes, + sizeof(quote->report_body.attributes))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_MR_ENCLAVE, + (uint8_t *)"e->report_body.mr_enclave, + sizeof(quote->report_body.mr_enclave))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_MR_SIGNER, + (uint8_t *)"e->report_body.mr_signer, + sizeof(quote->report_body.mr_signer))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_CONFIG_ID, + (uint8_t *)"e->report_body.config_id, + sizeof(quote->report_body.config_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_ISV_PROD_ID, + (uint8_t *)"e->report_body.isv_prod_id, + sizeof(quote->report_body.isv_prod_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_ISV_SVN, + (uint8_t *)"e->report_body.isv_svn, + sizeof(quote->report_body.isv_svn))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_CONFIG_SVN, + (uint8_t *)"e->report_body.config_svn, + sizeof(quote->report_body.config_svn))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_SGX_ISV_FAMILY_ID, + (uint8_t *)"e->report_body.isv_family_id, + sizeof(quote->report_body.isv_family_id))); + + *claims_out = claims; + *claims_length_out = claims_length; + claims = NULL; + + err = RATS_VERIFIER_ERR_NONE; +done: + if (claims) + free_claims_list(claims, claims_index); + return err; +} + rats_verifier_err_t sgx_ecdsa_verify_evidence(rats_verifier_ctx_t *ctx, attestation_evidence_t *evidence, - const uint8_t *hash, __attribute__((unused)) uint32_t hash_len, - attestation_endorsement_t *endorsements /* optional */, - __attribute__((unused)) claim_t **claims, - __attribute__((unused)) size_t *claims_length) + const uint8_t *hash, uint32_t hash_len, + attestation_endorsement_t *endorsements /* optional */, claim_t **claims, + size_t *claims_length) { RATS_DEBUG("ctx %p, evidence %p, hash %p\n", ctx, evidence, hash); @@ -407,5 +472,11 @@ sgx_ecdsa_verify_evidence(rats_verifier_ctx_t *ctx, attestation_evidence_t *evid RATS_ERR("failed to verify ecdsa\n"); #endif + if (err == RATS_VERIFIER_ERR_NONE) { + err = convert_quote_to_claims(pquote, quote_size, claims, claims_length); + if (err != RATS_VERIFIER_ERR_NONE) + RATS_ERR("failed to convert sgx_ecdsa quote to builtin claims: %#x\n", err); + } + return err; } diff --git a/verifiers/tdx-ecdsa/tdx-ecdsa.h b/verifiers/tdx-ecdsa/tdx-ecdsa.h index b89f451..65c8767 100644 --- a/verifiers/tdx-ecdsa/tdx-ecdsa.h +++ b/verifiers/tdx-ecdsa/tdx-ecdsa.h @@ -29,16 +29,16 @@ typedef struct { typedef struct { uint8_t tee_tcb_svn[16]; - uint8_t mrseam[RATS_SHA384_HASH_SIZE]; + uint8_t mr_seam[RATS_SHA384_HASH_SIZE]; uint8_t mrsigner_seam[RATS_SHA384_HASH_SIZE]; uint8_t seam_attributes[8]; uint8_t td_attributes[8]; uint8_t xfam[8]; - uint8_t mrtd[RATS_SHA384_HASH_SIZE]; - uint8_t mrconfig_id[RATS_SHA384_HASH_SIZE]; - uint8_t mrowner[RATS_SHA384_HASH_SIZE]; - uint8_t mrowner_config[RATS_SHA384_HASH_SIZE]; - uint8_t rtmr[TDX_NUM_RTMRS][RATS_SHA384_HASH_SIZE]; + uint8_t mr_td[RATS_SHA384_HASH_SIZE]; + uint8_t mr_config_id[RATS_SHA384_HASH_SIZE]; + uint8_t mr_owner[RATS_SHA384_HASH_SIZE]; + uint8_t mr_owner_config[RATS_SHA384_HASH_SIZE]; + uint8_t rt_mr[TDX_NUM_RTMRS][RATS_SHA384_HASH_SIZE]; uint8_t report_data[64]; } __attribute__((packed)) tdx_report_body_t; diff --git a/verifiers/tdx-ecdsa/verify_evidence.c b/verifiers/tdx-ecdsa/verify_evidence.c index 385c479..4fac841 100644 --- a/verifiers/tdx-ecdsa/verify_evidence.c +++ b/verifiers/tdx-ecdsa/verify_evidence.c @@ -121,53 +121,83 @@ rats_verifier_err_t ecdsa_verify_evidence(__attribute__((unused)) rats_verifier_ return err; } -#define TDX_CLAIMS_COUNT 4 - -#define TDX_CLAIM_RTMR0 "rtmr0" -#define TDX_CLAIM_RTMR1 "rtmr1" -#define TDX_CLAIM_RTMR2 "rtmr2" -#define TDX_CLAIM_RTMR3 "rtmr3" - -rats_verifier_err_t tdx_parse_claims(tdx_quote_t *quote, claim_t **claims_out, - size_t *claims_length_out) +rats_verifier_err_t convert_quote_to_claims(tdx_quote_t *quote, uint32_t quote_size, + claim_t **claims_out, size_t *claims_length_out) { - if (!quote || !claims_out || !claims_length_out) - return RATS_ERR_INVALID_PARAMETER; + if (!claims_out || !claims_length_out) + return RATS_VERIFIER_ERR_NONE; + if (!quote || !quote_size) + return RATS_VERIFIER_ERR_INVALID_PARAMETER; - rats_err_t err = RATS_ERR_UNKNOWN; - - size_t claims_index = 0; - uint64_t claims_size = TDX_CLAIMS_COUNT * sizeof(claim_t); - claim_t *claims = (claim_t *)malloc(claims_size); + claim_t *claims = NULL; + size_t claims_length = 0; + rats_verifier_err_t err = RATS_VERIFIER_ERR_UNKNOWN; if (claims == NULL) - return RATS_ERR_NO_MEM; - - CLAIM_CHECK(librats_add_claim(&claims[claims_index++], TDX_CLAIM_RTMR0, - sizeof(TDX_CLAIM_RTMR0), quote->report_body.rtmr[0], - sizeof(quote->report_body.rtmr[0]))); + return RATS_VERIFIER_ERR_NO_MEM; - CLAIM_CHECK(librats_add_claim(&claims[claims_index++], TDX_CLAIM_RTMR1, - sizeof(TDX_CLAIM_RTMR1), quote->report_body.rtmr[1], - sizeof(quote->report_body.rtmr[1]))); + claims_length = 2 + 14; /* 2 common claims + 14 tdx claims */ + claims = malloc(sizeof(claim_t) * claims_length); - CLAIM_CHECK(librats_add_claim(&claims[claims_index++], TDX_CLAIM_RTMR2, - sizeof(TDX_CLAIM_RTMR2), quote->report_body.rtmr[2], - sizeof(quote->report_body.rtmr[2]))); + size_t claims_index = 0; - CLAIM_CHECK(librats_add_claim(&claims[claims_index++], TDX_CLAIM_RTMR3, - sizeof(TDX_CLAIM_RTMR3), quote->report_body.rtmr[3], - sizeof(quote->report_body.rtmr[3]))); + /* common claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE, quote, + quote_size)); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_COMMON_QUOTE_TYPE, + "tdx_ecdsa", sizeof("tdx_ecdsa"))); + + /* tdx claims */ + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_TEE_TCB_SVN, + (uint8_t *)"e->report_body.tee_tcb_svn, + sizeof(quote->report_body.tee_tcb_svn))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MR_SEAM, + (uint8_t *)"e->report_body.mr_seam, + sizeof(quote->report_body.mr_seam))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MRSIGNER_SEAM, + (uint8_t *)"e->report_body.mrsigner_seam, + sizeof(quote->report_body.mrsigner_seam))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_SEAM_ATTRIBUTES, + (uint8_t *)"e->report_body.seam_attributes, + sizeof(quote->report_body.seam_attributes))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_TD_ATTRIBUTES, + (uint8_t *)"e->report_body.td_attributes, + sizeof(quote->report_body.td_attributes))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_XFAM, + (uint8_t *)"e->report_body.xfam, + sizeof(quote->report_body.xfam))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MR_TD, + (uint8_t *)"e->report_body.mr_td, + sizeof(quote->report_body.mr_td))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MR_CONFIG_ID, + (uint8_t *)"e->report_body.mr_config_id, + sizeof(quote->report_body.mr_config_id))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MR_OWNER, + (uint8_t *)"e->report_body.mr_owner, + sizeof(quote->report_body.mr_owner))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_MR_OWNER_CONFIG, + (uint8_t *)"e->report_body.mr_owner_config, + sizeof(quote->report_body.mr_owner_config))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_RT_MR0, + (uint8_t *)"e->report_body.rt_mr[0], + sizeof(quote->report_body.rt_mr[0]))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_RT_MR1, + (uint8_t *)"e->report_body.rt_mr[1], + sizeof(quote->report_body.rt_mr[1]))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_RT_MR2, + (uint8_t *)"e->report_body.rt_mr[2], + sizeof(quote->report_body.rt_mr[2]))); + CLAIM_CHECK(librats_add_claim(&claims[claims_index++], BUILT_IN_CLAIM_TDX_RT_MR3, + (uint8_t *)"e->report_body.rt_mr[3], + sizeof(quote->report_body.rt_mr[3]))); *claims_out = claims; - *claims_length_out = claims_index; + *claims_length_out = claims_length; claims = NULL; err = RATS_VERIFIER_ERR_NONE; - done: if (claims) free_claims_list(claims, claims_index); - return err; } @@ -183,14 +213,15 @@ rats_verifier_err_t tdx_ecdsa_verify_evidence(rats_verifier_ctx_t *ctx, rats_verifier_err_t err = RATS_VERIFIER_ERR_UNKNOWN; err = ecdsa_verify_evidence(ctx, ctx->opts->name, evidence, sizeof(attestation_evidence_t), hash, hash_len, endorsements); - if (err != RATS_VERIFIER_ERR_NONE) { - RATS_ERR("failed to verify ecdsa\n"); - return err; - } - - err = tdx_parse_claims((tdx_quote_t *)evidence->tdx.quote, claims, claims_length); if (err != RATS_VERIFIER_ERR_NONE) - RATS_ERR("failed to parse tdx claims\n"); + RATS_ERR("failed to verify ecdsa\n"); + return err; + if (err == RATS_VERIFIER_ERR_NONE) { + err = convert_quote_to_claims((tdx_quote_t *)evidence->tdx.quote, + evidence->tdx.quote_len, claims, claims_length); + if (err != RATS_VERIFIER_ERR_NONE) + RATS_ERR("failed to convert tdx_ecdsa quote to builtin claims: %#x\n", err); + } return err; }