Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
Automatically use /dev/sev vs /dev/sev-guest and appropriate IOCTLs t… (
Browse files Browse the repository at this point in the history
#22)

* Automatically use one of the PSP device names: /dev/sev or /dev/sev-guest as well as appropriate IOCTLs to support transition from 5.15 to 6.* Linux kernels.

Signed-off-by: Ken Gordon <[email protected]>

* Use helpers for the fake report tool.
* Add a standalone report decoder.
* Tidy the report data string decode so as to avoid trailing rubbish. Support full size report data.

Signed-off-by: Ken Gordon <[email protected]>
  • Loading branch information
KenGordon authored Apr 6, 2023
1 parent a8cbb5f commit c85bfab
Show file tree
Hide file tree
Showing 15 changed files with 578 additions and 300 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ The skr sidecar can be queried by application containers hosted in the same pod

The ``examples/skr`` shows an example of how the skr sidecar can be deployed and tested within a confidential container group on ACI.

## Fetching an attestion report.
``tools/get-snp-report provides a tool which will return an SNP attestation report from the AMD PSP via linux IOCTLs. it can take a hex encoded report data value on the command line. The output is a hex encoded binary object. If piped through hex2report it can be read by people. There are two implementations inside the one tool to support the different IOCTLs requirements between linux 5.15 and 6.1 and later.

### Third-party code
We modified the [AES unwrap key without padding method](https://github.com/NickBall/go-aes-key-wrap/blob/master/keywrap.go) to implement the aes key unwrap with padding method.

Expand All @@ -21,7 +24,7 @@ The encrypted filesystem sidecar uses the SKR library to release key material fr

The ``examples/encfs`` shows an example of how the encrypted filesystem sidecar can be deployed within a confidential container group on ACI.
## Dependencies:
- Golang 1.16 or later
- Golang 1.19 or later
- Docker
- GCC 9.4.0 or later

Expand Down
10 changes: 7 additions & 3 deletions tools/get-snp-report/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
CFLAGS:=-O2 -Wall
LDFLAGS:=-static -s # strip C binaries

all: bin/get-snp-report bin/get-fake-snp-report bin/verbose-report
all: bin/get-snp-report bin/get-fake-snp-report bin/verbose-report bin/hex2report

bin/get-fake-snp-report: get-fake-snp-report.o
bin/hex2report: hex2report.o helpers.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

bin/get-snp-report: get-snp-report.o
bin/get-fake-snp-report: get-fake-snp-report.o helpers.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

bin/get-snp-report: get-snp-report.o get-snp-report5.o get-snp-report6.o helpers.o
@mkdir -p bin
$(CC) $(LDFLAGS) -o $@ $^

Expand Down
9 changes: 9 additions & 0 deletions tools/get-snp-report/fetch5.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */

#pragma once

bool fetchAttestationReport5(const char* report_data_hexstring, void **snp_report);

// does /dev/sev exists. This is where the PSP is exposed in 5.15.*
bool supportsDevSev();
10 changes: 10 additions & 0 deletions tools/get-snp-report/fetch6.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* Copyright (c) Microsoft Corporation.
Licensed under the MIT License. */

#pragma once

bool fetchAttestationReport6(const char* report_data_hexstring, void **snp_report);

// 6.1 linux exposees the PSP via /dev/sev-guest

bool supportsDevSevGuest();
82 changes: 4 additions & 78 deletions tools/get-snp-report/get-fake-snp-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,89 +11,15 @@
#include <stdbool.h>
#include <stdlib.h>

#include "helpers.h"
#include "snp-psp.h"

#define PRINT_VAL(ptr, field) printBytes(#field, (const uint8_t *)&(ptr->field), sizeof(ptr->field), true)
#define PRINT_BYTES(ptr, field) printBytes(#field, (const uint8_t *)&(ptr->field), sizeof(ptr->field), false)

// Helper functions
uint8_t* decodeHexString(char *hexstring)
{
size_t len = strlen(hexstring);
uint8_t *byte_array = (uint8_t*) malloc(strlen(hexstring)*sizeof(uint8_t));

for (size_t i = 0; i < len; i+=2) {
sscanf(hexstring, "%2hhx", &byte_array[i/2]);
hexstring += 2;
}

return byte_array;
}

char* encodeHexToString(uint8_t byte_array[], size_t len)
{
char* hexstring = (char*) malloc((2*len+1)*sizeof(char));

for (size_t i = 0; i < len; i++)
sprintf(&hexstring[i*2], "%02x", byte_array[i]);

hexstring[2*len] = '\0'; // string padding character
return hexstring;
}

void printBytes(const char *desc, const uint8_t *data, size_t len, bool swap)
{
fprintf(stderr, " %s: ", desc);
int padding = 20 - strlen(desc);
if (padding < 0)
padding = 0;
for (int count = 0; count < padding; count++)
putchar(' ');

for (size_t pos = 0; pos < len; pos++) {
fprintf(stderr, "%02x", data[swap ? len - pos - 1 : pos]);
if (pos % 32 == 31)
printf("\n ");
else if (pos % 16 == 15)
putchar(' ');
}
fprintf(stderr, "\n");
}

void printReport(const snp_attestation_report *r)
{
PRINT_VAL(r, version);
PRINT_VAL(r, guest_svn);
PRINT_VAL(r, policy);
PRINT_VAL(r, family_id);
PRINT_VAL(r, image_id);
PRINT_VAL(r, vmpl);
PRINT_VAL(r, signature_algo);
PRINT_BYTES(r, platform_version);
PRINT_BYTES(r, platform_info);
PRINT_VAL(r, author_key_en);
PRINT_VAL(r, reserved1);
PRINT_BYTES(r, report_data);
PRINT_BYTES(r, measurement);
PRINT_BYTES(r, host_data);
PRINT_BYTES(r, id_key_digest);
PRINT_BYTES(r, author_key_digest);
PRINT_BYTES(r, report_id);
PRINT_BYTES(r, report_id_ma);
PRINT_VAL(r, reported_tcb);
PRINT_BYTES(r, reserved2);
PRINT_BYTES(r, chip_id);
PRINT_BYTES(r, reserved3);
PRINT_BYTES(r, signature);
}


bool fetchAttestationReport(char report_data_hexstring[], char host_data_hexstring[], void **snp_report)
{

snp_attestation_report attestation_report;

uint8_t *default_report = decodeHexString("01000000010000001f00030000000000010000000000000000000000000000000200000000000000000000000000000000000000010000000000000000000028010000000000000000000000000000007ab000a323b3c873f5b81bbe584e7c1a26bcf40dc27e00f8e0d144b1ed2d14f10000000000000000000000000000000000000000000000000000000000000000e29af700e85b39996fa38226d2804b78cad746ffef4477360a61b47874bdecd640f9d32f5ff64a55baad3c545484d9ed28603a3ea835a83bd688b0ec1dcb36b6b8c22412e5b63115b75db8628b989bc598c475ca5f7683e8d351e7e789a1baff19041750567161ad52bf0d152bd76d7c6f313d0a0fd72d0089692c18f521155800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040aea62690b08eb6d680392c9a9b3db56a9b3cc44083b9da31fb88bcfc493407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000028000000000000000000000000000000000000000000000000e6c86796cd44b0bc6b7c0d4fdab33e2807e14b5fc4538b3750921169d97bcf4447c7d3ab2a7c25f74c1641e2885c1011d025cc536f5c9a2504713136c7877f480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003131c0f3e7be5c6e400f22404596e1874381e99d03de45ef8b97eee0a0fa93a4911550330343f14dddbbd6c0db83744f000000000000000000000000000000000000000000000000db07c83c5e6162c2387f3b76cd547672657f6a5df99df98efee7c15349320d83e086c5003ec43050a9b18d1c39dedc340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
uint8_t *default_report = decodeHexString("01000000010000001f00030000000000010000000000000000000000000000000200000000000000000000000000000000000000010000000000000000000028010000000000000000000000000000007ab000a323b3c873f5b81bbe584e7c1a26bcf40dc27e00f8e0d144b1ed2d14f10000000000000000000000000000000000000000000000000000000000000000e29af700e85b39996fa38226d2804b78cad746ffef4477360a61b47874bdecd640f9d32f5ff64a55baad3c545484d9ed28603a3ea835a83bd688b0ec1dcb36b6b8c22412e5b63115b75db8628b989bc598c475ca5f7683e8d351e7e789a1baff19041750567161ad52bf0d152bd76d7c6f313d0a0fd72d0089692c18f521155800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040aea62690b08eb6d680392c9a9b3db56a9b3cc44083b9da31fb88bcfc493407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000028000000000000000000000000000000000000000000000000e6c86796cd44b0bc6b7c0d4fdab33e2807e14b5fc4538b3750921169d97bcf4447c7d3ab2a7c25f74c1641e2885c1011d025cc536f5c9a2504713136c7877f480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003131c0f3e7be5c6e400f22404596e1874381e99d03de45ef8b97eee0a0fa93a4911550330343f14dddbbd6c0db83744f000000000000000000000000000000000000000000000000db07c83c5e6162c2387f3b76cd547672657f6a5df99df98efee7c15349320d83e086c5003ec43050a9b18d1c39dedc340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 0);

memcpy((uint8_t*)&attestation_report, default_report, sizeof(snp_attestation_report));
memset(attestation_report.report_data, 0 , 64);
Expand All @@ -103,10 +29,10 @@ bool fetchAttestationReport(char report_data_hexstring[], char host_data_hexstri
// the report data is passed as a hexstring which needs to be decoded into an array of
// unsigned bytes

uint8_t *reportData = decodeHexString(report_data_hexstring);
uint8_t *reportData = decodeHexString(report_data_hexstring, 64);
memcpy(attestation_report.report_data, reportData , strlen(report_data_hexstring)/2);

uint8_t *hostData = decodeHexString(host_data_hexstring);
uint8_t *hostData = decodeHexString(host_data_hexstring, 32);
memcpy(attestation_report.host_data, hostData , strlen(host_data_hexstring)/2);

*snp_report = (snp_attestation_report *) malloc (sizeof(snp_attestation_report));
Expand Down
159 changes: 16 additions & 143 deletions tools/get-snp-report/get-snp-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,161 +11,34 @@
#include <stdbool.h>
#include <stdlib.h>

#include "snp-psp.h"
#include "snp-attestation.h"
#include "fetch5.h"
#include "fetch6.h"

#define PRINT_VAL(ptr, field) printBytes(#field, (const uint8_t *)&(ptr->field), sizeof(ptr->field), true)
#define PRINT_BYTES(ptr, field) printBytes(#field, (const uint8_t *)&(ptr->field), sizeof(ptr->field), false)

// Helper functions
uint8_t* decodeHexString(char *hexstring)
{
size_t len = strlen(hexstring);
uint8_t *byte_array = (uint8_t*) malloc(strlen(hexstring)*sizeof(uint8_t));

for (size_t i = 0; i < len; i+=2) {
sscanf(hexstring, "%2hhx", &byte_array[i/2]);
hexstring += 2;
}

return byte_array;
}

char* encodeHexToString(uint8_t byte_array[], size_t len)
{
char* hexstring = (char*) malloc((2*len+1)*sizeof(char));

for (size_t i = 0; i < len; i++)
sprintf(&hexstring[i*2], "%02x", byte_array[i]);

hexstring[2*len] = '\0'; // string padding character
return hexstring;
}

void printBytes(const char *desc, const uint8_t *data, size_t len, bool swap)
{
fprintf(stderr, " %s: ", desc);
int padding = 20 - strlen(desc);
if (padding < 0)
padding = 0;
for (int count = 0; count < padding; count++)
putchar(' ');

for (size_t pos = 0; pos < len; pos++) {
fprintf(stderr, "%02x", data[swap ? len - pos - 1 : pos]);
if (pos % 32 == 31)
printf("\n ");
else if (pos % 16 == 15)
putchar(' ');
}
fprintf(stderr, "\n");
}

void printReport(const snp_attestation_report *r)
{
PRINT_VAL(r, version);
PRINT_VAL(r, guest_svn);
PRINT_VAL(r, policy);
PRINT_VAL(r, family_id);
PRINT_VAL(r, image_id);
PRINT_VAL(r, vmpl);
PRINT_VAL(r, signature_algo);
PRINT_BYTES(r, platform_version);
PRINT_BYTES(r, platform_info);
PRINT_VAL(r, author_key_en);
PRINT_VAL(r, reserved1);
PRINT_BYTES(r, report_data);
PRINT_BYTES(r, measurement);
PRINT_BYTES(r, host_data);
PRINT_BYTES(r, id_key_digest);
PRINT_BYTES(r, author_key_digest);
PRINT_BYTES(r, report_id);
PRINT_BYTES(r, report_id_ma);
PRINT_VAL(r, reported_tcb);
PRINT_BYTES(r, reserved2);
PRINT_BYTES(r, chip_id);
PRINT_BYTES(r, reserved3);
PRINT_BYTES(r, signature);
}

bool fetchAttestationReport(char report_data_hexstring[], void **snp_report)
{
msg_report_req msg_report_in;
msg_response_resp msg_report_out;

int fd, rc;

struct sev_snp_guest_request payload = {
.req_msg_type = SNP_MSG_REPORT_REQ,
.rsp_msg_type = SNP_MSG_REPORT_RSP,
.msg_version = 1,
.request_len = sizeof(msg_report_in),
.request_uaddr = (uint64_t) (void*) &msg_report_in,
.response_len = sizeof(msg_report_out),
.response_uaddr = (uint64_t) (void*) &msg_report_out,
.error = 0
};

memset((void*) &msg_report_in, 0, sizeof(msg_report_in));
memset((void*) &msg_report_out, 0, sizeof(msg_report_out));

// MAA expects a SHA-256. So we use 32 bytes as size instead of msg_report_in.report_data
// the report data is passed as a hexstring which needs to be decoded into an array of
// unsigned bytes
uint8_t *reportData = decodeHexString(report_data_hexstring);
memcpy(msg_report_in.report_data, reportData, 32);

// open the file descriptor of the PSP
fd = open("/dev/sev", O_RDWR | O_CLOEXEC);

if (fd < 0) {
fprintf(stdout, "Failed to open /dev/sev\n");
return false;
}

// issue the custom SEV_SNP_GUEST_MSG_REPORT sys call to the sev driver
rc = ioctl(fd, SEV_SNP_GUEST_MSG_REPORT, &payload);

if (rc < 0) {
fprintf(stdout, "Failed to issue ioctl SEV_SNP_GUEST_MSG_REPORT\n");
return false;
}

#ifdef DEBUG_OUTPUT
fprintf(stderr, "Response header:\n");
uint8_t *hdr = (uint8_t*) &msg_report_out;

for (size_t i = 0; i < 32; i++) {
fprintf(stderr, "%02x", hdr[i]);
if (i % 16 == 15)
fprintf(stderr, "\n");
else
fprintf(stderr, " ");
}
fprintf(stderr, "Attestation report:\n");
printReport(&msg_report_out.report);
#endif

*snp_report = (snp_attestation_report *) malloc (sizeof(snp_attestation_report));
memcpy(*snp_report, &msg_report_out.report, sizeof(snp_attestation_report));

return true;
}

// Main expects the hex string representation of the report data as the only argument
// Prints the raw binary format of the report so it can be consumed by the tools under
// the directory internal/guest/attestation
int main(int argc, char *argv[])
{
bool success;
bool success = false;
uint8_t *snp_report_hex;
const char *report_data_hexstring = "";

if (argc > 1) {
report_data_hexstring = argv[1];
}

if (argc > 1) {
success = fetchAttestationReport(argv[1], (void*) &snp_report_hex);
} else {
success = fetchAttestationReport("", (void*) &snp_report_hex);
if (supportsDevSev()) {
success = fetchAttestationReport5(report_data_hexstring, (void*) &snp_report_hex);
} else if (supportsDevSevGuest()) {
success = fetchAttestationReport6(report_data_hexstring, (void*) &snp_report_hex);
} else {
fprintf(stderr, "No supported SNP device found\n");
}

if (success == true) {
if (success) {
for (size_t i = 0; i < sizeof(snp_attestation_report); i++) {
fprintf(stdout, "%02x", (uint8_t) snp_report_hex[i]);
}
Expand Down
Loading

0 comments on commit c85bfab

Please sign in to comment.