Skip to content

Commit 035e9aa

Browse files
committed
Lowram: Share buffers with non-overlapping lifetimes in keygen
Reuse t0 as the accumulator in mld_compute_t0_t1_tr_from_sk_components, and have the caller provide s1 already in NTT form, removing two allocations (s1hat and t) from the helper. In mld_sign_keypair_internal, share the s1 and t1 buffers via a union since s1hat is consumed before t1 is produced. Pack s1 into the secret key before the in-place NTT so the original coefficients are preserved. Split mld_pack_sk into mld_pack_sk_s1 and mld_pack_sk_rho_key_tr_s2_t0 to support packing s1 independently before the NTT. Signed-off-by: Matthias J. Kannwischer <matthias@zerorisc.com>
1 parent 9c62ded commit 035e9aa

18 files changed

Lines changed: 188 additions & 73 deletions

File tree

integration/opentitan/reduce_alloc.patch

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
# Copyright (c) The mldsa-native project authors
22
# SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT
33
diff --git a/sw/device/lib/crypto/include/mldsa.h b/sw/device/lib/crypto/include/mldsa.h
4-
index be11f20..26351ee 100644
4+
index be11f20..0000000 100644
55
--- a/sw/device/lib/crypto/include/mldsa.h
66
+++ b/sw/device/lib/crypto/include/mldsa.h
7-
@@ -41,16 +41,16 @@ enum {
7+
@@ -41,15 +41,15 @@ enum {
88
kOtcryptoMldsa87SeedBytes = 32,
99

1010
// Work buffer sizes in 32-bit words
1111
- kOtcryptoMldsa44WorkBufferKeypairWords = 32992 / sizeof(uint32_t),
1212
- kOtcryptoMldsa44WorkBufferSignWords = 32448 / sizeof(uint32_t),
13-
+ kOtcryptoMldsa44WorkBufferKeypairWords = 28960 / sizeof(uint32_t),
13+
+ kOtcryptoMldsa44WorkBufferKeypairWords = 16672 / sizeof(uint32_t),
1414
+ kOtcryptoMldsa44WorkBufferSignWords = 20256 / sizeof(uint32_t),
1515
kOtcryptoMldsa44WorkBufferVerifyWords = 22464 / sizeof(uint32_t),
1616

1717
- kOtcryptoMldsa65WorkBufferKeypairWords = 46304 / sizeof(uint32_t),
1818
- kOtcryptoMldsa65WorkBufferSignWords = 44768 / sizeof(uint32_t),
19-
+ kOtcryptoMldsa65WorkBufferKeypairWords = 40224 / sizeof(uint32_t),
19+
+ kOtcryptoMldsa65WorkBufferKeypairWords = 23840 / sizeof(uint32_t),
2020
+ kOtcryptoMldsa65WorkBufferSignWords = 26432 / sizeof(uint32_t),
2121
kOtcryptoMldsa65WorkBufferVerifyWords = 30720 / sizeof(uint32_t),
2222

2323
- kOtcryptoMldsa87WorkBufferKeypairWords = 62688 / sizeof(uint32_t),
2424
- kOtcryptoMldsa87WorkBufferSignWords = 59104 / sizeof(uint32_t),
25-
+ kOtcryptoMldsa87WorkBufferKeypairWords = 54560 / sizeof(uint32_t),
25+
+ kOtcryptoMldsa87WorkBufferKeypairWords = 32032 / sizeof(uint32_t),
2626
+ kOtcryptoMldsa87WorkBufferSignWords = 34624 / sizeof(uint32_t),
2727
kOtcryptoMldsa87WorkBufferVerifyWords = 41216 / sizeof(uint32_t),
2828
};

mldsa/mldsa_native.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,8 @@
260260
#undef mld_pack_sig_c
261261
#undef mld_pack_sig_h_poly
262262
#undef mld_pack_sig_z
263-
#undef mld_pack_sk
263+
#undef mld_pack_sk_rho_key_tr_s2_t0
264+
#undef mld_pack_sk_s1
264265
#undef mld_unpack_pk
265266
#undef mld_unpack_sig
266267
#undef mld_unpack_sk

mldsa/mldsa_native.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -912,35 +912,35 @@ int MLD_API_NAMESPACE(pk_from_sk)(
912912
*/
913913
/* check-magic: off */
914914
#if defined(MLD_API_LEGACY_CONFIG) || !defined(MLD_CONFIG_REDUCE_RAM)
915-
#define MLD_TOTAL_ALLOC_44_KEYPAIR_NO_PCT 41216
915+
#define MLD_TOTAL_ALLOC_44_KEYPAIR_NO_PCT 33024
916916
#define MLD_TOTAL_ALLOC_44_KEYPAIR_PCT 52544
917-
#define MLD_TOTAL_ALLOC_44_PK_FROM_SK 45248
917+
#define MLD_TOTAL_ALLOC_44_PK_FROM_SK 41152
918918
#define MLD_TOTAL_ALLOC_44_SIGN 48800
919919
#define MLD_TOTAL_ALLOC_44_VERIFY 38816
920-
#define MLD_TOTAL_ALLOC_65_KEYPAIR_NO_PCT 65792
920+
#define MLD_TOTAL_ALLOC_65_KEYPAIR_NO_PCT 54528
921921
#define MLD_TOTAL_ALLOC_65_KEYPAIR_PCT 79712
922-
#define MLD_TOTAL_ALLOC_65_PK_FROM_SK 71872
922+
#define MLD_TOTAL_ALLOC_65_PK_FROM_SK 65728
923923
#define MLD_TOTAL_ALLOC_65_SIGN 74432
924924
#define MLD_TOTAL_ALLOC_65_VERIFY 62432
925-
#define MLD_TOTAL_ALLOC_87_KEYPAIR_NO_PCT 104704
925+
#define MLD_TOTAL_ALLOC_87_KEYPAIR_NO_PCT 89344
926926
#define MLD_TOTAL_ALLOC_87_KEYPAIR_PCT 122624
927-
#define MLD_TOTAL_ALLOC_87_PK_FROM_SK 112832
927+
#define MLD_TOTAL_ALLOC_87_PK_FROM_SK 104640
928928
#define MLD_TOTAL_ALLOC_87_SIGN 115392
929929
#define MLD_TOTAL_ALLOC_87_VERIFY 99552
930930
#else /* MLD_API_LEGACY_CONFIG || !MLD_CONFIG_REDUCE_RAM */
931-
#define MLD_TOTAL_ALLOC_44_KEYPAIR_NO_PCT 28960
932-
#define MLD_TOTAL_ALLOC_44_KEYPAIR_PCT 28960
933-
#define MLD_TOTAL_ALLOC_44_PK_FROM_SK 32992
931+
#define MLD_TOTAL_ALLOC_44_KEYPAIR_NO_PCT 16672
932+
#define MLD_TOTAL_ALLOC_44_KEYPAIR_PCT 26208
933+
#define MLD_TOTAL_ALLOC_44_PK_FROM_SK 28896
934934
#define MLD_TOTAL_ALLOC_44_SIGN 20256
935935
#define MLD_TOTAL_ALLOC_44_VERIFY 22464
936-
#define MLD_TOTAL_ALLOC_65_KEYPAIR_NO_PCT 40224
937-
#define MLD_TOTAL_ALLOC_65_KEYPAIR_PCT 40224
938-
#define MLD_TOTAL_ALLOC_65_PK_FROM_SK 46304
936+
#define MLD_TOTAL_ALLOC_65_KEYPAIR_NO_PCT 23840
937+
#define MLD_TOTAL_ALLOC_65_KEYPAIR_PCT 36000
938+
#define MLD_TOTAL_ALLOC_65_PK_FROM_SK 40160
939939
#define MLD_TOTAL_ALLOC_65_SIGN 26432
940940
#define MLD_TOTAL_ALLOC_65_VERIFY 30720
941-
#define MLD_TOTAL_ALLOC_87_KEYPAIR_NO_PCT 54560
942-
#define MLD_TOTAL_ALLOC_87_KEYPAIR_PCT 54560
943-
#define MLD_TOTAL_ALLOC_87_PK_FROM_SK 62688
941+
#define MLD_TOTAL_ALLOC_87_KEYPAIR_NO_PCT 32032
942+
#define MLD_TOTAL_ALLOC_87_KEYPAIR_PCT 48448
943+
#define MLD_TOTAL_ALLOC_87_PK_FROM_SK 54496
944944
#define MLD_TOTAL_ALLOC_87_SIGN 34624
945945
#define MLD_TOTAL_ALLOC_87_VERIFY 41216
946946
#endif /* !(MLD_API_LEGACY_CONFIG || !MLD_CONFIG_REDUCE_RAM) */

mldsa/mldsa_native_asm.S

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@
265265
#undef mld_pack_sig_c
266266
#undef mld_pack_sig_h_poly
267267
#undef mld_pack_sig_z
268-
#undef mld_pack_sk
268+
#undef mld_pack_sk_rho_key_tr_s2_t0
269+
#undef mld_pack_sk_s1
269270
#undef mld_unpack_pk
270271
#undef mld_unpack_sig
271272
#undef mld_unpack_sk

mldsa/src/packing.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,19 @@ void mld_unpack_pk(uint8_t rho[MLDSA_SEEDBYTES], mld_polyveck *t1,
5151
}
5252

5353
MLD_INTERNAL_API
54-
void mld_pack_sk(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
55-
const uint8_t rho[MLDSA_SEEDBYTES],
56-
const uint8_t tr[MLDSA_TRBYTES],
57-
const uint8_t key[MLDSA_SEEDBYTES], const mld_polyveck *t0,
58-
const mld_polyvecl *s1, const mld_polyveck *s2)
54+
void mld_pack_sk_s1(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
55+
const mld_polyvecl *s1)
56+
{
57+
mld_polyvecl_pack_eta(sk + 2 * MLDSA_SEEDBYTES + MLDSA_TRBYTES, s1);
58+
}
59+
60+
MLD_INTERNAL_API
61+
void mld_pack_sk_rho_key_tr_s2_t0(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
62+
const uint8_t rho[MLDSA_SEEDBYTES],
63+
const uint8_t tr[MLDSA_TRBYTES],
64+
const uint8_t key[MLDSA_SEEDBYTES],
65+
const mld_polyveck *t0,
66+
const mld_polyveck *s2)
5967
{
6068
mld_memcpy(sk, rho, MLDSA_SEEDBYTES);
6169
sk += MLDSA_SEEDBYTES;
@@ -66,7 +74,7 @@ void mld_pack_sk(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
6674
mld_memcpy(sk, tr, MLDSA_TRBYTES);
6775
sk += MLDSA_TRBYTES;
6876

69-
mld_polyvecl_pack_eta(sk, s1);
77+
/* s1 already packed via mld_pack_sk_s1 */
7078
sk += MLDSA_L * MLDSA_POLYETA_PACKEDBYTES;
7179

7280
mld_polyveck_pack_eta(sk, s2);

mldsa/src/packing.h

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,38 +31,56 @@ __contract__(
3131
);
3232

3333

34-
#define mld_pack_sk MLD_NAMESPACE_KL(pack_sk)
34+
#define mld_pack_sk_s1 MLD_NAMESPACE_KL(pack_sk_s1)
3535
/*************************************************
36-
* Name: mld_pack_sk
36+
* Name: mld_pack_sk_s1
3737
*
38-
* Description: Bit-pack secret key sk = (rho, tr, key, t0, s1, s2).
38+
* Description: Bit-pack the s1 component into the secret key.
39+
*
40+
* Arguments: - uint8_t sk[]: output byte array
41+
* - const mld_polyvecl *s1: pointer to vector s1
42+
**************************************************/
43+
MLD_INTERNAL_API
44+
void mld_pack_sk_s1(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
45+
const mld_polyvecl *s1)
46+
__contract__(
47+
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
48+
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
49+
requires(forall(k1, 0, MLDSA_L,
50+
array_abs_bound(s1->vec[k1].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
51+
assigns(memory_slice(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
52+
);
53+
54+
#define mld_pack_sk_rho_key_tr_s2_t0 MLD_NAMESPACE_KL(pack_sk_rho_key_tr_s2_t0)
55+
/*************************************************
56+
* Name: mld_pack_sk_rho_key_tr_s2_t0
57+
*
58+
* Description: Bit-pack rho, key, tr, s2, t0 into the secret key.
59+
* s1 must already be packed via mld_pack_sk_s1.
3960
*
4061
* Arguments: - uint8_t sk[]: output byte array
4162
* - const uint8_t rho[]: byte array containing rho
4263
* - const uint8_t tr[]: byte array containing tr
4364
* - const uint8_t key[]: byte array containing key
4465
* - const mld_polyveck *t0: pointer to vector t0
45-
* - const mld_polyvecl *s1: pointer to vector s1
4666
* - const mld_polyveck *s2: pointer to vector s2
4767
**************************************************/
4868
MLD_INTERNAL_API
49-
void mld_pack_sk(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
50-
const uint8_t rho[MLDSA_SEEDBYTES],
51-
const uint8_t tr[MLDSA_TRBYTES],
52-
const uint8_t key[MLDSA_SEEDBYTES], const mld_polyveck *t0,
53-
const mld_polyvecl *s1, const mld_polyveck *s2)
69+
void mld_pack_sk_rho_key_tr_s2_t0(uint8_t sk[MLDSA_CRYPTO_SECRETKEYBYTES],
70+
const uint8_t rho[MLDSA_SEEDBYTES],
71+
const uint8_t tr[MLDSA_TRBYTES],
72+
const uint8_t key[MLDSA_SEEDBYTES],
73+
const mld_polyveck *t0,
74+
const mld_polyveck *s2)
5475
__contract__(
5576
requires(memory_no_alias(sk, MLDSA_CRYPTO_SECRETKEYBYTES))
5677
requires(memory_no_alias(rho, MLDSA_SEEDBYTES))
5778
requires(memory_no_alias(tr, MLDSA_TRBYTES))
5879
requires(memory_no_alias(key, MLDSA_SEEDBYTES))
5980
requires(memory_no_alias(t0, sizeof(mld_polyveck)))
60-
requires(memory_no_alias(s1, sizeof(mld_polyvecl)))
6181
requires(memory_no_alias(s2, sizeof(mld_polyveck)))
6282
requires(forall(k0, 0, MLDSA_K,
6383
array_bound(t0->vec[k0].coeffs, 0, MLDSA_N, -(1<<(MLDSA_D-1)) + 1, (1<<(MLDSA_D-1)) + 1)))
64-
requires(forall(k1, 0, MLDSA_L,
65-
array_abs_bound(s1->vec[k1].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
6684
requires(forall(k2, 0, MLDSA_K,
6785
array_abs_bound(s2->vec[k2].coeffs, 0, MLDSA_N, MLDSA_ETA + 1)))
6886
assigns(memory_slice(sk, MLDSA_CRYPTO_SECRETKEYBYTES))

mldsa/src/poly.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ void mld_poly_power2round(mld_poly *a1, mld_poly *a0, const mld_poly *a)
508508
__loop__(
509509
assigns(i, memory_slice(a0, sizeof(mld_poly)), memory_slice(a1, sizeof(mld_poly)))
510510
invariant(i <= MLDSA_N)
511+
invariant(forall(k0, i, MLDSA_N, a->coeffs[k0] == loop_entry(*a).coeffs[k0]))
511512
invariant(array_bound(a0->coeffs, 0, i, -(MLD_2_POW_D/2)+1, (MLD_2_POW_D/2)+1))
512513
invariant(array_bound(a1->coeffs, 0, i, 0, ((MLDSA_Q - 1) / MLD_2_POW_D) + 1))
513514
decreases(MLDSA_N - i)

mldsa/src/poly.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ void mld_poly_power2round(mld_poly *a1, mld_poly *a0, const mld_poly *a)
213213
__contract__(
214214
requires(memory_no_alias(a0, sizeof(mld_poly)))
215215
requires(memory_no_alias(a1, sizeof(mld_poly)))
216-
requires(memory_no_alias(a, sizeof(mld_poly)))
216+
requires(a0 == a)
217217
requires(array_bound(a->coeffs, 0, MLDSA_N, 0, MLDSA_Q))
218218
assigns(memory_slice(a1, sizeof(mld_poly)))
219219
assigns(memory_slice(a0, sizeof(mld_poly)))

mldsa/src/polyvec.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ void mld_polyveck_power2round(mld_polyveck *v1, mld_polyveck *v0,
655655
__loop__(
656656
assigns(i, memory_slice(v0, sizeof(mld_polyveck)), memory_slice(v1, sizeof(mld_polyveck)))
657657
invariant(i <= MLDSA_K)
658+
invariant(forall(k0, i, MLDSA_K, array_bound(v->vec[k0].coeffs, 0, MLDSA_N, 0, MLDSA_Q)))
658659
invariant(forall(k1, 0, i, array_bound(v0->vec[k1].coeffs, 0, MLDSA_N, -(MLD_2_POW_D/2)+1, (MLD_2_POW_D/2)+1)))
659660
invariant(forall(k2, 0, i, array_bound(v1->vec[k2].coeffs, 0, MLDSA_N, 0, ((MLDSA_Q - 1) / MLD_2_POW_D) + 1)))
660661
decreases(MLDSA_K - i)

mldsa/src/polyvec.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ void mld_polyveck_power2round(mld_polyveck *v1, mld_polyveck *v0,
369369
__contract__(
370370
requires(memory_no_alias(v1, sizeof(mld_polyveck)))
371371
requires(memory_no_alias(v0, sizeof(mld_polyveck)))
372-
requires(memory_no_alias(v, sizeof(mld_polyveck)))
372+
requires(v0 == v)
373373
requires(forall(k0, 0, MLDSA_K, array_bound(v->vec[k0].coeffs, 0, MLDSA_N, 0, MLDSA_Q)))
374374
assigns(memory_slice(v1, sizeof(mld_polyveck)))
375375
assigns(memory_slice(v0, sizeof(mld_polyveck)))

0 commit comments

Comments
 (0)