From: Steffen Eiden <seiden@linux.ibm.com>
To: Thomas Huth <thuth@redhat.com>,
Janosch Frank <frankja@linux.ibm.com>,
Claudio Imbrenda <imbrenda@linux.ibm.com>,
David Hildenbrand <david@redhat.com>
Cc: kvm@vger.kernel.org, linux-s390@vger.kernel.org
Subject: [kvm-unit-tests PATCH v3 5/5] s390x: uv-guest: Add attestation tests
Date: Tue, 22 Feb 2022 14:54:56 +0000 [thread overview]
Message-ID: <20220222145456.9956-6-seiden@linux.ibm.com> (raw)
In-Reply-To: <20220222145456.9956-1-seiden@linux.ibm.com>
Adds several tests to verify correct error paths of attestation.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
lib/s390x/asm/uv.h | 5 +-
s390x/uv-guest.c | 193 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 196 insertions(+), 2 deletions(-)
diff --git a/lib/s390x/asm/uv.h b/lib/s390x/asm/uv.h
index c330c0f8..e5f7aa72 100644
--- a/lib/s390x/asm/uv.h
+++ b/lib/s390x/asm/uv.h
@@ -108,7 +108,10 @@ struct uv_cb_qui {
u8 reserved88[158 - 136]; /* 0x0088 */
uint16_t max_guest_cpus; /* 0x009e */
u64 uv_feature_indications; /* 0x00a0 */
- u8 reserveda8[200 - 168]; /* 0x00a8 */
+ uint8_t reserveda8[224 - 168]; /* 0x00a8 */
+ uint64_t supp_att_hdr_ver; /* 0x00e0 */
+ uint64_t supp_paf; /* 0x00e8 */
+ uint8_t reservedf0[256 - 240]; /* 0x00f0 */
} __attribute__((packed)) __attribute__((aligned(8)));
struct uv_cb_cgc {
diff --git a/s390x/uv-guest.c b/s390x/uv-guest.c
index 77057bd2..77edbba2 100644
--- a/s390x/uv-guest.c
+++ b/s390x/uv-guest.c
@@ -2,10 +2,11 @@
/*
* Guest Ultravisor Call tests
*
- * Copyright (c) 2020 IBM Corp
+ * Copyright IBM Corp. 2020, 2022
*
* Authors:
* Janosch Frank <frankja@linux.ibm.com>
+ * Steffen Eiden <seiden@linux.ibm.com>
*/
#include <libcflat.h>
@@ -53,6 +54,15 @@ static void test_priv(void)
check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
report_prefix_pop();
+ report_prefix_push("attest");
+ uvcb.cmd = UVC_CMD_ATTESTATION;
+ uvcb.len = sizeof(struct uv_cb_attest);
+ expect_pgm_int();
+ enter_pstate();
+ uv_call_once(0, (uint64_t)&uvcb);
+ check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
+ report_prefix_pop();
+
report_prefix_pop();
}
@@ -111,7 +121,187 @@ static void test_sharing(void)
cc = uv_call(0, (u64)&uvcb);
report(cc == 0 && uvcb.header.rc == UVC_RC_EXECUTED, "unshare");
report_prefix_pop();
+}
+
+#define ARCB_VERSION_NONE 0
+#define ARCB_VERSION_1 0x0100
+#define ARCB_MEAS_NONE 0
+#define ARCB_MEAS_HMAC_SHA512 1
+#define MEASUREMENT_SIZE_HMAC_SHA512 64
+#define PAF_PHKH_ATT (1ULL << 61)
+#define ADDITIONAL_SIZE_PAF_PHKH_ATT 32
+/* arcb with one key slot and no nonce */
+struct uv_arcb_v1 {
+ uint64_t reserved0; /* 0x0000 */
+ uint32_t req_ver; /* 0x0008 */
+ uint32_t req_len; /* 0x000c */
+ uint8_t iv[12]; /* 0x0010 */
+ uint32_t reserved1c; /* 0x001c */
+ uint8_t reserved20[7]; /* 0x0020 */
+ uint8_t nks; /* 0x0027 */
+ uint32_t reserved28; /* 0x0028 */
+ uint32_t sea; /* 0x002c */
+ uint64_t plaint_att_flags; /* 0x0030 */
+ uint32_t meas_alg_id; /* 0x0038 */
+ uint32_t reserved3c; /* 0x003c */
+ uint8_t cpk[160]; /* 0x0040 */
+ uint8_t key_slot[80]; /* 0x00e0 */
+ uint8_t meas_key[64]; /* 0x0130 */
+ uint8_t tag[16]; /* 0x0170 */
+} __attribute__((packed));
+
+struct attest_request_v1 {
+ struct uv_arcb_v1 arcb;
+ uint8_t measurement[MEASUREMENT_SIZE_HMAC_SHA512];
+ uint8_t additional[ADDITIONAL_SIZE_PAF_PHKH_ATT];
+};
+
+static void test_attest_v1(u64 supported_paf)
+{
+ struct uv_cb_attest uvcb = {
+ .header.cmd = UVC_CMD_ATTESTATION,
+ .header.len = sizeof(uvcb),
+ };
+ struct attest_request_v1 *attest_req = (void *)page;
+ struct uv_arcb_v1 *arcb = &attest_req->arcb;
+ int cc;
+
+ memset((void *)page, 0, PAGE_SIZE);
+
+ /*
+ * Create a minimal arcb/uvcb such that FW has everything to start
+ * unsealing the request. However, this unsealing will fail as the
+ * kvm-unit-test framework provides no cryptography functions that
+ * would be needed to seal such requests.
+ */
+ arcb->req_ver = ARCB_VERSION_1;
+ arcb->req_len = sizeof(*arcb);
+ arcb->nks = 1;
+ arcb->sea = sizeof(arcb->meas_key);
+ arcb->plaint_att_flags = PAF_PHKH_ATT;
+ arcb->meas_alg_id = ARCB_MEAS_HMAC_SHA512;
+ uvcb.arcb_addr = (uint64_t)&attest_req->arcb;
+ uvcb.measurement_address = (uint64_t)attest_req->measurement;
+ uvcb.measurement_length = sizeof(attest_req->measurement);
+ uvcb.add_data_address = (uint64_t)attest_req->additional;
+ uvcb.add_data_length = sizeof(attest_req->additional);
+
+ uvcb.continuation_token = 0xff;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0101, "invalid continuation token");
+ uvcb.continuation_token = 0;
+
+ uvcb.user_data_length = sizeof(uvcb.user_data) + 1;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0102, "invalid user data size");
+ uvcb.user_data_length = 0;
+
+ uvcb.arcb_addr = get_ram_size() + PAGE_SIZE;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0103, "invalid address arcb");
+ uvcb.arcb_addr = page;
+
+ /* 0104 - 0105 need an unseal-able request */
+
+ arcb->req_ver = ARCB_VERSION_NONE;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0106, "unsupported version");
+ arcb->req_ver = ARCB_VERSION_1;
+
+ arcb->req_len += 1;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0107, "invalid arcb size 1");
+ arcb->req_len -= 1;
+
+ /*
+ * The arcb needs to grow as well if number of key slots (nks)
+ * is increased. However, this is not the case and there is no explicit
+ * 'too many/less nks for that arcb size' error code -> expect 0x0107
+ */
+ arcb->nks = 2;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0107, "invalid arcb size 2");
+ arcb->nks = 1;
+
+ arcb->nks = 0;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0108, "invalid num key slots");
+ arcb->nks = 1;
+
+ /*
+ * Possible valid size (when using nonce).
+ * However, req_len too small to host a nonce
+ */
+ arcb->sea = 80;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0109, "invalid encrypted size 1");
+ arcb->sea = 17;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x0109, "invalid encrypted size 2");
+ arcb->sea = 64;
+
+ arcb->plaint_att_flags = supported_paf ^ GENMASK_ULL(63, 0);
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x010a, "invalid flag");
+ arcb->plaint_att_flags = PAF_PHKH_ATT;
+
+ arcb->meas_alg_id = ARCB_MEAS_NONE;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x010b, "invalid measurement algorithm");
+ arcb->meas_alg_id = ARCB_MEAS_HMAC_SHA512;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x010c, "unable unseal");
+
+ uvcb.measurement_length = 0;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x010d, "invalid measurement size");
+ uvcb.measurement_length = sizeof(attest_req->measurement);
+
+ uvcb.add_data_length = 0;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc == 1 && uvcb.header.rc == 0x010e, "invalid additional size");
+ uvcb.add_data_length = sizeof(attest_req->additional);
+}
+
+static void test_attest(void)
+{
+ struct uv_cb_attest uvcb = {
+ .header.cmd = UVC_CMD_ATTESTATION,
+ .header.len = sizeof(uvcb),
+ };
+ const struct uv_cb_qui *uvcb_qui = uv_get_query_data();
+ int cc;
+
+ report_prefix_push("attest");
+
+ if (!uv_query_test_call(BIT_UVC_CMD_ATTESTATION)) {
+ report_skip("Attestation not supported.");
+ goto done;
+ }
+
+ /* Verify that the UV supports at least one header version */
+ report(uvcb_qui->supp_att_hdr_ver, "has hdr support");
+
+ memset((void *)page, 0, PAGE_SIZE);
+
+ uvcb.header.len -= 1;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc && uvcb.header.rc == UVC_RC_INV_LEN, "invalid uvcb size 1");
+ uvcb.header.len += 1;
+
+ uvcb.header.len += 1;
+ cc = uv_call(0, (uint64_t)&uvcb);
+ report(cc && uvcb.header.rc == UVC_RC_INV_LEN, "invalid uvcb size 2");
+ uvcb.header.len -= 1;
+
+ report_prefix_push("v1");
+ if (test_bit_inv(0, &uvcb_qui->supp_att_hdr_ver))
+ test_attest_v1(uvcb_qui->supp_paf);
+ else
+ report_skip("Attestation version 1 not supported");
+ report_prefix_pop();
+done:
report_prefix_pop();
}
@@ -193,6 +383,7 @@ int main(void)
test_invalid();
test_query();
test_sharing();
+ test_attest();
free_page((void *)page);
done:
report_prefix_pop();
--
2.30.2
next prev parent reply other threads:[~2022-02-22 14:55 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-02-22 14:54 [kvm-unit-tests PATCH v3 0/5] s390x: Attestation tests Steffen Eiden
2022-02-22 14:54 ` [kvm-unit-tests PATCH v3 1/5] s390x: uv-host: Add attestation test Steffen Eiden
2022-03-23 8:18 ` Janosch Frank
2022-02-22 14:54 ` [kvm-unit-tests PATCH v3 2/5] s390x: lib: Add QUI getter Steffen Eiden
2022-02-23 15:37 ` Claudio Imbrenda
2022-03-23 8:07 ` Janosch Frank
2022-02-22 14:54 ` [kvm-unit-tests PATCH v3 3/5] s390x: uv-guest: remove duplicated checks Steffen Eiden
2022-02-22 14:54 ` [kvm-unit-tests PATCH v3 4/5] s390x: uv-guest: add share bit test Steffen Eiden
2022-02-23 15:36 ` Claudio Imbrenda
2022-03-23 8:16 ` Janosch Frank
2022-02-22 14:54 ` Steffen Eiden [this message]
2022-02-23 15:48 ` [kvm-unit-tests PATCH v3 5/5] s390x: uv-guest: Add attestation tests Claudio Imbrenda
2022-03-23 8:39 ` Janosch Frank
2022-03-23 10:07 ` Claudio Imbrenda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220222145456.9956-6-seiden@linux.ibm.com \
--to=seiden@linux.ibm.com \
--cc=david@redhat.com \
--cc=frankja@linux.ibm.com \
--cc=imbrenda@linux.ibm.com \
--cc=kvm@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.