Skip to content

Commit

Permalink
[sw] Change cert template engine to pre-generated method.
Browse files Browse the repository at this point in the history
The current certificate builder library consumes ~7KB.
Additionally, the immutable ROM extension duplicates the ASN.1/CBOR library,
adding another ~1.5KB.

Given the proximity to the 64KB size limit, this change aims to provide a
more lightweight certificate construction approach.

Change-Id: I11a10ca1c833d238cae67ef30daf9ffcac40e9ae
Signed-off-by: Yi-Hsuan Deng <[email protected]>
  • Loading branch information
sasdf committed Jan 21, 2025
1 parent 89cd29d commit 4fcab61
Show file tree
Hide file tree
Showing 18 changed files with 1,293 additions and 575 deletions.
15 changes: 11 additions & 4 deletions rules/certificates.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,21 @@ def certificate_template(name, template, cert_format = "x509"):
output_group = "unittest",
)

if cert_format == "x509":
runtime_deps = [
"@//sw/device/silicon_creator/lib/cert:asn1",
"@//sw/device/silicon_creator/lib/cert:template",
]
else:
runtime_deps = [
"@//sw/device/silicon_creator/lib/cert:cbor",
]

native.cc_library(
name = "{}_library".format(name),
srcs = [":{}_srcs".format(name)],
hdrs = [":{}_hdrs".format(name)],
deps = [
"@//sw/device/silicon_creator/lib/cert:asn1",
"@//sw/device/silicon_creator/lib/cert:cbor",
],
deps = runtime_deps,
)

native.cc_test(
Expand Down
11 changes: 11 additions & 0 deletions sw/device/silicon_creator/lib/cert/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ cc_test(
],
)

cc_library(
name = "template",
srcs = ["template.c"],
hdrs = ["template.h"],
deps = [
"//sw/device/lib/base:macros",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
],
)

cc_library(
name = "cert",
srcs = ["cert.c"],
Expand Down
23 changes: 15 additions & 8 deletions sw/device/silicon_creator/lib/cert/cdi_0.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,50 @@
// (x and y) which are 32-bytes integers.
owner_intermediate_pub_key_ec_x: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 32],
},
owner_intermediate_pub_key_ec_y: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 32],
},
// Owner intermediate public key ID: this is a 20-byte hash
// derived from the owner intermediate public key.
owner_intermediate_pub_key_id: {
type: "byte-array",
size: 20,
exact-size: 20,
exact-int-size: 20,
},
// This is the identifier of the public key used to
// sign this certificate (creator key).
creator_pub_key_id: {
type: "byte-array",
size: 20,
exact-size: 20,
exact-int-size: 20,
},
// Hash of the ROM_EXT (SHA256).
rom_ext_hash: {
type: "byte-array",
size: 32,
exact-size: 32,
},
// ROM_EXT security version, used to prevent rollback.
rom_ext_security_version: {
type: "integer",
size: 4,
exact-size: 4,
exact-int-size: 4,
}
// Certificate signature: the result of signing with ECDSA
// are two integers named "r" and "s"
cert_signature_r: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 32],
},
cert_signature_s: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 32],
},
},

Expand Down
25 changes: 16 additions & 9 deletions sw/device/silicon_creator/lib/cert/cdi_1.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,55 @@
// (x and y) which are 32-bytes integers.
owner_pub_key_ec_x: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 33],
},
owner_pub_key_ec_y: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 33],
},
// Owner public key ID: this is a 20-byte hash
// derived from the owner public key.
owner_pub_key_id: {
type: "byte-array",
size: 20,
exact-size: 20,
exact-int-size: 20,
},
// This is the identifier of the public key used to
// sign this certificate (owner intermediate key).
owner_intermediate_pub_key_id: {
type: "byte-array",
size: 20,
exact-size: 20,
exact-int-size: 20,
},
// Hash of the owner stage firmware (SHA256).
owner_hash: {
type: "byte-array",
size: 32,
exact-size: 32,
},
// Hash of the owner manifest (SHA256).
owner_manifest_hash: {
type: "byte-array",
size: 32,
exact-size: 32,
},
// Owner security version, used to prevent rollback.
owner_security_version: {
type: "integer",
size: 4,
exact-size: 4,
exact-int-size: 4,
}
// Certificate signature: the result of signing with ECDSA
// are two integers named "r" and "s"
cert_signature_r: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 33],
},
cert_signature_s: {
type: "integer",
size: 32,
exact-size: 32,
int-size: [24, 33],
},
},

Expand Down
114 changes: 83 additions & 31 deletions sw/device/silicon_creator/lib/cert/dice.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ static ecdsa_p256_signature_t curr_tbs_signature = {.r = {0}, .s = {0}};
static uint8_t cdi_0_tbs_buffer[kCdi0MaxTbsSizeBytes];
static cdi_0_sig_values_t cdi_0_cert_params = {
.tbs = cdi_0_tbs_buffer,
.tbs_size = kCdi0MaxTbsSizeBytes,
};
static uint8_t cdi_1_tbs_buffer[kCdi1MaxTbsSizeBytes];
static cdi_1_sig_values_t cdi_1_cert_params = {
.tbs = cdi_1_tbs_buffer,
.tbs_size = kCdi1MaxTbsSizeBytes,
};

const dice_cert_format_t kDiceCertFormat = kDiceCertFormatX509TcbInfo;
Expand All @@ -58,29 +56,42 @@ rom_error_t dice_uds_tbs_cert_build(
hmac_digest_t *otp_rot_creator_auth_state_measurement,
cert_key_id_pair_t *key_ids, ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size) {
static_assert(kUdsExactOtpCreatorSwCfgHashSizeBytes == kHmacDigestNumBytes,
"Invalid variable size.");
static_assert(kUdsExactOtpOwnerSwCfgHashSizeBytes == kHmacDigestNumBytes,
"Invalid variable size.");
static_assert(
kUdsExactOtpRotCreatorAuthCodesignHashSizeBytes == kHmacDigestNumBytes,
"Invalid variable size.");
static_assert(
kUdsExactOtpRotCreatorAuthStateHashSizeBytes == kHmacDigestNumBytes,
"Invalid variable size.");
static_assert(kUdsExactCreatorPubKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(kUdsExactAuthKeyKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(
kUdsExactCreatorPubKeyEcXSizeBytes == kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");
static_assert(
kUdsExactCreatorPubKeyEcYSizeBytes == kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");

// Generate the TBS certificate.
uds_tbs_values_t uds_cert_tbs_params = {
.otp_creator_sw_cfg_hash =
(unsigned char *)otp_creator_sw_cfg_measurement->digest,
.otp_creator_sw_cfg_hash_size = kHmacDigestNumBytes,
.otp_owner_sw_cfg_hash =
(unsigned char *)otp_owner_sw_cfg_measurement->digest,
.otp_owner_sw_cfg_hash_size = kHmacDigestNumBytes,
.otp_rot_creator_auth_codesign_hash =
(unsigned char *)otp_rot_creator_auth_codesign_measurement->digest,
.otp_rot_creator_auth_codesign_hash_size = kHmacDigestNumBytes,
.otp_rot_creator_auth_state_hash =
(unsigned char *)otp_rot_creator_auth_state_measurement->digest,
.otp_rot_creator_auth_state_hash_size = kHmacDigestNumBytes,
.debug_flag = is_debug_exposed(),
.creator_pub_key_id = (unsigned char *)key_ids->cert->digest,
.creator_pub_key_id_size = kCertKeyIdSizeInBytes,
.auth_key_key_id = (unsigned char *)key_ids->endorsement->digest,
.auth_key_key_id_size = kCertKeyIdSizeInBytes,
.creator_pub_key_ec_x = (unsigned char *)uds_pubkey->x,
.creator_pub_key_ec_x_size = kEcdsaP256PublicKeyCoordBytes,
.creator_pub_key_ec_y = (unsigned char *)uds_pubkey->y,
.creator_pub_key_ec_y_size = kEcdsaP256PublicKeyCoordBytes,
};
HARDENED_RETURN_IF_ERROR(
uds_build_tbs(&uds_cert_tbs_params, tbs_cert, tbs_cert_size));
Expand All @@ -93,36 +104,55 @@ rom_error_t dice_cdi_0_cert_build(hmac_digest_t *rom_ext_measurement,
cert_key_id_pair_t *key_ids,
ecdsa_p256_public_key_t *cdi_0_pubkey,
uint8_t *cert, size_t *cert_size) {
// Modify the security_version integer to achieve fixed-length encoding.
rom_ext_security_version &= 0x7fffffff;
rom_ext_security_version |= 0x40000000;

static_assert(kCdi0ExactRomExtHashSizeBytes == kDiceMeasurementSizeInBytes,
"Invalid variable size.");
static_assert(
kCdi0ExactOwnerIntermediatePubKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(kCdi0ExactCreatorPubKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(kCdi0ExactOwnerIntermediatePubKeyEcXSizeBytes ==
kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");
static_assert(kCdi0ExactOwnerIntermediatePubKeyEcYSizeBytes ==
kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");

// Generate the TBS certificate.
cdi_0_tbs_values_t cdi_0_cert_tbs_params = {
.rom_ext_hash = (unsigned char *)rom_ext_measurement->digest,
.rom_ext_hash_size = kDiceMeasurementSizeInBytes,
.rom_ext_security_version = rom_ext_security_version,
.owner_intermediate_pub_key_id = (unsigned char *)key_ids->cert->digest,
.owner_intermediate_pub_key_id_size = kCertKeyIdSizeInBytes,
.creator_pub_key_id = (unsigned char *)key_ids->endorsement->digest,
.creator_pub_key_id_size = kCertKeyIdSizeInBytes,
.owner_intermediate_pub_key_ec_x = (unsigned char *)cdi_0_pubkey->x,
.owner_intermediate_pub_key_ec_x_size = kEcdsaP256PublicKeyCoordBytes,
.owner_intermediate_pub_key_ec_y = (unsigned char *)cdi_0_pubkey->y,
.owner_intermediate_pub_key_ec_y_size = kEcdsaP256PublicKeyCoordBytes,
};

size_t tbs_size = kCdi0MaxTbsSizeBytes;
HARDENED_RETURN_IF_ERROR(cdi_0_build_tbs(&cdi_0_cert_tbs_params,
cdi_0_cert_params.tbs,
&cdi_0_cert_params.tbs_size));
cdi_0_cert_params.tbs, &tbs_size));

// Sign the TBS and generate the certificate.
hmac_digest_t tbs_digest;
hmac_sha256(cdi_0_cert_params.tbs, cdi_0_cert_params.tbs_size, &tbs_digest);
hmac_sha256(cdi_0_cert_params.tbs, tbs_size, &tbs_digest);
HARDENED_RETURN_IF_ERROR(
otbn_boot_attestation_endorse(&tbs_digest, &curr_tbs_signature));
util_p256_signature_le_to_be_convert(curr_tbs_signature.r,
curr_tbs_signature.s);

static_assert(
kCdi0ExactCertSignatureRSizeBytes == kAttestationSignatureBytes / 2,
"Invalid variable size.");
static_assert(
kCdi0ExactCertSignatureSSizeBytes == kAttestationSignatureBytes / 2,
"Invalid variable size.");

cdi_0_cert_params.cert_signature_r = (unsigned char *)curr_tbs_signature.r;
cdi_0_cert_params.cert_signature_r_size = kAttestationSignatureBytes / 2;
cdi_0_cert_params.cert_signature_s = (unsigned char *)curr_tbs_signature.s;
cdi_0_cert_params.cert_signature_s_size = kAttestationSignatureBytes / 2;
HARDENED_RETURN_IF_ERROR(
cdi_0_build_cert(&cdi_0_cert_params, cert, cert_size));

Expand All @@ -140,39 +170,61 @@ rom_error_t dice_cdi_1_cert_build(hmac_digest_t *owner_measurement,
cert_key_id_pair_t *key_ids,
ecdsa_p256_public_key_t *cdi_1_pubkey,
uint8_t *cert, size_t *cert_size) {
// Modify the security_version integer to achieve fixed-length encoding.
owner_security_version &= 0x7fffffff;
owner_security_version |= 0x40000000;

static_assert(kCdi1ExactOwnerHashSizeBytes == kDiceMeasurementSizeInBytes,
"Invalid variable size.");
static_assert(
kCdi1ExactOwnerManifestHashSizeBytes == kDiceMeasurementSizeInBytes,
"Invalid variable size.");
static_assert(kCdi1ExactOwnerPubKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(
kCdi1ExactOwnerIntermediatePubKeyIdSizeBytes == kCertKeyIdSizeInBytes,
"Invalid variable size.");
static_assert(
kCdi1ExactOwnerPubKeyEcXSizeBytes == kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");
static_assert(
kCdi1ExactOwnerPubKeyEcYSizeBytes == kEcdsaP256PublicKeyCoordBytes,
"Invalid variable size.");

// Generate the TBS certificate.
cdi_1_tbs_values_t cdi_1_cert_tbs_params = {
.owner_hash = (unsigned char *)owner_measurement->digest,
.owner_hash_size = kDiceMeasurementSizeInBytes,
.owner_manifest_hash =
(unsigned char *)owner_manifest_measurement->digest,
.owner_manifest_hash_size = kDiceMeasurementSizeInBytes,
.owner_security_version = owner_security_version,
.owner_pub_key_id = (unsigned char *)key_ids->cert->digest,
.owner_pub_key_id_size = kCertKeyIdSizeInBytes,
.owner_intermediate_pub_key_id =
(unsigned char *)key_ids->endorsement->digest,
.owner_intermediate_pub_key_id_size = kCertKeyIdSizeInBytes,
.owner_pub_key_ec_x = (unsigned char *)cdi_1_pubkey->x,
.owner_pub_key_ec_x_size = kEcdsaP256PublicKeyCoordBytes,
.owner_pub_key_ec_y = (unsigned char *)cdi_1_pubkey->y,
.owner_pub_key_ec_y_size = kEcdsaP256PublicKeyCoordBytes,
};

size_t tbs_size = kCdi1MaxTbsSizeBytes;
HARDENED_RETURN_IF_ERROR(cdi_1_build_tbs(&cdi_1_cert_tbs_params,
cdi_1_cert_params.tbs,
&cdi_1_cert_params.tbs_size));
cdi_1_cert_params.tbs, &tbs_size));

// Sign the TBS and generate the certificate.
hmac_digest_t tbs_digest;
hmac_sha256(cdi_1_cert_params.tbs, cdi_1_cert_params.tbs_size, &tbs_digest);
hmac_sha256(cdi_1_cert_params.tbs, tbs_size, &tbs_digest);
HARDENED_RETURN_IF_ERROR(
otbn_boot_attestation_endorse(&tbs_digest, &curr_tbs_signature));
util_p256_signature_le_to_be_convert(curr_tbs_signature.r,
curr_tbs_signature.s);

static_assert(
kCdi0ExactCertSignatureRSizeBytes == kAttestationSignatureBytes / 2,
"Invalid variable size.");
static_assert(
kCdi0ExactCertSignatureSSizeBytes == kAttestationSignatureBytes / 2,
"Invalid variable size.");

cdi_1_cert_params.cert_signature_r = (unsigned char *)curr_tbs_signature.r;
cdi_1_cert_params.cert_signature_r_size = kAttestationSignatureBytes / 2;
cdi_1_cert_params.cert_signature_s = (unsigned char *)curr_tbs_signature.s;
cdi_1_cert_params.cert_signature_s_size = kAttestationSignatureBytes / 2;
HARDENED_RETURN_IF_ERROR(
cdi_1_build_cert(&cdi_1_cert_params, cert, cert_size));

Expand Down
Loading

0 comments on commit 4fcab61

Please sign in to comment.