From 8c3f1b58298ace464e18e33cd6ba91cee78eeee1 Mon Sep 17 00:00:00 2001 From: kkrentz Date: Wed, 10 Aug 2022 11:43:33 +0200 Subject: [PATCH] FHMQV-C-based remote attestation --- sdk/include/shared/attestation.h | 6 +++ sdk/include/verifier/Report.hpp | 8 ++++ sdk/src/verifier/Report.cpp | 26 ++++++++++ sm/src/enclave.c | 8 ++++ sm/src/enclave.h | 7 +++ sm/src/sm.c | 82 ++++++++++++++++++++++++++++++++ sm/src/sm.h | 5 ++ 7 files changed, 142 insertions(+) create mode 100644 sdk/include/shared/attestation.h diff --git a/sdk/include/shared/attestation.h b/sdk/include/shared/attestation.h new file mode 100644 index 000000000..3bc318031 --- /dev/null +++ b/sdk/include/shared/attestation.h @@ -0,0 +1,6 @@ +#ifndef __ATTESTATION_H__ +#define __ATTESTATION_H__ + +#define WITH_TRAP 1 + +#endif // __ATTESTATION_H__ diff --git a/sdk/include/verifier/Report.hpp b/sdk/include/verifier/Report.hpp index aba157e48..60b126358 100644 --- a/sdk/include/verifier/Report.hpp +++ b/sdk/include/verifier/Report.hpp @@ -7,13 +7,21 @@ #include #include #include "Keys.hpp" +#include "shared/attestation.h" #include "verifier/json11.h" struct enclave_report_t { byte hash[MDSIZE]; uint64_t data_len; byte data[ATTEST_DATA_MAXLEN]; +#if WITH_TRAP + byte ephemeral_public_key_compressed[PUBLIC_KEY_COMPRESSED_SIZE]; + byte fhmqv_key[MDSIZE]; + byte servers_fhmqv_mic[MDSIZE]; + byte clients_fhmqv_mic[MDSIZE]; +#else /* WITH_TRAP */ byte signature[SIGNATURE_SIZE]; +#endif /* WITH_TRAP */ }; struct sm_report_t { diff --git a/sdk/src/verifier/Report.cpp b/sdk/src/verifier/Report.cpp index 392ef8baa..c40d98add 100644 --- a/sdk/src/verifier/Report.cpp +++ b/sdk/src/verifier/Report.cpp @@ -58,8 +58,15 @@ Report::fromJson(std::string jsonstr) { report.enclave.data_len = json["enclave"]["datalen"].int_value(); std::string enclave_data = json["enclave"]["data"].string_value(); HexToBytes(report.enclave.data, report.enclave.data_len, enclave_data); +#if WITH_TRAP + std::string servers_fhmqv_mic = json["enclave"]["servers_fhmqv_mic"].string_value(); + HexToBytes(report.enclave.servers_fhmqv_mic, sizeof(report.enclave.servers_fhmqv_mic), servers_fhmqv_mic); + std::string clients_fhmqv_mic = json["enclave"]["clients_fhmqv_mic"].string_value(); + HexToBytes(report.enclave.clients_fhmqv_mic, sizeof(report.enclave.clients_fhmqv_mic), clients_fhmqv_mic); +#else /* WITH_TRAP */ std::string enclave_signature = json["enclave"]["signature"].string_value(); HexToBytes(report.enclave.signature, SIGNATURE_SIZE, enclave_signature); +#endif /* WITH_TRAP */ } void @@ -88,8 +95,15 @@ Report::stringfy() { {"datalen", static_cast(report.enclave.data_len)}, {"data", BytesToHex(report.enclave.data, report.enclave.data_len)}, +#if WITH_TRAP + {"servers_fhmqv_mic", + BytesToHex(report.enclave.servers_fhmqv_mic, sizeof(report.enclave.servers_fhmqv_mic))}, + {"clients_fhmqv_mic", + BytesToHex(report.enclave.clients_fhmqv_mic, sizeof(report.enclave.clients_fhmqv_mic))}, +#else /* WITH_TRAP */ {"signature", BytesToHex(report.enclave.signature, SIGNATURE_SIZE)}, +#endif /* WITH_TRAP */ }, }, }; @@ -112,8 +126,16 @@ Report::printPretty() { << std::endl; std::cout << std::endl << "\t\t=== Enclave Application ===" << std::endl; std::cout << "Hash: " << BytesToHex(report.enclave.hash, MDSIZE) << std::endl; +#if WITH_TRAP + std::cout << "Server's FHMQV MIC: " + << BytesToHex(report.enclave.servers_fhmqv_mic, sizeof(report.enclave.servers_fhmqv_mic)) + << std::endl; + std::cout << "Client's FHMQV MIC: " + << BytesToHex(report.enclave.clients_fhmqv_mic, sizeof(report.enclave.clients_fhmqv_mic)) +#else /* WITH_TRAP */ std::cout << "Signature: " << BytesToHex(report.enclave.signature, SIGNATURE_SIZE) +#endif /* WITH_TRAP */ << std::endl; std::cout << "Enclave Data: " << BytesToHex(report.enclave.data, report.enclave.data_len) @@ -161,11 +183,15 @@ Report::checkSignaturesOnly(const byte* dev_public_key) { sm_valid = uECC_verify(dev_public_key, md, MDSIZE, report.sm.signature, uECC_CURVE()); /* verify Enclave report */ +#if WITH_TRAP + enclave_valid = 1; +#else /* WITH_TRAP */ uECC_decompress(report.sm.public_key, sm_public_key, uECC_CURVE()); memcpy(scratchpad, report.enclave.hash, MDSIZE); memcpy(scratchpad + MDSIZE, report.enclave.data, report.enclave.data_len); SHA_256.hash(scratchpad, MDSIZE + report.enclave.data_len, md); enclave_valid = uECC_verify(sm_public_key, md, MDSIZE, report.enclave.signature, uECC_CURVE()); +#endif /* WITH_TRAP */ return sm_valid && enclave_valid; } diff --git a/sm/src/enclave.c b/sm/src/enclave.c index efe8c6f59..7ee873a87 100644 --- a/sm/src/enclave.c +++ b/sm/src/enclave.c @@ -637,6 +637,13 @@ unsigned long attest_enclave(uintptr_t report_ptr, uintptr_t data, uintptr_t siz sbi_memcpy(report.sm.signature, sm_signature, SIGNATURE_SIZE); sbi_memcpy(report.enclave.hash, enclaves[eid].hash, MDSIZE); +#if WITH_TRAP + if (!report.enclave.data_len) { + /* this is for printing hashes at start up */ + } else if (sm_fhmqv(&report.enclave)) { + return SBI_ERR_SM_ENCLAVE_UNKNOWN_ERROR; + } +#else /* WITH_TRAP */ { byte digest[MDSIZE]; hash_ctx ctx; @@ -648,6 +655,7 @@ unsigned long attest_enclave(uintptr_t report_ptr, uintptr_t data, uintptr_t siz return SBI_ERR_SM_ENCLAVE_UNKNOWN_ERROR; } } +#endif /* WITH_TRAP */ spin_lock(&encl_lock); diff --git a/sm/src/enclave.h b/sm/src/enclave.h index e635e5a80..9313607f1 100644 --- a/sm/src/enclave.h +++ b/sm/src/enclave.h @@ -83,7 +83,14 @@ struct enclave_report byte hash[MDSIZE]; uint64_t data_len; byte data[ATTEST_DATA_MAXLEN]; +#if WITH_TRAP + byte ephemeral_public_key_compressed[PUBLIC_KEY_COMPRESSED_SIZE]; + byte fhmqv_key[MDSIZE]; + byte servers_fhmqv_mic[MDSIZE]; + byte clients_fhmqv_mic[MDSIZE]; +#else /* WITH_TRAP */ byte signature[SIGNATURE_SIZE]; +#endif /* WITH_TRAP */ }; struct sm_report { diff --git a/sm/src/sm.c b/sm/src/sm.c index e7196fd01..3e0f46f88 100644 --- a/sm/src/sm.c +++ b/sm/src/sm.c @@ -65,6 +65,88 @@ static int rng(uint8_t *dest, unsigned size) return 1; } +#if WITH_TRAP +int sm_fhmqv(struct enclave_report *enclave_report) +{ + const uint8_t *spka; /* client's static public key */ + uint8_t epka[PUBLIC_KEY_SIZE]; /* clients ephemeral public key */ + uint8_t epkb[PUBLIC_KEY_SIZE]; + hash_ctx ctx; + uint8_t d[MDSIZE]; + uint8_t e[MDSIZE]; + uint8_t eskb[PRIVATE_KEY_SIZE]; + uint8_t sigma[MDSIZE]; + uint8_t ikm[4 * PUBLIC_KEY_SIZE]; + uint8_t okm[2 * MDSIZE]; + sha_256_hmac_context_t hmac_ctx; + + if (enclave_report->data_len + != (PUBLIC_KEY_SIZE + PUBLIC_KEY_COMPRESSED_SIZE)) { + return -1; + } + spka = enclave_report->data; + uECC_decompress(enclave_report->data + PUBLIC_KEY_SIZE, epka, uECC_CURVE()); + if (!uECC_make_key(epkb, eskb, uECC_CURVE())) { + return -1; + } + uECC_compress(epkb, + enclave_report->ephemeral_public_key_compressed, + uECC_CURVE()); + + hash_init(&ctx); + hash_extend(&ctx, epka, sizeof(epka)); + hash_extend(&ctx, epkb, sizeof(epkb)); + hash_extend(&ctx, spka, PUBLIC_KEY_SIZE); + hash_extend(&ctx, sm_public_key, sizeof(sm_public_key)); + + hash_finalize(d, &ctx); + sbi_memcpy(e + (sizeof(e) / 2), d, sizeof(e) / 2); + sbi_memset(e, 0, sizeof(e) / 2); + sbi_memset(d, 0, sizeof(d) / 2); + + if (!uECC_shared_fhmqv_secret(sigma, + sm_private_key, + eskb, + spka, + epka, + e, + d, + uECC_CURVE())) { + return -1; + } + sbi_memcpy(ikm, spka, PUBLIC_KEY_SIZE); + sbi_memcpy(ikm + PUBLIC_KEY_SIZE, + sm_public_key, + sizeof(sm_public_key)); + sbi_memcpy(ikm + PUBLIC_KEY_SIZE + sizeof(sm_public_key), + epka, + sizeof(epka)); + sbi_memcpy(ikm + PUBLIC_KEY_SIZE + sizeof(sm_public_key) + sizeof(epka), + epkb, + sizeof(epkb)); + kdf( + NULL, 0, /* TODO use salt */ + sigma, sizeof(sigma), + ikm, sizeof(ikm), + okm, sizeof(okm)); + sbi_memcpy(enclave_report->fhmqv_key, + okm + sizeof(okm) / 2, + sizeof(okm) / 2); + sha_256_hmac_init(&hmac_ctx, okm, sizeof(okm) / 2); + sha_256_hmac_update(&hmac_ctx, sm_public_key, sizeof(sm_public_key)); + sha_256_hmac_update(&hmac_ctx, epkb, sizeof(epkb)); + sha_256_hmac_update(&hmac_ctx, + enclave_report->hash, + sizeof(enclave_report->hash)); + sha_256_hmac_finish(&hmac_ctx, enclave_report->servers_fhmqv_mic); + sha_256_hmac_init(&hmac_ctx, okm, sizeof(okm) / 2); + sha_256_hmac_update(&hmac_ctx, spka, PUBLIC_KEY_SIZE); + sha_256_hmac_update(&hmac_ctx, epka, sizeof(epka)); + sha_256_hmac_finish(&hmac_ctx, enclave_report->clients_fhmqv_mic); + return 0; +} +#endif /* WITH_TRAP */ + int sm_sign(void* signature, byte digest[MDSIZE]) { if (!uECC_sign(sm_private_key, digest, MDSIZE, signature, uECC_CURVE())) { diff --git a/sm/src/sm.h b/sm/src/sm.h index a6be0fb8e..766796552 100644 --- a/sm/src/sm.h +++ b/sm/src/sm.h @@ -11,6 +11,7 @@ #include "sm-sbi.h" #include +#include "attestation.h" #include "sm_call.h" #include "sm_err.h" @@ -19,6 +20,10 @@ void sm_init(bool cold_boot); /* platform specific functions */ #define ATTESTATION_KEY_LENGTH 64 void sm_retrieve_pubkey(void* dest); +#if WITH_TRAP +struct enclave_report; +int sm_fhmqv(struct enclave_report *enclave_report); +#endif /* WITH_TRAP */ int sm_sign(void* signature, byte digest[MDSIZE]); int sm_derive_sealing_key(unsigned char *key, const unsigned char *key_ident,