cr50: in dev mode allow unverified certificates

When running signed with dev keys and the fallback certificate is not
available, proceed installing unverified root certificate. This at
least allows to keep basic TPM functions like storing objects in NVMEM
to keep going. Added a new return value to indicate this condition.

BRANCH=cr50, cr50-mp
BUG=none
TEST=verified that it is possible to switch chromebook between prod
     and dev modes when running with a dev signed Cr50.

Change-Id: I5b16d0bcbcfb25368f65075e1d2d485a69cb729f
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1054990
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Andrey Pronin <apronin@chromium.org>
This commit is contained in:
Vadim Bendebury
2018-05-10 21:41:33 -07:00
committed by chrome-bot
parent d9354c9cd9
commit 607865dca4
4 changed files with 49 additions and 26 deletions

View File

@@ -1293,17 +1293,9 @@ int board_is_first_factory_boot(void)
}
/* Determine key type based on the key ID. */
static const char *key_type(uint32_t key_id)
static const char *key_type(const struct SignedHeader *h)
{
/*
* It is a mere convention, but all prod keys are required to have key
* IDs such, that bit D2 is set, and all dev keys are required to have
* key IDs such, that bit D2 is not set.
*
* This convention is enforced at the key generation time.
*/
if (key_id & (1 << 2))
if (G_SIGNED_FOR_PROD(h))
return "prod";
else
return "dev";
@@ -1330,12 +1322,12 @@ static int command_sysinfo(int argc, char **argv)
active = system_get_ro_image_copy();
vaddr = get_program_memory_addr(active);
h = (const struct SignedHeader *)vaddr;
ccprintf("RO keyid: 0x%08x(%s)\n", h->keyid, key_type(h->keyid));
ccprintf("RO keyid: 0x%08x(%s)\n", h->keyid, key_type(h));
active = system_get_image_copy();
vaddr = get_program_memory_addr(active);
h = (const struct SignedHeader *)vaddr;
ccprintf("RW keyid: 0x%08x(%s)\n", h->keyid, key_type(h->keyid));
ccprintf("RW keyid: 0x%08x(%s)\n", h->keyid, key_type(h));
ccprintf("DEV_ID: 0x%08x 0x%08x\n",
GREG32(FUSE, DEV_ID0), GREG32(FUSE, DEV_ID1));

View File

@@ -24,6 +24,7 @@
#include "flash_info.h"
#include "printf.h"
#include "registers.h"
#include "system.h"
#include "tpm_manufacture.h"
#include "tpm_registers.h"
@@ -610,10 +611,10 @@ enum manufacturing_status tpm_endorse(void)
HASH_update(&hmac.hash, p, RO_CERTS_REGION_SIZE - 32);
if (!DCRYPTO_equals(p + RO_CERTS_REGION_SIZE - 32,
DCRYPTO_HMAC_final(&hmac), 32)) {
#ifdef CR50_INCLUDE_FALLBACK_CERT
CPRINTF("%s: bad cert region hmac; falling back\n"
" to fixed endorsement\n", __func__);
const struct SignedHeader *h;
CPRINTF("%s: bad cert region hmac;", __func__);
#ifdef CR50_INCLUDE_FALLBACK_CERT
/* HMAC verification failure indicates either
* a manufacture fault, or mis-match in
* production mode and currently running
@@ -625,21 +626,39 @@ enum manufacturing_status tpm_endorse(void)
* by production infrastructure.
*/
if (!install_fixed_certs()) {
CPRINTF("%s: failed to install fixed "
"endorsement certs; \n"
" unknown endorsement state\n",
__func__);
CPRINTF(" failed to install fixed "
"endorsement certs;");
result = mnf_hmac_mismatch;
break;
}
#else
CPRINTF("%s: bad cert region hmac; no certs installed!"
"\n", __func__);
#endif
h = (const struct SignedHeader *)
get_program_memory_addr
(system_get_image_copy());
if (G_SIGNED_FOR_PROD(h)) {
/* TODO(ngm): is this state considered
* endorsement failure?
/* TODO(ngm): is this state considered
* endorsement failure?
*/
CPRINTF("NO certs installed\n");
result = mnf_hmac_mismatch;
break;
}
/*
* This will install bogus certificate, will happen
* only when Cr50 image is signed with dev key.
*
* Installing bogus certificate helps with simple TPM
* operations, as it allows to prevent TPM going
* through manufacturing process after every reset,
* but the generated RSA endorsement will not
* correspond to the certificate, which will cause
* problems when TPM identity is required.
*/
result = mnf_hmac_mismatch;
break;
result = mnf_unverified_cert;
CPRINTF("instaling UNVERIFIED certs\n");
#endif
}
if (!handle_cert(

View File

@@ -67,4 +67,15 @@ BUILD_ASSERT(sizeof(struct SignedHeader) == 1024);
BUILD_ASSERT(offsetof(struct SignedHeader, info_chk_) == 1020);
#define TOP_IMAGE_SIZE_BIT (1 << \
(sizeof(((struct SignedHeader *)0)->image_size) * 8 - 1))
/*
* It is a mere convention, but all prod keys are required to have key IDs
* such, that bit D2 is set, and all dev keys are required to have key IDs
* such, that bit D2 is not set.
*
* This convention is enforced at the key generation time.
*/
#define G_SIGNED_FOR_PROD(h) ((h)->keyid & (1 << 2))
#endif /* __CROS_EC_SIGNED_HEADER_H */

View File

@@ -28,6 +28,7 @@ enum manufacturing_status {
mnf_ecc_proc = 9,
mnf_store = 10,
mnf_manufactured = 11,
mnf_unverified_cert = 12,
};
enum manufacturing_status tpm_endorse(void);