From c90a6253140bdb72b2b819bb09981b3fe3c3c4fc Mon Sep 17 00:00:00 2001 From: Tim Trippel Date: Thu, 29 Aug 2024 09:07:43 -0700 Subject: [PATCH] [cert] move cert keygen function to otbn_boot_services lib This moves the `cert_ecc_p256_keygen()` function from the `cert` lib to the `otbn_boot_services` lib to simplify on-host unit testing of the `cert` lib. The `otbn_boot_services` lib is only tested on-device at the moment due to the dependencies on specific OpenTitan hardware that is difficult to mock. In refactoring this, the cert_unittest is now fixed. Signed-off-by: Tim Trippel --- sw/device/silicon_creator/lib/BUILD | 1 + sw/device/silicon_creator/lib/cert/BUILD | 2 - sw/device/silicon_creator/lib/cert/cert.c | 37 ------------------- sw/device/silicon_creator/lib/cert/cert.h | 17 --------- .../silicon_creator/lib/otbn_boot_services.c | 35 ++++++++++++++++++ .../silicon_creator/lib/otbn_boot_services.h | 29 ++++++++++++++- sw/device/silicon_creator/manuf/base/BUILD | 1 + .../manuf/base/ft_personalize.c | 9 +++-- .../manuf/base/tpm_personalize_ext.c | 3 +- sw/device/silicon_creator/rom_ext/rom_ext.c | 12 +++--- 10 files changed, 79 insertions(+), 67 deletions(-) diff --git a/sw/device/silicon_creator/lib/BUILD b/sw/device/silicon_creator/lib/BUILD index 35ac3f22bfcbf..5106307847547 100644 --- a/sw/device/silicon_creator/lib/BUILD +++ b/sw/device/silicon_creator/lib/BUILD @@ -477,6 +477,7 @@ cc_library( "//sw/device/silicon_creator/lib:dbg_print", "//sw/device/silicon_creator/lib:error", "//sw/device/silicon_creator/lib/base:sec_mmio", + "//sw/device/silicon_creator/lib/base:util", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:hmac", "//sw/device/silicon_creator/lib/drivers:keymgr", diff --git a/sw/device/silicon_creator/lib/cert/BUILD b/sw/device/silicon_creator/lib/cert/BUILD index 177bafefedb86..54186f4ace855 100644 --- a/sw/device/silicon_creator/lib/cert/BUILD +++ b/sw/device/silicon_creator/lib/cert/BUILD @@ -67,8 +67,6 @@ cc_library( "//hw/top_earlgrey/ip_autogen/flash_ctrl:flash_ctrl_c_regs", "//sw/device/lib/base:hardened", "//sw/device/silicon_creator/lib:error", - "//sw/device/silicon_creator/lib:otbn_boot_services", - "//sw/device/silicon_creator/lib/base:util", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:hmac", "//sw/device/silicon_creator/lib/drivers:keymgr", diff --git a/sw/device/silicon_creator/lib/cert/cert.c b/sw/device/silicon_creator/lib/cert/cert.c index 3ed2a8ffac485..0082f438ca60c 100644 --- a/sw/device/silicon_creator/lib/cert/cert.c +++ b/sw/device/silicon_creator/lib/cert/cert.c @@ -5,53 +5,16 @@ #include "sw/device/silicon_creator/lib/cert/cert.h" #include "sw/device/lib/base/hardened.h" -#include "sw/device/silicon_creator/lib/base/util.h" #include "sw/device/silicon_creator/lib/cert/asn1.h" #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" -#include "sw/device/silicon_creator/lib/drivers/hmac.h" #include "sw/device/silicon_creator/lib/drivers/keymgr.h" #include "sw/device/silicon_creator/lib/error.h" -#include "sw/device/silicon_creator/lib/otbn_boot_services.h" #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h" #include "flash_ctrl_regs.h" // Generated. static uint8_t actual_serial_number[kCertX509Asn1SerialNumberSizeInBytes] = {0}; -/** - * Helper function to convert an attestation public key from little to big - * endian in place. - */ -static void curr_pubkey_le_to_be_convert(ecdsa_p256_public_key_t *pubkey) { - util_reverse_bytes(pubkey->x, kEcdsaP256PublicKeyCoordBytes); - util_reverse_bytes(pubkey->y, kEcdsaP256PublicKeyCoordBytes); -} - -rom_error_t cert_ecc_p256_keygen(sc_keymgr_ecc_key_t key, - hmac_digest_t *pubkey_id, - ecdsa_p256_public_key_t *pubkey) { - HARDENED_RETURN_IF_ERROR(sc_keymgr_state_check(key.required_keymgr_state)); - - // Generate / sideload key material into OTBN, and generate the ECC keypair. - HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_keygen( - key.keygen_seed_idx, key.type, *key.keymgr_diversifier, pubkey)); - - // Keys are represented in certificates in big endian format, but the key is - // output from OTBN in little endian format, so we convert the key to - // big endian format. - curr_pubkey_le_to_be_convert(pubkey); - - // Generate the key ID. - // - // Note: the certificate generation functions expect the digest to be in big - // endian form, but the HMAC driver returns the digest in little endian, so we - // re-format it. - hmac_sha256(pubkey, sizeof(*pubkey), pubkey_id); - util_reverse_bytes(pubkey_id, sizeof(*pubkey_id)); - - return kErrorOk; -} - uint32_t cert_x509_asn1_decode_size_header(const uint8_t *header) { if (header[0] != 0x30 || header[1] != 0x82) { return 0; diff --git a/sw/device/silicon_creator/lib/cert/cert.h b/sw/device/silicon_creator/lib/cert/cert.h index 66bb1800a675b..78130c024c048 100644 --- a/sw/device/silicon_creator/lib/cert/cert.h +++ b/sw/device/silicon_creator/lib/cert/cert.h @@ -91,23 +91,6 @@ typedef struct cert_key_id_pair { hmac_digest_t *cert; } cert_key_id_pair_t; -/** - * Generates an ECC P256 keypair to build a certificate around, using Keymgr - * and OTBN, returning the public key and a key ID (which is a SHA256 digest of - * the public key). - * - * Preconditions: keymgr has been initialized and cranked to the desired stage. - * - * @param key The description of the desired key to generate. - * @param[out] pubkey_id The public key ID (for embedding into certificates). - * @param[out] pubkey The public key. - * @return The result of the operation. - */ -OT_WARN_UNUSED_RESULT -rom_error_t cert_ecc_p256_keygen(sc_keymgr_ecc_key_t key, - hmac_digest_t *pubkey_id, - ecdsa_p256_public_key_t *pubkey); - /** * Decodes the ASN1 size header word to extract the number of bytes contained in * the ASN1 blob. diff --git a/sw/device/silicon_creator/lib/otbn_boot_services.c b/sw/device/silicon_creator/lib/otbn_boot_services.c index 9491af6a4ffc3..4d2ee98530071 100644 --- a/sw/device/silicon_creator/lib/otbn_boot_services.c +++ b/sw/device/silicon_creator/lib/otbn_boot_services.c @@ -6,6 +6,7 @@ #include "sw/device/silicon_creator/lib/attestation.h" #include "sw/device/silicon_creator/lib/base/sec_mmio.h" +#include "sw/device/silicon_creator/lib/base/util.h" #include "sw/device/silicon_creator/lib/dbg_print.h" #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/drivers/hmac.h" @@ -154,6 +155,40 @@ rom_error_t otbn_boot_attestation_keygen( return kErrorOk; } +/** + * Helper function to convert an ECC P256 public key from little to big endian + * in place. + */ +static void pubkey_le_to_be_convert(ecdsa_p256_public_key_t *pubkey) { + util_reverse_bytes(pubkey->x, kEcdsaP256PublicKeyCoordBytes); + util_reverse_bytes(pubkey->y, kEcdsaP256PublicKeyCoordBytes); +} + +rom_error_t otbn_boot_cert_ecc_p256_keygen(sc_keymgr_ecc_key_t key, + hmac_digest_t *pubkey_id, + ecdsa_p256_public_key_t *pubkey) { + HARDENED_RETURN_IF_ERROR(sc_keymgr_state_check(key.required_keymgr_state)); + + // Generate / sideload key material into OTBN, and generate the ECC keypair. + HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_keygen( + key.keygen_seed_idx, key.type, *key.keymgr_diversifier, pubkey)); + + // Keys are represented in certificates in big endian format, but the key is + // output from OTBN in little endian format, so we convert the key to + // big endian format. + pubkey_le_to_be_convert(pubkey); + + // Generate the key ID. + // + // Note: the certificate generation functions expect the digest to be in big + // endian form, but the HMAC driver returns the digest in little endian, so we + // re-format it. + hmac_sha256(pubkey, sizeof(*pubkey), pubkey_id); + util_reverse_bytes(pubkey_id, sizeof(*pubkey_id)); + + return kErrorOk; +} + rom_error_t otbn_boot_attestation_key_save( uint32_t additional_seed_idx, sc_keymgr_key_type_t key_type, sc_keymgr_diversification_t diversification) { diff --git a/sw/device/silicon_creator/lib/otbn_boot_services.h b/sw/device/silicon_creator/lib/otbn_boot_services.h index 0f6c12e586a4e..9ffa3ab5d1bf4 100644 --- a/sw/device/silicon_creator/lib/otbn_boot_services.h +++ b/sw/device/silicon_creator/lib/otbn_boot_services.h @@ -60,8 +60,17 @@ rom_error_t otbn_boot_attestation_keygen( uint32_t additional_seed_idx, sc_keymgr_key_type_t key_type, sc_keymgr_diversification_t diversification, ecdsa_p256_public_key_t *public_key); + /** - * Generate an attestation public key from a keymgr-derived secret. + * Generate a deterministic ECC P256 attestation public key from a + * keymgr-derived secret. + * + * This routine may be used to generate DICE attestation keys, TPM identity + * keys, or any other deterministic asymmetric ECC P256 keys required. DICE keys + * should be contructed from the "attestation" keymgr key type, while TPM keys + * should be constructed form the "sealing" key type. The former are bound to + * firmware updates, and change when ROM_EXT or Owner firmware is updated. The + * latter remain stable across the lifetime of an ownership of the chip. * * This routine triggers the key manager to sideload key material into OTBN, * and also loads in an extra seed to XOR with the key material. The final @@ -91,6 +100,24 @@ rom_error_t otbn_boot_attestation_keygen( sc_keymgr_diversification_t diversification, ecdsa_p256_public_key_t *public_key); +/** + * Wrapper for `otbn_boot_attestation_keygen()` that generates an ECC P256 + * keypair to build a certificate around, using Keymgr and OTBN, returning the + * public key (in big endian order for inserting into a cert) and a key ID + * (which is a SHA256 digest of the public key). + * + * Preconditions: keymgr has been initialized and cranked to the desired stage. + * + * @param key The description of the desired key to generate. + * @param[out] pubkey_id The public key ID (for embedding into certificates). + * @param[out] pubkey The public key. + * @return The result of the operation. + */ +OT_WARN_UNUSED_RESULT +rom_error_t otbn_boot_cert_ecc_p256_keygen(sc_keymgr_ecc_key_t key, + hmac_digest_t *pubkey_id, + ecdsa_p256_public_key_t *pubkey); + /** * Saves an attestation private key to OTBN's scratchpad. * diff --git a/sw/device/silicon_creator/manuf/base/BUILD b/sw/device/silicon_creator/manuf/base/BUILD index 04abb49a9f907..281419f5f13a8 100644 --- a/sw/device/silicon_creator/manuf/base/BUILD +++ b/sw/device/silicon_creator/manuf/base/BUILD @@ -264,6 +264,7 @@ cc_library( "//sw/device/lib/testing/test_framework:status", "//sw/device/lib/testing/test_framework:ujson_ottf", "//sw/device/silicon_creator/lib:attestation", + "//sw/device/silicon_creator/lib:otbn_boot_services", "//sw/device/silicon_creator/lib/cert", "//sw/device/silicon_creator/lib/cert:tpm", "//sw/device/silicon_creator/lib/cert:tpm_ek_template_library", diff --git a/sw/device/silicon_creator/manuf/base/ft_personalize.c b/sw/device/silicon_creator/manuf/base/ft_personalize.c index e95acc816c18f..29b173036f497 100644 --- a/sw/device/silicon_creator/manuf/base/ft_personalize.c +++ b/sw/device/silicon_creator/manuf/base/ft_personalize.c @@ -361,7 +361,8 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) { // Generate UDS keys and (TBS) cert. curr_cert_size = kUdsMaxTbsSizeBytes; - TRY(cert_ecc_p256_keygen(kDiceKeyUds, &uds_pubkey_id, &curr_pubkey)); + TRY(otbn_boot_cert_ecc_p256_keygen(kDiceKeyUds, &uds_pubkey_id, + &curr_pubkey)); TRY(otbn_boot_attestation_key_save(kDiceKeyUds.keygen_seed_idx, kDiceKeyUds.type, *kDiceKeyUds.keymgr_diversifier)); @@ -378,7 +379,8 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) { TRY(sc_keymgr_owner_int_advance(&sealing_binding_value, &attestation_binding_value, /*max_key_version=*/0)); - TRY(cert_ecc_p256_keygen(kDiceKeyCdi0, &cdi_0_pubkey_id, &curr_pubkey)); + TRY(otbn_boot_cert_ecc_p256_keygen(kDiceKeyCdi0, &cdi_0_pubkey_id, + &curr_pubkey)); TRY(dice_cdi_0_cert_build((hmac_digest_t *)certgen_inputs.rom_ext_measurement, certgen_inputs.rom_ext_security_version, &cdi_0_key_ids, &curr_pubkey, all_certs, @@ -393,7 +395,8 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) { TRY(sc_keymgr_owner_advance(&sealing_binding_value, &attestation_binding_value, /*max_key_version=*/0)); - TRY(cert_ecc_p256_keygen(kDiceKeyCdi1, &cdi_1_pubkey_id, &curr_pubkey)); + TRY(otbn_boot_cert_ecc_p256_keygen(kDiceKeyCdi1, &cdi_1_pubkey_id, + &curr_pubkey)); TRY(dice_cdi_1_cert_build( (hmac_digest_t *)certgen_inputs.owner_measurement, (hmac_digest_t *)certgen_inputs.owner_manifest_measurement, diff --git a/sw/device/silicon_creator/manuf/base/tpm_personalize_ext.c b/sw/device/silicon_creator/manuf/base/tpm_personalize_ext.c index ca9c1313afe2c..891998f6641e8 100644 --- a/sw/device/silicon_creator/manuf/base/tpm_personalize_ext.c +++ b/sw/device/silicon_creator/manuf/base/tpm_personalize_ext.c @@ -13,6 +13,7 @@ #include "sw/device/silicon_creator/lib/cert/tpm_ek.h" // Generated. #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/drivers/hmac.h" +#include "sw/device/silicon_creator/lib/otbn_boot_services.h" #include "sw/device/silicon_creator/manuf/base/personalize_ext.h" #include "sw/device/silicon_creator/manuf/lib/personalize.h" @@ -82,7 +83,7 @@ static status_t personalize_gen_tpm_ek_certificate( kAttestationSeedWords)); // Generate TPM EK keys and (TBS) cert. - TRY(cert_ecc_p256_keygen(kTpmKeyEk, &tpm_pubkey_id, &curr_pubkey)); + TRY(otbn_boot_cert_ecc_p256_keygen(kTpmKeyEk, &tpm_pubkey_id, &curr_pubkey)); curr_cert_size = sizeof(cert_buffer); TRY(tpm_ek_tbs_cert_build(&tpm_key_ids, &curr_pubkey, cert_buffer, diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index 52744c6c90e0c..3b9cc0530a13c 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -344,8 +344,8 @@ static rom_error_t rom_ext_attestation_silicon(void) { // Generate UDS keys. sc_keymgr_advance_state(); - HARDENED_RETURN_IF_ERROR(cert_ecc_p256_keygen(kDiceKeyUds, &uds_pubkey_id, - &curr_attestation_pubkey)); + HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen( + kDiceKeyUds, &uds_pubkey_id, &curr_attestation_pubkey)); HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save( kDiceKeyUds.keygen_seed_idx, kDiceKeyUds.type, *kDiceKeyUds.keymgr_diversifier)); @@ -396,8 +396,8 @@ static rom_error_t rom_ext_attestation_creator( sc_keymgr_owner_int_advance(/*sealing_binding=*/&seal_binding_value, /*attest_binding=*/&boot_measurements.rom_ext, rom_ext_manifest->max_key_version)); - HARDENED_RETURN_IF_ERROR(cert_ecc_p256_keygen(kDiceKeyCdi0, &cdi_0_pubkey_id, - &curr_attestation_pubkey)); + HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen( + kDiceKeyCdi0, &cdi_0_pubkey_id, &curr_attestation_pubkey)); hardened_bool_t cert_valid = kHardenedBoolFalse; uint32_t cert_size = 0; HARDENED_RETURN_IF_ERROR(cert_x509_asn1_check_serial_number( @@ -438,8 +438,8 @@ static rom_error_t rom_ext_attestation_owner(const manifest_t *owner_manifest) { sc_keymgr_owner_advance(/*sealing_binding=*/&zero_binding_value, /*attest_binding=*/&boot_measurements.bl0, owner_manifest->max_key_version)); - HARDENED_RETURN_IF_ERROR(cert_ecc_p256_keygen(kDiceKeyCdi1, &cdi_1_pubkey_id, - &curr_attestation_pubkey)); + HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen( + kDiceKeyCdi1, &cdi_1_pubkey_id, &curr_attestation_pubkey)); hardened_bool_t cert_valid = kHardenedBoolFalse; uint32_t cert_size = 0; HARDENED_RETURN_IF_ERROR(cert_x509_asn1_check_serial_number(