summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-09-28 12:57:33 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-10-02 23:28:24 -0700
commit2341692a8fe7f9b6327a060659b1e76bbe114e12 (patch)
tree9ea72f755273254cbf47e03e170a4c21d4f629ea
parent34ce0a90a59979f7a82e7efdd41481370fb31498 (diff)
downloadchrome-ec-2341692a8fe7f9b6327a060659b1e76bbe114e12.tar.gz
common: add TPM vendor command to support RMA authentication
The new vendor command operates in two modes: when received with a zero size payload, it triggers the Cr50 to generate a new RMA authentication challenge and the expected authentication code value. When receive with the payload, it compares the received payload with the pre-calculate authentication code, and returns to the host the comparison result (passed/not passed). A care is taken not to accept payload until at least there is a valid calculated auth code present (to avoid reporting a match on a payload of all zeros). Test config needed to be modified to allow compiling of the ccprintf wrapper. BRANCH=cr50 BUG=b:37952913 TEST=with the rest of the patches applied observed expected behavior of generating challenge/response and verifying the auth code. Change-Id: I30638b0ceef68830565f222dd1f4af17cfc8d7ef Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/690992
-rw-r--r--common/rma_auth.c104
-rw-r--r--include/tpm_vendor_cmds.h1
-rw-r--r--test/test_config.h2
3 files changed, 107 insertions, 0 deletions
diff --git a/common/rma_auth.c b/common/rma_auth.c
index 8ff7f1aa06..ade4e4697b 100644
--- a/common/rma_auth.c
+++ b/common/rma_auth.c
@@ -9,10 +9,13 @@
#include "base32.h"
#include "byteorder.h"
#include "chip/g/board_id.h"
+#include "console.h"
#include "curve25519.h"
+#include "extension.h"
#include "rma_auth.h"
#include "system.h"
#include "timer.h"
+#include "tpm_vendor_cmds.h"
#include "util.h"
#ifdef CONFIG_DCRYPTO
@@ -20,6 +23,9 @@
#else
#include "sha256.h"
#endif
+
+#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
+
/* Minimum time since system boot or last challenge before making a new one */
#define CHALLENGE_INTERVAL (10 * SECOND)
@@ -153,6 +159,10 @@ int rma_try_authcode(const char *code)
if (!tries_left)
return EC_ERROR_ACCESS_DENIED;
+ /* Fail if auth code has not been calculated yet. */
+ if (!*authcode)
+ return EC_ERROR_ACCESS_DENIED;
+
if (safe_memcmp(authcode, code, RMA_AUTHCODE_CHARS)) {
/* Mismatch */
tries_left--;
@@ -169,3 +179,97 @@ int rma_try_authcode(const char *code)
return rv;
}
+
+/*
+ * Trigger generating of the new challenge/authcode pair. If successful, store
+ * the challenge in the vendor command response buffer and send it to the
+ * sender. If not successful - return the error value to the sender.
+ */
+static enum vendor_cmd_rc get_challenge(uint8_t *buf, size_t *buf_size)
+{
+ int rv;
+ size_t i;
+
+ if (*buf_size < sizeof(challenge)) {
+ *buf_size = 1;
+ buf[0] = VENDOR_RC_RESPONSE_TOO_BIG;
+ return buf[0];
+ }
+
+ rv = rma_create_challenge();
+ if (rv != EC_SUCCESS) {
+ *buf_size = 1;
+ buf[0] = rv;
+ return buf[0];
+ }
+
+ *buf_size = sizeof(challenge) - 1;
+ memcpy(buf, rma_get_challenge(), *buf_size);
+
+ CPRINTF("%s: generated challenge:\n", __func__);
+ for (i = 0; i < *buf_size; i++)
+ CPRINTF("%c", ((uint8_t *)buf)[i]);
+ CPRINTF("\n");
+
+ CPRINTF("%s: expected authcode: ", __func__);
+ for (i = 0; i < RMA_AUTHCODE_CHARS; i++)
+ CPRINTF("%c", authcode[i]);
+ CPRINTF("\n");
+
+ return VENDOR_RC_SUCCESS;
+}
+
+/*
+ * Compare response sent by the operator with the pre-compiled auth code.
+ * Return error code or success depending on the comparison results.
+ */
+static enum vendor_cmd_rc process_response(uint8_t *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ int rv;
+
+ *response_size = 1; /* Just in case there is an error. */
+
+ if (input_size != RMA_AUTHCODE_CHARS) {
+ CPRINTF("%s: authcode size %d\n",
+ __func__, input_size);
+ buf[0] = VENDOR_RC_BOGUS_ARGS;
+ return buf[0];
+ }
+
+ rv = rma_try_authcode(buf);
+
+ if (rv == EC_SUCCESS) {
+ CPRINTF("%s: success!\n", __func__);
+ *response_size = 0;
+ return VENDOR_RC_SUCCESS;
+ }
+
+ CPRINTF("%s: authcode mismatch\n", __func__);
+ buf[0] = VENDOR_RC_INTERNAL_ERROR;
+ return buf[0];
+}
+
+/*
+ * Handle the VENDOR_CC_RMA_CHALLENGE_RESPONSE command. When received with
+ * empty payload - this is a request to generate a new challenge, when
+ * received with a payload, this is a request to check if the payload matches
+ * the previously calculated auth code.
+ */
+static enum vendor_cmd_rc rma_challenge_response(enum vendor_cmd_cc code,
+ void *buf,
+ size_t input_size,
+ size_t *response_size)
+{
+ if (!input_size)
+ /*
+ * This is a request for the challenge, get it and send it
+ * back.
+ */
+ return get_challenge(buf, response_size);
+
+ return process_response(buf, input_size, response_size);
+}
+DECLARE_VENDOR_COMMAND(VENDOR_CC_RMA_CHALLENGE_RESPONSE,
+ rma_challenge_response);
diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h
index 59331313d9..b46e0af754 100644
--- a/include/tpm_vendor_cmds.h
+++ b/include/tpm_vendor_cmds.h
@@ -43,6 +43,7 @@ enum vendor_cmd_cc {
VENDOR_CC_U2F_APDU = 27,
VENDOR_CC_POP_LOG_ENTRY = 28,
VENDOR_CC_GET_REC_BTN = 29,
+ VENDOR_CC_RMA_CHALLENGE_RESPONSE = 30,
LAST_VENDOR_COMMAND = 65535,
};
diff --git a/test/test_config.h b/test/test_config.h
index 23d836ffd9..2cb1baf124 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -66,6 +66,8 @@
#define CONFIG_RMA_AUTH_SERVER_KEY_ID RMA_TEST_SERVER_KEY_ID
#define CONFIG_RNG
#define CONFIG_SHA256
+#define CC_EXTENSION CC_COMMAND
+
#endif
#ifdef TEST_RSA