-
Notifications
You must be signed in to change notification settings - Fork 977
[crypto] ML-DSA-87: sec_a2b, sec_b2a, sec_add, sec_unmask (1/14)
#29639
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: master
Are you sure you want to change the base?
Changes from all commits
42f0d3d
222ae81
dfc2dcf
05543fd
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 |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| /* Copyright lowRISC contributors (OpenTitan project). */ | ||
| /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ | ||
| /* SPDX-License-Identifier: Apache-2.0 */ | ||
|
|
||
| /* Secure masked gadgets. */ | ||
|
|
||
| .globl sec_a2b_8x32 | ||
| .globl sec_b2a_8x32 | ||
| .globl sec_add_8x32 | ||
| .globl sec_unmask_8x32 | ||
|
|
||
| /* | ||
|
|
||
| The masking accelerator supports three functions that operate in a vectroized | ||
| fashion on 8 coefficients in a single WDR. The interface consists of four input | ||
| WSRs to pass two shared vectors to the accelerator, MAI_IN0_S0 and MAI_IN0_S1 | ||
| for the first input and MAI_IN1_S0 and MAI_IN1_S1 for the second input which is | ||
| only used for the second summand in the secure addition. The shared result of | ||
| the operation can be read in the MAI_RES_S0 and MAI_RES_S1 WSRs. The interface | ||
| has a single control register MAI_CTRL that instruments the accelerator and | ||
| immediately triggers a computation upon seeing a valid configuration value. | ||
|
|
||
| Note that some routines of this modules draw randomness from URND for masking | ||
| purposes, hence while an MAI operation is ongoing, URND bits shall not be | ||
| shared between different routines. | ||
|
|
||
| Most routines of this module are a direct implementation of the gadgets in the | ||
| work of Azouaoui et al. [1]. | ||
|
|
||
| [1] https://tches.iacr.org/index.php/TCHES/article/view/11158/10597 | ||
|
|
||
| */ | ||
andrea-caforio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /* | ||
| * Configuration values for the MAI_CTRL register. | ||
| */ | ||
| .set MAI_CTRL_A2B, 0x1 | ||
| .set MAI_CTRL_B2A, 0x3 | ||
| .set MAI_CTRL_ADD, 0x5 | ||
|
|
||
| .text | ||
|
|
||
| /* MAI interface polling routine. */ | ||
| _mai_poll: | ||
| csrrs x20, MAI_STATUS, x0 | ||
| andi x20, x20, 0x1 | ||
| bne x20, x0, _mai_poll | ||
| ret | ||
|
|
||
| /** | ||
| * Convert the arithmetic sharing of a vector of 8 coefficients (x0_A, x1_A) to | ||
| * a Boolean sharing (x0_B, x1_B). | ||
| * | ||
| * @param[in] w0: x0_A, first arithmetic share. | ||
| * @param[in] w1: x1_A, second arithmetic share. | ||
| * @param[out] w0: x0_B, first Boolean share. | ||
| * @param[out] w1: x1_B, second Boolean share | ||
| */ | ||
| sec_a2b_8x32: | ||
| /* Write the two shares to the input WSRs (intersperse with configuration of | ||
| MAI_CTRL to not access both shares in subsequent instructions). */ | ||
| bn.wsrw MAI_IN0_S0, w0 | ||
| addi x20, x0, MAI_CTRL_A2B | ||
| bn.wsrw MAI_IN0_S1, w1 | ||
|
|
||
| /* Trigger the conversion. */ | ||
| csrrw x0, MAI_CTRL, x20 | ||
|
|
||
| /* TODO: Replace with deterministic wait, once exact latency is known. */ | ||
| jal x1, _mai_poll | ||
|
|
||
| /* Read back the result. */ | ||
| bn.wsrr w0, MAI_RES_S0 | ||
|
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 save to overwrite
Contributor
Author
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. I think it is okay. There shouldn't be any leakage. |
||
| bn.xor w31, w31, w31 /* dummy */ | ||
| bn.wsrr w1, MAI_RES_S1 | ||
|
|
||
| ret | ||
|
|
||
| /** | ||
| * Convert the Boolean sharing of a vector of 8 coefficients (x0_B, x1_B) to a | ||
| * arithmetic sharing (x0_A, x1_A). | ||
| * | ||
| * @param[in] w0: x0_B, first arithmetic share. | ||
| * @param[in] w1: x1_B, second arithmetic share. | ||
| * @param[out] w0: x0_A, first Boolean share. | ||
| * @param[out] w1: x1_A, second Boolean share | ||
| */ | ||
| sec_b2a_8x32: | ||
| /* Write the two shares to the input WSRs (intersperse with configuration of | ||
| MAI_CTRL to not access both shares in subsequent instructions). */ | ||
| bn.wsrw MAI_IN0_S0, w0 | ||
| addi x20, x0, MAI_CTRL_B2A | ||
| bn.wsrw MAI_IN0_S1, w1 | ||
|
|
||
| /* Trigger the conversion. */ | ||
| csrrw x0, MAI_CTRL, x20 | ||
|
|
||
| /* TODO: Replace with deterministic wait, once latency is known. */ | ||
| jal x1, _mai_poll | ||
|
|
||
| /* Read back the result. */ | ||
| bn.wsrr w0, MAI_RES_S0 | ||
| bn.xor w31, w31, w31 /* dummy */ | ||
| bn.wsrr w1, MAI_RES_S1 | ||
|
|
||
| ret | ||
|
|
||
| /** | ||
| * Calculate a vectorized addition modulo 2^32 of 8 Boolean-shared coefficients. | ||
| * | ||
| * @param[in] w0: x0_B, first Boolean share of x | ||
| * @param[in] w1: x1_B, second Boolean share of x. | ||
| * @param[in] w2: y0_B, first Boolean share of y | ||
| * @param[in] w3: y1_B, second Boolean share of y. | ||
| * @param[out] w0: z0_B, first Boolean share of the result z = x + y. | ||
| * @param[out] w1: z1_B, second Boolean share of the result z = x + y. | ||
| */ | ||
| sec_add_8x32: | ||
| /* Write the two summands to the input WSRs (intersperse with configuration of | ||
| MAI_CTRL to not access both shares in subsequent instructions). */ | ||
| bn.wsrw MAI_IN0_S0, w0 | ||
| bn.wsrw MAI_IN1_S0, w2 | ||
|
|
||
| addi x20, x0, MAI_CTRL_ADD | ||
|
|
||
| bn.wsrw MAI_IN0_S1, w1 | ||
| bn.wsrw MAI_IN1_S1, w3 | ||
|
|
||
| /* Trigger the conversion. */ | ||
| csrrw x0, MAI_CTRL, x20 | ||
|
|
||
| /* TODO: Replace with deterministic wait, once latency is known. */ | ||
| jal x1, _mai_poll | ||
|
|
||
| /* Read back the result. */ | ||
| bn.wsrr w0, MAI_RES_S0 | ||
| bn.xor w31, w31, w31 /* dummy */ | ||
| bn.wsrr w1, MAI_RES_S1 | ||
|
|
||
| ret | ||
|
|
||
| /** | ||
| * Securely unmask a vector of 8 Boolean-shared coefficients. | ||
| * | ||
| * This is an implementation of the `SecUnMask` function (Algorithm 3 in [1]). | ||
| * | ||
| * @param[in] w0: x0_B, first Boolean share of x | ||
| * @param[in] w1: x1_B, second Boolean share of x. | ||
| * @param[out] w0: x, unmasked value x. | ||
| */ | ||
| sec_unmask_8x32: | ||
| /* Sample a fresh random mask and XOR it to the shares before unmasking. */ | ||
| bn.wsrr w20, URND | ||
|
|
||
| bn.xor w0, w0, w20 | ||
| bn.xor w31, w31, w31 /* dummy */ | ||
| bn.xor w1, w1, w20 | ||
|
|
||
| bn.xor w0, w0, w1 | ||
|
|
||
| ret | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| { | ||
| "entrypoint": "main", | ||
| "output": { | ||
| "regs": { | ||
| "w2": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* Copyright lowRISC contributors (OpenTitan project). */ | ||
| /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ | ||
| /* SPDX-License-Identifier: Apache-2.0 */ | ||
|
|
||
| /* Randomized test to verify the A2B conversion. */ | ||
|
|
||
| .section .text.start | ||
|
|
||
| main: | ||
| la x31, _stack | ||
| bn.xor w31, w31, w31 | ||
|
|
||
| la x2, _params | ||
| bn.lid x0, 0(x2) | ||
| bn.wsrw MOD, w0 | ||
|
|
||
| bn.not w2, w31 /* flag */ | ||
| bn.shv.8s w3, w2 >> 10 /* mask */ | ||
|
|
||
| /* Generate 100 random arithmetically shared vectors and verify that they can | ||
| be correctly converted to Boolean shares. */ | ||
| loopi 100, 10 | ||
| /* Random vector of coefficients < q. */ | ||
| bn.wsrr w4, URND | ||
| bn.and w4, w4, w3 | ||
|
|
||
| /* Random coefficient masks < q. */ | ||
| bn.wsrr w5, URND | ||
| bn.and w5, w5, w3 | ||
|
|
||
| /* Create the two arithmetic shares and trigger the conversion. */ | ||
| bn.subvm.8s w0, w4, w5 | ||
| bn.mov w1, w5 | ||
| jal x1, sec_a2b_8x32 | ||
|
|
||
| /* Unmask the result. */ | ||
| bn.xor w0, w0, w1 | ||
|
|
||
| /* Check that the unmask result is equal to the initial vector. */ | ||
| bn.cmp w0, w4, FG0 | ||
| bn.sel w2, w2, w31, FG0.Z | ||
| /* End of loop */ | ||
|
|
||
| ecall | ||
|
|
||
| .data | ||
| .balign 32 | ||
|
|
||
| _params: | ||
| .word 0x007fe001 /* q */ | ||
| .word 0xfc7fdfff /* mu */ | ||
| .word 0x0000a3fa /* n^-1 * R^3 mod q */ | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
|
|
||
| _stack: | ||
| .zero 4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| { | ||
| "entrypoint": "main", | ||
| "output": { | ||
| "regs": { | ||
| "w4": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| /* Copyright lowRISC contributors (OpenTitan project). */ | ||
| /* Licensed under the Apache License, Version 2.0, see LICENSE for details. */ | ||
| /* SPDX-License-Identifier: Apache-2.0 */ | ||
|
|
||
| /* Randomized test to verify the secure addition. */ | ||
|
|
||
| .section .text.start | ||
|
|
||
| main: | ||
| la x31, _stack | ||
| bn.xor w31, w31, w31 | ||
|
|
||
| la x2, _params | ||
| bn.lid x0, 0(x2) | ||
| bn.wsrw MOD, w0 | ||
|
|
||
| bn.not w4, w31 /* flag */ | ||
|
|
||
| /* Generate 100 random Boolean-shared summands and verify that they can be | ||
| correctly added together. */ | ||
| loopi 100, 13 | ||
| /* Random vectors x and y < 2^32. */ | ||
| bn.wsrr w5, URND | ||
| bn.wsrr w6, URND | ||
|
|
||
| /* Expected result x + y mod 2^32. */ | ||
| bn.addv.8s w7, w5, w6 | ||
|
|
||
| /* Random masks */ | ||
| bn.wsrr w8, URND | ||
| bn.wsrr w9, URND | ||
|
|
||
| /* Create the two Boolean shares and trigger the conversion. */ | ||
| bn.xor w0, w5, w8 | ||
| bn.mov w1, w8 | ||
| bn.xor w2, w6, w9 | ||
| bn.mov w3, w9 | ||
| jal x1, sec_add_8x32 | ||
|
|
||
| /* Unmask the result. */ | ||
| bn.xor w0, w0, w1 | ||
|
|
||
| /* Check that the unmask result is equal to the initial vector. */ | ||
| bn.cmp w0, w7, FG0 | ||
| bn.sel w4, w4, w31, FG0.Z | ||
| /* End of loop */ | ||
|
|
||
| ecall | ||
|
|
||
| .data | ||
| .balign 32 | ||
|
|
||
| _params: | ||
| .word 0x007fe001 /* q */ | ||
| .word 0xfc7fdfff /* mu */ | ||
| .word 0x0000a3fa /* n^-1 * R^3 mod q */ | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
| .word 0x00000000 | ||
|
|
||
| _stack: | ||
| .zero 4 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // Copyright lowRISC contributors (OpenTitan project). | ||
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| { | ||
| "entrypoint": "main", | ||
| "output": { | ||
| "regs": { | ||
| "w2": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" | ||
| } | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.