Skip to content

Commit 76ea290

Browse files
committed
Destruct intermediate buffers on the stack
FIPS 204, Section 3.6.3 demands the destruction of intermediate values before returning to the caller. This commit implements this. A new function mld_zeroize() is introduced which is used to wipe intermediate stack buffers prior to function return. By default, mld_zeroize() is implemented via SecureZeroMemory on Windows, and a plain memset + compiler barrier otherwise. If neither makes sense, compilation fails. Using memset_s would be preferred, but there is no portable way of detecting whether it is available. If users need to register a custom mld_zeroize, they can do so by defining MLD_CONFIG_CUSTOM_ZEROIZE and defining mld_zeroize_native, similar to how the arithmetic and FIPS-202 backends work. This includes the case where the user does not wish to do stack zeroization, or has an entirely separate (and more robust) method for it, such as compiler instrumentation. In this case, mld_zeroize_native() can be set to a no-op. Signed-off-by: Jake Massimo <[email protected]>
1 parent 616ca6d commit 76ea290

File tree

21 files changed

+278
-28
lines changed

21 files changed

+278
-28
lines changed

mldsa/common.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef MLD_COMMON_H
77
#define MLD_COMMON_H
88

9+
#include "cbmc.h"
910
#include "params.h"
1011
#include "sys.h"
1112

@@ -51,4 +52,54 @@
5152
#if defined(MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202)
5253
#include MLD_CONFIG_FIPS202_BACKEND_FILE
5354
#endif
55+
56+
#if !defined(__ASSEMBLER__)
57+
#include <string.h>
58+
59+
/*************************************************
60+
* Name: mld_zeroize
61+
*
62+
* Description: Force-zeroize a buffer.
63+
* FIPS 204. Section 3.6.3 Destruction of intermediate values.
64+
*
65+
* Arguments: void *ptr: pointer to buffer to be zeroed
66+
* size_t len: Amount of bytes to be zeroed
67+
**************************************************/
68+
static MLD_INLINE void mld_zeroize(void *ptr, size_t len)
69+
__contract__(
70+
requires(memory_no_alias(ptr, len))
71+
assigns(memory_slice(ptr, len))
72+
);
73+
74+
#if defined(MLD_CONFIG_CUSTOM_ZEROIZE)
75+
static MLD_INLINE void mld_zeroize(void *ptr, size_t len)
76+
{
77+
mld_zeroize_native(ptr, len);
78+
}
79+
#elif defined(MLD_SYS_WINDOWS)
80+
#include <windows.h>
81+
static MLD_INLINE void mld_zeroize(void *ptr, size_t len)
82+
{
83+
SecureZeroMemory(ptr, len);
84+
}
85+
#elif defined(MLD_HAVE_INLINE_ASM)
86+
static MLD_INLINE void mld_zeroize(void *ptr, size_t len)
87+
{
88+
memset(ptr, 0, len);
89+
/* This follows OpenSSL and seems sufficient to prevent the compiler
90+
* from optimizing away the memset.
91+
*
92+
* If there was a reliable way to detect availability of memset_s(),
93+
* that would be preferred. */
94+
__asm__ __volatile__("" : : "r"(ptr) : "memory");
95+
}
96+
#else /* !MLD_CONFIG_CUSTOM_ZEROIZE && !MLD_SYS_WINDOWS && MLD_HAVE_INLINE_ASM \
97+
*/
98+
#error No plausibly-secure implementation of mld_zeroize available. Please provide your own using MLD_CONFIG_CUSTOM_ZEROIZE.
99+
#endif /* !MLD_CONFIG_CUSTOM_ZEROIZE && !MLD_SYS_WINDOWS && \
100+
!MLD_HAVE_INLINE_ASM */
101+
102+
#endif /* !__ASSEMBLER__ */
103+
104+
54105
#endif /* !MLD_COMMON_H */

mldsa/config.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,46 @@
5959
#define MLD_CONFIG_FIPS202_BACKEND_FILE "fips202/native/auto.h"
6060
#endif
6161

62+
/******************************************************************************
63+
* Name: MLD_CONFIG_CUSTOM_ZEROIZE
64+
*
65+
* Description: In compliance with FIPS 204 Section 3.6.3, mldsa-native zeroizes
66+
* intermediate stack buffers before returning from function calls.
67+
*
68+
* Set this option and define `mld_zeroize_native` if you want to
69+
* use a custom method to zeroize intermediate stack buffers.
70+
* The default implementation uses SecureZeroMemory on Windows
71+
* and a memset + compiler barrier otherwise. If neither of those
72+
* is available on the target platform, compilation will fail,
73+
* and you will need to use MLD_CONFIG_CUSTOM_ZEROIZE to provide
74+
* a custom implementation of `mld_zeroize_native()`.
75+
*
76+
* WARNING:
77+
* The explicit stack zeroization conducted by mldsa-native
78+
* reduces the likelihood of data leaking on the stack, but
79+
* does not eliminate it! The C standard makes no guarantee about
80+
* where a compiler allocates structures and whether/where it makes
81+
* copies of them. Also, in addition to entire structures, there
82+
* may also be potentially exploitable leakage of individual values
83+
* on the stack.
84+
*
85+
* If you need bullet-proof zeroization of the stack, you need to
86+
* consider additional measures instead of what this feature
87+
* provides. In this case, you can set mld_zeroize_native to a
88+
* no-op.
89+
*
90+
*****************************************************************************/
91+
/* #define MLD_CONFIG_CUSTOM_ZEROIZE
92+
#if !defined(__ASSEMBLER__)
93+
#include <stdint.h>
94+
#include "sys.h"
95+
static MLD_INLINE void mld_zeroize_native(void *ptr, size_t len)
96+
{
97+
... your implementation ...
98+
}
99+
#endif
100+
*/
101+
62102
/******************************************************************************
63103
* Name: MLD_CONFIG_KEYGEN_PCT
64104
*

mldsa/fips202/fips202.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,8 +437,8 @@ void shake128_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state)
437437

438438
void shake128_release(keccak_state *state)
439439
{
440-
(void)state;
441-
/* TODO: add secure zeroization*/
440+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
441+
mld_zeroize(state, sizeof(keccak_state));
442442
}
443443

444444
/*************************************************
@@ -535,8 +535,8 @@ void shake256_squeezeblocks(uint8_t *out, size_t nblocks, keccak_state *state)
535535

536536
void shake256_release(keccak_state *state)
537537
{
538-
(void)state;
539-
/* TODO: add secure zeroization*/
538+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
539+
mld_zeroize(state, sizeof(keccak_state));
540540
}
541541

542542
/*************************************************
@@ -560,6 +560,9 @@ void shake128(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen)
560560
outlen -= nblocks * SHAKE128_RATE;
561561
out += nblocks * SHAKE128_RATE;
562562
shake128_squeeze(out, outlen, &state);
563+
564+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
565+
mld_zeroize(&state, sizeof(state));
563566
}
564567

565568
/*************************************************
@@ -583,6 +586,9 @@ void shake256(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen)
583586
outlen -= nblocks * SHAKE256_RATE;
584587
out += nblocks * SHAKE256_RATE;
585588
shake256_squeeze(out, outlen, &state);
589+
590+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
591+
mld_zeroize(&state, sizeof(state));
586592
}
587593

588594
/*************************************************
@@ -606,6 +612,9 @@ void sha3_256(uint8_t h[SHA3_256_HASHBYTES], const uint8_t *in, size_t inlen)
606612
{
607613
store64(h + 8 * i, s[i]);
608614
}
615+
616+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
617+
mld_zeroize(s, sizeof(s));
609618
}
610619

611620
/*************************************************
@@ -629,4 +638,7 @@ void sha3_512(uint8_t h[SHA3_512_HASHBYTES], const uint8_t *in, size_t inlen)
629638
{
630639
store64(h + 8 * i, s[i]);
631640
}
641+
642+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
643+
mld_zeroize(s, sizeof(s));
632644
}

mldsa/fips202/fips202x4.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,8 @@ void mld_shake128x4_squeezeblocks(uint8_t *out0, uint8_t *out1, uint8_t *out2,
123123
void mld_shake128x4_init(mld_shake128x4ctx *state) { (void)state; }
124124
void mld_shake128x4_release(mld_shake128x4ctx *state)
125125
{
126-
/* Specification: Partially implements
127-
* @[FIPS203, Section 3.3, Destruction of intermediate values] */
128-
(void)state;
129-
/*mld_zeroize(state, sizeof(mld_shake128x4ctx));*/
126+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
127+
mld_zeroize(state, sizeof(mld_shake128x4ctx));
130128
}
131129

132130

@@ -150,8 +148,6 @@ void mld_shake256x4_squeezeblocks(uint8_t *out0, uint8_t *out1, uint8_t *out2,
150148
void mld_shake256x4_init(mld_shake256x4ctx *state) { (void)state; }
151149
void mld_shake256x4_release(mld_shake256x4ctx *state)
152150
{
153-
/* Specification: Partially implements
154-
* @[FIPS203, Section 3.3, Destruction of intermediate values] */
155-
(void)state;
156-
/*mld_zeroize(state, sizeof(mld_shake256x4ctx));*/
151+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
152+
mld_zeroize(state, sizeof(mld_shake256x4ctx));
157153
}

mldsa/poly.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ void mld_poly_uniform(mld_poly *a, const uint8_t seed[MLDSA_SEEDBYTES + 2])
376376
ctr = mld_rej_uniform(a->coeffs, MLDSA_N, ctr, buf, buflen);
377377
}
378378
mld_xof128_release(&state);
379+
380+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
381+
mld_zeroize(buf, sizeof(buf));
379382
}
380383

381384
void mld_poly_uniform_4x(mld_poly *vec0, mld_poly *vec1, mld_poly *vec2,
@@ -431,6 +434,9 @@ void mld_poly_uniform_4x(mld_poly *vec0, mld_poly *vec1, mld_poly *vec2,
431434
ctr[3] = mld_rej_uniform(vec3->coeffs, MLDSA_N, ctr[3], buf[3], buflen);
432435
}
433436
mld_xof128_x4_release(&state);
437+
438+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
439+
mld_zeroize(buf, sizeof(buf));
434440
}
435441

436442
/*************************************************
@@ -628,6 +634,10 @@ void mld_poly_uniform_eta_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
628634
}
629635

630636
mld_xof256_x4_release(&state);
637+
638+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
639+
mld_zeroize(buf, sizeof(buf));
640+
mld_zeroize(extseed, sizeof(extseed));
631641
}
632642

633643

@@ -651,6 +661,10 @@ void mld_poly_uniform_gamma1(mld_poly *a, const uint8_t seed[MLDSA_CRHBYTES],
651661
mld_polyz_unpack(a, buf);
652662

653663
mld_xof256_release(&state);
664+
665+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
666+
mld_zeroize(buf, sizeof(buf));
667+
mld_zeroize(extseed, sizeof(extseed));
654668
}
655669

656670
void mld_poly_uniform_gamma1_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
@@ -690,6 +704,10 @@ void mld_poly_uniform_gamma1_4x(mld_poly *r0, mld_poly *r1, mld_poly *r2,
690704
mld_polyz_unpack(r2, buf[2]);
691705
mld_polyz_unpack(r3, buf[3]);
692706
mld_xof256_x4_release(&state);
707+
708+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
709+
mld_zeroize(buf, sizeof(buf));
710+
mld_zeroize(extseed, sizeof(extseed));
693711
}
694712

695713

@@ -764,6 +782,10 @@ void mld_poly_challenge(mld_poly *c, const uint8_t seed[MLDSA_CTILDEBYTES])
764782
signs >>= 1;
765783
}
766784

785+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
786+
mld_zeroize(buf, sizeof(buf));
787+
mld_zeroize(&signs, sizeof(signs));
788+
767789
mld_assert_bound(c->coeffs, MLDSA_N, -1, 2);
768790
}
769791

mldsa/polyvec.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ void mld_polyvec_matrix_expand(mld_polyvecl mat[MLDSA_K],
110110
mld_poly_permute_bitrev_to_custom(mat[i].vec[j].coeffs);
111111
}
112112
}
113+
114+
/* FIPS 204. Section 3.6.3 Destruction of intermediate values. */
115+
mld_zeroize(seed_ext, sizeof(seed_ext));
113116
}
114117

115118
void mld_polyvec_matrix_pointwise_montgomery(mld_polyveck *t,

0 commit comments

Comments
 (0)