summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2016-07-14 20:49:07 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2016-07-17 17:28:13 +0000
commit5155c10c671fd9cc683baa84001e4183c0521555 (patch)
tree3c89ef5a9c50f108ba27e927646128a6a704e7f4
parent61a0fe734e808d1dbdf56fb6023e04adf66553b3 (diff)
downloadchrome-ec-5155c10c671fd9cc683baa84001e4183c0521555.tar.gz
CR50: improve certificate installation error reporting
A lot of things can go wrong when installing certificates, and the process is happening in a locked down environment, which greatly complicates troubleshooting. This patch adds simple error reporting: should there be an error, a two byte line number of the point where error was reported in manufacture.c is returned. In case of success, the request phase returns the full PDU. as before, and the cert installation phase returns a 16 bit zero value. An added benefit is receiving of the zero size response, which indicates that the manufacture command is not supported on the target. BRANCH=none BUG=chrome-os-partner:50115 TEST=tried to install a certificate on an unprepared device, observed the following expected response: $ sudo ./cros_ack.py -i /tmp Starting MPSSE at 800 kHz Connected to device vid:did:rid of 1ae0:0028:00 CHIP ID: 00:0200428401000003:010039:0200 New max timeout: 31 s RSA PERSO RESULT: 287 ECC PERSO RESULT: 341 FAIL Change-Id: Ib0661afae322eb70700fd6d12ab2e96017baf0bf Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/360682 Tested-by: Nagendra Modadugu <ngm@google.com> Reviewed-by: Nagendra Modadugu <ngm@google.com>
-rw-r--r--board/cr50/tpm2/manufacture.c155
-rwxr-xr-xtest/tpm_test/cros_ack.py20
2 files changed, 118 insertions, 57 deletions
diff --git a/board/cr50/tpm2/manufacture.c b/board/cr50/tpm2/manufacture.c
index 7f230aed6d..8dba5e18bf 100644
--- a/board/cr50/tpm2/manufacture.c
+++ b/board/cr50/tpm2/manufacture.c
@@ -44,7 +44,7 @@
#define INFO1_SENTINEL_OFFSET FLASH_INFO_MANUFACTURE_STATE_OFFSET
#define INFO1_EPS_OFFSET FLASH_INFO_MANUFACTURE_STATE_OFFSET
-#define CPRINTF(format, args...) cprintf(CC_TPM, format, ## args)
+#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ## args)
#define FRAME_SIZE 1024
#define KEY_SIZE 32
@@ -123,6 +123,9 @@ struct cros_perso_ok_response_v0 {
uint16_t ok;
} __packed;
+/* Is set to the line number where error was detected, zero on success. */
+static uint16_t error_code;
+
/* TODO(ngm): replace with real pub key. */
static const uint32_t ENDORSEMENT_CA_RSA_N[64] = {
0xfa3b34ed, 0x3c59ad05, 0x912d6623, 0x83302402,
@@ -269,18 +272,21 @@ static int validate_cert_rsa(
TPM2B_PRIVATE_KEY_RSA p;
if (_cpri__GenerateKeyRSA(
- &N.b, &p.b, 2048, RSA_F4,
- TPM_ALG_SHA256, &seed.b, VENDOR_EK_RSA_LABEL,
- (TPM2B *) &RSA_TEMPLATE_EK_EXTRA.b, NULL)
- != CRYPT_SUCCESS)
+ &N.b, &p.b, 2048, RSA_F4,
+ TPM_ALG_SHA256, &seed.b, VENDOR_EK_RSA_LABEL,
+ (TPM2B *) &RSA_TEMPLATE_EK_EXTRA.b, NULL)
+ != CRYPT_SUCCESS) {
+ error_code = __LINE__;
break;
+ }
if (memstr(cert->cert, cert->cert_len,
- N.b.buffer, N.b.size) >= 0)
+ N.b.buffer, N.b.size) >= 0) {
result = 1;
- else
+ } else {
+ error_code = __LINE__;
result = 0;
-
+ }
memset(N.b.buffer, 0, 256);
memset(p.b.buffer, 0, 128);
} while (0);
@@ -320,17 +326,21 @@ static int validate_cert_ecc(
TPM2B_ECC_PARAMETER d;
if (_cpri__GenerateKeyEcc(
- &q, &d, TPM_ECC_NIST_P256, TPM_ALG_SHA256,
- &seed.b, VENDOR_EK_ECC_LABEL,
- (TPM2B *) &ECC_TEMPLATE_EK_EXTRA.b, NULL)
- != CRYPT_SUCCESS)
+ &q, &d, TPM_ECC_NIST_P256, TPM_ALG_SHA256,
+ &seed.b, VENDOR_EK_ECC_LABEL,
+ (TPM2B *) &ECC_TEMPLATE_EK_EXTRA.b, NULL)
+ != CRYPT_SUCCESS) {
+ error_code = __LINE__;
break;
+ }
if (memstr(cert->cert, cert->cert_len,
- q.x.b.buffer, P256_NBYTES) >= 0)
+ q.x.b.buffer, P256_NBYTES) >= 0) {
result = 1;
- else
+ } else {
+ error_code = __LINE__;
result = 0;
+ }
memset(q.x.b.buffer, 0, P256_NBYTES);
memset(q.y.b.buffer, 0, P256_NBYTES);
@@ -347,24 +357,31 @@ static int validate_cert(
const uint8_t eps[PRIMARY_SEED_SIZE])
{
if (cert_info->component_type != CROS_PERSO_COMPONENT_TYPE_RSA_CERT &&
- cert_info->component_type !=
- CROS_PERSO_COMPONENT_TYPE_P256_CERT)
+ cert_info->component_type !=
+ CROS_PERSO_COMPONENT_TYPE_P256_CERT) {
+ error_code = __LINE__;
return 0; /* Invalid component type. */
+ }
if (cert_info->component_size != sizeof(
- struct cros_perso_certificate_response_v0))
+ struct cros_perso_certificate_response_v0)) {
+ error_code = __LINE__;
return 0; /* Invalid component size. */
+ }
/* TODO(ngm): verify key_id against HIK/FRK0. */
if (cert->cert_len > CROS_ENDORSEMENT_CERT_MAX_SIZE ||
- cert->cert_len > MAX_NV_BUFFER_SIZE)
+ cert->cert_len > MAX_NV_BUFFER_SIZE) {
+ error_code = __LINE__;
return 0;
+ }
/* Verify certificate signature. */
if (!DCRYPTO_x509_verify(cert->cert, cert->cert_len,
- &ENDORSEMENT_CA_RSA_PUB))
+ &ENDORSEMENT_CA_RSA_PUB)) {
+ error_code = __LINE__;
return 0;
-
+ }
/* Generate corresponding key, and match cert. */
/* TODO(ngm): time consuming: remove from production runs. */
if (cert_info->component_type == CROS_PERSO_COMPONENT_TYPE_RSA_CERT)
@@ -494,35 +511,56 @@ static int compute_frk2(uint8_t frk2[AES256_BLOCK_CIPHER_KEY_SIZE])
GREG32(KEYMGR, SHA_TRIG) =
GC_KEYMGR_SHA_TRIG_TRIG_RESET_MASK;
- if (hw_key_ladder_step(KEYMGR_CERT_0))
+ if (hw_key_ladder_step(KEYMGR_CERT_0)) {
+ error_code = __LINE__;
return 0;
+ }
/* Derive HC_PHIK --> Deposited into ISR0 */
- if (hw_key_ladder_step(KEYMGR_CERT_3))
+ if (hw_key_ladder_step(KEYMGR_CERT_3)) {
+ error_code = __LINE__;
return 0;
+ }
/* Cryptographically mix OBS-FBS --> Deposited into ISR1 */
- if (hw_key_ladder_step(KEYMGR_CERT_4))
+ if (hw_key_ladder_step(KEYMGR_CERT_4)) {
+ error_code = __LINE__;
return 0;
+ }
+
/* Derive HIK_RT --> Deposited into ISR0 */
- if (hw_key_ladder_step(KEYMGR_CERT_5))
+ if (hw_key_ladder_step(KEYMGR_CERT_5)) {
+ error_code = __LINE__;
return 0;
+ }
+
/* Derive BL_HIK --> Deposited into ISR0 */
- if (hw_key_ladder_step(KEYMGR_CERT_7))
+ if (hw_key_ladder_step(KEYMGR_CERT_7)) {
+ error_code = __LINE__;
return 0;
+ }
/* Generate FRK2 by executing certs 15, 20, 25, and 26 */
- if (hw_key_ladder_step(KEYMGR_CERT_15))
+ if (hw_key_ladder_step(KEYMGR_CERT_15)) {
+ error_code = __LINE__;
return 0;
- if (hw_key_ladder_step(KEYMGR_CERT_20))
+ }
+
+ if (hw_key_ladder_step(KEYMGR_CERT_20)) {
+ error_code = __LINE__;
return 0;
+ }
for (i = 0; i < k_cr50_max_fw_major_version -
K_CROS_FW_MAJOR_VERSION; i++) {
- if (hw_key_ladder_step(KEYMGR_CERT_25))
+ if (hw_key_ladder_step(KEYMGR_CERT_25)) {
+ error_code = __LINE__;
return 0;
+ }
}
- if (hw_key_ladder_step(KEYMGR_CERT_26))
+ if (hw_key_ladder_step(KEYMGR_CERT_26)) {
+ error_code = __LINE__;
return 0;
+ }
memcpy(frk2, (void *) GREG32_ADDR(KEYMGR, HKEY_FRR0),
AES256_BLOCK_CIPHER_KEY_SIZE);
return 1;
@@ -544,6 +582,7 @@ static int get_decrypted_eps(uint8_t eps[PRIMARY_SEED_SIZE])
if (flash_physical_info_read_word(
INFO1_EPS_OFFSET + i, &word) != EC_SUCCESS) {
memset(frk2, 0, sizeof(frk2));
+ error_code = __LINE__;
return 0; /* Flash read INFO1 failed. */
}
memcpy(eps + i, &word, sizeof(word));
@@ -624,6 +663,13 @@ int tpm_manufactured(void)
#endif
}
+static void prepare_ack_cmd_error_return(uint16_t *buffer,
+ size_t *response_size, uint16_t code)
+{
+ *buffer = code;
+ *response_size = sizeof(code);
+}
+
static void ack_command_handler(void *request, size_t command_size,
size_t *response_size)
{
@@ -638,18 +684,22 @@ static void ack_command_handler(void *request, size_t command_size,
struct cros_ack_response_v0 *ack_response = request;
CPRINTF("%s size %d\n", __func__, command_size);
- *response_size = 0;
- if (tpm_manufactured())
+ if (tpm_manufactured()) {
+ prepare_ack_cmd_error_return(request,
+ response_size, __LINE__);
return;
+ }
if (command_size) {
- CPRINTF("%s command size is %d\n", __func__, command_size);
+ prepare_ack_cmd_error_return(request,
+ response_size, __LINE__);
return;
}
if (!get_hw_cat(&hw_cat)) {
- CPRINTF("%s unknown hw category %d\n", __func__, hw_cat);
+ prepare_ack_cmd_error_return(request,
+ response_size, __LINE__);
return;
}
@@ -686,43 +736,50 @@ static int p256_cert_done;
static void perso_command_handler(void *request, size_t command_size,
size_t *response_size)
{
- uint16_t ok = RESPONSE_NOT_OK;
uint8_t eps[PRIMARY_SEED_SIZE];
const struct cros_perso_response_v0 *perso_response = request;
struct cros_perso_ok_response_v0 *ok_response =
(struct cros_perso_ok_response_v0 *) request;
CPRINTF("%s size %d\n", __func__, command_size);
- *response_size = 0;
+ *response_size = sizeof(*ok_response);
+ error_code = ~0; /* catch all. */
do {
- if (tpm_manufactured())
+ if (tpm_manufactured()) {
+ error_code = __LINE__;
break;
+ }
- if (command_size != sizeof(struct cros_perso_response_v0))
+ if (command_size != sizeof(struct cros_perso_response_v0)) {
+ error_code = __LINE__;
break;
+ }
if (!get_decrypted_eps(eps))
break;
/* Write RSA / P256 endorsement certificate. */
if (!validate_cert(&perso_response->cert_info,
- &perso_response->cert, eps))
- break; /* Invalid cert. */
+ &perso_response->cert, eps))
+ break;
if (!rsa_cert_done && !p256_cert_done)
/* Input validated; initialize flash, TPM globals. */
- if (TPM_Manufacture(1) != 0)
+ if (TPM_Manufacture(1) != 0) {
+ error_code = __LINE__;
break;
+ }
+ /* TODO(ngm): verify that storage succeeded. */
if (!store_cert(perso_response->cert_info.component_type,
- &perso_response->cert))
+ &perso_response->cert)) {
+ error_code = __LINE__;
break; /* Internal failure. */
-
- /* TODO(ngm): verify that storage succeeded. */
+ }
if (perso_response->cert_info.component_type ==
- CROS_PERSO_COMPONENT_TYPE_RSA_CERT)
+ CROS_PERSO_COMPONENT_TYPE_RSA_CERT)
rsa_cert_done = 1;
else
p256_cert_done = 1;
@@ -732,8 +789,10 @@ static void perso_command_handler(void *request, size_t command_size,
flash_info_write_enable();
/* Copy EPS from INFO1 to flash data region. */
- if (!store_eps(eps))
+ if (!store_eps(eps)) {
+ error_code = __LINE__;
break;
+ }
/* TODO: generate RSA and ECC keys,
* and verify matching cert.
@@ -742,13 +801,11 @@ static void perso_command_handler(void *request, size_t command_size,
/* Mark as manufactured. */
manufacture_complete();
}
-
- ok = RESPONSE_OK;
+ error_code = 0;
} while (0);
memset(eps, 0, sizeof(eps));
- *response_size = sizeof(*ok_response);
- ok_response->ok = ok;
+ ok_response->ok = error_code;
}
DECLARE_EXTENSION_COMMAND(EXTENSION_MANUFACTURE_ACK, ack_command_handler);
diff --git a/test/tpm_test/cros_ack.py b/test/tpm_test/cros_ack.py
index d2f2b4e99b..801378e85a 100755
--- a/test/tpm_test/cros_ack.py
+++ b/test/tpm_test/cros_ack.py
@@ -134,12 +134,16 @@ def cros_ack():
# Skip sending the TPM2_Startup() command.
try_startup=False)
wrapped_response = t.command(t.wrap_ext_command(subcmd.MANUFACTURE_ACK, ''))
- if len(wrapped_response) == TPM_HEADER_SIZE:
- print('Error: manufacture complete, or unknown error')
+ if len(wrapped_response) <= TPM_HEADER_SIZE:
+ print('Error: manufacture not supported')
return False
# Skip over TPM header and unpack Ack response.
ack_body = wrapped_response[TPM_HEADER_SIZE:]
+ if len(ack_body) == 2:
+ print('Error: %d' % struct.unpack('<H', ack_body))
+ return False
+
ack = CrosAckResponse_v0._make(struct.unpack(
CrosAckResponse_v0_FMT, ack_body))
@@ -168,20 +172,20 @@ def cros_ack():
response = t.command(blob.rsa_blob)
# Skip over TPM header and unpack Ok response.
rsa_ok = struct.unpack(CrosOkResponse_v0_FMT, response[TPM_HEADER_SIZE:])[0]
- print(utils.cursor_back() + 'RSA PERSO RESULT: %x' % rsa_ok)
+ print(utils.cursor_back() + 'RSA PERSO RESULT: %d' % rsa_ok)
# Blobs include serialized TPM header.
response = t.command(blob.ecc_blob)
# Skip over TPM header and unpack Ok response.
ecc_ok = struct.unpack(CrosOkResponse_v0_FMT, response[TPM_HEADER_SIZE:])[0]
- print(utils.cursor_back() + 'ECC PERSO RESULT: %x' % ecc_ok)
+ print(utils.cursor_back() + 'ECC PERSO RESULT: %d' % ecc_ok)
- if rsa_ok == ecc_ok and ecc_ok == 0x8080:
- print(utils.cursor_back() + 'SUCCESS')
- return True
- else:
+ if rsa_ok or ecc_ok:
print(utils.cursor_back() + 'FAIL')
return False
+ else:
+ print(utils.cursor_back() + 'SUCCESS')
+ return True
def parse_args():