Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
cx_mldsa_rounding.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2026 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
21#include "cx_mldsa_rounding.h"
22
23int32_t MLDSA_ROUNDING_power2round(int32_t a, int32_t *a0)
24{
25 int32_t a1;
26 a1 = (a + (1 << (MLDSA_D - 1)) - 1) >> MLDSA_D;
27 *a0 = a - (a1 << MLDSA_D);
28 return a1;
29}
30
31int32_t MLDSA_ROUNDING_decompose(int32_t a, int32_t *a0, int32_t gamma2)
32{
33 int32_t a1;
34 a1 = (a + 127) >> 7;
35
36 if (gamma2 == (MLDSA_Q - 1) / 32) {
37 a1 = (a1 * 1025 + (1 << 21)) >> 22;
38 a1 &= 15;
39 }
40 else {
41 // gamma2 == (MLDSA_Q - 1) / 88
42 a1 = (a1 * 11275 + (1 << 23)) >> 24;
43 a1 ^= ((43 - a1) >> 31) & a1;
44 }
45
46 *a0 = a - a1 * 2 * gamma2;
47 *a0 -= (((MLDSA_Q - 1) / 2 - *a0) >> 31) & MLDSA_Q;
48 return a1;
49}
50
51uint32_t MLDSA_ROUNDING_make_hint(int32_t a0, int32_t a1, int32_t gamma2)
52{
53 if ((a0 > gamma2) || (a0 < -gamma2) || ((a0 == -gamma2) && (a1 != 0))) {
54 return 1U;
55 }
56 return 0U;
57}
58
59int32_t MLDSA_ROUNDING_use_hint(int32_t a, uint32_t hint, int32_t gamma2)
60{
61 int32_t a0, a1;
62 a1 = MLDSA_ROUNDING_decompose(a, &a0, gamma2);
63
64 if (hint == 0U) {
65 return a1;
66 }
67
68 if (gamma2 == (MLDSA_Q - 1) / 32) {
69 if (a0 > 0) {
70 return (a1 + 1) & 15;
71 }
72 else {
73 return (a1 - 1) & 15;
74 }
75 }
76 else {
77 // gamma2 == (MLDSA_Q - 1) / 88
78 if (a0 > 0) {
79 return (a1 == 43) ? 0 : a1 + 1;
80 }
81 else {
82 return (a1 == 0) ? 43 : a1 - 1;
83 }
84 }
85}
86
88{
89 for (uint32_t i = 0U; i < MLDSA_N; i++) {
90 a1->coeffs[i] = MLDSA_ROUNDING_power2round(a->coeffs[i], &a0->coeffs[i]);
91 }
92}
93
95 mldsa_poly *a0,
96 const mldsa_poly *a,
97 int32_t gamma2)
98{
99 for (uint32_t i = 0U; i < MLDSA_N; i++) {
100 a1->coeffs[i] = MLDSA_ROUNDING_decompose(a->coeffs[i], &a0->coeffs[i], gamma2);
101 }
102}
103
105 const mldsa_poly *a,
106 const mldsa_poly *h,
107 int32_t gamma2)
108{
109 for (uint32_t i = 0U; i < MLDSA_N; i++) {
110 b->coeffs[i] = MLDSA_ROUNDING_use_hint(a->coeffs[i], (uint32_t) h->coeffs[i], gamma2);
111 }
112}
int32_t MLDSA_ROUNDING_power2round(int32_t a, int32_t *a0)
For coefficient a, compute high and low bits a0, a1 such that a mod q = a1*2^D + a0,...
void MLDSA_ROUNDING_poly_use_hint(mldsa_poly *b, const mldsa_poly *a, const mldsa_poly *h, int32_t gamma2)
Applies use_hint to all coefficients of a polynomial.
void MLDSA_ROUNDING_poly_decompose(mldsa_poly *a1, mldsa_poly *a0, const mldsa_poly *a, int32_t gamma2)
Applies decompose to all coefficients of a polynomial.
int32_t MLDSA_ROUNDING_decompose(int32_t a, int32_t *a0, int32_t gamma2)
For coefficient a, compute high and low bits a0, a1 such that a mod q = a1*ALPHA + a0,...
uint32_t MLDSA_ROUNDING_make_hint(int32_t a0, int32_t a1, int32_t gamma2)
Compute hint bit. Returns 1 if adding ct0 to w - ct0 would change the high bits (i....
int32_t MLDSA_ROUNDING_use_hint(int32_t a, uint32_t hint, int32_t gamma2)
Correct high bits using hint.
void MLDSA_ROUNDING_poly_power2round(mldsa_poly *a1, mldsa_poly *a0, const mldsa_poly *a)
Applies power2round to all coefficients of a polynomial.
#define MLDSA_D
Definition lcx_mldsa.h:39
#define MLDSA_N
Definition lcx_mldsa.h:37
#define MLDSA_Q
Definition lcx_mldsa.h:38
Polynomial with MLDSA_N int32_t coefficients.
int32_t coeffs[MLDSA_N]