Skip to content

Commit

Permalink
[personalization] add Dev Seed hash to the set of perso TLV objects
Browse files Browse the repository at this point in the history
The dev seed hash object is an array of two 64 byte variables, which
are 16th generation HMAC KDF of the entropy produced on the device.

The new object is passed in a perso TLV blob along with the
certificates generated on the device.

The object contents are hashed in the same hash stream where
certificates' contents are hashed, the resulting hash is compared by
the host with the locally produced hash.

The Cros personalization end to end test succeeds, the Dev seed hash
is printed out in the test log.

Signed-off-by: Vadim Bendebury <[email protected]>
  • Loading branch information
Vadim Bendebury authored and timothytrippel committed Aug 30, 2024
1 parent 435f799 commit 32c42ca
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 33 deletions.
1 change: 1 addition & 0 deletions sw/device/silicon_creator/manuf/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ cc_library(
"//sw/device/silicon_creator/lib/drivers:flash_ctrl",
"//sw/device/silicon_creator/lib/drivers:hmac",
"//sw/device/silicon_creator/manuf/base:perso_tlv_data",
"//sw/device/silicon_creator/manuf/lib:flash_info_fields",
"//sw/device/silicon_creator/manuf/lib:personalize",
],
)
Expand Down
25 changes: 14 additions & 11 deletions sw/device/silicon_creator/manuf/base/ft_personalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,8 @@ static status_t hash_certificate(const flash_ctrl_info_page_t *page,
return OK_STATUS();
}

static status_t log_hash_of_all_certs(ujson_t *uj) {
static status_t hash_all_certs(void) {
uint32_t cert_size;
serdes_sha256_hash_t hash;
hmac_sha256_init();

// Push all certificates into the hash.
Expand All @@ -309,14 +308,6 @@ static status_t log_hash_of_all_certs(ujson_t *uj) {
}
}

// Log the final hash of all certificates to the host and console.
hmac_sha256_process();
hmac_sha256_final((hmac_digest_t *)&hash);
RESP_OK(ujson_serialize_serdes_sha256_hash_t, uj, &hash);
LOG_INFO("SHA256 hash of all certificates: %08x%08x%08x%08x%08x%08x%08x%08x",
hash.data[7], hash.data[6], hash.data[5], hash.data[4], hash.data[3],
hash.data[2], hash.data[1], hash.data[0]);

return OK_STATUS();
}

Expand Down Expand Up @@ -592,6 +583,10 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
return OK_STATUS();
}

static status_t send_final_hash(ujson_t *uj, serdes_sha256_hash_t *hash) {
return RESP_OK(ujson_serialize_serdes_sha256_hash_t, uj, hash);
}

bool test_main(void) {
CHECK_STATUS_OK(peripheral_handles_init());
ujson_t uj = ujson_ottf_console();
Expand All @@ -609,14 +604,22 @@ bool test_main(void) {
CHECK_STATUS_OK(personalize_extension_pre_cert_endorse(&pre_endorse));

CHECK_STATUS_OK(personalize_endorse_certificates(&uj));
CHECK_STATUS_OK(hash_all_certs());

personalize_extension_post_endorse_t post_endorse = {
.uj = &uj,
.perso_blob_from_host = &perso_blob_from_host,
.cert_flash_layout = cert_flash_layout};
CHECK_STATUS_OK(personalize_extension_post_cert_endorse(&post_endorse));

CHECK_STATUS_OK(log_hash_of_all_certs(&uj));
// Log the hash of all perso objects to the host and console.
serdes_sha256_hash_t hash;
hmac_sha256_process();
hmac_sha256_final((hmac_digest_t *)&hash);
CHECK_STATUS_OK(send_final_hash(&uj, &hash));
LOG_INFO("SHA256 hash of all perso objects: %08x%08x%08x%08x%08x%08x%08x%08x",
hash.data[7], hash.data[6], hash.data[5], hash.data[4], hash.data[3],
hash.data[2], hash.data[1], hash.data[0]);

// DO NOT CHANGE THE BELOW STRING without modifying the host code in
// sw/host/provisioning/ft_lib/src/lib.rs
Expand Down
13 changes: 13 additions & 0 deletions sw/device/silicon_creator/manuf/base/perso_tlv_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,19 @@ typedef enum perso_tlv_obj_header_fields {
kObjhTypeFieldMask = (1 << kObjhTypeFieldWidth) - 1,
} perso_tlv_obj_header_fields_t;

typedef struct perso_tlv_dev_seed_element {
uint32_t el[8];
} perso_tlv_dev_seed_element_t;

typedef struct perso_tlv_dev_seed {
perso_tlv_dev_seed_element_t key;
perso_tlv_dev_seed_element_t context;
} perso_tlv_dev_seed_t;

typedef struct perso_tlv_dev_seed_set {
perso_tlv_dev_seed_t seeds[2];
} perso_tlv_dev_seed_set_t;

/**
* The x509 certificate is prepended by a 16 bits header followed by the ASCII
* characters of the certificate name, followed by the certificate body.
Expand Down
2 changes: 2 additions & 0 deletions sw/device/silicon_creator/manuf/extensions/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cc_library(
"@//sw/device/lib/testing/test_framework:ujson_ottf",
"@//sw/device/silicon_creator/lib/cert",
"@//sw/device/silicon_creator/manuf/base:personalize_ext",
"@//sw/device/silicon_creator/manuf/lib:flash_info_fields",
],
)

Expand All @@ -43,6 +44,7 @@ cc_library(
"@//sw/device/lib/testing/test_framework:ujson_ottf",
"@//sw/device/silicon_creator/lib/cert",
"@//sw/device/silicon_creator/manuf/base:personalize_ext",
"@//sw/device/silicon_creator/manuf/lib:flash_info_fields",
],
)

Expand Down
14 changes: 0 additions & 14 deletions sw/device/silicon_creator/manuf/lib/flash_info_fields.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,20 +99,6 @@ const flash_info_field_t kFlashInfoFieldTpmEkAttestationKeySeed = {
.byte_offset = kFlashInfoFieldTpmEkKeySeedIdx * kAttestationSeedBytes,
};

const flash_info_field_t kFlashInfoFieldTpmCekAttestationKeySeed = {
.partition = 0,
.bank = 0,
.page = 4,
.byte_offset = kFlashInfoFieldTpmCekKeySeedIdx * kAttestationSeedBytes,
};

const flash_info_field_t kFlashInfoFieldTpmCikAttestationKeySeed = {
.partition = 0,
.bank = 0,
.page = 4,
.byte_offset = kFlashInfoFieldTpmCikKeySeedIdx * kAttestationSeedBytes,
};

const flash_info_field_t kFlashInfoFieldAttestationKeyGenVersion = {
.partition = 0,
.bank = 0,
Expand Down
3 changes: 1 addition & 2 deletions sw/device/silicon_creator/manuf/lib/flash_info_fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ enum {
kFlashInfoFieldCdi0KeySeedIdx = 1,
kFlashInfoFieldCdi1KeySeedIdx = 2,
kFlashInfoFieldTpmEkKeySeedIdx = 3,
kFlashInfoFieldTpmCekKeySeedIdx = 4,
kFlashInfoFieldTpmCikKeySeedIdx = 5,
};

extern const flash_info_field_t kFlashInfoFieldDeviceId;
Expand All @@ -58,6 +56,7 @@ extern const flash_info_field_t kFlashInfoFieldCdi1AttestationKeySeed;
extern const flash_info_field_t kFlashInfoFieldTpmEkAttestationKeySeed;
extern const flash_info_field_t kFlashInfoFieldTpmCekAttestationKeySeed;
extern const flash_info_field_t kFlashInfoFieldTpmCikAttestationKeySeed;
extern const flash_info_field_t kFlashInfoFieldDevSeedSeed;
extern const flash_info_field_t kFlashInfoFieldAttestationKeyGenVersion;

/**
Expand Down
31 changes: 27 additions & 4 deletions sw/host/provisioning/ft_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,22 @@ fn push_endorsed_cert(
Ok(())
}

fn process_dev_seeds(seeds: &[u8]) -> Result<()> {
let expected_seed_num = 2usize;
let seed_size = 64usize;

if seeds.len() != seed_size * expected_seed_num {
bail!("Unexpected seeds perso object size {}", seeds.len())
}

for i in 0..expected_seed_num {
let seed = &seeds[i * seed_size..(i + 1) * seed_size];

log::info!("Seed #{}: {}", i, hex::encode(seed))
}
Ok(())
}

fn provision_certificates(
transport: &TransportWrapper,
cert_endorsement_key_wrapper: KeyWrapper,
Expand Down Expand Up @@ -308,8 +324,6 @@ fn provision_certificates(
}
};

log::info!("start of the body {}", hex::encode(&perso_blob.body[0..10]));

// Extract certificate byte vectors, endorse TBS certs, and ensure they parse with OpenSSL.
// During the process, both:
// 1. prepare a UJSON payload of endorsed certs to send back to the device,
Expand All @@ -324,14 +338,23 @@ fn provision_certificates(
for _ in 0..perso_blob.num_objs {
log::info!("Processing next object");
let header = get_obj_header(&perso_blob.body[start..])?;
let obj_header_size = std::mem::size_of::<ObjHeaderType>();

if header.obj_size > (perso_blob.body.len() - start) {
bail!("Perso blob overflow!");
}
start += obj_header_size;
match header.obj_type {
ObjType::EndorsedX509Cert | ObjType::UnendorsedX509Cert => (),
ObjType::DevSeed => {
start += header.obj_size;
let dev_seed_size = header.obj_size - obj_header_size;
let seeds = &perso_blob.body[start..start + dev_seed_size];
cert_hasher.update(seeds);
process_dev_seeds(seeds)?;
start += dev_seed_size;
continue;
}
}
start += std::mem::size_of::<ObjHeaderType>();

// The next object is a cert, let's retrieve its properties (name, needs
// endorsement, etc.)
Expand Down
4 changes: 2 additions & 2 deletions sw/host/provisioning/perso_tlv_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use anyhow::{bail, Result};

// Types of objects which can come from the device in the perso blob.
#[repr(C)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ObjType {
UnendorsedX509Cert = perso_tlv_objects::perso_tlv_object_type_kPersoObjectTypeX509Tbs as isize,
EndorsedX509Cert = perso_tlv_objects::perso_tlv_object_type_kPersoObjectTypeX509Cert as isize,
Expand All @@ -18,7 +18,7 @@ impl ObjType {
match value {
0 => Ok(ObjType::UnendorsedX509Cert),
1 => Ok(ObjType::EndorsedX509Cert),
3 => Ok(ObjType::DevSeed),
2 => Ok(ObjType::DevSeed),
_ => bail!("incorrect input value of {value} for ObjType"),
}
}
Expand Down

0 comments on commit 32c42ca

Please sign in to comment.