Skip to content

Commit

Permalink
init/snp: Attest with keybroker KBS server
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Fanelli <tfanelli@redhat.com>
  • Loading branch information
tylerfanelli committed Mar 15, 2024
1 parent 79d993c commit be0df60
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 25 deletions.
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ SEV_LD_FLAGS = -lcurl -lidn2 -lssl -lcrypto -lzstd -lz -lbrotlidec-static \
-lbrotlicommon-static

INIT_DEFS =
ifeq ($(SEV),1)
VARIANT = -sev
FEATURE_FLAGS := --features amd-sev
INIT_DEFS += -DSEV=1
INIT_DEFS += $(SEV_LD_FLAGS)
INIT_SRC += $(SNP_INIT_SRC)
endif
ifeq ($(NET),1)
FEATURE_FLAGS += --features net
endif
Expand Down
3 changes: 2 additions & 1 deletion examples/snp-config-attest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
"ram_mib": 2048,
"tee": "snp",
"tee_data": "{\"gen\":\"milan\"}",
"attestation_url": "http://127.0.0.1:8000"
"attestation_url": "http://127.0.0.1:8000",
"host_data": ""
}
23 changes: 17 additions & 6 deletions init/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ static int jsoneq(const char *, jsmntok_t *, const char *);

#ifdef SEV
static char *sev_get_luks_passphrase(int *);
static char *snp_get_luks_passphrase(char *, char *, char *, int *);
static char *snp_get_luks_passphrase(char *, char *, char *, char *, int *);
#endif

char DEFAULT_KRUN_INIT[] = "/bin/sh";
Expand Down Expand Up @@ -87,9 +87,11 @@ static char *
get_luks_passphrase(int *pass_len)
{
int fd, ret, num_tokens, wid_found, url_found, tee_found, tee_data_found;
int host_data_found;
uint64_t dev_size, tc_size;
char wid[256], url[256], *tc_json, *tok_start, *tok_end;
char footer[KRUN_FOOTER_LEN], tee[256], tee_data[256], *return_str;
char host_data[256];
jsmn_parser parser;
jsmntok_t *tokens;
size_t tok_size;
Expand Down Expand Up @@ -194,7 +196,7 @@ get_luks_passphrase(int *pass_len)
goto free_mem;
}

wid_found = url_found = tee_found = tee_data_found = 0;
wid_found = url_found = tee_found = tee_data_found = host_data_found = 0;

for (int i = 1; i < num_tokens - 1; ++i) {
tok_start = tc_json + tokens[i + 1].start;
Expand All @@ -212,7 +214,10 @@ get_luks_passphrase(int *pass_len)
} else if (!jsoneq(tc_json, &tokens[i], "tee_data")) {
strncpy(tee_data, tok_start, tok_size);
tee_data_found = 1;
}
} else if (!jsoneq(tc_json, &tokens[i], "host_data")) {
strncpy(host_data, tok_start, tok_size);
host_data_found = 1;
}
}

if (!wid_found) {
Expand All @@ -226,6 +231,9 @@ get_luks_passphrase(int *pass_len)
} else if (!tee_found) {
printf("Unable to find TEE generation server URL\n");

goto free_mem;
} else if (host_data_found == 0) {
printf("Unable to find HOST_DATA string\n");
goto free_mem;
}

Expand All @@ -235,7 +243,8 @@ get_luks_passphrase(int *pass_len)
goto free_mem;
}

return_str = snp_get_luks_passphrase(url, wid, tee_data, pass_len);
return_str = snp_get_luks_passphrase(url, wid, tee_data,
host_data, pass_len);
} else if (strcmp(tee, "sev") == 0) {
return_str = sev_get_luks_passphrase(pass_len);
}
Expand All @@ -257,7 +266,8 @@ get_luks_passphrase(int *pass_len)
}

static char *
snp_get_luks_passphrase(char *url, char *wid, char *tee_data, int *pass_len)
snp_get_luks_passphrase(char *url, char *wid, char *tee_data, char *host_data,
int *pass_len)
{
char *pass;

Expand All @@ -266,7 +276,7 @@ snp_get_luks_passphrase(char *url, char *wid, char *tee_data, int *pass_len)
return NULL;
}

if (snp_attest(pass, url, wid, tee_data) == 0) {
if (snp_attest(pass, url, wid, tee_data, host_data) == 0) {
*pass_len = strlen(pass);
return pass;
}
Expand Down Expand Up @@ -769,6 +779,7 @@ int main(int argc, char **argv)
char *rlimits;
char **config_argv, **exec_argv;


#ifdef SEV
if (chroot_luks() < 0) {
printf("Couldn't switch to LUKS volume, bailing out\n");
Expand Down
2 changes: 1 addition & 1 deletion init/tee/kbs/kbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ int read_cookie_val(char *, char *);
int json_parse_str(char *, char *, char *);

// kbs_types.c
int kbs_request_marshal(char *, int, char *);
int kbs_request_marshal(char *, int);
int kbs_challenge(CURL *, char *, char *, char *);
int kbs_attest(CURL *, char *, struct snp_report *, BIGNUM *, BIGNUM *, char *);
int kbs_get_key(CURL *, char *, char *, EVP_PKEY *, char *);
Expand Down
10 changes: 8 additions & 2 deletions init/tee/kbs/kbs_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,22 @@ rsa_pkey_decrypt(EVP_PKEY *pkey, char *enc, char **plain_ptr)
{
int rc;
EVP_PKEY_CTX *ctx;
char enc_bin[4096], *plain;
char ciphertext[4096], enc_bin[4096], *plain;
size_t enc_bin_len, secret_plain_len = 4096;

rc = -1;

if (json_parse_str(ciphertext, "ciphertext", enc) < 0) {
printf("Unable to find \"ciphertext\" label from response\n");

return rc;
}

/*
* Decode the hex-encoded string to its byte format.
*/
if (OPENSSL_hexstr2buf_ex((unsigned char *) enc_bin, 4096, &enc_bin_len,
enc, '\0') != 1) {
ciphertext, '\0') != 1) {
printf("Error converting hex to buf\n");

return rc;
Expand Down
9 changes: 5 additions & 4 deletions init/tee/kbs/kbs_curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ kbs_curl_post(CURL *curl, char *url, char *in, char *out, int type)

session_id_label = NULL;
while (cks) {
session_id_label = find_cookie(cks->data, "session_id");
session_id_label = find_cookie(cks->data, "kbs-session-id");

if (session_id_label)
break;
Expand Down Expand Up @@ -118,6 +118,7 @@ kbs_curl_post(CURL *curl, char *url, char *in, char *out, int type)

code = curl_easy_perform(curl);
if (code != CURLE_OK && code != CURLE_WRITE_ERROR) {
printf("cURL error: %s\n", curl_easy_strerror(code));
KBS_CURL_ERR("CURL_EASY_PERFORM");
}

Expand Down Expand Up @@ -150,7 +151,7 @@ kbs_curl_get(CURL *curl, char *url, char *wid, char *out, int type)
* this session ID.
*/
while (cookies != NULL) {
session_id_label = find_cookie(cookies->data, "session_id");
session_id_label = find_cookie(cookies->data, "kbs-session-id");
if (session_id_label)
break;

Expand All @@ -176,7 +177,7 @@ kbs_curl_get(CURL *curl, char *url, char *wid, char *out, int type)
* The location of the KBS key is located at
* $ATTESTATION_URL/kbs/v0/key/$WORKLOAD_ID.
*/
sprintf(full_url, "%s/kbs/v0/key/%s", url, wid);
sprintf(full_url, "%s/kbs/v0/resource/passphrase", url);

if (curl_easy_setopt(curl, CURLOPT_URL, full_url) != CURLE_OK) {
KBS_CURL_ERR("CURLOPT_URL");
Expand Down Expand Up @@ -213,7 +214,7 @@ kbs_curl_set_headers(CURL *curl, char *session)
* Add the session ID cookie if the session ID exists.
*/
if (session) {
sprintf(session_buf, "Cookie: session_id=%s", session);
sprintf(session_buf, "Cookie: kbs-session-id=%s", session);
curl_slist_append(slist, session_buf);
}

Expand Down
12 changes: 7 additions & 5 deletions init/tee/kbs/kbs_types.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ static void kbs_attestation_marshal_tee_pubkey(char *, BIGNUM *, BIGNUM *);
* KBS REQUEST.
*/
int
kbs_request_marshal(char *json_request, int tee, char *workload_id)
kbs_request_marshal(char *json_request, int tee)
{
char *teestr;

Expand All @@ -37,8 +37,7 @@ kbs_request_marshal(char *json_request, int tee, char *workload_id)
* Build the KBS REQUEST JSON string.
*/
sprintf(json_request,
"{\"extra-params\":\"{\\\"workload_id\\\":\\\"%s\\\"}\",\"tee\":\"%s\",\"version\":\"0.0.0\"}",
workload_id,
"{\"extra-params\":\"{}\",\"tee\":\"%s\",\"version\":\"0.0.0\"}",
teestr);

return 0;
Expand Down Expand Up @@ -240,12 +239,15 @@ kbs_attestation_marshal_tee_pubkey(char *json, BIGNUM *mod, BIGNUM *exp)
sprintf(buf, "\"tee-pubkey\":{");
strcat(json, buf);

sprintf(buf, "\"kty\":\"\",");
strcat(json, buf);

sprintf(buf, "\"alg\":\"RSA\",");
strcat(json, buf);

sprintf(buf, "\"k-mod\":\"%s\",", mod_b64);
sprintf(buf, "\"n\":\"%s\",", mod_b64);
strcat(json, buf);

sprintf(buf, "\"k-exp\":\"%s\"},", exp_b64);
sprintf(buf, "\"e\":\"%s\"},", exp_b64);
strcat(json, buf);
}
71 changes: 68 additions & 3 deletions init/tee/snp_attest.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,28 @@
#define NONCE_MAX 1024
#define JSON_MAX 1024
#define GEN_MAX 32
#define HOST_DATA_MAX 32

static int snp_get_report(const uint8_t *, size_t, struct snp_report *);
static int SNP_ATTEST_ERR(char *);
static void json_fmt(char *);
static int b64_decode(char *, unsigned char **, size_t *);
static int b64_decode_len(char *);

int
snp_attest(char *pass, char *url, char *wid, char *tee_data)
snp_attest(char *pass, char *url, char *wid, char *tee_data, char *encoded)
{
CURL *curl;
char nonce[NONCE_MAX], json[JSON_MAX], gen[GEN_MAX];
unsigned char host_data[HOST_DATA_MAX];
struct snp_report report;
EVP_PKEY *pkey;
BIGNUM *n, *e;
unsigned int hash_size;
uint8_t *hash;
size_t host_data_size = HOST_DATA_MAX;

if (kbs_request_marshal(json, TEE_SNP, wid) < 0)
if (kbs_request_marshal(json, TEE_SNP) < 0)
return SNP_ATTEST_ERR("Unable to marshal KBS REQUEST");

curl = curl_easy_init();
Expand All @@ -63,6 +68,12 @@ snp_attest(char *pass, char *url, char *wid, char *tee_data)
if (snp_get_report(hash, hash_size, &report) != EXIT_SUCCESS)
return SNP_ATTEST_ERR("Unable to retrieve attestation report");

if (b64_decode(encoded, (unsigned char **) &host_data,
&host_data_size) < 0)
return SNP_ATTEST_ERR("Unable to decode HOST_DATA string");

memcpy((void *) report.host_data, (void *) host_data, host_data_size);

if (kbs_attest(curl, url, &report, n, e, gen) < 0)
return SNP_ATTEST_ERR("Unable to complete KBS ATTESTATION");

Expand Down Expand Up @@ -150,7 +161,7 @@ snp_get_report(const uint8_t *data, size_t data_sz, struct snp_report *report)
rc = errno;
perror("ioctl");
fprintf(stderr, "errno is %u\n", errno);
fprintf(stderr, "firmware error %#llx\n", guest_req.fw_err);
fprintf(stderr, "firmware error %x\n", guest_req.fw_error);
fprintf(stderr, "report error %x\n", report_resp->status);

goto out_close;
Expand Down Expand Up @@ -221,3 +232,57 @@ json_fmt(char *str)

strcpy(str, cpy);
}

/*
* Safely decode a base64-encoded string.
*/
static int
b64_decode(char *encoded, unsigned char **buf, size_t *len)
{
BIO *bio, *b64;
int decode_len;

decode_len = b64_decode_len(encoded);
*buf = (unsigned char *) malloc(decode_len + 1);
(*buf)[decode_len] = '\0';

bio = BIO_new_mem_buf(encoded, -1);
b64 = BIO_new(BIO_f_base64());
bio = BIO_push(b64, bio);

BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
*len = BIO_read(bio, *buf, strlen(encoded));

if (*len != decode_len)
return -1;

BIO_free_all(bio);

return 0;
}

/*
* Get the length of a base64 decoded string.
*/
static int
b64_decode_len(char *encoded)
{
size_t len, padding;
char last, next_last;

len = strlen(encoded);
padding = 0;

if (len < 2)
return -1;

last = encoded[len - 1];
next_last = encoded[len - 2];

if (last == '=' && next_last == '=')
padding = 2;
else if (last == '=')
padding = 1;

return ((len * 3) / 4) - padding;
}
2 changes: 1 addition & 1 deletion init/tee/snp_attest.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,6 @@ struct msg_report_resp {
};

// snp_attest.c
int snp_attest(char *, char *, char *, char *);
int snp_attest(char *, char *, char *, char *, char *);

#endif /* _SNP_ATTEST */
2 changes: 2 additions & 0 deletions src/vmm/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct TeeConfig {
pub tee: Tee,
pub tee_data: String,
pub attestation_url: String,
pub host_data: String,
}

#[cfg(feature = "tee")]
Expand All @@ -75,6 +76,7 @@ impl Default for TeeConfig {
tee: Tee::Sev,
tee_data: "".to_string(),
attestation_url: "".to_string(),
host_data: "".to_string(),
}
}
}
Expand Down

0 comments on commit be0df60

Please sign in to comment.