summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2018-05-26 21:01:12 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-30 20:38:52 -0700
commit7b0018521683070cfa5beda948a8ea5278d802cc (patch)
tree4da96a4d1b0f9091f1f63079d37e407b13a1f8ce
parent815251b070b5ab2d0c9a78ab659e02ce69ec50e8 (diff)
downloadchrome-ec-7b0018521683070cfa5beda948a8ea5278d802cc.tar.gz
cr50: move RMA challenge-response to P256
Using the p256 curve is beneficial, because RMA feature is currently the only user of the x25519 curve in Cr50, whereas p256 support is required by other subsystems and its implementation is based on dcrypto. The p256 public key is 65 bytes in size, appropriate adjustments are being made for the structure storing the server public key and the key ID. The compact representation of the p256 public key requires 33 bytes, including the X coordinate and one extra byte used to communicate if the omitted Y coordinate is odd or even. The challenge structure communicated to the RMA server allows exactly 32 bytes for the public key. To comply, the generated ephemeral public key is used in compressed form (only the X coordinate is used). For the server to properly uncompress the public key one extra bit is required, to indicate if the original key's Y coordinate is odd or even. Since there is no room for the extra bit in the challenge structure, a convention is used where the generated ephemeral public key is guaranteed to have an odd Y coordinate. When generating the ephemeral key, the Y coordinate is checked, and if it is even, generation attempt is repeated. Some clean up is also included: even with debug enabled, generated challenge is displayed only once as a long string, convenient for copying and pasting. The new feature is not yet enabled, p256 support on the RMA server side is not yet available. Enabling p256 curve for RMA authentication saves 5336 bytes of the flash space. BRANCH=cr50, cr50-mp BUG=b:73296606 TEST=enabled CONFIG_RMA_AUTH_USE_P256 in board.h, generated challenge and verified matching auth code generated by the rma_reset utility. Change-Id: I857543c89a7c33c6fc2dc00e142fe9fa6fc642cf Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1074743 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--board/cr50/board.h9
-rw-r--r--board/cr50/rma_key_blob.p256.testbin0 -> 66 bytes
-rw-r--r--common/build.mk8
-rw-r--r--common/rma_auth.c137
-rw-r--r--include/config.h6
5 files changed, 123 insertions, 37 deletions
diff --git a/board/cr50/board.h b/board/cr50/board.h
index e0c38c6b2e..58d8faeb65 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -349,7 +349,6 @@ enum nvmem_users {
#define I2C_PORT_MASTER 0
#define CONFIG_BASE32
-#define CONFIG_CURVE25519
#define CONFIG_RMA_AUTH
#define CONFIG_RNG
@@ -358,4 +357,12 @@ enum nvmem_users {
/* Enable hardware backed brute force resistance feature */
#define CONFIG_PINWEAVER
+/*
+ * While RMA server support is not ready keep using x25519. Switching to P256
+ * saves 5336 bytes of flash space.
+ */
+/* #define CONFIG_RMA_AUTH_USE_P256 */
+#ifndef CONFIG_RMA_AUTH_USE_P256
+#define CONFIG_CURVE25519
+#endif
#endif /* __CROS_EC_BOARD_H */
diff --git a/board/cr50/rma_key_blob.p256.test b/board/cr50/rma_key_blob.p256.test
new file mode 100644
index 0000000000..0e5cba1a6c
--- /dev/null
+++ b/board/cr50/rma_key_blob.p256.test
Binary files differ
diff --git a/common/build.mk b/common/build.mk
index d1d6f88ee4..f39c716d80 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -179,9 +179,15 @@ endif
ifeq ($(TEST_BUILD),)
+ifeq ($(CONFIG_RMA_AUTH_USE_P256),)
+BLOB_FILE = rma_key_blob.test
+else
+BLOB_FILE = rma_key_blob.p256.test
+endif
+
$(out)/RW/common/rma_auth.o: $(out)/rma_key_from_blob.h
-$(out)/rma_key_from_blob.h: board/$(BOARD)/rma_key_blob.test util/bin2h.sh
+$(out)/rma_key_from_blob.h: board/$(BOARD)/$(BLOB_FILE) util/bin2h.sh
$(Q)util/bin2h.sh RMA_KEY_BLOB $< $@
endif
diff --git a/common/rma_auth.c b/common/rma_auth.c
index 51516966b8..87894e70ad 100644
--- a/common/rma_auth.c
+++ b/common/rma_auth.c
@@ -11,7 +11,9 @@
#include "ccd_config.h"
#include "chip/g/board_id.h"
#include "console.h"
+#ifdef CONFIG_CURVE25519
#include "curve25519.h"
+#endif
#include "extension.h"
#include "hooks.h"
#include "rma_auth.h"
@@ -20,10 +22,17 @@
#include "timer.h"
#include "tpm_registers.h"
#include "tpm_vendor_cmds.h"
+#ifdef CONFIG_RMA_AUTH_USE_P256
+#include "trng.h"
+#endif
#include "util.h"
#ifndef TEST_BUILD
+#include "cryptoc/util.h"
#include "rma_key_from_blob.h"
+#else
+/* Cryptoc library is not available to the test layer. */
+#define always_memset memset
#endif
#ifdef CONFIG_DCRYPTO
@@ -40,12 +49,18 @@
/* Number of tries to properly enter auth code */
#define MAX_AUTHCODE_TRIES 3
+#ifdef CONFIG_RMA_AUTH_USE_P256
+#define RMA_SERVER_PUB_KEY_SZ 65
+#else
+#define RMA_SERVER_PUB_KEY_SZ 32
+#endif
+
/* Server public key and key ID */
static const struct {
union {
- uint8_t raw_blob[33];
+ uint8_t raw_blob[RMA_SERVER_PUB_KEY_SZ + 1];
struct {
- uint8_t server_pub_key[32];
+ uint8_t server_pub_key[RMA_SERVER_PUB_KEY_SZ];
volatile uint8_t server_key_id;
};
};
@@ -53,7 +68,7 @@ static const struct {
.raw_blob = RMA_KEY_BLOB
};
-BUILD_ASSERT(sizeof(rma_key_blob) == 33);
+BUILD_ASSERT(sizeof(rma_key_blob) == (RMA_SERVER_PUB_KEY_SZ + 1));
static char challenge[RMA_CHALLENGE_BUF_SIZE];
static char authcode[RMA_AUTHCODE_BUF_SIZE];
@@ -87,6 +102,71 @@ static void hash_buffer(void *dest, size_t dest_size,
memcpy(dest, temp, dest_size);
}
+#ifdef CONFIG_RMA_AUTH_USE_P256
+/*
+ * Generate a p256 key pair, such that Y coordinate component of the public
+ * key is an odd value. Use the X component value as the compressed public key
+ * to be sent to the server. Multiply server public key by our private key to
+ * generate the shared secret.
+ *
+ * @pub_key - array to return 32 bytes of the X coordinate public key
+ * component.
+ * @secet - array to return the X coordinate of the product of the server
+ * public key multiplied by our private key.
+ */
+static void p256_get_pub_key_and_secret(uint8_t pub_key[P256_NBYTES],
+ uint8_t secret[P256_NBYTES])
+{
+ uint8_t buf[SHA256_DIGEST_SIZE];
+ p256_int d;
+ p256_int pk_x;
+ p256_int pk_y;
+
+ /* Get some noise for private key. */
+ rand_bytes(buf, sizeof(buf));
+
+ /*
+ * By convention with the RMA server the Y coordinate of the Cr50
+ * public key component is required to be an odd value. Keep trying
+ * until the genreated bublic key has the compliant Y coordinate.
+ */
+ while (1) {
+ HASH_CTX sha;
+
+ if (DCRYPTO_p256_key_from_bytes(&pk_x, &pk_y, &d, buf)) {
+
+ /* Is Y coordinate an odd value? */
+ if (p256_is_odd(&pk_y))
+ break; /* Yes it is, got a good key. */
+ }
+
+ /* Did not succeed, rehash the private key and try again. */
+ DCRYPTO_SHA256_init(&sha, 0);
+ HASH_update(&sha, buf, sizeof(buf));
+ memcpy(buf, HASH_final(&sha), sizeof(buf));
+ }
+
+ /* X coordinate is passed to the server as the public key. */
+ p256_to_bin(&pk_x, pub_key);
+
+ /*
+ * Now let's calculate the secret as a the server pub key multiplied
+ * by our private key.
+ */
+ p256_from_bin(rma_key_blob.raw_blob + 1, &pk_x);
+ p256_from_bin(rma_key_blob.raw_blob + 1 + P256_NBYTES, &pk_y);
+
+ /* Use input space for storing multiplication results. */
+ DCRYPTO_p256_point_mul(&pk_x, &pk_y, &d, &pk_x, &pk_y);
+
+ /* X value is the seed for the shared secret. */
+ p256_to_bin(&pk_x, secret);
+
+ /* Wipe out the private key just in case. */
+ always_memset(&d, 0, sizeof(d));
+}
+#endif
+
/**
* Create a new RMA challenge/response
*
@@ -139,15 +219,18 @@ int rma_create_challenge(void)
device_id, unique_device_id_size);
}
- /* Calculate a new ephemeral key pair */
+ /* Calculate a new ephemeral key pair and the shared secret. */
+#ifdef CONFIG_RMA_AUTH_USE_P256
+ p256_get_pub_key_and_secret(c.device_pub_key, secret);
+#endif
+#ifdef CONFIG_CURVE25519
X25519_keypair(c.device_pub_key, temp);
-
+ X25519(secret, temp, rma_key_blob.server_pub_key);
+#endif
/* Encode the challenge */
if (base32_encode(challenge, sizeof(challenge), cptr, 8 * sizeof(c), 9))
return EC_ERROR_UNKNOWN;
- /* Calculate the shared secret */
- X25519(secret, temp, rma_key_blob.server_pub_key);
/*
* Auth code is a truncated HMAC of the ephemeral public key, BoardID,
@@ -206,6 +289,7 @@ int rma_try_authcode(const char *code)
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;
@@ -223,22 +307,19 @@ static enum vendor_cmd_rc get_challenge(uint8_t *buf, size_t *buf_size)
*buf_size = sizeof(challenge) - 1;
memcpy(buf, rma_get_challenge(), *buf_size);
+
+ CPRINTF("generated challenge:\n\n");
+ for (i = 0; i < *buf_size; i++)
+ CPRINTF("%c", ((uint8_t *)buf)[i]);
+ CPRINTF("\n\n");
+
#ifdef CR50_DEV
- {
- size_t i;
-
- 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");
- }
-#endif
+ CPRINTF("expected authcode: ");
+ for (i = 0; i < RMA_AUTHCODE_CHARS; i++)
+ CPRINTF("%c", authcode[i]);
+ CPRINTF("\n");
+#endif
return VENDOR_RC_SUCCESS;
}
@@ -429,20 +510,6 @@ static int rma_auth_cmd(int argc, char **argv)
if (tpmh->command_code) {
ccprintf("RMA Auth error 0x%x\n", be32toh(tpmh->command_code));
rv = EC_ERROR_UNKNOWN;
- } else {
- /* Success, let's print out the challenge. */
- int i;
- char *challenge = (char *)(tpmh + 1);
-
- for (i = 0; i < RMA_CHALLENGE_CHARS; i++) {
- if (!(i % 5)) {
- if (!(i % 20))
- ccprintf("\n");
- ccprintf(" ");
- }
- ccprintf("%c", challenge[i]);
- }
- ccprintf("\n");
}
shared_mem_release(tpmh);
diff --git a/include/config.h b/include/config.h
index faf6f42764..44dac98103 100644
--- a/include/config.h
+++ b/include/config.h
@@ -2349,6 +2349,12 @@
/* Support RMA auth challenge-response */
#undef CONFIG_RMA_AUTH
+/*
+ * Use the p256 curve for RMA challenge-response calculations (x21559 is used
+ * by default).
+ */
+#undef CONFIG_RMA_AUTH_USE_P256
+
/* Enable hardware Random Number generator support */
#undef CONFIG_RNG