Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions crypto/fipsmodule/ml_dsa/ml_dsa_ref/poly.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,29 +228,34 @@ void ml_dsa_poly_use_hint(ml_dsa_params *params,
* Arguments: - const poly *a: pointer to polynomial
* - int32_t B: norm bound
*
* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 1 otherwise.
* Returns 0 if norm is strictly smaller than B <= (Q-1)/8 and 0xFFFFFFFF otherwise.
**************************************************/
int ml_dsa_poly_chknorm(const ml_dsa_poly *a, int32_t B) {
uint32_t ml_dsa_poly_chknorm(const ml_dsa_poly *a, int32_t B) {
unsigned int i;
int32_t t;
uint32_t r = 0;

if(B > (ML_DSA_Q-1)/8) {
return 1;
return 0xFFFFFFFF;
}

/* It is ok to leak which coefficient violates the bound since
the probability for each coefficient is independent of secret
data but we must not leak the sign of the centralized representative. */
/* Constant-time implementation to avoid timing side-channel attacks.
We accumulate violations using bitwise OR instead of early exit.

Note: This uses constant_time_ge_w(t, B) instead of the mldsa-native
pattern constant_time_msb_w(B - 1 - t) because AWS-LC's constant-time
utilities handle the >= comparison correctly, while the subtraction
approach can cause unsigned underflow issues when t < B. Both are
mathematically equivalent: (t >= B) == (B - 1 - t < 0). */
for(i = 0; i < ML_DSA_N; ++i) {
/* Absolute value */
t = constant_time_select_int(constant_time_msb_w(a->coeffs[i]),
-a->coeffs[i], a->coeffs[i]);

if(t >= B) {
return 1;
}
/* Check if t >= B and accumulate result */
r |= constant_time_ge_w((uint32_t)t, (uint32_t)B);
}
return 0;
return r;
}

/*************************************************
Expand Down
2 changes: 1 addition & 1 deletion crypto/fipsmodule/ml_dsa/ml_dsa_ref/poly.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void ml_dsa_poly_use_hint(ml_dsa_params *params,
const ml_dsa_poly *a,
const ml_dsa_poly *h);

int ml_dsa_poly_chknorm(const ml_dsa_poly *a, int32_t B);
uint32_t ml_dsa_poly_chknorm(const ml_dsa_poly *a, int32_t B);

void ml_dsa_poly_uniform(ml_dsa_poly *a,
const uint8_t seed[ML_DSA_SEEDBYTES],
Expand Down
32 changes: 20 additions & 12 deletions crypto/fipsmodule/ml_dsa/ml_dsa_ref/polyvec.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,20 @@ void ml_dsa_polyvecl_pointwise_acc_montgomery(ml_dsa_params *params,
* - int32_t B: norm bound
*
* Returns 0 if norm of all polynomials is strictly smaller than B <= (Q-1)/8
* and 1 otherwise.
* and 0xFFFFFFFF otherwise.
**************************************************/
int ml_dsa_polyvecl_chknorm(ml_dsa_params *params, const polyvecl *v, int32_t bound) {
uint32_t ml_dsa_polyvecl_chknorm(ml_dsa_params *params, const polyvecl *v, int32_t bound) {
unsigned int i;
uint32_t r = 0;

/* Reference: Leaks which polynomial violates the bound via a conditional.
* We are more conservative to reduce the number of declassifications in
* constant-time testing.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Reference: Leaks which polynomial violates the bound via a conditional.
* We are more conservative to reduce the number of declassifications in
* constant-time testing.
*/

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed!

for(i = 0; i < params->l; ++i) {
if(ml_dsa_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
r |= ml_dsa_poly_chknorm(&v->vec[i], bound);
}
return 0;
return r;
}

/**************************************************************/
Expand Down Expand Up @@ -418,16 +422,20 @@ void ml_dsa_polyveck_pointwise_poly_montgomery(ml_dsa_params *params,
* - int32_t B: norm bound
*
* Returns 0 if norm of all polynomials are strictly smaller than B <= (Q-1)/8
* and 1 otherwise.
* and 0xFFFFFFFF otherwise.
**************************************************/
int ml_dsa_polyveck_chknorm(ml_dsa_params *params, const polyveck *v, int32_t bound) {
uint32_t ml_dsa_polyveck_chknorm(ml_dsa_params *params, const polyveck *v, int32_t bound) {
unsigned int i;
uint32_t r = 0;

/* Reference: Leaks which polynomial violates the bound via a conditional.
* We are more conservative to reduce the number of declassifications in
* constant-time testing.
*/
for(i = 0; i < params->k; ++i) {
if(ml_dsa_poly_chknorm(&v->vec[i], bound)) {
return 1;
}
r |= ml_dsa_poly_chknorm(&v->vec[i], bound);
}
return 0;
return r;
}

/*************************************************
Expand Down
4 changes: 2 additions & 2 deletions crypto/fipsmodule/ml_dsa/ml_dsa_ref/polyvec.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void ml_dsa_polyvecl_pointwise_acc_montgomery(ml_dsa_params *params,
const polyvecl *u,
const polyvecl *v);

int ml_dsa_polyvecl_chknorm(ml_dsa_params *params, const polyvecl *v, int32_t B);
uint32_t ml_dsa_polyvecl_chknorm(ml_dsa_params *params, const polyvecl *v, int32_t B);

typedef struct {
ml_dsa_poly vec[ML_DSA_K_MAX];
Expand Down Expand Up @@ -77,7 +77,7 @@ void ml_dsa_polyveck_pointwise_poly_montgomery(ml_dsa_params *params,
const ml_dsa_poly *a,
const polyveck *v);

int ml_dsa_polyveck_chknorm(ml_dsa_params *params, const polyveck *v, int32_t B);
uint32_t ml_dsa_polyveck_chknorm(ml_dsa_params *params, const polyveck *v, int32_t B);

void ml_dsa_polyveck_power2round(ml_dsa_params *params,
polyveck *v1,
Expand Down
10 changes: 7 additions & 3 deletions crypto/fipsmodule/ml_dsa/ml_dsa_ref/sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ int ml_dsa_sign_internal(ml_dsa_params *params,
uint8_t seedbuf[2*ML_DSA_SEEDBYTES + ML_DSA_TRBYTES + 2*ML_DSA_CRHBYTES];
uint8_t *rho, *tr, *key, *mu, *rhoprime;
uint16_t nonce = 0;
uint32_t z_invalid, w0_invalid, h_invalid;
polyvecl mat[ML_DSA_K_MAX], s1, y, z;
polyveck t0, s2, w1, w0, h;
ml_dsa_poly cp;
Expand Down Expand Up @@ -248,7 +249,8 @@ int ml_dsa_sign_internal(ml_dsa_params *params,
ml_dsa_polyvecl_invntt_tomont(params, &z);
ml_dsa_polyvecl_add(params, &z, &z, &y);
ml_dsa_polyvecl_reduce(params, &z);
if(ml_dsa_polyvecl_chknorm(params, &z, params->gamma1 - params->beta)) {
z_invalid = ml_dsa_polyvecl_chknorm(params, &z, params->gamma1 - params->beta);
if(z_invalid) {
goto rej;
}

Expand All @@ -258,15 +260,17 @@ int ml_dsa_sign_internal(ml_dsa_params *params,
ml_dsa_polyveck_invntt_tomont(params, &h);
ml_dsa_polyveck_sub(params, &w0, &w0, &h);
ml_dsa_polyveck_reduce(params, &w0);
if(ml_dsa_polyveck_chknorm(params, &w0, params->gamma2 - params->beta)) {
w0_invalid = ml_dsa_polyveck_chknorm(params, &w0, params->gamma2 - params->beta);
if(w0_invalid) {
goto rej;
}

/* FIPS 204: line 25 */
ml_dsa_polyveck_pointwise_poly_montgomery(params, &h, &cp, &t0);
ml_dsa_polyveck_invntt_tomont(params, &h);
ml_dsa_polyveck_reduce(params, &h);
if(ml_dsa_polyveck_chknorm(params, &h, params->gamma2)) {
h_invalid = ml_dsa_polyveck_chknorm(params, &h, params->gamma2);
if(h_invalid) {
goto rej;
}

Expand Down
Loading