diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2018-05-26 21:01:12 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-30 20:38:52 -0700 |
commit | 7b0018521683070cfa5beda948a8ea5278d802cc (patch) | |
tree | 4da96a4d1b0f9091f1f63079d37e407b13a1f8ce | |
parent | 815251b070b5ab2d0c9a78ab659e02ce69ec50e8 (diff) | |
download | chrome-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.h | 9 | ||||
-rw-r--r-- | board/cr50/rma_key_blob.p256.test | bin | 0 -> 66 bytes | |||
-rw-r--r-- | common/build.mk | 8 | ||||
-rw-r--r-- | common/rma_auth.c | 137 | ||||
-rw-r--r-- | include/config.h | 6 |
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 Binary files differnew file mode 100644 index 0000000000..0e5cba1a6c --- /dev/null +++ b/board/cr50/rma_key_blob.p256.test 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 |