From: Joey Gouly <joey.gouly@arm.com>
To: Andrew Jones <andrew.jones@linux.dev>, <kvmarm@lists.linux.dev>,
<kvm@vger.kernel.org>
Cc: <joey.gouly@arm.com>, Alexandru Elisei <alexandru.elisei@arm.com>,
Christoffer Dall <christoffer.dall@arm.com>,
Fuad Tabba <tabba@google.com>,
Jean-Philippe Brucker <jean-philippe@linaro.org>,
Joey Gouly <Joey.Gouly@arm.com>, Marc Zyngier <maz@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Oliver Upton <oliver.upton@linux.dev>,
Paolo Bonzini <pbonzini@redhat.com>,
Quentin Perret <qperret@google.com>,
Steven Price <steven.price@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
"Thomas Huth" <thuth@redhat.com>, Will Deacon <will@kernel.org>,
Zenghui Yu <yuzenghui@huawei.com>, <linux-coco@lists.linux.dev>,
<kvmarm@lists.cs.columbia.edu>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>,
Mate Toth-Pal <mate.toth-pal@arm.com>
Subject: [RFC kvm-unit-tests 22/27] arm: Add a library to verify tokens using the QCBOR library
Date: Fri, 27 Jan 2023 11:41:03 +0000 [thread overview]
Message-ID: <20230127114108.10025-23-joey.gouly@arm.com> (raw)
In-Reply-To: <20230127114108.10025-1-joey.gouly@arm.com>
From: Mate Toth-Pal <mate.toth-pal@arm.com>
Add a library wrapper around the QCBOR for parsing the Arm CCA attestation
tokens.
Signed-off-by: Mate Toth-Pal <mate.toth-pal@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
---
arm/Makefile.arm64 | 7 +-
lib/token_verifier/attest_defines.h | 50 +++
lib/token_verifier/token_dumper.c | 158 ++++++++
lib/token_verifier/token_dumper.h | 15 +
lib/token_verifier/token_verifier.c | 591 ++++++++++++++++++++++++++++
lib/token_verifier/token_verifier.h | 77 ++++
6 files changed, 897 insertions(+), 1 deletion(-)
create mode 100644 lib/token_verifier/attest_defines.h
create mode 100644 lib/token_verifier/token_dumper.c
create mode 100644 lib/token_verifier/token_dumper.h
create mode 100644 lib/token_verifier/token_verifier.c
create mode 100644 lib/token_verifier/token_verifier.h
diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
index 8d450de9..f57d0a95 100644
--- a/arm/Makefile.arm64
+++ b/arm/Makefile.arm64
@@ -11,6 +11,7 @@ arch_LDFLAGS += -z notext
CFLAGS += -mstrict-align
CFLAGS += -I $(SRCDIR)/lib/qcbor/inc
CFLAGS += -DQCBOR_DISABLE_FLOAT_HW_USE -DQCBOR_DISABLE_PREFERRED_FLOAT -DUSEFULBUF_DISABLE_ALL_FLOAT
+CFLAGS += -I $(SRCDIR)/lib/token_verifier
mno_outline_atomics := $(call cc-option, -mno-outline-atomics, "")
CFLAGS += $(mno_outline_atomics)
@@ -28,6 +29,9 @@ cflatobjs += lib/arm64/spinlock.o
cflatobjs += lib/arm64/gic-v3-its.o lib/arm64/gic-v3-its-cmd.o
cflatobjs += lib/arm64/rsi.o
cflatobjs += lib/qcbor/src/qcbor_decode.o lib/qcbor/src/UsefulBuf.o
+cflatobjs += lib/token_verifier/token_verifier.o
+cflatobjs += lib/token_verifier/token_dumper.o
+
OBJDIRS += lib/arm64
@@ -44,4 +48,5 @@ include $(SRCDIR)/$(TEST_DIR)/Makefile.common
arch_clean: arm_clean
$(RM) lib/arm64/.*.d \
- lib/qcbor/src/.*.d
+ lib/qcbor/src/.*.d \
+ lib/token_verifier/.*.d
diff --git a/lib/token_verifier/attest_defines.h b/lib/token_verifier/attest_defines.h
new file mode 100644
index 00000000..daf51c5f
--- /dev/null
+++ b/lib/token_verifier/attest_defines.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+
+#ifndef __ATTEST_DEFINES_H__
+#define __ATTEST_DEFINES_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TAG_COSE_SIGN1 (18)
+#define TAG_CCA_TOKEN (399)
+
+#define CCA_PLAT_TOKEN (44234) /* 0xACCA */
+#define CCA_REALM_DELEGATED_TOKEN (44241)
+
+/* CCA Platform Attestation Token */
+#define CCA_PLAT_CHALLENGE (10) /* EAT nonce */
+#define CCA_PLAT_INSTANCE_ID (256) /* EAT ueid */
+#define CCA_PLAT_PROFILE (265) /* EAT profile */
+#define CCA_PLAT_SECURITY_LIFECYCLE (2395)
+#define CCA_PLAT_IMPLEMENTATION_ID (2396)
+#define CCA_PLAT_SW_COMPONENTS (2399)
+#define CCA_PLAT_VERIFICATION_SERVICE (2400)
+#define CCA_PLAT_CONFIGURATION (2401)
+#define CCA_PLAT_HASH_ALGO_ID (2402)
+
+/* CCA Realm Delegated Attestation Token */
+#define CCA_REALM_CHALLENGE (10) /* EAT nonce */
+#define CCA_REALM_PERSONALIZATION_VALUE (44235)
+#define CCA_REALM_HASH_ALGO_ID (44236)
+#define CCA_REALM_PUB_KEY (44237)
+#define CCA_REALM_INITIAL_MEASUREMENT (44238)
+#define CCA_REALM_EXTENSIBLE_MEASUREMENTS (44239)
+#define CCA_REALM_PUB_KEY_HASH_ALGO_ID (44240)
+
+/* Software components */
+#define CCA_SW_COMP_MEASUREMENT_VALUE (2)
+#define CCA_SW_COMP_VERSION (4)
+#define CCA_SW_COMP_SIGNER_ID (5)
+#define CCA_SW_COMP_HASH_ALGORITHM (6)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ATTEST_DEFINES_H__ */
diff --git a/lib/token_verifier/token_dumper.c b/lib/token_verifier/token_dumper.c
new file mode 100644
index 00000000..15f17956
--- /dev/null
+++ b/lib/token_verifier/token_dumper.c
@@ -0,0 +1,158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+#include "attest_defines.h"
+#include "token_dumper.h"
+
+#define COLUMN_WIDTH "20"
+
+void print_raw_token(const char *token, size_t size)
+{
+ int i;
+ char byte;
+
+ printf("\r\nCopy paste token to www.cbor.me\r\n");
+ for (i = 0; i < size; ++i) {
+ byte = token[i];
+ if (byte == 0)
+ printf("0x%#02x ", byte);
+ else
+ printf("0x%02x ", byte);
+ if (((i + 1) % 8) == 0)
+ printf("\r\n");
+ }
+ printf("\r\n");
+}
+
+static void print_indent(int indent_level)
+{
+ int i;
+
+ for (i = 0; i < indent_level; ++i) {
+ printf(" ");
+ }
+}
+
+static void print_byte_string(const char *name, int index,
+ struct q_useful_buf_c buf)
+{
+ int i;
+
+ printf("%-"COLUMN_WIDTH"s (#%d) = [", name, index);
+ for (i = 0; i < buf.len; ++i) {
+ printf("%02x", ((uint8_t *)buf.ptr)[i]);
+ }
+ printf("]\r\n");
+}
+
+static void print_text(const char *name, int index, struct q_useful_buf_c buf)
+{
+ int i;
+
+ printf("%-"COLUMN_WIDTH"s (#%d) = \"", name, index);
+ for (i = 0; i < buf.len; ++i) {
+ printf("%c", ((uint8_t *)buf.ptr)[i]);
+ }
+ printf("\"\r\n");
+}
+
+static void print_claim(struct claim_t *claim, int indent_level)
+{
+ print_indent(indent_level);
+ if (claim->present) {
+ switch (claim->type) {
+ case CLAIM_INT64:
+ printf("%-"COLUMN_WIDTH"s (#%" PRId64 ") = %" PRId64
+ "\r\n", claim->title,
+ claim->key, claim->int_data);
+ break;
+ case CLAIM_BOOL:
+ printf("%-"COLUMN_WIDTH"s (#%" PRId64 ") = %s\r\n",
+ claim->title, claim->key,
+ claim->bool_data?"true":"false");
+ break;
+ case CLAIM_BSTR:
+ print_byte_string(claim->title, claim->key,
+ claim->buffer_data);
+ break;
+ case CLAIM_TEXT:
+ print_text(claim->title, claim->key,
+ claim->buffer_data);
+ break;
+ default:
+ printf("* Internal error at %s:%d.\r\n", __FILE__,
+ (int)__LINE__);
+ break;
+ }
+ } else {
+ printf("* Missing%s claim with key: %" PRId64 " (%s)\r\n",
+ claim->mandatory?" mandatory":"",
+ claim->key, claim->title);
+ }
+}
+
+static void print_cose_sign1_wrapper(const char *token_type,
+ struct claim_t *cose_sign1_wrapper)
+{
+ printf("\r\n== %s Token cose header:\r\n", token_type);
+ print_claim(cose_sign1_wrapper + 0, 0);
+ /* Don't print wrapped token bytestring */
+ print_claim(cose_sign1_wrapper + 2, 0);
+ printf("== End of %s Token cose header\r\n\r\n", token_type);
+}
+
+void print_token(struct attestation_claims *claims)
+{
+ int i;
+
+ print_cose_sign1_wrapper("Realm", claims->realm_cose_sign1_wrapper);
+
+ printf("\r\n== Realm Token:\r\n");
+ /* print the claims except the last one. That is printed in detail
+ * below.
+ */
+ for (i = 0; i < CLAIM_COUNT_REALM_TOKEN; ++i) {
+ struct claim_t *claim = claims->realm_token_claims + i;
+
+ print_claim(claim, 0);
+ }
+
+ printf("%-"COLUMN_WIDTH"s (#%d)\r\n", "Realm measurements",
+ CCA_REALM_EXTENSIBLE_MEASUREMENTS);
+ for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) {
+ struct claim_t *claim = claims->realm_measurement_claims + i;
+
+ print_claim(claim, 1);
+ }
+ printf("== End of Realm Token.\r\n");
+
+ print_cose_sign1_wrapper("Platform", claims->plat_cose_sign1_wrapper);
+
+ printf("\r\n== Platform Token:\r\n");
+ for (i = 0; i < CLAIM_COUNT_PLATFORM_TOKEN; ++i) {
+ struct claim_t *claim = claims->plat_token_claims + i;
+
+ print_claim(claim, 0);
+ }
+ printf("== End of Platform Token\r\n\r\n");
+
+ printf("\r\n== Platform Token SW components:\r\n");
+
+ for (i = 0; i < MAX_SW_COMPONENT_COUNT; ++i) {
+ struct sw_component_t *component =
+ claims->sw_component_claims + i;
+
+ if (component->present) {
+ printf(" SW component #%d:\r\n", i);
+ for (int j = 0; j < CLAIM_COUNT_SW_COMPONENT; ++j) {
+ print_claim(component->claims + j, 2);
+ }
+ }
+ }
+ printf("== End of Platform Token SW components\r\n\r\n");
+}
diff --git a/lib/token_verifier/token_dumper.h b/lib/token_verifier/token_dumper.h
new file mode 100644
index 00000000..96cc0744
--- /dev/null
+++ b/lib/token_verifier/token_dumper.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+
+#ifndef __TOKEN_DUMPER_H__
+#define __TOKEN_DUMPER_H__
+
+#include "token_verifier.h"
+
+void print_raw_token(const char *token, size_t size);
+void print_token(struct attestation_claims *claims);
+
+#endif /* __TOKEN_DUMPER_H__ */
diff --git a/lib/token_verifier/token_verifier.c b/lib/token_verifier/token_verifier.c
new file mode 100644
index 00000000..ba2a89f6
--- /dev/null
+++ b/lib/token_verifier/token_verifier.c
@@ -0,0 +1,591 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+
+#include <libcflat.h>
+#include <inttypes.h>
+#include <qcbor/qcbor_decode.h>
+#include <qcbor/qcbor_spiffy_decode.h>
+#include "attest_defines.h"
+#include "token_verifier.h"
+#include "token_dumper.h"
+
+#define SHA256_SIZE 32
+#define SHA512_SIZE 64
+
+#define RETURN_ON_DECODE_ERROR(p_context) \
+ do { \
+ QCBORError ret; \
+ ret = QCBORDecode_GetError(p_context); \
+ if (ret != QCBOR_SUCCESS) { \
+ printf("QCBOR decode failed with error at %s:%d." \
+ " err = %d\r\n", \
+ __FILE__, (int)__LINE__, (int)ret); \
+ return TOKEN_VERIFICATION_ERR_QCBOR(ret); \
+ } \
+ } while (0)
+
+static void init_claim(struct claim_t *claim,
+ bool mandatory, enum claim_data_type type,
+ int64_t key, const char *title, bool present)
+{
+ claim->mandatory = mandatory;
+ claim->type = type;
+ claim->key = key;
+ claim->title = title;
+ claim->present = present;
+}
+
+static int init_cose_wrapper_claim(struct claim_t *cose_sign1_wrapper)
+{
+ struct claim_t *c;
+
+ /* The cose wrapper looks like the following:
+ * - Protected header (bytestring).
+ * - Unprotected header: might contain 0 items. This is a map. Due to
+ * the way this thing is implemented, it is not in the below list,
+ * but is handled in the verify_token_cose_sign1_wrapping
+ * function.
+ * - Payload: Platform token (bytestring). The content is passed for
+ * verify_platform_token.
+ * - Signature.
+ */
+ c = cose_sign1_wrapper;
+ /* This structure is in an array, so the key is not used */
+ init_claim(c++, true, CLAIM_BSTR, 0, "Protected header", false);
+ init_claim(c++, true, CLAIM_BSTR, 0, "Platform token payload", false);
+ init_claim(c++, true, CLAIM_BSTR, 0, "Signature", false);
+ if (c > cose_sign1_wrapper + CLAIM_COUNT_COSE_SIGN1_WRAPPER) {
+ return TOKEN_VERIFICATION_ERR_INIT_ERROR;
+ }
+ return 0;
+}
+
+static int init_claims(struct attestation_claims *attest_claims)
+{
+ int i;
+ int ret;
+ struct claim_t *c;
+ /* TODO: All the buffer overwrite checks are happening too late.
+ * Either remove, or find a better way.
+ */
+ c = attest_claims->realm_token_claims;
+ init_claim(c++, true, CLAIM_BSTR, CCA_REALM_CHALLENGE, "Realm challenge", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_REALM_PERSONALIZATION_VALUE, "Realm personalization value", false);
+ init_claim(c++, true, CLAIM_TEXT, CCA_REALM_HASH_ALGO_ID, "Realm hash algo id", false);
+ init_claim(c++, true, CLAIM_TEXT, CCA_REALM_PUB_KEY_HASH_ALGO_ID, "Realm public key hash algo id", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_REALM_PUB_KEY, "Realm signing public key", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_REALM_INITIAL_MEASUREMENT, "Realm initial measurement", false);
+ /* Realm extensible measurements are not present here as they are
+ * encoded as a CBOR array, and it is handled specially in
+ * verify_realm_token().
+ */
+ if (c > attest_claims->realm_token_claims + CLAIM_COUNT_REALM_TOKEN) {
+ return TOKEN_VERIFICATION_ERR_INIT_ERROR;
+ }
+
+ ret = init_cose_wrapper_claim(attest_claims->realm_cose_sign1_wrapper);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = init_cose_wrapper_claim(attest_claims->plat_cose_sign1_wrapper);
+ if (ret != 0) {
+ return ret;
+ }
+
+ c = attest_claims->plat_token_claims;
+ init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_CHALLENGE, "Challenge", false);
+ init_claim(c++, false, CLAIM_TEXT, CCA_PLAT_VERIFICATION_SERVICE, "Verification service", false);
+ init_claim(c++, true, CLAIM_TEXT, CCA_PLAT_PROFILE, "Profile", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_INSTANCE_ID, "Instance ID", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_IMPLEMENTATION_ID, "Implementation ID", false);
+ init_claim(c++, true, CLAIM_INT64, CCA_PLAT_SECURITY_LIFECYCLE, "Lifecycle", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_CONFIGURATION, "Configuration", false);
+ init_claim(c++, true, CLAIM_TEXT, CCA_PLAT_HASH_ALGO_ID, "Platform hash algo", false);
+ if (c > attest_claims->plat_token_claims +
+ CLAIM_COUNT_PLATFORM_TOKEN) {
+ return TOKEN_VERIFICATION_ERR_INIT_ERROR;
+ }
+
+ for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) {
+ c = attest_claims->realm_measurement_claims + i;
+ init_claim(c, true, CLAIM_BSTR, i,
+ "Realm extensible measurements", false);
+ }
+
+ for (i = 0; i < MAX_SW_COMPONENT_COUNT; ++i) {
+ struct sw_component_t *component =
+ attest_claims->sw_component_claims + i;
+
+ component->present = false;
+ c = component->claims;
+ init_claim(c++, false, CLAIM_TEXT, CCA_SW_COMP_HASH_ALGORITHM, "Hash algo.", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_SW_COMP_MEASUREMENT_VALUE, "Meas. val.", false);
+ init_claim(c++, false, CLAIM_TEXT, CCA_SW_COMP_VERSION, "Version", false);
+ init_claim(c++, true, CLAIM_BSTR, CCA_SW_COMP_SIGNER_ID, "Signer ID", false);
+ if (c > component->claims + CLAIM_COUNT_SW_COMPONENT) {
+ return TOKEN_VERIFICATION_ERR_INIT_ERROR;
+ }
+ }
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+static int handle_claim_decode_error(const struct claim_t *claim,
+ QCBORError err)
+{
+ if (err == QCBOR_ERR_LABEL_NOT_FOUND) {
+ if (claim->mandatory) {
+ printf("Mandatory claim with key %" PRId64 " (%s) is "
+ "missing from token.\r\n", claim->key,
+ claim->title);
+ return TOKEN_VERIFICATION_ERR_MISSING_MANDATORY_CLAIM;
+ }
+ } else {
+ printf("Decode failed with error at %s:%d. err = %d key = %"
+ PRId64 " (%s).\r\n", __FILE__, (int)__LINE__, err,
+ claim->key, claim->title);
+ return TOKEN_VERIFICATION_ERR_QCBOR(err);
+ }
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+/* Consume claims from a map.
+ *
+ * This function iterates on the array 'claims', and looks up items with the
+ * specified keys. If a claim flagged as mandatory is not found, an error is
+ * returned. The function doesn't checks for extra items. So if the map contains
+ * items with keys that are not in the claims array, no error is reported.
+ *
+ * The map needs to be 'entered' before calling this function, and be 'exited'
+ * after it returns.
+ */
+static int get_claims_from_map(QCBORDecodeContext *p_context,
+ struct claim_t *claims,
+ size_t num_of_claims)
+{
+ QCBORError err;
+ int token_verification_error;
+ int i;
+
+ for (i = 0; i < num_of_claims; ++i) {
+ struct claim_t *claim = claims + i;
+
+ switch (claim->type) {
+ case CLAIM_INT64:
+ QCBORDecode_GetInt64InMapN(p_context, claim->key,
+ &(claim->int_data));
+ break;
+ case CLAIM_BOOL:
+ QCBORDecode_GetBoolInMapN(p_context, claim->key,
+ &(claim->bool_data));
+ break;
+ case CLAIM_BSTR:
+ QCBORDecode_GetByteStringInMapN(p_context, claim->key,
+ &(claim->buffer_data));
+ break;
+ case CLAIM_TEXT:
+ QCBORDecode_GetTextStringInMapN(p_context, claim->key,
+ &(claim->buffer_data));
+ break;
+ default:
+ printf("Internal error at %s:%d.\r\n",
+ __FILE__, (int)__LINE__);
+ return TOKEN_VERIFICATION_ERR_INTERNAL_ERROR;
+ }
+ err = QCBORDecode_GetAndResetError(p_context);
+ if (err == QCBOR_SUCCESS) {
+ claim->present = true;
+ } else {
+ token_verification_error =
+ handle_claim_decode_error(claim, err);
+ if (token_verification_error !=
+ TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return token_verification_error;
+ }
+ }
+ }
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+/* Consume a single claim from an array and from the top level.
+ *
+ * The claim's 'key' and 'mandatory' attribute is not used in this function.
+ * The claim is considered mandatory.
+ */
+static int get_claim(QCBORDecodeContext *p_context, struct claim_t *claim)
+{
+ QCBORError err;
+
+ switch (claim->type) {
+ case CLAIM_INT64:
+ QCBORDecode_GetInt64(p_context, &(claim->int_data));
+ break;
+ case CLAIM_BOOL:
+ QCBORDecode_GetBool(p_context, &(claim->bool_data));
+ break;
+ case CLAIM_BSTR:
+ QCBORDecode_GetByteString(p_context, &(claim->buffer_data));
+ break;
+ case CLAIM_TEXT:
+ QCBORDecode_GetTextString(p_context, &(claim->buffer_data));
+ break;
+ default:
+ printf("Internal error at %s:%d.\r\n",
+ __FILE__, (int)__LINE__);
+ break;
+ }
+ err = QCBORDecode_GetAndResetError(p_context);
+ if (err == QCBOR_SUCCESS) {
+ claim->present = true;
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+ }
+ printf("Decode failed with error at %s:%d. err = %d claim: \"%s\".\r\n",
+ __FILE__, (int)__LINE__, err, claim->title);
+ return TOKEN_VERIFICATION_ERR_QCBOR(err);
+}
+
+/* Consume claims from an array and from the top level.
+ *
+ * This function iterates on the array 'claims', and gets an item for each
+ * element. If the array or the cbor runs out of elements before reaching the
+ * end of the 'claims' array, then error is returned.
+ *
+ * The claim's 'key' and 'mandatory' attribute is not used in this function.
+ * All the elements considered mandatory.
+ */
+static int get_claims(QCBORDecodeContext *p_context, struct claim_t *claims,
+ size_t num_of_claims)
+{
+ QCBORError err;
+ int i;
+
+ for (i = 0; i < num_of_claims; ++i) {
+ struct claim_t *claim = claims + i;
+
+ err = get_claim(p_context, claim);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+ }
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+static int verify_platform_token(struct q_useful_buf_c buf,
+ struct attestation_claims *attest_claims)
+{
+ QCBORDecodeContext context;
+ int err;
+ int label, index;
+
+ QCBORDecode_Init(&context, buf, QCBOR_DECODE_MODE_NORMAL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_EnterMap(&context, NULL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ err = get_claims_from_map(&context,
+ attest_claims->plat_token_claims,
+ CLAIM_COUNT_PLATFORM_TOKEN);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ label = CCA_PLAT_SW_COMPONENTS;
+ QCBORDecode_EnterArrayFromMapN(&context, label);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ index = 0;
+ while (1) {
+ QCBORDecode_EnterMap(&context, NULL);
+ if (QCBORDecode_GetError(&context) == QCBOR_ERR_NO_MORE_ITEMS) {
+ /* This is OK. We just reached the end of the array.
+ * Break from the loop.
+ */
+ break;
+ }
+
+ if (index >= MAX_SW_COMPONENT_COUNT) {
+ printf("Not enough slots in sw_component_claims.\r\n");
+ printf("Increase MAX_SW_COMPONENT_COUNT in %s.\r\n",
+ __FILE__);
+ return TOKEN_VERIFICATION_ERR_INTERNAL_ERROR;
+ }
+
+ err = get_claims_from_map(&context,
+ attest_claims->sw_component_claims[index].claims,
+ CLAIM_COUNT_SW_COMPONENT);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+ attest_claims->sw_component_claims[index].present = true;
+
+ QCBORDecode_ExitMap(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ ++index;
+ }
+ /* We only get here if the decode error code was a
+ * QCBOR_ERR_NO_MORE_ITEMS which is expected when the end of an array is
+ * reached. In this case the processing must be continued, so clear the
+ * error.
+ */
+ QCBORDecode_GetAndResetError(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_ExitArray(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_ExitMap(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_Finish(&context);
+
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+static bool verify_length_of_measurement(size_t len)
+{
+ size_t allowed_lengths[] = {SHA256_SIZE, SHA512_SIZE};
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(allowed_lengths); ++i) {
+ if (len == allowed_lengths[i])
+ return true;
+ }
+
+ return false;
+}
+
+static int verify_realm_token(struct q_useful_buf_c buf,
+ struct attestation_claims *attest_claims)
+{
+ QCBORDecodeContext context;
+ int err;
+ int i;
+
+ QCBORDecode_Init(&context, buf, QCBOR_DECODE_MODE_NORMAL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_EnterMap(&context, NULL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ err = get_claims_from_map(&context, attest_claims->realm_token_claims,
+ CLAIM_COUNT_REALM_TOKEN);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ /* Now get the realm extensible measurements */
+ QCBORDecode_EnterArrayFromMapN(&context,
+ CCA_REALM_EXTENSIBLE_MEASUREMENTS);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ err = get_claims(&context,
+ attest_claims->realm_measurement_claims,
+ CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) {
+ struct claim_t *claims =
+ attest_claims->realm_measurement_claims;
+ struct q_useful_buf_c buf = claims[i].buffer_data;
+
+ if (!verify_length_of_measurement(buf.len)) {
+ return TOKEN_VERIFICATION_ERR_INVALID_CLAIM_LEN;
+ }
+ }
+
+ QCBORDecode_ExitArray(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_ExitMap(&context);
+ QCBORDecode_Finish(&context);
+
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+/* Returns a pointer to the wrapped token in: 'token_payload'.
+ * Returns the claims in the wrapper in cose_sign1_wrapper.
+ */
+static int verify_token_cose_sign1_wrapping(
+ struct q_useful_buf_c token,
+ struct q_useful_buf_c *token_payload,
+ struct claim_t *cose_sign1_wrapper)
+{
+ QCBORDecodeContext context;
+ QCBORItem item;
+ int err;
+
+ QCBORDecode_Init(&context, token, QCBOR_DECODE_MODE_NORMAL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* Check COSE tag. */
+ QCBORDecode_PeekNext(&context, &item);
+ if (!QCBORDecode_IsTagged(&context, &item,
+ TAG_COSE_SIGN1)) {
+ return TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG;
+ }
+
+ QCBORDecode_EnterArray(&context, NULL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* Protected header */
+ err = get_claim(&context, cose_sign1_wrapper);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ /* Unprotected header. The map is always present, but may contain 0
+ * items.
+ */
+ QCBORDecode_EnterMap(&context, NULL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* Skip the content for now. */
+
+ QCBORDecode_ExitMap(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* Payload */
+ err = get_claim(&context, cose_sign1_wrapper + 1);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ /* Signature */
+ err = get_claim(&context, cose_sign1_wrapper + 2);
+ if (err != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return err;
+ }
+
+ QCBORDecode_ExitArray(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ *token_payload = cose_sign1_wrapper[1].buffer_data;
+
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+static int verify_cca_token(struct q_useful_buf_c token,
+ struct q_useful_buf_c *platform_token,
+ struct q_useful_buf_c *realm_token)
+{
+ QCBORDecodeContext context;
+ QCBORItem item;
+ QCBORError err;
+
+ QCBORDecode_Init(&context, token, QCBOR_DECODE_MODE_NORMAL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* ================== Check CCA_TOKEN tag =========================== */
+ QCBORDecode_PeekNext(&context, &item);
+ if (!QCBORDecode_IsTagged(&context, &item, TAG_CCA_TOKEN)) {
+ return TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG;
+ }
+
+ /* ================== Get the the platform token ==================== */
+ QCBORDecode_EnterMap(&context, NULL);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /*
+ * First element is the CCA platfrom token which is a
+ * COSE_Sign1_Tagged object. It has byte stream wrapper.
+ */
+ QCBORDecode_GetByteStringInMapN(&context, CCA_PLAT_TOKEN,
+ platform_token);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* ================== Get the the realm token ======================= */
+ /*
+ * Second element is the delegated realm token which is a
+ * COSE_Sign1_Tagged object. It has byte stream wrapper.
+ */
+ QCBORDecode_GetByteStringInMapN(&context, CCA_REALM_DELEGATED_TOKEN,
+ realm_token);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ QCBORDecode_ExitMap(&context);
+ RETURN_ON_DECODE_ERROR(&context);
+
+ /* Finishing up the decoding of the top-level wrapper */
+ err = QCBORDecode_Finish(&context);
+ if (err != QCBOR_SUCCESS) {
+ printf("QCBOR decode failed with error at %s:%d. err = %d\r\n",
+ __FILE__, (int)__LINE__, (int)err);
+ return TOKEN_VERIFICATION_ERR_QCBOR(err);
+ }
+
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
+/*
+ * This function expect two COSE_Sing1_Tagged object wrapped with a tagged map:
+ *
+ * cca-token = #6.44234(cca-token-map) ; 44234 = 0xACCA
+ *
+ * cca-platform-token = COSE_Sign1_Tagged
+ * cca-realm-delegated-token = COSE_Sign1_Tagged
+ *
+ * cca-token-map = {
+ * 0 => cca-platform-token
+ * 1 => cca-realm-delegated-token
+ * }
+ *
+ * COSE_Sign1_Tagged = #6.18(COSE_Sign1)
+ */
+int verify_token(const char *token, size_t size,
+ struct attestation_claims *attest_claims)
+{
+ /* TODO: do signature check */
+ /* TODO: Add tag check on tokens */
+ struct q_useful_buf_c buf = {token, size};
+ int ret;
+ struct q_useful_buf_c realm_token;
+ struct q_useful_buf_c realm_token_payload;
+ struct q_useful_buf_c platform_token;
+ struct q_useful_buf_c platform_token_payload;
+
+ ret = init_claims(attest_claims);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+
+ /* Verify top-level token map and extract the two sub-tokens */
+ ret = verify_cca_token(buf, &platform_token, &realm_token);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+
+ /* Verify the COSE_Sign1 wrapper of the realm token */
+ ret = verify_token_cose_sign1_wrapping(realm_token,
+ &realm_token_payload,
+ attest_claims->realm_cose_sign1_wrapper);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+ /* Verify the payload of the realm token */
+ ret = verify_realm_token(realm_token_payload, attest_claims);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+
+ /* Verify the COSE_Sign1 wrapper of the platform token */
+ ret = verify_token_cose_sign1_wrapping(platform_token,
+ &platform_token_payload,
+ attest_claims->plat_cose_sign1_wrapper);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+ /* Verify the payload of the platform token */
+ ret = verify_platform_token(platform_token_payload, attest_claims);
+ if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) {
+ return ret;
+ }
+
+ return TOKEN_VERIFICATION_ERR_SUCCESS;
+}
+
diff --git a/lib/token_verifier/token_verifier.h b/lib/token_verifier/token_verifier.h
new file mode 100644
index 00000000..ec3ab9c9
--- /dev/null
+++ b/lib/token_verifier/token_verifier.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 Arm Limited.
+ * All rights reserved.
+ */
+
+#ifndef __TOKEN_VERIFIER_H__
+#define __TOKEN_VERIFIER_H__
+
+#include <qcbor/qcbor_decode.h>
+
+#define TOKEN_VERIFICATION_ERR_SUCCESS 0
+#define TOKEN_VERIFICATION_ERR_INIT_ERROR 1
+#define TOKEN_VERIFICATION_ERR_MISSING_MANDATORY_CLAIM 2
+#define TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG 3
+#define TOKEN_VERIFICATION_ERR_INVALID_CLAIM_LEN 4
+#define TOKEN_VERIFICATION_ERR_INTERNAL_ERROR 5
+#define TOKEN_VERIFICATION_ERR_QCBOR(qcbor_err) (1000 + qcbor_err)
+
+/* Number of realm extensible measurements (REM) */
+#define REM_COUNT 4
+
+#define MAX_SW_COMPONENT_COUNT 16
+
+#define CLAIM_COUNT_REALM_TOKEN 6
+#define CLAIM_COUNT_COSE_SIGN1_WRAPPER 3
+#define CLAIM_COUNT_PLATFORM_TOKEN 8
+#define CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS REM_COUNT
+#define CLAIM_COUNT_SW_COMPONENT 4
+
+/* This tells how the data should be interpreted in the claim_t struct, and not
+ * necessarily is the same as the item's major type in the token.
+ */
+enum claim_data_type {
+ CLAIM_INT64,
+ CLAIM_BOOL,
+ CLAIM_BSTR,
+ CLAIM_TEXT,
+};
+
+struct claim_t {
+ /* 'static' */
+ bool mandatory;
+ enum claim_data_type type;
+ int64_t key;
+ const char *title;
+
+ /* filled during verification */
+ bool present;
+ union {
+ int64_t int_data;
+ bool bool_data;
+ /* Used for text and bytestream as well */
+ /* TODO: Add expected length check as well? */
+ struct q_useful_buf_c buffer_data;
+ };
+};
+
+struct sw_component_t {
+ bool present;
+ struct claim_t claims[CLAIM_COUNT_SW_COMPONENT];
+};
+
+struct attestation_claims {
+ struct claim_t realm_cose_sign1_wrapper[CLAIM_COUNT_COSE_SIGN1_WRAPPER];
+ struct claim_t realm_token_claims[CLAIM_COUNT_REALM_TOKEN];
+ struct claim_t realm_measurement_claims[CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS];
+ struct claim_t plat_cose_sign1_wrapper[CLAIM_COUNT_COSE_SIGN1_WRAPPER];
+ struct claim_t plat_token_claims[CLAIM_COUNT_PLATFORM_TOKEN];
+ struct sw_component_t sw_component_claims[MAX_SW_COMPONENT_COUNT];
+};
+
+/* Returns TOKEN_VERIFICATION_ERR* */
+int verify_token(const char *token, size_t size,
+ struct attestation_claims *attest_claims);
+
+#endif /* __TOKEN_VERIFIER_H__ */
--
2.17.1
next prev parent reply other threads:[~2023-01-27 11:43 UTC|newest]
Thread overview: 190+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-27 11:22 [RFC] Support for Arm CCA VMs on Linux Suzuki K Poulose
2023-01-27 11:27 ` [RFC PATCH 00/14] arm64: Support for running as a guest in Arm CCA Steven Price
2023-01-27 11:27 ` [RFC PATCH 01/14] arm64: remove redundant 'extern' Steven Price
2023-01-27 11:27 ` [RFC PATCH 02/14] arm64: rsi: Add RSI definitions Steven Price
2023-01-27 11:27 ` [RFC PATCH 03/14] arm64: Detect if in a realm and set RIPAS RAM Steven Price
2023-01-27 11:27 ` [RFC PATCH 04/14] arm64: realm: Query IPA size from the RMM Steven Price
2023-01-27 11:27 ` [RFC PATCH 05/14] arm64: Mark all I/O as non-secure shared Steven Price
2023-01-27 11:27 ` [RFC PATCH 06/14] fixmap: Allow architecture overriding set_fixmap_io Steven Price
2023-01-27 11:27 ` [RFC PATCH 07/14] arm64: Override set_fixmap_io Steven Price
2023-01-27 11:27 ` [RFC PATCH 08/14] arm64: Make the PHYS_MASK_SHIFT dynamic Steven Price
2023-01-27 11:27 ` [RFC PATCH 09/14] arm64: Enforce bounce buffers for realm DMA Steven Price
2023-01-27 11:27 ` [RFC PATCH 10/14] arm64: Enable memory encrypt for Realms Steven Price
2023-01-27 11:27 ` [RFC PATCH 11/14] arm64: Force device mappings to be non-secure shared Steven Price
2023-01-27 11:27 ` [RFC PATCH 12/14] efi: arm64: Map Device with Prot Shared Steven Price
2023-01-27 11:27 ` [RFC PATCH 13/14] arm64: realm: Support nonsecure ITS emulation shared Steven Price
2023-01-27 11:27 ` [RFC PATCH 14/14] HACK: Accept prototype RSI version Steven Price
2023-01-27 11:29 ` [RFC PATCH 00/28] arm64: Support for Arm CCA in KVM Steven Price
2023-01-27 11:29 ` [RFC PATCH 01/28] arm64: RME: Handle Granule Protection Faults (GPFs) Steven Price
2023-01-27 11:29 ` [RFC PATCH 02/28] arm64: RME: Add SMC definitions for calling the RMM Steven Price
2023-01-27 11:29 ` [RFC PATCH 03/28] arm64: RME: Add wrappers for RMI calls Steven Price
2023-02-13 16:43 ` Zhi Wang
2024-03-18 7:03 ` Ganapatrao Kulkarni
2024-03-18 11:22 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 04/28] arm64: RME: Check for RME support at KVM init Steven Price
2023-02-13 15:48 ` Zhi Wang
2023-02-13 15:59 ` Steven Price
2023-03-04 12:07 ` Zhi Wang
2023-02-13 15:55 ` Zhi Wang
2024-03-18 7:17 ` Ganapatrao Kulkarni
2024-03-18 11:22 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 05/28] arm64: RME: Define the user ABI Steven Price
2023-02-13 16:04 ` Zhi Wang
2023-03-01 11:54 ` Steven Price
2023-03-01 20:21 ` Zhi Wang
2023-01-27 11:29 ` [RFC PATCH 06/28] arm64: RME: ioctls to create and configure realms Steven Price
2023-02-07 12:25 ` Jean-Philippe Brucker
2023-02-07 12:55 ` Suzuki K Poulose
2023-02-13 16:10 ` Zhi Wang
2023-03-01 11:55 ` Steven Price
2023-03-01 20:33 ` Zhi Wang
2023-03-06 19:10 ` Zhi Wang
2023-03-10 15:47 ` Steven Price
2024-03-18 7:40 ` Ganapatrao Kulkarni
2024-03-18 11:22 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 07/28] arm64: kvm: Allow passing machine type in KVM creation Steven Price
2023-02-13 16:35 ` Zhi Wang
2023-03-01 11:55 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 08/28] arm64: RME: Keep a spare page delegated to the RMM Steven Price
2023-02-13 16:47 ` Zhi Wang
2023-03-01 11:55 ` Steven Price
2023-03-01 20:50 ` Zhi Wang
2023-01-27 11:29 ` [RFC PATCH 09/28] arm64: RME: RTT handling Steven Price
2023-02-13 17:44 ` Zhi Wang
2023-03-03 14:04 ` Steven Price
2023-03-04 12:32 ` Zhi Wang
2024-03-18 11:01 ` Ganapatrao Kulkarni
2024-03-18 11:25 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 10/28] arm64: RME: Allocate/free RECs to match vCPUs Steven Price
2023-02-13 18:08 ` Zhi Wang
2023-03-03 14:05 ` Steven Price
2023-03-04 12:46 ` Zhi Wang
2023-01-27 11:29 ` [RFC PATCH 11/28] arm64: RME: Support for the VGIC in realms Steven Price
2023-01-27 11:29 ` [RFC PATCH 12/28] KVM: arm64: Support timers in realm RECs Steven Price
2024-03-18 11:28 ` Ganapatrao Kulkarni
2024-03-18 14:14 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 13/28] arm64: RME: Allow VMM to set RIPAS Steven Price
2023-02-17 13:07 ` Zhi Wang
2023-03-03 14:05 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 14/28] arm64: RME: Handle realm enter/exit Steven Price
2023-01-27 11:29 ` [RFC PATCH 15/28] KVM: arm64: Handle realm MMIO emulation Steven Price
2023-03-06 15:37 ` Zhi Wang
2023-03-10 15:47 ` Steven Price
2023-03-14 15:44 ` Zhi Wang
2023-03-22 11:51 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 16/28] arm64: RME: Allow populating initial contents Steven Price
2023-03-06 17:34 ` Zhi Wang
2023-03-10 15:47 ` Steven Price
2023-03-14 15:31 ` Zhi Wang
2023-03-22 11:51 ` Steven Price
2023-01-27 11:29 ` [RFC PATCH 17/28] arm64: RME: Runtime faulting of memory Steven Price
2023-03-06 18:20 ` Zhi Wang
2023-03-10 15:47 ` Steven Price
2023-03-14 16:41 ` Zhi Wang
2023-01-27 11:29 ` [RFC PATCH 18/28] KVM: arm64: Handle realm VCPU load Steven Price
2023-01-27 11:29 ` [RFC PATCH 19/28] KVM: arm64: Validate register access for a Realm VM Steven Price
2023-01-27 11:29 ` [RFC PATCH 20/28] KVM: arm64: Handle Realm PSCI requests Steven Price
2023-01-27 11:29 ` [RFC PATCH 21/28] KVM: arm64: WARN on injected undef exceptions Steven Price
2023-01-27 11:29 ` [RFC PATCH 22/28] arm64: Don't expose stolen time for realm guests Steven Price
2023-01-27 11:29 ` [RFC PATCH 23/28] KVM: arm64: Allow activating realms Steven Price
2023-01-27 11:29 ` [RFC PATCH 24/28] arm64: rme: allow userspace to inject aborts Steven Price
2023-01-27 11:29 ` [RFC PATCH 25/28] arm64: rme: support RSI_HOST_CALL Steven Price
2023-01-27 11:29 ` [RFC PATCH 26/28] arm64: rme: Allow checking SVE on VM instance Steven Price
2023-01-27 11:29 ` [RFC PATCH 27/28] arm64: RME: Always use 4k pages for realms Steven Price
2023-01-27 11:29 ` [RFC PATCH 28/28] HACK: Accept prototype RMI versions Steven Price
2023-01-27 11:39 ` [RFC kvmtool 00/31] arm64: Support for Arm Confidential Compute Architecture Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 01/31] arm64: Disable MTE when CFI flash is emulated Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 02/31] script: update_headers: Ignore missing architectures Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 03/31] hw: cfi flash: Handle errors in memory transitions Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 04/31] Add --nocompat option to disable compat warnings Suzuki K Poulose
2023-01-27 12:19 ` Alexandru Elisei
2023-01-27 11:39 ` [RFC kvmtool 05/31] arm64: Check pvtime support against the KVM instance Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 06/31] arm64: Check SVE capability on the VM instance Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 07/31] arm64: Add option to disable SVE Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 08/31] linux: Update kernel headers for RME support Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 09/31] arm64: Add --realm command line option Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 10/31] arm64: Create a realm virtual machine Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 11/31] arm64: Lock realm RAM in memory Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 12/31] arm64: Create Realm Descriptor Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 13/31] arm64: Add --measurement-algo command line option for a realm Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 14/31] arm64: Add configuration step for Realms Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 15/31] arm64: Add support for Realm Personalisation Value Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 16/31] arm64: Add support for specifying the SVE vector length for Realm Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 17/31] arm: Add kernel size to VM context Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 18/31] arm64: Populate initial realm contents Suzuki K Poulose
2023-03-02 14:03 ` Piotr Sawicki
2023-03-02 14:06 ` Suzuki K Poulose
2023-10-02 9:28 ` Piotr Sawicki
2023-01-27 11:39 ` [RFC kvmtool 19/31] arm64: Don't try to set PSTATE for VCPUs belonging to a realm Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 20/31] arm64: Finalize realm VCPU after reset Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 21/31] init: Add last_{init, exit} list macros Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 22/31] arm64: Activate realm before the first VCPU is run Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 23/31] arm64: Specify SMC as the PSCI conduits for realms Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 24/31] arm64: Don't try to debug a realm Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 25/31] arm64: realm: Double the IPA space Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 26/31] virtio: Add a wrapper for get_host_features Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 27/31] virtio: Add arch specific hook for virtio host flags Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 28/31] arm64: realm: Enforce virtio F_ACCESS_PLATFORM flag Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 29/31] mmio: add arch hook for an unhandled MMIO access Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 30/31] arm64: realm: inject an abort on " Suzuki K Poulose
2023-01-27 11:39 ` [RFC kvmtool 31/31] arm64: Allow the user to create a realm Suzuki K Poulose
2023-10-02 9:45 ` [RFC kvmtool 00/31] arm64: Support for Arm Confidential Compute Architecture Piotr Sawicki
2023-01-27 11:40 ` [RFC kvm-unit-tests 00/27] " Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 01/27] lib/string: include stddef.h for size_t Joey Gouly
2023-01-31 14:43 ` Thomas Huth
2023-01-27 11:40 ` [RFC kvm-unit-tests 02/27] arm: Expand SMCCC arguments and return values Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 03/27] arm: realm: Add RSI interface header Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 04/27] arm: Make physical address mask dynamic Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 05/27] arm: Introduce NS_SHARED PTE attribute Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 06/27] arm: Move io_init after vm initialization Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 07/27] arm: realm: Make uart available before MMU is enabled Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 08/27] arm: realm: Realm initialisation Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 09/27] arm: realm: Add support for changing the state of memory Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 10/27] arm: realm: Set RIPAS state for RAM Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 11/27] arm: realm: Early memory setup Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 12/27] arm: realm: Add RSI version test Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 13/27] arm: selftest: realm: skip pabt test when running in a realm Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 14/27] arm: realm: add hvc and RSI_HOST_CALL tests Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 15/27] arm: realm: Add test for FPU/SIMD context save/restore Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 16/27] arm: realm: Add tests for in realm SEA Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 17/27] lib/alloc_page: Add shared page allocation support Joey Gouly
2023-01-27 11:40 ` [RFC kvm-unit-tests 18/27] arm: gic-v3-its: Use shared pages wherever needed Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 19/27] arm: realm: Enable memory encryption Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 20/27] qcbor: Add QCBOR as a submodule Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 21/27] arm: Add build steps for QCBOR library Joey Gouly
2023-01-27 11:41 ` Joey Gouly [this message]
2023-01-27 11:41 ` [RFC kvm-unit-tests 23/27] arm: realm: add RSI interface for attestation measurements Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 24/27] arm: realm: Add helpers to decode RSI return codes Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 25/27] arm: realm: Add Realm attestation tests Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 26/27] arm: realm: Add a test for shared memory Joey Gouly
2023-01-27 11:41 ` [RFC kvm-unit-tests 27/27] NOT-FOR-MERGING: add run-realm-tests Joey Gouly
2023-01-27 15:26 ` [RFC] Support for Arm CCA VMs on Linux Jean-Philippe Brucker
2023-02-28 23:35 ` Itaru Kitayama
2023-03-01 9:20 ` Jean-Philippe Brucker
2023-03-01 22:12 ` Itaru Kitayama
2023-03-02 9:18 ` Jean-Philippe Brucker
2023-03-03 9:46 ` Jean-Philippe Brucker
2023-03-03 9:54 ` Suzuki K Poulose
2023-03-03 11:39 ` Jean-Philippe Brucker
2023-03-03 12:08 ` Andrew Jones
2023-03-03 12:19 ` Suzuki K Poulose
2023-03-03 13:06 ` Cornelia Huck
2023-03-03 13:57 ` Jean-Philippe Brucker
2023-02-10 16:51 ` Ryan Roberts
2023-02-10 22:53 ` Itaru Kitayama
2023-02-17 8:02 ` Itaru Kitayama
2023-02-20 10:51 ` Ryan Roberts
2023-02-14 17:13 ` Dr. David Alan Gilbert
2023-03-01 9:58 ` Suzuki K Poulose
2023-03-02 16:46 ` Dr. David Alan Gilbert
2023-03-02 19:02 ` Suzuki K Poulose
2023-07-14 13:46 ` Jonathan Cameron
2023-07-14 15:03 ` Suzuki K Poulose
2023-07-14 16:28 ` Jonathan Cameron
2023-07-17 9:40 ` Suzuki K Poulose
2023-10-02 12:43 ` Suzuki K Poulose
2024-01-10 5:40 ` Itaru Kitayama
2024-01-10 11:41 ` Suzuki K Poulose
2024-01-10 13:44 ` Suzuki K Poulose
2024-01-19 1:26 ` Itaru Kitayama
2024-01-12 5:01 ` Itaru Kitayama
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=20230127114108.10025-23-joey.gouly@arm.com \
--to=joey.gouly@arm.com \
--cc=alexandru.elisei@arm.com \
--cc=andrew.jones@linux.dev \
--cc=christoffer.dall@arm.com \
--cc=jean-philippe@linaro.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=mate.toth-pal@arm.com \
--cc=maz@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=pbonzini@redhat.com \
--cc=qperret@google.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=thuth@redhat.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).