diff options
author | Randall Spangler <rspangler@chromium.org> | 2017-06-21 13:10:57 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-06-30 16:02:50 -0700 |
commit | 282765fdd409fd16ed1e092e5d7fee8de5af7a5a (patch) | |
tree | 6ba38fa099ef790c72d34f1caa458bd731aa39d3 /common | |
parent | 4a8b509020ce5104abf9b43335283cb39c7b75b2 (diff) | |
download | chrome-ec-282765fdd409fd16ed1e092e5d7fee8de5af7a5a.tar.gz |
common: Add RMA reset auth challenge-response crypto
RMA auth uses X25519 to generate a relatively small challenge and
response.
Currently, nothing calls the rma_auth code. We'll need console and
TPM vendor commands to do so.
BUG=b:37952913
BRANCH=none
TEST=make buildall
Change-Id: Iec7f2d0e3dc8243f79b009ead16bb3ba9f1bef9d
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/544184
Diffstat (limited to 'common')
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/rma_auth.c | 123 |
2 files changed, 124 insertions, 0 deletions
diff --git a/common/build.mk b/common/build.mk index d264c6c2e5..9954798988 100644 --- a/common/build.mk +++ b/common/build.mk @@ -81,6 +81,7 @@ common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o common-$(CONFIG_PSTORE)+=pstore_commands.o common-$(CONFIG_PWM)+=pwm.o common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o +common-$(CONFIG_RMA_AUTH)+=rma_auth.o common-$(CONFIG_RSA)+=rsa.o common-$(CONFIG_ROLLBACK)+=rollback.o common-$(CONFIG_RWSIG)+=rwsig.o diff --git a/common/rma_auth.c b/common/rma_auth.c new file mode 100644 index 0000000000..f178524927 --- /dev/null +++ b/common/rma_auth.c @@ -0,0 +1,123 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* RMA authorization challenge-response */ + +#include "common.h" +#include "base32.h" +#include "chip/g/board_id.h" +#include "curve25519.h" +#include "rma_auth.h" +#include "sha256.h" +#include "system.h" +#include "timer.h" +#include "util.h" + +/* Minimum time since system boot or last challenge before making a new one */ +#define CHALLENGE_INTERVAL (10 * SECOND) + +/* Number of tries to properly enter auth code */ +#define MAX_AUTHCODE_TRIES 3 + +/* Server public key and key ID */ +static const uint8_t server_pub_key[32] = CONFIG_RMA_AUTH_SERVER_PUBLIC_KEY; +static const uint8_t server_key_id = CONFIG_RMA_AUTH_SERVER_KEY_ID; + +static char challenge[RMA_CHALLENGE_BUF_SIZE]; +static char authcode[RMA_AUTHCODE_BUF_SIZE]; +static int tries_left; +static uint64_t last_challenge_time; + +/** + * Create a new RMA challenge/response + * + * @return EC_SUCCESS, EC_ERROR_TIMEOUT if too soon since the last challenge, + * or other non-zero error code. + */ +int rma_create_challenge(void) +{ + uint8_t temp[32]; /* Private key or HMAC */ + uint8_t secret[32]; + struct rma_challenge c; + struct board_id bid; + uint8_t *device_id; + uint8_t *cptr = (uint8_t *)&c; + uint64_t t; + + /* Clear the current challenge and authcode, if any */ + memset(challenge, 0, sizeof(challenge)); + memset(authcode, 0, sizeof(authcode)); + + /* Rate limit challenges */ + t = get_time().val; + if (t - last_challenge_time < CHALLENGE_INTERVAL) + return EC_ERROR_TIMEOUT; + last_challenge_time = t; + + memset(&c, 0, sizeof(c)); + c.version_key_id = RMA_CHALLENGE_VKID_BYTE( + RMA_CHALLENGE_VERSION, server_key_id); + + if (read_board_id(&bid)) + return EC_ERROR_UNKNOWN; + memcpy(c.board_id, &bid.type, sizeof(c.board_id)); + + if (system_get_chip_unique_id(&device_id) != sizeof(c.device_id)) + return EC_ERROR_UNKNOWN; + memcpy(c.device_id, device_id, sizeof(c.device_id)); + + /* Calculate a new ephemeral key pair */ + X25519_keypair(c.device_pub_key, temp); + + /* 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, server_pub_key); + + /* + * Auth code is a truncated HMAC of the ephemeral public key, BoardID, + * and DeviceID. Those are all in the right order in the challenge + * struct, after the version/key id byte. + */ + hmac_SHA256(temp, secret, sizeof(secret), cptr + 1, sizeof(c) - 1); + if (base32_encode(authcode, sizeof(authcode), temp, + RMA_AUTHCODE_CHARS * 5, 0)) + return EC_ERROR_UNKNOWN; + + tries_left = MAX_AUTHCODE_TRIES; + return EC_SUCCESS; +} + +const char *rma_get_challenge(void) +{ + return challenge; +} + +int rma_try_authcode(const char *code) +{ + int rv = EC_ERROR_INVAL; + + /* Fail if out of tries */ + if (!tries_left) + return EC_ERROR_ACCESS_DENIED; + + if (safe_memcmp(authcode, code, RMA_AUTHCODE_CHARS)) { + /* Mismatch */ + tries_left--; + } else { + rv = EC_SUCCESS; + tries_left = 0; + } + + /* Clear challenge and response if out of tries */ + if (!tries_left) { + memset(challenge, 0, sizeof(challenge)); + memset(authcode, 0, sizeof(authcode)); + } + + return rv; +} |