Skip to content

Commit

Permalink
FHMQV-C-based remote attestation
Browse files Browse the repository at this point in the history
  • Loading branch information
kkrentz committed Jan 30, 2024
1 parent eebe2ec commit 8922e76
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 0 deletions.
8 changes: 8 additions & 0 deletions sdk/include/verifier/Report.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@
#include "Keys.hpp"
#include "verifier/json11.h"

#ifndef WITH_TRAP
#define WITH_TRAP 1
#endif

struct enclave_report_t {
byte hash[MDSIZE];
uint64_t data_len;
byte data[ATTEST_DATA_MAXLEN];
#if WITH_TRAP
byte fhmqv_mic[MDSIZE];
#else /* WITH_TRAP */
byte signature[SIGNATURE_SIZE];
#endif /* WITH_TRAP */
};

struct sm_report_t {
Expand Down
20 changes: 20 additions & 0 deletions sdk/src/verifier/Report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ 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 enclave_fhmqv_mic = json["enclave"]["fhmqv_mic"].string_value();
HexToBytes(report.enclave.fhmqv_mic, sizeof(report.enclave.fhmqv_mic), enclave_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
Expand Down Expand Up @@ -88,8 +93,13 @@ Report::stringfy() {
{"datalen", static_cast<int>(report.enclave.data_len)},
{"data",
BytesToHex(report.enclave.data, report.enclave.data_len)},
#if WITH_TRAP
{"fhmqv_mic",
BytesToHex(report.enclave.fhmqv_mic, sizeof(report.enclave.fhmqv_mic))},
#else /* WITH_TRAP */
{"signature",
BytesToHex(report.enclave.signature, SIGNATURE_SIZE)},
#endif /* WITH_TRAP */
},
},
};
Expand All @@ -112,8 +122,13 @@ 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 << "FHMQV MIC: "
<< BytesToHex(report.enclave.fhmqv_mic, sizeof(report.enclave.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)
Expand Down Expand Up @@ -162,10 +177,15 @@ Report::checkSignaturesOnly(const byte* dev_public_key) {

/* verify Enclave report */
uECC_decompress(report.sm.public_key, sm_public_key, uECC_CURVE());
#if WITH_TRAP
/* TODO */
enclave_valid = 1;
#else /* WITH_TRAP */
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;
}
Expand Down
41 changes: 41 additions & 0 deletions sm/src/enclave.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,23 @@ static unsigned long copy_enclave_data(struct enclave* enclave,

/* copies data into enclave, destination must be inside EPM */
static unsigned long copy_enclave_report(struct enclave* enclave,
#if WITH_TRAP
uintptr_t dest, struct report* source,
unsigned char fhmqv_key[PRIVATE_KEY_SIZE],
unsigned char clients_fhmqv_mic[MDSIZE]) {
unsigned char buf[2048];

sbi_memcpy(buf, source, sizeof(struct report));
sbi_memset(buf + sizeof(struct report), 0, 2048 - sizeof(struct report) - MDSIZE - PRIVATE_KEY_SIZE);
sbi_memcpy(buf + 2048 - PRIVATE_KEY_SIZE, fhmqv_key, PRIVATE_KEY_SIZE);
sbi_memcpy(buf + 2048 - PRIVATE_KEY_SIZE - MDSIZE, clients_fhmqv_mic, MDSIZE);

int illegal = copy_from_sm(dest, buf, sizeof(buf));
#else /* WITH_TRAP */
uintptr_t dest, struct report* source) {

int illegal = copy_from_sm(dest, source, sizeof(struct report));
#endif /* WITH_TRAP */

if(illegal)
return SBI_ERR_SM_ENCLAVE_ILLEGAL_ARGUMENT;
Expand Down Expand Up @@ -606,7 +620,12 @@ unsigned long attest_enclave(uintptr_t report_ptr, uintptr_t data, uintptr_t siz
int attestable;
struct report report;
int ret;
#if WITH_TRAP
unsigned char fhmqv_key[PRIVATE_KEY_SIZE];
unsigned char clients_fhmqv_mic[MDSIZE];
#else /* WITH_TRAP */
unsigned char scratchpad[MDSIZE + ATTEST_DATA_MAXLEN];
#endif /* WITH_TRAP */

if (size > ATTEST_DATA_MAXLEN)
return SBI_ERR_SM_ENCLAVE_ILLEGAL_ARGUMENT;
Expand Down Expand Up @@ -638,18 +657,40 @@ 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 */
sbi_memset(report.enclave.fhmqv_mic, 0, MDSIZE);
sbi_memset(fhmqv_key, 0, sizeof(fhmqv_key));
} else if (report.enclave.data_len < PUBLIC_KEY_SIZE + PUBLIC_KEY_COMPRESSED_SIZE) {
goto err_unlock;
} else if (sm_fhmqv(report.enclave.fhmqv_mic,
clients_fhmqv_mic,
fhmqv_key,
report.enclave.data, report.enclave.data_len,
report.enclave.hash)) {
goto err_unlock;
}
#else /* WITH_TRAP */
sbi_memcpy(scratchpad, report.enclave.hash, MDSIZE);
sbi_memcpy(scratchpad + MDSIZE, report.enclave.data, report.enclave.data_len);
if (sm_sign(report.enclave.signature, scratchpad, MDSIZE + report.enclave.data_len)) {
goto err_unlock;
}
#endif /* WITH_TRAP */

spin_lock(&encl_lock);

/* copy report to the enclave */
ret = copy_enclave_report(&enclaves[eid],
report_ptr,
#if WITH_TRAP
&report,
fhmqv_key,
clients_fhmqv_mic);
#else /* WITH_TRAP */
&report);
#endif /* WITH_TRAP */

if (ret) {
ret = SBI_ERR_SM_ENCLAVE_ILLEGAL_ARGUMENT;
Expand Down
4 changes: 4 additions & 0 deletions sm/src/enclave.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,11 @@ struct enclave_report
byte hash[MDSIZE];
uint64_t data_len;
byte data[ATTEST_DATA_MAXLEN];
#if WITH_TRAP
byte fhmqv_mic[MDSIZE];
#else /* WITH_TRAP */
byte signature[SIGNATURE_SIZE];
#endif /* WITH_TRAP */
};
struct sm_report
{
Expand Down
76 changes: 76 additions & 0 deletions sm/src/sm.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,82 @@ static int osm_init(void)
return region;
}

#if WITH_TRAP
int sm_fhmqv(unsigned char *enclaves_fhmqv_mic,
unsigned char *clients_fhmqv_mic,
unsigned char *fhmqv_key,
unsigned char *data, size_t len,
const unsigned char *enclave_hash)
{
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];
sha_256_context_t ctx;
byte d[MDSIZE];
byte e[MDSIZE];
uint8_t eskb[PRIVATE_KEY_SIZE];
uint8_t sigma[MDSIZE];
uint8_t ikm[4 * PUBLIC_KEY_SIZE];
uint8_t okm[2 * MDSIZE];
uint8_t auth_data[2 * PUBLIC_KEY_SIZE + MDSIZE];

if (len != (PUBLIC_KEY_SIZE + 2 * PUBLIC_KEY_COMPRESSED_SIZE)) {
return -1;
}
spka = data;
data += PUBLIC_KEY_SIZE;
len -= PUBLIC_KEY_SIZE;
uECC_decompress(data, epka, uECC_CURVE());
data += PUBLIC_KEY_COMPRESSED_SIZE;
len -= PUBLIC_KEY_COMPRESSED_SIZE;
if (!uECC_make_key(epkb, eskb, uECC_CURVE())) {
return -1;
}
uECC_compress(epkb, data, uECC_CURVE());
data += PUBLIC_KEY_COMPRESSED_SIZE;
len -= PUBLIC_KEY_COMPRESSED_SIZE;

SHA_256.init(&ctx);
SHA_256.update(&ctx, epka, PUBLIC_KEY_SIZE);
SHA_256.update(&ctx, epkb, PUBLIC_KEY_SIZE);
SHA_256.update(&ctx, spka, PUBLIC_KEY_SIZE);
SHA_256.update(&ctx, sm_public_key, PUBLIC_KEY_SIZE);

SHA_256.finalize(&ctx, d);
sbi_memcpy(e + MDSIZE / 2, d, MDSIZE / 2);
sbi_memset(e, 0, MDSIZE / 2);
sbi_memset(d, 0, MDSIZE / 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, PUBLIC_KEY_SIZE);
sbi_memcpy(ikm + 2 * PUBLIC_KEY_SIZE, epka, PUBLIC_KEY_SIZE);
sbi_memcpy(ikm + 3 * PUBLIC_KEY_SIZE, epkb, PUBLIC_KEY_SIZE);
sha_256_hkdf(NULL, 0, /* TODO use salt */
sigma, sizeof(sigma),
ikm, sizeof(ikm),
okm, sizeof(okm));
sbi_memcpy(fhmqv_key, okm + MDSIZE, MDSIZE);
sbi_memcpy(auth_data, sm_public_key, PUBLIC_KEY_SIZE);
sbi_memcpy(auth_data + PUBLIC_KEY_SIZE, epkb, PUBLIC_KEY_SIZE);
sbi_memcpy(auth_data + 2 * PUBLIC_KEY_SIZE, enclave_hash, MDSIZE);
sha_256_hmac(okm, MDSIZE, auth_data, sizeof(auth_data), enclaves_fhmqv_mic);
sbi_memcpy(auth_data, spka, PUBLIC_KEY_SIZE);
sbi_memcpy(auth_data + PUBLIC_KEY_SIZE, epka, PUBLIC_KEY_SIZE);
sha_256_hmac(okm, MDSIZE, auth_data, 2 * PUBLIC_KEY_SIZE, clients_fhmqv_mic);
return 0;
}
#endif /* WITH_TRAP */

int sm_sign(void* signature, const void* data, size_t len)
{
unsigned char md[MDSIZE];
Expand Down
9 changes: 9 additions & 0 deletions sm/src/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@
#include "sm_call.h"
#include "sm_err.h"

#define WITH_TRAP 1

void sm_init(bool cold_boot);

/* platform specific functions */
#define ATTESTATION_KEY_LENGTH 64
void sm_retrieve_pubkey(void* dest);
#if WITH_TRAP
int sm_fhmqv(unsigned char *enclaves_fhmqv_mic,
unsigned char *clients_fhmqv_mic,
unsigned char *fhmqv_key,
unsigned char *data, size_t len,
const unsigned char *enclave_hash);
#endif /* WITH_TRAP */
int sm_sign(void* sign, const void* data, size_t len);
void sm_derive_sealing_key(unsigned char *key,
const unsigned char *key_ident,
Expand Down

0 comments on commit 8922e76

Please sign in to comment.