-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[sw] Pull-in MLDSA software impl for eg100 #30552
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
base: earlgrey_1.0.0
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,16 @@ rom_error_t kmac_kmac256_sw_configure(void); | |
| */ | ||
| rom_error_t kmac_kmac256_hw_configure(void); | ||
|
|
||
| /** | ||
| * Configure the KMAC block at startup for SHAKE-128 operation. | ||
| * | ||
| * Sets the KMAC block to use software entropy and sets the mode to SHAKE-128. | ||
| * | ||
| * @return Error code indicating if the operation succeeded. | ||
| */ | ||
| OT_WARN_UNUSED_RESULT | ||
| rom_error_t kmac_shake128_configure(void); | ||
|
|
||
| /** | ||
| * Configure the KMAC block at startup. | ||
| * | ||
|
|
@@ -145,6 +155,37 @@ void kmac_shake256_squeeze_start(void); | |
| OT_WARN_UNUSED_RESULT | ||
| rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen); | ||
|
|
||
| /** | ||
| * Squeeze arbitrary number of words from the Keccak state. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it really an arbitrary number of words or should it be a multiple of |
||
| * | ||
| * This function will read out_words from the Keccak state, and if necessary | ||
| * triggers additional hardware permutation runs using the rate_words. | ||
| * Unlike squeeze_end, it does not mark the operation as DONE. | ||
| * | ||
| * @param out Output buffer. | ||
| * @param out_words Desired length of output in 32-bit words. | ||
| * @param rate_words Keccak rate in 32-bit words. | ||
| * @return Error code indicating if the operation succeeded. | ||
| */ | ||
| OT_WARN_UNUSED_RESULT | ||
| rom_error_t kmac_squeeze_words(uint32_t *out, size_t out_words, | ||
| size_t rate_words); | ||
|
|
||
| /** | ||
| * End the squeeze phase and release the KMAC hardware block. | ||
| * | ||
| * @return Error code indicating if the operation succeeded. | ||
| */ | ||
| OT_WARN_UNUSED_RESULT | ||
| rom_error_t kmac_done(void); | ||
|
|
||
| /** | ||
| * Check if the KMAC block is in the squeezing phase. | ||
| * | ||
| * @return True if KMAC is squeezing, false otherwise. | ||
| */ | ||
| bool kmac_is_squeezing(void); | ||
|
|
||
| /** | ||
| * Load an unmasked software key into KMAC. | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,46 @@ | ||||||||
| # Copyright lowRISC contributors (OpenTitan project). | ||||||||
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||
|
|
||||||||
| load( | ||||||||
| "//rules/opentitan:defs.bzl", | ||||||||
| "EARLGREY_TEST_ENVS", | ||||||||
| "opentitan_test", | ||||||||
| ) | ||||||||
|
|
||||||||
| package(default_visibility = ["//visibility:public"]) | ||||||||
|
|
||||||||
| cc_library( | ||||||||
| name = "mldsa_test_utils", | ||||||||
| srcs = [ | ||||||||
| "mldsa_test_utils.c", | ||||||||
| ], | ||||||||
| hdrs = [ | ||||||||
| "mldsa_test_utils.h", | ||||||||
| ], | ||||||||
| deps = [ | ||||||||
| "//sw/device/lib/runtime:log", | ||||||||
| ], | ||||||||
| ) | ||||||||
|
|
||||||||
| cc_library( | ||||||||
| name = "mldsa_testvectors", | ||||||||
| srcs = ["mldsa_testvectors.c"], | ||||||||
| hdrs = ["mldsa_testvectors.h"], | ||||||||
| deps = [ | ||||||||
| "//third_party/embedpqc:mldsa44_tiny", | ||||||||
| ], | ||||||||
| ) | ||||||||
|
|
||||||||
| opentitan_test( | ||||||||
| name = "mldsa44_tiny_test", | ||||||||
| srcs = ["mldsa44_tiny_test.c"], | ||||||||
| exec_env = EARLGREY_TEST_ENVS, | ||||||||
| deps = [ | ||||||||
| ":mldsa_test_utils", | ||||||||
| ":mldsa_testvectors", | ||||||||
| "//sw/device/lib/runtime:log", | ||||||||
| "//sw/device/lib/testing/test_framework:ottf_main", | ||||||||
| "//third_party/embedpqc/ports:mldsa44_tiny_caller", | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think this could be added to make the includes more robust. |
||||||||
| ], | ||||||||
| ) | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| #include "third_party/embedpqc/mldsa44_tiny.h" | ||
|
|
||
| #include "sw/device/lib/runtime/log.h" | ||
| #include "sw/device/lib/testing/test_framework/check.h" | ||
| #include "sw/device/lib/testing/test_framework/ottf_main.h" | ||
| #include "sw/device/tests/embedpqc/mldsa_test_utils.h" | ||
| #include "sw/device/tests/embedpqc/mldsa_testvectors.h" | ||
| #include "third_party/embedpqc/ports/mldsa44_tiny_caller.h" | ||
|
|
||
| OTTF_DEFINE_TEST_CONFIG(); | ||
|
|
||
| bool test_main(void) { | ||
| LOG_INFO("MLDSA44-TINY Test starting..."); | ||
|
|
||
| // Allocate a single static buffer to reuse for all RAM outputs to save BSS | ||
| // space. | ||
| static uint8_t buf[MLDSA44_SIGNATURE_BYTES]; | ||
|
|
||
| // 1. Keygen Test | ||
| paint_stack(); | ||
| mldsa44_tiny_pub_from_seed_with_stack(buf, kMldsa44KeygenSeed, | ||
| &mldsa_stack[MLDSA_STACK_SIZE]); | ||
| size_t keygen_stack = get_max_stack_usage(); | ||
| LOG_INFO("mldsa44_tiny_pub_from_seed Max Stack Usage: %u bytes", | ||
| (unsigned int)keygen_stack); | ||
|
|
||
| CHECK(check_arrays_eq_verbose(buf, kMldsa44ExpectedPublicKey, | ||
| MLDSA44_PUBLIC_KEY_BYTES), | ||
| "PublicKey mismatch!"); | ||
| LOG_INFO("Keygen Test Passed."); | ||
|
|
||
| // 2. Sign Test | ||
| paint_stack(); | ||
| mldsa44_tiny_sign_deterministic_with_stack( | ||
| buf, kMldsa44SignSeed, kMldsa44Message, sizeof(kMldsa44Message), | ||
| &mldsa_stack[MLDSA_STACK_SIZE]); | ||
| size_t sign_stack = get_max_stack_usage(); | ||
| LOG_INFO("mldsa44_tiny_sign Max Stack Usage: %u bytes", | ||
| (unsigned int)sign_stack); | ||
|
|
||
| CHECK(check_arrays_eq_verbose(buf, kMldsa44ExpectedSignature, | ||
| MLDSA44_SIGNATURE_BYTES), | ||
| "Signature mismatch!"); | ||
| LOG_INFO("Sign Test Passed."); | ||
|
|
||
| // 3. Verify Test | ||
| mldsa44_tiny_pub_from_seed_with_stack(buf, kMldsa44SignSeed, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we compare here to a golden public key? On the other hand, if this fails, the verify below would also fail. So fine for me to leave it as it is. |
||
| &mldsa_stack[MLDSA_STACK_SIZE]); | ||
| paint_stack(); | ||
| int verify_res = mldsa44_tiny_verify_with_stack( | ||
| buf, kMldsa44ExpectedSignature, kMldsa44Message, sizeof(kMldsa44Message), | ||
| &mldsa_stack[MLDSA_STACK_SIZE]); | ||
| size_t verify_stack = get_max_stack_usage(); | ||
| LOG_INFO("mldsa44_tiny_verify Max Stack Usage: %u bytes", | ||
| (unsigned int)verify_stack); | ||
|
|
||
| CHECK(verify_res != 0, "mldsa44_tiny_verify failed!"); | ||
| LOG_INFO("Verify Test Passed."); | ||
|
|
||
| LOG_INFO("MLDSA44-TINY Test completed successfully!"); | ||
| return true; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| #include "sw/device/tests/embedpqc/mldsa_test_utils.h" | ||
|
|
||
| #include "sw/device/lib/runtime/log.h" | ||
|
|
||
| __attribute__((aligned(16))) uint8_t mldsa_stack[MLDSA_STACK_SIZE]; | ||
|
|
||
| void paint_stack(void) { | ||
| for (size_t i = 0; i < MLDSA_STACK_SIZE; i++) { | ||
| mldsa_stack[i] = 0xA5; | ||
| } | ||
| } | ||
|
|
||
| size_t get_max_stack_usage(void) { | ||
| for (size_t i = 0; i < MLDSA_STACK_SIZE; i++) { | ||
| if (mldsa_stack[i] != 0xA5) { | ||
| return MLDSA_STACK_SIZE - i; | ||
| } | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| bool check_arrays_eq_verbose(const uint8_t *got, const uint8_t *expected, | ||
| size_t len) { | ||
| bool match = true; | ||
| for (size_t i = 0; i < len; ++i) { | ||
| if (got[i] != expected[i]) { | ||
| LOG_INFO("Mismatch at index %u: got 0x%02x, expected 0x%02x", | ||
| (unsigned int)i, got[i], expected[i]); | ||
| match = false; | ||
| break; | ||
| } | ||
| } | ||
| return match; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| #ifndef OPENTITAN_SW_DEVICE_TESTS_EMBEDPQC_MLDSA_TEST_UTILS_H_ | ||
| #define OPENTITAN_SW_DEVICE_TESTS_EMBEDPQC_MLDSA_TEST_UTILS_H_ | ||
|
|
||
| #include <stdbool.h> | ||
| #include <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #define MLDSA_STACK_SIZE (64 * 1024) | ||
| extern uint8_t mldsa_stack[MLDSA_STACK_SIZE]; | ||
|
|
||
| /** | ||
| * Fills the custom stack buffer with a predefined pattern (0xA5) to allow | ||
| * stack high-watermark usage measurement. | ||
| */ | ||
| void paint_stack(void); | ||
|
|
||
| /** | ||
| * Analyzes the custom stack buffer to find the deepest modified address | ||
| * (non-0xA5) and returns the maximum stack usage in bytes. | ||
| * | ||
| * @return Deepest stack usage in bytes. | ||
| */ | ||
| size_t get_max_stack_usage(void); | ||
|
|
||
| /** | ||
| * Verbose array comparison helper that compares two byte buffers and logs | ||
| * the index, got value, and expected value of the first mismatch encountered. | ||
| * | ||
| * @param got The byte buffer obtained. | ||
| * @param expected The expected byte buffer. | ||
| * @param len Length of the buffers to compare in bytes. | ||
| * @return True if the buffers match exactly, False otherwise. | ||
| */ | ||
| bool check_arrays_eq_verbose(const uint8_t *got, const uint8_t *expected, | ||
| size_t len); | ||
|
|
||
| #endif // OPENTITAN_SW_DEVICE_TESTS_EMBEDPQC_MLDSA_TEST_UTILS_H_ |
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.
In cryptolib, we have:
opentitan/sw/device/lib/crypto/drivers/kmac.c
Line 762 in 56715af
So here we are running an additional CMD.RUN after a last full block. This is fine.