diff options
-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 |