[manuf] send RMA token hash from the host instead of generating on device#24203
[manuf] send RMA token hash from the host instead of generating on device#24203timothytrippel merged 2 commits intolowRISC:masterfrom vbendeb:rma-token-hash
Conversation
what happened BRANCH=none BUG=b: TEST=manual Signed-off-by: Vadim Bendebury <vbendeb@google.com>
|
rebased and made sure that the previously failing tests pass. Had to move the RMA hash retrieval into |
timothytrippel
left a comment
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
| 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); |
There was a problem hiding this comment.
the personalize lib should not be tied to the ujson console (see above comment); it should just take as input the hashed token
| host_ecc_sk: PathBuf, | ||
| timeout: Duration, | ||
| ) -> Result<()> { | ||
| fn process_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> { |
There was a problem hiding this comment.
| fn process_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> { | |
| fn send_rma_unlock_token(transport: &TransportWrapper, timeout: Duration) -> Result<()> { |
| let mut token = ArrayVec::<u32, 4>::new(); | ||
|
|
||
| token = (0..token.len()) | ||
| .map(|_| rand::random::<u32>()) |
There was a problem hiding this comment.
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.
| // Life cycle tokens are hashed using a keccak hashing algorithm. The result is | ||
| // a 16 byte value represented as a vector of two u64s. |
There was a problem hiding this comment.
use doc comments here
| // 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. |
|
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? |
|
By "hash import code" do you mean the single call to |
|
well, this and also printing the text prompt on the device console which
triggers the host sending of the hash. The prompt is something which can
easily get out of sync, if it is duplicated in multiple places.
…On Mon, Aug 5, 2024 at 11:12 AM Timothy Trippel ***@***.***> wrote:
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.
—
Reply to this email directly, view it on GitHub
<#24203 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABNLPHYCED27FPATKLLGRFTZP66BXAVCNFSM6AAAAABL3PMYI2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDENRZGYZTCMBYGA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
|
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 |
| ; | ||
| 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 ..."); |
There was a problem hiding this comment.
| ; | |
| 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.)
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
| 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
sw/host/provisioning/ft/src/main.rs
Outdated
| let _test_exit_token = | ||
| hex_string_to_u32_arrayvec::<4>(opts.provisioning_data.test_exit_token.as_str())?; | ||
|
|
||
| let rma_uncock_token_hash = |
There was a problem hiding this comment.
| let rma_uncock_token_hash = | |
| let rma_unlock_token_hash = |
sw/host/provisioning/ft/src/main.rs
Outdated
| &_perso_certgen_inputs, | ||
| opts.timeout, | ||
| opts.provisioning_data.ca_certificate, | ||
| &rma_uncock_token_hash, |
There was a problem hiding this comment.
| &rma_uncock_token_hash, | |
| &rma_unlock_token_hash, |
| host_ecc_sk: PathBuf, | ||
| } | ||
|
|
||
| fn rma_unlock_token_export(opts: &Opts, transport: &TransportWrapper) -> Result<()> { |
There was a problem hiding this comment.
| fn rma_unlock_token_export(opts: &Opts, transport: &TransportWrapper) -> Result<()> { | |
| fn send_rma_unlock_token(opts: &Opts, transport: &TransportWrapper) -> Result<()> { |
There was a problem hiding this comment.
or something like that
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>
|
updated, PTAL |
timothytrippel
left a comment
There was a problem hiding this comment.
LGTM, thanks @vbendeb !
|
Successfully created backport PR for |
Fixes #24034.