Skip to content

[manuf] send RMA token hash from the host instead of generating on device#24203

Merged
timothytrippel merged 2 commits intolowRISC:masterfrom
vbendeb:rma-token-hash
Aug 6, 2024
Merged

[manuf] send RMA token hash from the host instead of generating on device#24203
timothytrippel merged 2 commits intolowRISC:masterfrom
vbendeb:rma-token-hash

Conversation

@vbendeb
Copy link

@vbendeb vbendeb commented Aug 1, 2024

Fixes #24034.

@vbendeb vbendeb requested review from a team as code owners August 1, 2024 23:14
@vbendeb vbendeb requested review from jwnrt and moidx and removed request for a team August 1, 2024 23:14
@moidx moidx requested a review from timothytrippel August 1, 2024 23:32
@timothytrippel timothytrippel removed the request for review from jwnrt August 2, 2024 00:26
@timothytrippel timothytrippel changed the title Rma token hash [manuf] send RMA token hash from the host instead of generating on device Aug 2, 2024
what happened

BRANCH=none
BUG=b:
TEST=manual

Signed-off-by: Vadim Bendebury <vbendeb@google.com>
@vbendeb vbendeb requested a review from cfrantz as a code owner August 2, 2024 21:51
@vbendeb
Copy link
Author

vbendeb commented Aug 2, 2024

rebased and made sure that the previously failing tests pass. Had to move the RMA hash retrieval into manuf_personalize_device_secrets() to keep it in common code, not sure how clean this is from the overall SW architecture standpoiont

Copy link
Contributor

@timothytrippel timothytrippel left a comment

Choose a reason for hiding this comment

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

Thanks @vbendeb ! Mostly looks good, just a couple of cleanups / improvments that will make FT provisioning flow in this repo useful during chip bringups.

// console.
LOG_INFO("Waiting For RMA Unlock Token Hash ...");

CHECK_STATUS_OK(UJSON_WITH_CRC(ujson_deserialize_rma_unlock_token_hash_t, uj,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should leave the reading/deserialization of the token from the console to the actual test part (i.e., put it back in the ft_personalize.c file), to facilitate dependency injection of tokens during testing of this library. The personalize library should have no notion of a console uart, it should just be provided with the token hash and write it to OTP.

Copy link
Author

Choose a reason for hiding this comment

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

done

status_t manuf_personalize_device_secrets(dif_flash_ctrl_state_t *flash_state,
const dif_lc_ctrl_t *lc_ctrl,
const dif_otp_ctrl_t *otp_ctrl,
ujson_t *uj);
Copy link
Contributor

Choose a reason for hiding this comment

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

the personalize lib should not be tied to the ujson console (see above comment); it should just take as input the hashed token

Copy link
Author

Choose a reason for hiding this comment

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

done

host_ecc_sk: PathBuf,
timeout: Duration,
) -> Result<()> {
fn process_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
fn process_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> {
fn send_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> {

Copy link
Author

Choose a reason for hiding this comment

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

done

let mut token = ArrayVec::<u32, 4>::new();

token = (0..token.len())
.map(|_| rand::random::<u32>())
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than generate random tokens, could we make the token an input to the FT test harness (similar to how the host_sk was before), and put it in sw/device/silicon_creator/manuf/base/provisioning_inputs.bzl? The reason is because the FT test harness (sw/host/provisioning/ft/src/main.rs) will be used by benchtop provisioning flows during initial chip bringup, and we want the HSM in the provisioning infrastructure to generate the LC tokens and then just pass them along to the test harness as inputs.

Comment on lines +37 to +38
// Life cycle tokens are hashed using a keccak hashing algorithm. The result is
// a 16 byte value represented as a vector of two u64s.
Copy link
Contributor

Choose a reason for hiding this comment

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

use doc comments here

Suggested change
// Life cycle tokens are hashed using a keccak hashing algorithm. The result is
// a 16 byte value represented as a vector of two u64s.
/// Life cycle tokens are hashed using a keccak hashing algorithm. The result is
/// a 16 byte value represented as a vector of two u64s.

Copy link
Author

Choose a reason for hiding this comment

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

Modified and re-tested, PTAL

@vbendeb
Copy link
Author

vbendeb commented Aug 5, 2024

Sure, @timothytrippel the comments make sense, I was not comfortable bringing the ujson object into personalize.c, but I ended up doing this because I wanted to keep the hash import code in one place and use it where needed (in two different tests now).

Is there a good location for this to avoid duplication?

@timothytrippel
Copy link
Contributor

By "hash import code" do you mean the single call to CHECK_STATUS_OK(UJSON_WITH_CRC(ujson_deserialize_rma_unlock_token_hash_t, uj, &token_hash));? It is ok to duplicate this call across tests, it was duplicated when importing the host_sk struct before.

@vbendeb
Copy link
Author

vbendeb commented Aug 5, 2024 via email

@timothytrippel
Copy link
Contributor

Ah, the text prompt though is a contract betweeen the device code and host (test harness) code for a specific test. What is important is that the text prompt used in the personalize_functest device code, matches what is expected in its host test harness code, and likewise the text prompt used in the ft_personalize.c device code matches, what is expected in its matching host test harness code. Specifically, it is not required (and more importantly should not be required) that the synchronization text prompts used in one test match all other text prompts across all other tests that parse the same UJSON message immediately after. The text prompt used in the personalize_functest could be different than the text prompt used in the ft_personalize binary, or rather a test harness could choose not to have a synchronization message all together to improve performance. We want to maintain this flexibility across tests as we may want to optimize a specific test flow later without changing all other tests that do not need to be optimized, and may benefit from more explicit test synchronization console messages.

@timothytrippel timothytrippel self-requested a review August 6, 2024 15:45
Comment on lines +195 to +199
;
LOG_INFO("Provisioning OTP SECRET2 and keymgr flash info pages ...");

// Perform OTP and flash info writes.
LOG_INFO("Provisioning OTP SECRET2 and keymgr flash info pages ...");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
;
LOG_INFO("Provisioning OTP SECRET2 and keymgr flash info pages ...");
// Perform OTP and flash info writes.
LOG_INFO("Provisioning OTP SECRET2 and keymgr flash info pages ...");

We should try to keep console prints in the test itself, not in the libs, since we will want to optimize/remove console prints later on to optimize provisioning throughput. (Also, this looks accidentally duplicated.)

Copy link
Author

Choose a reason for hiding this comment

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

oops, not sure how I missed this, too many back and forths

const dif_otp_ctrl_t *otp_ctrl,
wrapped_rma_unlock_token_t *rma_unlock_token) {
static status_t otp_partition_secret2_configure(const dif_otp_ctrl_t *otp_ctrl,
const lc_token_hash_t *hash) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const lc_token_hash_t *hash) {
const lc_token_hash_t *rma_unlock_token_hash) {

nit: update "@param[out]" above: this is no longer an output

Copy link
Author

Choose a reason for hiding this comment

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

done

let _test_exit_token =
hex_string_to_u32_arrayvec::<4>(opts.provisioning_data.test_exit_token.as_str())?;

let rma_uncock_token_hash =
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let rma_uncock_token_hash =
let rma_unlock_token_hash =

Copy link
Author

Choose a reason for hiding this comment

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

done

&_perso_certgen_inputs,
opts.timeout,
opts.provisioning_data.ca_certificate,
&rma_uncock_token_hash,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
&rma_uncock_token_hash,
&rma_unlock_token_hash,

Copy link
Author

Choose a reason for hiding this comment

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

done

host_ecc_sk: PathBuf,
}

fn rma_unlock_token_export(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
fn rma_unlock_token_export(opts: &Opts, transport: &TransportWrapper) -> Result<()> {
fn send_rma_unlock_token(opts: &Opts, transport: &TransportWrapper) -> Result<()> {

Copy link
Contributor

Choose a reason for hiding this comment

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

or something like that

Copy link
Author

Choose a reason for hiding this comment

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

done

Generating the RMA unlock token on the device and then transferring it
to the host for future registering is pretty cumbersome: since the
token must not be sent over the host connection in clear a whole ECDH
key exchange and generating of an AES key on the target are required.

It is much cleaner to have the token generated on the host and have
just the hash sent to the device. No need to encrypt the hash, fewer
messages sent back and forth.

This also removes a lot of complexity from the device code.

Tested by verifying that both personalize_functest and
ft_provision_fpga test pass on the FPGA setup.

Signed-off-by: Vadim Bendebury <vbendeb@google.com>
@vbendeb
Copy link
Author

vbendeb commented Aug 6, 2024

updated, PTAL

@timothytrippel timothytrippel self-requested a review August 6, 2024 21:29
Copy link
Contributor

@timothytrippel timothytrippel left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @vbendeb !

@timothytrippel timothytrippel merged commit e2e4c03 into lowRISC:master Aug 6, 2024
@vbendeb vbendeb deleted the rma-token-hash branch August 18, 2024 22:41
@timothytrippel timothytrippel added the CherryPick:earlgrey_1.0.0 This PR should be cherry-picked to earlgrey_1.0.0 label Oct 17, 2024
@github-actions
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CherryPick:earlgrey_1.0.0 This PR should be cherry-picked to earlgrey_1.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[manuf] inject RMA unlock tokens from host instead of generating on device

3 participants