Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[personalisation] dev seed hash generation and transfer #24407

Merged
merged 2 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -270,6 +270,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
26 changes: 14 additions & 12 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 @@ -553,7 +544,6 @@ static status_t personalize_endorse_certificates(ujson_t *uj) {
// We just prepared the set of wrapped certificates, let's trust that the
// data is correct and does not need more validation.
memcpy(&crth, certs, sizeof(crth));
crth = __builtin_bswap16(crth);
certs += sizeof(crth);
PERSO_TLV_GET_FIELD(Crth, NameSize, crth, &name_len);
memcpy(name, certs, name_len);
Expand Down Expand Up @@ -590,6 +580,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 @@ -607,14 +601,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
8 changes: 2 additions & 6 deletions sw/device/silicon_creator/manuf/base/perso_tlv_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ status_t perso_tlv_set_cert_block(const uint8_t *buf, size_t max_room,
perso_tlv_object_header_t obj_type;

memcpy(&objh, buf, sizeof(objh));
objh = __builtin_bswap16(objh);
PERSO_TLV_GET_FIELD(Objh, Size, objh, &obj_size);

if (obj_size > max_room)
Expand All @@ -53,7 +52,6 @@ status_t perso_tlv_set_cert_block(const uint8_t *buf, size_t max_room,
// Let's retrieve cert wrapper header.
block->wrapped_cert_p = buf;
memcpy(&crth, buf, sizeof(crth));
crth = __builtin_bswap16(crth);
max_room -= sizeof(crth);
buf += sizeof(crth);
PERSO_TLV_GET_FIELD(Crth, Size, crth, &wrapped_cert_size);
Expand Down Expand Up @@ -148,10 +146,8 @@ status_t perso_tlv_prepare_cert_for_shipping(const char *name,
PERSO_TLV_SET_FIELD(Crth, Size, cert_header, wrapped_len);
PERSO_TLV_SET_FIELD(Crth, NameSize, cert_header, name_len);

uint16_t swapped = __builtin_bswap16(obj_header);
TRY(perso_tlv_push_to_blob(&swapped, sizeof(obj_header), pb));
swapped = __builtin_bswap16(cert_header);
TRY(perso_tlv_push_to_blob(&swapped, sizeof(cert_header), pb));
TRY(perso_tlv_push_to_blob(&obj_header, sizeof(obj_header), pb));
TRY(perso_tlv_push_to_blob(&cert_header, sizeof(cert_header), pb));
TRY(perso_tlv_push_to_blob(name, name_len, pb));
TRY(perso_tlv_push_to_blob(cert_body, cert_size, pb));
pb->num_objs++;
Expand Down
37 changes: 26 additions & 11 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 All @@ -73,23 +86,25 @@ typedef enum perso_tlv_cert_header_fields {
kCrthNameSizeFieldMask = (1 << kCrthNameSizeFieldWidth) - 1,
} perso_tlv_cert_header_fields_t;

// Helper macros allowing set or get various header fields.
#define PERSO_TLV_SET_FIELD(type_name, field_name, full_value, field_value) \
{ \
uint16_t mask = k##type_name##field_name##FieldMask; \
uint16_t shift = k##type_name##field_name##FieldShift; \
uint16_t fieldv = (uint16_t)field_value; \
uint16_t fullv = (uint16_t)full_value; \
fieldv = field_value & mask; \
mask = (uint16_t)(mask << shift); \
full_value = (uint16_t)((fullv & ~mask) | (((uint16_t)fieldv) << shift)); \
// Helper macros allowing set or get various object and certificate header
// fields. Operate on objects in big endian representation, as they are
// transferred over wire.
#define PERSO_TLV_SET_FIELD(type_name, field_name, full_value, field_value) \
{ \
uint16_t mask = k##type_name##field_name##FieldMask; \
uint16_t shift = k##type_name##field_name##FieldShift; \
uint16_t fieldv = (uint16_t)(field_value)&mask; \
uint16_t fullv = __builtin_bswap16((uint16_t)(full_value)); \
mask = (uint16_t)(mask << shift); \
(full_value) = __builtin_bswap16( \
(uint16_t)((fullv & ~mask) | (((uint16_t)fieldv) << shift))); \
}

#define PERSO_TLV_GET_FIELD(type_name, field_name, full_value, field_value) \
{ \
uint16_t mask = k##type_name##field_name##FieldMask; \
uint16_t shift = k##type_name##field_name##FieldShift; \
*field_value = (full_value >> shift) & mask; \
*(field_value) = (__builtin_bswap16(full_value) >> shift) & mask; \
}

/**
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 => (),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, what is the point of this? Maybe this "match" block should just be an if header.obj_type == ObjType::DevSeed?

Since it is not relevant to this PR, maybe submit a follow up to clean this up?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense with future enhancements in mind - more object types would be processed here, receiving a blob with an unsupported type would not go unnoticed, etc.

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
Loading