-
Notifications
You must be signed in to change notification settings - Fork 45
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
Execute FIPS Self Test in Runtime #684
Conversation
4f3d0b2
to
b8553bf
Compare
3ad0673
to
1e2c0ce
Compare
if let SelfTestStatus::InProgress(execute) = drivers.self_test_status { | ||
if drivers.mbox.lock() == false { | ||
match execute(drivers) { | ||
Ok(_) => drivers.self_test_status = SelfTestStatus::Done, | ||
Err(e) => caliptra_drivers::report_fw_error_non_fatal(e.into()), | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a specific reason SelfTest can't be blocking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to “reply with data” to conform with new FIPS API (response contains header + checksum), but the mailbox SRAM would already be mutated with the image.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alternative approach is to make the image-verification digest generic, using the sha384 peripheral instead of sha384acc with the mailbox.
If we want to abandon calling back into ROM forever, perhaps just using the sha384 peripheral is better...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep this run-self-test mailbox API as is. If a future version of FIPS ever needs us to test the sha384acc peripheral with something other than empty input data we'll need a mechanism to modify the mailbox.
8bd794f
to
6734392
Compare
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
.mailbox_execute(u32::from(CommandId::SELF_TEST), payload.as_bytes()) | ||
.unwrap_err(); | ||
|
||
hw.step_until_boot_status( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is realistic to expect callers to do this. Also, I'm not sure the boot status register is really intended to be used once we've fully booted.
Perhaps the mailbox response from the SELF_TEST command should explain to the user that the test is currently in progress.
Maybe it would be simpler if this were two separate commands CommandId::SELF_TEST_START
and CommandID:SELF_TEST_GET_RESULT
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
runtime/src/lib.rs
Outdated
@@ -256,7 +291,18 @@ fn handle_command(drivers: &mut Drivers) -> CaliptraResult<MboxStatusE> { | |||
#[cfg(feature = "test_only_commands")] | |||
CommandId::TEST_ONLY_HMAC384_VERIFY => HmacVerifyCmd::execute(drivers, cmd_bytes), | |||
CommandId::VERSION => FipsVersionCmd::execute(drivers), | |||
CommandId::SELF_TEST => FipsSelfTestCmd::execute(drivers), | |||
#[cfg(feature = "fips_self_test")] | |||
CommandId::SELF_TEST => match drivers.self_test_status { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you should overload the SELF_TEST command for the "start" and "get result" phases. The response in both cases is an empty success result, which isn't very informative. See my comments in smoke_test.rs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
#[cfg(feature = "fips_self_test")] | ||
CommandId::SELF_TEST => match drivers.self_test_status { | ||
SelfTestStatus::Idle => { | ||
drivers.self_test_status = SelfTestStatus::InProgress(fips_self_test_cmd::execute); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to take a function? Or could the handler code in goto_idle just call fips_self_test_cmd::execute
directly? I feel like the current code is a bit hard to follow.
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
8c49288
to
dbd83b8
Compare
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
dbd83b8
to
1a6b7ff
Compare
When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead.
fe40e89
to
bcf5b40
Compare
@mhatrevi , ajisaxena : please give feedback on changes in crates owned by msft. |
) * Decouple dependency of Kat execution from Rom * Decouple verification environment from ROM dependency * Move fips-self-test test to test crate * Use conditional compilation to build caliptra-runtime as ROM image * Postpone self test execution * Fix 1600 byte ROM size regression in #684 When callers from separate crates call a large generic function like verify_lms_signature_cfi(), rustc 1.70 may build multiple versions (depending on optimizer heuristics), even when all the generic parameters are identical. This is bad, as it can bloat the binary and the second copy violates the FIPS requirements that the same machine code be used for the KAT as the actual implementation. To defend against it, we provide a non-generic function that production firmware should call instead. * Rename goto_idle to enter_idle * Fix typo * Renamed SELF_TEST * START/GET_PROGRESS commands * kats executes before image verification * Remove persistent_data from venv * Implement FIPS commands in ROM VERSION SELF_TEST SHUTDOWN * Fix unassigned error codes * Address feedback - Remove mut from fips create_slice - Use copy_bytes_to_mbox in write_response - Restore idevid tests mistakenly removed - Add bounds checking on fmc and rt sizes * Rom itegrity test call from Runtime. * Fixes for gate --------- Co-authored-by: Anthony Rocha <anthony.rocha@amd.com> Co-authored-by: Kor Nielsen <kor@google.com>
changes were included with PR #693 |
This commit enables Runtime to run FIPS Self Tests as follows : KATs, verification of firmware image in ICCM, and ROM integrity test.
Runtime copies image from ICCM to mailbox SRAM , so it needs to fake a send a transaction and hold the mailbox lock while the image is being validated,. It defers the actual self test execution until the mailbox lock can be acquired. SoC must "poll" for self test completion.