[perso_fw] Refactor code to make the live set of variables during perso stages more clear - #31014
Conversation
3e7c2dd to
9ba21b3
Compare
|
|
||
| typedef struct perso_stage_specific_data { | ||
| perso_stage_t stage; | ||
| union { |
There was a problem hiding this comment.
NOTE: This optimization assumes that
personalize_extension_pre_cert_endorsedoes not store any references to the pre-endorsement stage specific data after the call ends. Since the underlying buffer will be re-used for post endorsement specific data, the data pointed to by such references will get invalidated.
Can we add this assumption in commit message somewhere in the comments?
There was a problem hiding this comment.
Done. Added a comment in code on top of struct perso_stage_specific_data declaration (which has the union that necessitates this behavior). Also added a comment in the extension functions declarations in sw/device/silicon_creator/manuf/base/personalize_ext.h
| size_t curr_cert_size = 0; | ||
|
|
||
| // Generate UDS keys and (TBS) cert. | ||
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= |
There was a problem hiding this comment.
Rather than this construction, should we create a constant that sizes all_certs and then do this comparison with that constant?
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= | ||
| kCdi1MaxCertSizeBytes, | ||
| "CDI1 cert won't fit into `all_certs`"); |
There was a problem hiding this comment.
And again here: compare constants rather than this exciting sizeof expression.
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= | ||
| kCdi0MaxCertSizeBytes, | ||
| "CDI0 cert won't fit into `all_certs`"); |
There was a problem hiding this comment.
And again here: compare constants rather than this exciting sizeof expression.
| TRY(personalize_endorse_certificates(uj, &perso_data.stages_shared_data, | ||
| post_endorse_data, &cert_offsets)); | ||
| TRY(hash_all_certs(&post_endorse_data->cert_buffer)); | ||
| { |
There was a problem hiding this comment.
Leave a comment here clearly stating that there is no re-use of data in the post_endorse_data buffer between the stages and that (IIUC), the post_endorse_data buffer is used like a working memory buffer in each stage.
(That is, after each of personalize_endorse_certificates and hash_all_certs use the buffer as a temporary holding buffer and it has no useful data inside of it after the functions return).
9ba21b3 to
ca72a0e
Compare
| size_t curr_cert_size = 0; | ||
|
|
||
| // Generate UDS keys and (TBS) cert. | ||
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= |
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= | ||
| kCdi0MaxCertSizeBytes, | ||
| "CDI0 cert won't fit into `all_certs`"); |
| static_assert(sizeof(((perso_stages_shared_data_t *)NULL)->all_certs) >= | ||
| kCdi1MaxCertSizeBytes, | ||
| "CDI1 cert won't fit into `all_certs`"); |
| TRY(personalize_endorse_certificates(uj, &perso_data.stages_shared_data, | ||
| post_endorse_data, &cert_offsets)); | ||
| TRY(hash_all_certs(&post_endorse_data->cert_buffer)); | ||
| { |
|
|
||
| typedef struct perso_stage_specific_data { | ||
| perso_stage_t stage; | ||
| union { |
There was a problem hiding this comment.
Done. Added a comment in code on top of struct perso_stage_specific_data declaration (which has the union that necessitates this behavior). Also added a comment in the extension functions declarations in sw/device/silicon_creator/manuf/base/personalize_ext.h
…ped static variables This commits moves most of the global static variables into function local scope. The motive behind this refactor is to allow better reason about the liveness of these variables when doing future changes to this code. The declarations are pushed as deep in the call chain as possible based on how the variables are used currently - I removed `static` qualifier from `uds_key_ids` and `cdi_0_key_ids` since the compiler could not statically initialize fields with `uds_pubkey_id` (because now it is an input to the function) - I added checks for size of `all_certs` against max size of DICE certificates. This should not cause any behavior change since `all_certs` is statically allocated to be much larger than max size of DICE certificates - I removed `orig_num_objects_from_host`. Instead the function now has a local variable to temporarily store the original count, and the count is restored before the function returns Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.6% 30.4Ki .bss NAN% 0 26.4% 8.00Ki provision.all_certs NAN% 0 16.5% 5.01Ki provision.blob_from_host NAN% 0 16.5% 5.01Ki provision.blob_to_host NAN% 0 13.2% 4.00Ki owner_page NAN% 0 6.6% 2.00Ki personalize_endorse_certificates.dice_page NAN% 0 6.5% 1.97Ki main_spi_buf NAN% 0 3.3% 1024 hash_certificate.cert_buffer NAN% 0 2.3% 708 measure_otp_partition.otp_state NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 64 personalize_gen_dice_certificates.cdi_0_pubkey NAN% 0 0.2% 64 personalize_gen_dice_certificates.curr_pubkey NAN% 0 0.2% 64 provision.uds_pubkey NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 provision.certgen_inputs NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 32 personalize_gen_dice_certificates.attestation_binding_value NAN% 0 0.1% 32 personalize_gen_dice_certificates.cdi_0_pubkey_id NAN% 0 0.1% 32 personalize_gen_dice_certificates.cdi_1_pubkey_id NAN% 0 0.1% 32 personalize_gen_dice_certificates.sealing_binding_value NAN% 0 0.1% 32 personalize_gen_dice_certificates.uds_endorsement_key_id NAN% 0 0.1% 32 personalize_gen_dice_certificates.zero_digest NAN% 0 0.1% 32 provision.otp_creator_sw_cfg_measurement NAN% 0 0.1% 32 provision.otp_owner_sw_cfg_measurement NAN% 0 0.1% 32 provision.otp_rot_creator_auth_codesign_measurement NAN% 0 0.1% 32 provision.otp_rot_creator_auth_state_measurement NAN% 0 0.1% 32 provision.uds_pubkey_id ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
This commit removes `static` qualifier from few static variables which were moved to function scope in the previous commit. I arbitraily chose 32 bytes as the limit so as to not increase the total stack usage while also reducing a little bit of `.bss` section use. The stack variables are zero-initialized as they were earlier when they were static Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.5% 30.1Ki .bss NAN% 0 26.6% 8.00Ki provision.all_certs NAN% 0 16.7% 5.01Ki provision.blob_from_host NAN% 0 16.7% 5.01Ki provision.blob_to_host NAN% 0 13.3% 4.00Ki owner_page NAN% 0 6.7% 2.00Ki personalize_endorse_certificates.dice_page NAN% 0 6.6% 1.97Ki main_spi_buf NAN% 0 3.3% 1024 hash_certificate.cert_buffer NAN% 0 2.3% 704 measure_otp_partition.otp_state NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 64 personalize_gen_dice_certificates.cdi_0_pubkey NAN% 0 0.2% 64 personalize_gen_dice_certificates.curr_pubkey NAN% 0 0.2% 64 provision.uds_pubkey NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 provision.certgen_inputs NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 32 personalize_gen_dice_certificates.attestation_binding_value NAN% 0 0.1% 32 personalize_gen_dice_certificates.sealing_binding_value ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
ca72a0e to
08210eb
Compare
|
Rebased on latest |
This commits makes appropriate function parameters `const` qualified. The motive behind this change is to make it easier to reason about mutability of the static variables left in the previous commit. A notable refactor in this commit is change from `perso_tlv_get_cert_obj` to `perso_tlv_get_cert_obj_view`. The new function now returns `perso_tlv_cert_obj_view_t` instead of `perso_tlv_cert_obj_t`. `perso_tlv_cert_obj_view_t` is similar to `perso_tlv_cert_obj_t`, but internally it uses const pointers to the underlying buffer (hence giving only immutable access/view to the underlying buffer). This allows making the buffer passed to `perso_tlv_get_cert_obj_view` `const` qualified, which in turn helps confirm that `personalize_endorse_certificates` uses `blob_to_host` only for reads. I also changes `zero_digest` to `const static` so that it can be moved to `.rodata` Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.5% 30.1Ki .bss NAN% 0 26.6% 8.00Ki provision.all_certs NAN% 0 16.7% 5.01Ki provision.blob_from_host NAN% 0 16.7% 5.01Ki provision.blob_to_host NAN% 0 13.3% 4.00Ki owner_page NAN% 0 6.7% 2.00Ki personalize_endorse_certificates.dice_page NAN% 0 6.6% 1.97Ki main_spi_buf NAN% 0 3.3% 1024 hash_certificate.cert_buffer NAN% 0 2.3% 704 measure_otp_partition.otp_state NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 64 personalize_gen_dice_certificates.cdi_0_pubkey NAN% 0 0.2% 64 personalize_gen_dice_certificates.curr_pubkey NAN% 0 0.2% 64 provision.uds_pubkey NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 provision.certgen_inputs NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 32 personalize_gen_dice_certificates.attestation_binding_value NAN% 0 0.1% 32 personalize_gen_dice_certificates.sealing_binding_value ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
…chain This commit moves the static variables that were not marked with `const` qualifier up in the call chain. I have moved them to the function where the 2 major stages of provisioning occur: pre-endorsement and post-endorsement. The motive behind this changes is to (in the future) split the variables into different sets based on which stages use them I also added 2 types `cert_scratch_buffer_t` and `aligned_dice_storage_page_t` so that the alignment requirement on `cert_buffer` and `dice_page` can be expressed in function parameters until it is not needed anymore Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.5% 30.1Ki .bss NAN% 0 26.6% 8.00Ki provision.all_certs NAN% 0 16.7% 5.01Ki provision.blob_from_host NAN% 0 16.7% 5.01Ki provision.blob_to_host NAN% 0 13.3% 4.00Ki owner_page NAN% 0 6.7% 2.00Ki provision.dice_page NAN% 0 6.6% 1.97Ki main_spi_buf NAN% 0 3.3% 1024 provision.cert_buffer NAN% 0 2.3% 704 provision.otp_state NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 64 provision.cdi_0_pubkey NAN% 0 0.2% 64 provision.curr_pubkey NAN% 0 0.2% 64 provision.uds_pubkey NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 provision.certgen_inputs NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 32 provision.attestation_binding_value NAN% 0 0.1% 32 provision.sealing_binding_value ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
This commit splits the static variables moved up the call chain in the previous commit. The variables are split into 2 categories at first level: variables that are used by both pre-endorsement and post-endorsement stages, and variables that are used by only one of those stages. The variables used only by one stage are put into a union to save space in SRAM. Since the stages occur one after another, only the stage specific and shared variables need to be live for a given stage. **NOTE: This optimization assumes that `personalize_extension_pre_cert_endorse` does not store any references to the pre-endorsement stage specific data after the call ends.** Since the underlying buffer will be re-used for post endorsement specific data, the data pointed to by such references will get invalidated. Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.3% 29.8Ki .bss NAN% 0 72.9% 21.7Ki provision.perso_data NAN% 0 13.4% 4.00Ki owner_page NAN% 0 6.6% 1.97Ki main_spi_buf NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 24 rand_testutils_rng_ctx ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
This commit changes the function signatures to reduce the number of parameters. In the previous commit, the functions had too many parameters and many parameters had the same type. So a simple mistake such as swapping 2 parameters in the long list would be hard to detect. With a smaller list and different types for parameters where possible, such mistakes could be avoided. New types are also added to help with reducing the parameters count. Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 18.3% 29.8Ki .bss NAN% 0 72.9% 21.7Ki provision.perso_data NAN% 0 13.4% 4.00Ki owner_page NAN% 0 6.6% 1.97Ki main_spi_buf NAN% 0 1.9% 588 cdi_1_tbs_buffer NAN% 0 1.6% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.7% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 24 rand_testutils_rng_ctx NAN% 0 0.1% 20 xDelayedTaskList1 ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
… in union Based on the observation that `dice_page` and `certs_buffer` are not live together, this commit further splits post-endorsement stage specific static variables into 2 groups and puts them into a union. This saves a little bit more space in `.bss` section. Size for few entries in `.bss` section from `ft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elf` after this change: ``` 0.0% 0 17.8% 28.8Ki .bss NAN% 0 72.0% 20.7Ki provision.perso_data NAN% 0 13.9% 4.00Ki owner_page NAN% 0 6.9% 1.97Ki main_spi_buf NAN% 0 2.0% 588 cdi_1_tbs_buffer NAN% 0 1.7% 488 cdi_0_tbs_buffer NAN% 0 0.9% 272 ottf_console_spi_getc.info NAN% 0 0.8% 224 otbn_boot_attestation_key_clear.dmem_backup NAN% 0 0.3% 100 pxReadyTasksLists NAN% 0 0.2% 64 curr_tbs_signature NAN% 0 0.2% 52 main_console NAN% 0 0.1% 40 status_report_list NAN% 0 0.1% 24 rand_testutils_rng_ctx NAN% 0 0.1% 20 xDelayedTaskList1 ``` Signed-off-by: Lovepreet Singh <lpsingh@google.com>
08210eb to
8db9142
Compare
This PR changes the perso firmware code to make it clear which set of variables are meant to be live during pre and post endorsement. It also puts the set of variables that are expected to be live during only one of the pre or post endorsement stage in a union to save some space in SRAM.
The PR consists of a series of commits with each commit making simple mechanical changes, trying to keep the behavior of the code same during each commit
.bssuse further by putting more static variables in unionOutput from
bloatyforft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elfbefore this series of commits:Output from
bloatyforft_personalize_emulation_dice_mldsa_sim_qemu_rom_with_fake_keys.elfafter this series of commits:These changes are on top of PR #30994