1*8fb009dcSAndroid Build Coastguard Worker /* Copyright (c) 2023, Google LLC
2*8fb009dcSAndroid Build Coastguard Worker *
3*8fb009dcSAndroid Build Coastguard Worker * Permission to use, copy, modify, and/or distribute this software for any
4*8fb009dcSAndroid Build Coastguard Worker * purpose with or without fee is hereby granted, provided that the above
5*8fb009dcSAndroid Build Coastguard Worker * copyright notice and this permission notice appear in all copies.
6*8fb009dcSAndroid Build Coastguard Worker *
7*8fb009dcSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8*8fb009dcSAndroid Build Coastguard Worker * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9*8fb009dcSAndroid Build Coastguard Worker * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10*8fb009dcSAndroid Build Coastguard Worker * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11*8fb009dcSAndroid Build Coastguard Worker * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12*8fb009dcSAndroid Build Coastguard Worker * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13*8fb009dcSAndroid Build Coastguard Worker * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14*8fb009dcSAndroid Build Coastguard Worker
15*8fb009dcSAndroid Build Coastguard Worker #define OPENSSL_UNSTABLE_EXPERIMENTAL_DILITHIUM
16*8fb009dcSAndroid Build Coastguard Worker #include <openssl/experimental/dilithium.h>
17*8fb009dcSAndroid Build Coastguard Worker
18*8fb009dcSAndroid Build Coastguard Worker #include <assert.h>
19*8fb009dcSAndroid Build Coastguard Worker #include <stdlib.h>
20*8fb009dcSAndroid Build Coastguard Worker
21*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bytestring.h>
22*8fb009dcSAndroid Build Coastguard Worker #include <openssl/rand.h>
23*8fb009dcSAndroid Build Coastguard Worker
24*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
25*8fb009dcSAndroid Build Coastguard Worker #include "../keccak/internal.h"
26*8fb009dcSAndroid Build Coastguard Worker #include "./internal.h"
27*8fb009dcSAndroid Build Coastguard Worker
28*8fb009dcSAndroid Build Coastguard Worker #define DEGREE 256
29*8fb009dcSAndroid Build Coastguard Worker #define K 6
30*8fb009dcSAndroid Build Coastguard Worker #define L 5
31*8fb009dcSAndroid Build Coastguard Worker #define ETA 4
32*8fb009dcSAndroid Build Coastguard Worker #define TAU 49
33*8fb009dcSAndroid Build Coastguard Worker #define BETA 196
34*8fb009dcSAndroid Build Coastguard Worker #define OMEGA 55
35*8fb009dcSAndroid Build Coastguard Worker
36*8fb009dcSAndroid Build Coastguard Worker #define RHO_BYTES 32
37*8fb009dcSAndroid Build Coastguard Worker #define SIGMA_BYTES 64
38*8fb009dcSAndroid Build Coastguard Worker #define K_BYTES 32
39*8fb009dcSAndroid Build Coastguard Worker #define TR_BYTES 64
40*8fb009dcSAndroid Build Coastguard Worker #define MU_BYTES 64
41*8fb009dcSAndroid Build Coastguard Worker #define RHO_PRIME_BYTES 64
42*8fb009dcSAndroid Build Coastguard Worker #define LAMBDA_BITS 192
43*8fb009dcSAndroid Build Coastguard Worker #define LAMBDA_BYTES (LAMBDA_BITS / 8)
44*8fb009dcSAndroid Build Coastguard Worker
45*8fb009dcSAndroid Build Coastguard Worker // 2^23 - 2^13 + 1
46*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kPrime = 8380417;
47*8fb009dcSAndroid Build Coastguard Worker // Inverse of -kPrime modulo 2^32
48*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kPrimeNegInverse = 4236238847;
49*8fb009dcSAndroid Build Coastguard Worker static const int kDroppedBits = 13;
50*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kHalfPrime = (8380417 - 1) / 2;
51*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kGamma1 = 1 << 19;
52*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kGamma2 = (8380417 - 1) / 32;
53*8fb009dcSAndroid Build Coastguard Worker // 256^-1 mod kPrime, in Montgomery form.
54*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kInverseDegreeMontgomery = 41978;
55*8fb009dcSAndroid Build Coastguard Worker
56*8fb009dcSAndroid Build Coastguard Worker typedef struct scalar {
57*8fb009dcSAndroid Build Coastguard Worker uint32_t c[DEGREE];
58*8fb009dcSAndroid Build Coastguard Worker } scalar;
59*8fb009dcSAndroid Build Coastguard Worker
60*8fb009dcSAndroid Build Coastguard Worker typedef struct vectork {
61*8fb009dcSAndroid Build Coastguard Worker scalar v[K];
62*8fb009dcSAndroid Build Coastguard Worker } vectork;
63*8fb009dcSAndroid Build Coastguard Worker
64*8fb009dcSAndroid Build Coastguard Worker typedef struct vectorl {
65*8fb009dcSAndroid Build Coastguard Worker scalar v[L];
66*8fb009dcSAndroid Build Coastguard Worker } vectorl;
67*8fb009dcSAndroid Build Coastguard Worker
68*8fb009dcSAndroid Build Coastguard Worker typedef struct matrix {
69*8fb009dcSAndroid Build Coastguard Worker scalar v[K][L];
70*8fb009dcSAndroid Build Coastguard Worker } matrix;
71*8fb009dcSAndroid Build Coastguard Worker
72*8fb009dcSAndroid Build Coastguard Worker /* Arithmetic */
73*8fb009dcSAndroid Build Coastguard Worker
74*8fb009dcSAndroid Build Coastguard Worker // This bit of Python will be referenced in some of the following comments:
75*8fb009dcSAndroid Build Coastguard Worker //
76*8fb009dcSAndroid Build Coastguard Worker // q = 8380417
77*8fb009dcSAndroid Build Coastguard Worker // # Inverse of -q modulo 2^32
78*8fb009dcSAndroid Build Coastguard Worker // q_neg_inverse = 4236238847
79*8fb009dcSAndroid Build Coastguard Worker // # 2^64 modulo q
80*8fb009dcSAndroid Build Coastguard Worker // montgomery_square = 2365951
81*8fb009dcSAndroid Build Coastguard Worker //
82*8fb009dcSAndroid Build Coastguard Worker // def bitreverse(i):
83*8fb009dcSAndroid Build Coastguard Worker // ret = 0
84*8fb009dcSAndroid Build Coastguard Worker // for n in range(8):
85*8fb009dcSAndroid Build Coastguard Worker // bit = i & 1
86*8fb009dcSAndroid Build Coastguard Worker // ret <<= 1
87*8fb009dcSAndroid Build Coastguard Worker // ret |= bit
88*8fb009dcSAndroid Build Coastguard Worker // i >>= 1
89*8fb009dcSAndroid Build Coastguard Worker // return ret
90*8fb009dcSAndroid Build Coastguard Worker //
91*8fb009dcSAndroid Build Coastguard Worker // def montgomery_reduce(x):
92*8fb009dcSAndroid Build Coastguard Worker // a = (x * q_neg_inverse) % 2**32
93*8fb009dcSAndroid Build Coastguard Worker // b = x + a * q
94*8fb009dcSAndroid Build Coastguard Worker // assert b & 0xFFFF_FFFF == 0
95*8fb009dcSAndroid Build Coastguard Worker // c = b >> 32
96*8fb009dcSAndroid Build Coastguard Worker // assert c < q
97*8fb009dcSAndroid Build Coastguard Worker // return c
98*8fb009dcSAndroid Build Coastguard Worker //
99*8fb009dcSAndroid Build Coastguard Worker // def montgomery_transform(x):
100*8fb009dcSAndroid Build Coastguard Worker // return montgomery_reduce(x * montgomery_square)
101*8fb009dcSAndroid Build Coastguard Worker
102*8fb009dcSAndroid Build Coastguard Worker // kNTTRootsMontgomery = [
103*8fb009dcSAndroid Build Coastguard Worker // montgomery_transform(pow(1753, bitreverse(i), q)) for i in range(256)
104*8fb009dcSAndroid Build Coastguard Worker // ]
105*8fb009dcSAndroid Build Coastguard Worker static const uint32_t kNTTRootsMontgomery[256] = {
106*8fb009dcSAndroid Build Coastguard Worker 4193792, 25847, 5771523, 7861508, 237124, 7602457, 7504169, 466468,
107*8fb009dcSAndroid Build Coastguard Worker 1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103,
108*8fb009dcSAndroid Build Coastguard Worker 2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868,
109*8fb009dcSAndroid Build Coastguard Worker 6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005,
110*8fb009dcSAndroid Build Coastguard Worker 2706023, 95776, 3077325, 3530437, 6718724, 4788269, 5842901, 3915439,
111*8fb009dcSAndroid Build Coastguard Worker 4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118,
112*8fb009dcSAndroid Build Coastguard Worker 6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596,
113*8fb009dcSAndroid Build Coastguard Worker 811944, 531354, 954230, 3881043, 3900724, 5823537, 2071892, 5582638,
114*8fb009dcSAndroid Build Coastguard Worker 4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196,
115*8fb009dcSAndroid Build Coastguard Worker 7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922,
116*8fb009dcSAndroid Build Coastguard Worker 3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370,
117*8fb009dcSAndroid Build Coastguard Worker 7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987,
118*8fb009dcSAndroid Build Coastguard Worker 5037034, 264944, 508951, 3097992, 44288, 7280319, 904516, 3958618,
119*8fb009dcSAndroid Build Coastguard Worker 4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969, 7063561,
120*8fb009dcSAndroid Build Coastguard Worker 189548, 4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330,
121*8fb009dcSAndroid Build Coastguard Worker 1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961,
122*8fb009dcSAndroid Build Coastguard Worker 2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955,
123*8fb009dcSAndroid Build Coastguard Worker 266997, 2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039,
124*8fb009dcSAndroid Build Coastguard Worker 900702, 1859098, 909542, 819034, 495491, 6767243, 8337157, 7857917,
125*8fb009dcSAndroid Build Coastguard Worker 7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579,
126*8fb009dcSAndroid Build Coastguard Worker 342297, 286988, 5942594, 4108315, 3437287, 5038140, 1735879, 203044,
127*8fb009dcSAndroid Build Coastguard Worker 2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974,
128*8fb009dcSAndroid Build Coastguard Worker 4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447,
129*8fb009dcSAndroid Build Coastguard Worker 7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775,
130*8fb009dcSAndroid Build Coastguard Worker 7100756, 1917081, 5834105, 7005614, 1500165, 777191, 2235880, 3406031,
131*8fb009dcSAndroid Build Coastguard Worker 7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136, 4603424,
132*8fb009dcSAndroid Build Coastguard Worker 6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531, 7173032,
133*8fb009dcSAndroid Build Coastguard Worker 5196991, 162844, 1616392, 3014001, 810149, 1652634, 4686184, 6581310,
134*8fb009dcSAndroid Build Coastguard Worker 5341501, 3523897, 3866901, 269760, 2213111, 7404533, 1717735, 472078,
135*8fb009dcSAndroid Build Coastguard Worker 7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524,
136*8fb009dcSAndroid Build Coastguard Worker 5441381, 6144432, 7959518, 6094090, 183443, 7403526, 1612842, 4834730,
137*8fb009dcSAndroid Build Coastguard Worker 7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782};
138*8fb009dcSAndroid Build Coastguard Worker
139*8fb009dcSAndroid Build Coastguard Worker // Reduces x mod kPrime in constant time, where 0 <= x < 2*kPrime.
reduce_once(uint32_t x)140*8fb009dcSAndroid Build Coastguard Worker static uint32_t reduce_once(uint32_t x) {
141*8fb009dcSAndroid Build Coastguard Worker declassify_assert(x < 2 * kPrime);
142*8fb009dcSAndroid Build Coastguard Worker // return x < kPrime ? x : x - kPrime;
143*8fb009dcSAndroid Build Coastguard Worker return constant_time_select_int(constant_time_lt_w(x, kPrime), x, x - kPrime);
144*8fb009dcSAndroid Build Coastguard Worker }
145*8fb009dcSAndroid Build Coastguard Worker
146*8fb009dcSAndroid Build Coastguard Worker // Returns the absolute value in constant time.
abs_signed(uint32_t x)147*8fb009dcSAndroid Build Coastguard Worker static uint32_t abs_signed(uint32_t x) {
148*8fb009dcSAndroid Build Coastguard Worker // return is_positive(x) ? x : -x;
149*8fb009dcSAndroid Build Coastguard Worker // Note: MSVC doesn't like applying the unary minus operator to unsigned types
150*8fb009dcSAndroid Build Coastguard Worker // (warning C4146), so we write the negation as a bitwise not plus one
151*8fb009dcSAndroid Build Coastguard Worker // (assuming two's complement representation).
152*8fb009dcSAndroid Build Coastguard Worker return constant_time_select_int(constant_time_lt_w(x, 0x80000000), x, ~x + 1);
153*8fb009dcSAndroid Build Coastguard Worker }
154*8fb009dcSAndroid Build Coastguard Worker
155*8fb009dcSAndroid Build Coastguard Worker // Returns the absolute value modulo kPrime.
abs_mod_prime(uint32_t x)156*8fb009dcSAndroid Build Coastguard Worker static uint32_t abs_mod_prime(uint32_t x) {
157*8fb009dcSAndroid Build Coastguard Worker declassify_assert(x < kPrime);
158*8fb009dcSAndroid Build Coastguard Worker // return x > kHalfPrime ? kPrime - x : x;
159*8fb009dcSAndroid Build Coastguard Worker return constant_time_select_int(constant_time_lt_w(kHalfPrime, x), kPrime - x,
160*8fb009dcSAndroid Build Coastguard Worker x);
161*8fb009dcSAndroid Build Coastguard Worker }
162*8fb009dcSAndroid Build Coastguard Worker
163*8fb009dcSAndroid Build Coastguard Worker // Returns the maximum of two values in constant time.
maximum(uint32_t x,uint32_t y)164*8fb009dcSAndroid Build Coastguard Worker static uint32_t maximum(uint32_t x, uint32_t y) {
165*8fb009dcSAndroid Build Coastguard Worker // return x < y ? y : x;
166*8fb009dcSAndroid Build Coastguard Worker return constant_time_select_int(constant_time_lt_w(x, y), y, x);
167*8fb009dcSAndroid Build Coastguard Worker }
168*8fb009dcSAndroid Build Coastguard Worker
scalar_add(scalar * out,const scalar * lhs,const scalar * rhs)169*8fb009dcSAndroid Build Coastguard Worker static void scalar_add(scalar *out, const scalar *lhs, const scalar *rhs) {
170*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
171*8fb009dcSAndroid Build Coastguard Worker out->c[i] = reduce_once(lhs->c[i] + rhs->c[i]);
172*8fb009dcSAndroid Build Coastguard Worker }
173*8fb009dcSAndroid Build Coastguard Worker }
174*8fb009dcSAndroid Build Coastguard Worker
scalar_sub(scalar * out,const scalar * lhs,const scalar * rhs)175*8fb009dcSAndroid Build Coastguard Worker static void scalar_sub(scalar *out, const scalar *lhs, const scalar *rhs) {
176*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
177*8fb009dcSAndroid Build Coastguard Worker out->c[i] = reduce_once(kPrime + lhs->c[i] - rhs->c[i]);
178*8fb009dcSAndroid Build Coastguard Worker }
179*8fb009dcSAndroid Build Coastguard Worker }
180*8fb009dcSAndroid Build Coastguard Worker
reduce_montgomery(uint64_t x)181*8fb009dcSAndroid Build Coastguard Worker static uint32_t reduce_montgomery(uint64_t x) {
182*8fb009dcSAndroid Build Coastguard Worker uint64_t a = (uint32_t)x * kPrimeNegInverse;
183*8fb009dcSAndroid Build Coastguard Worker uint64_t b = x + a * kPrime;
184*8fb009dcSAndroid Build Coastguard Worker declassify_assert((b & 0xffffffff) == 0);
185*8fb009dcSAndroid Build Coastguard Worker uint32_t c = b >> 32;
186*8fb009dcSAndroid Build Coastguard Worker return reduce_once(c);
187*8fb009dcSAndroid Build Coastguard Worker }
188*8fb009dcSAndroid Build Coastguard Worker
189*8fb009dcSAndroid Build Coastguard Worker // Multiply two scalars in the number theoretically transformed state.
scalar_mult(scalar * out,const scalar * lhs,const scalar * rhs)190*8fb009dcSAndroid Build Coastguard Worker static void scalar_mult(scalar *out, const scalar *lhs, const scalar *rhs) {
191*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
192*8fb009dcSAndroid Build Coastguard Worker out->c[i] = reduce_montgomery((uint64_t)lhs->c[i] * (uint64_t)rhs->c[i]);
193*8fb009dcSAndroid Build Coastguard Worker }
194*8fb009dcSAndroid Build Coastguard Worker }
195*8fb009dcSAndroid Build Coastguard Worker
196*8fb009dcSAndroid Build Coastguard Worker // In place number theoretic transform of a given scalar.
197*8fb009dcSAndroid Build Coastguard Worker //
198*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 35 (`NTT`).
scalar_ntt(scalar * s)199*8fb009dcSAndroid Build Coastguard Worker static void scalar_ntt(scalar *s) {
200*8fb009dcSAndroid Build Coastguard Worker // Step: 1, 2, 4, 8, ..., 128
201*8fb009dcSAndroid Build Coastguard Worker // Offset: 128, 64, 32, 16, ..., 1
202*8fb009dcSAndroid Build Coastguard Worker int offset = DEGREE;
203*8fb009dcSAndroid Build Coastguard Worker for (int step = 1; step < DEGREE; step <<= 1) {
204*8fb009dcSAndroid Build Coastguard Worker offset >>= 1;
205*8fb009dcSAndroid Build Coastguard Worker int k = 0;
206*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < step; i++) {
207*8fb009dcSAndroid Build Coastguard Worker assert(k == 2 * offset * i);
208*8fb009dcSAndroid Build Coastguard Worker const uint32_t step_root = kNTTRootsMontgomery[step + i];
209*8fb009dcSAndroid Build Coastguard Worker for (int j = k; j < k + offset; j++) {
210*8fb009dcSAndroid Build Coastguard Worker uint32_t even = s->c[j];
211*8fb009dcSAndroid Build Coastguard Worker uint32_t odd =
212*8fb009dcSAndroid Build Coastguard Worker reduce_montgomery((uint64_t)step_root * (uint64_t)s->c[j + offset]);
213*8fb009dcSAndroid Build Coastguard Worker s->c[j] = reduce_once(odd + even);
214*8fb009dcSAndroid Build Coastguard Worker s->c[j + offset] = reduce_once(kPrime + even - odd);
215*8fb009dcSAndroid Build Coastguard Worker }
216*8fb009dcSAndroid Build Coastguard Worker k += 2 * offset;
217*8fb009dcSAndroid Build Coastguard Worker }
218*8fb009dcSAndroid Build Coastguard Worker }
219*8fb009dcSAndroid Build Coastguard Worker }
220*8fb009dcSAndroid Build Coastguard Worker
221*8fb009dcSAndroid Build Coastguard Worker // In place inverse number theoretic transform of a given scalar.
222*8fb009dcSAndroid Build Coastguard Worker //
223*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 36 (`NTT^-1`).
scalar_inverse_ntt(scalar * s)224*8fb009dcSAndroid Build Coastguard Worker static void scalar_inverse_ntt(scalar *s) {
225*8fb009dcSAndroid Build Coastguard Worker // Step: 128, 64, 32, 16, ..., 1
226*8fb009dcSAndroid Build Coastguard Worker // Offset: 1, 2, 4, 8, ..., 128
227*8fb009dcSAndroid Build Coastguard Worker int step = DEGREE;
228*8fb009dcSAndroid Build Coastguard Worker for (int offset = 1; offset < DEGREE; offset <<= 1) {
229*8fb009dcSAndroid Build Coastguard Worker step >>= 1;
230*8fb009dcSAndroid Build Coastguard Worker int k = 0;
231*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < step; i++) {
232*8fb009dcSAndroid Build Coastguard Worker assert(k == 2 * offset * i);
233*8fb009dcSAndroid Build Coastguard Worker const uint32_t step_root =
234*8fb009dcSAndroid Build Coastguard Worker kPrime - kNTTRootsMontgomery[step + (step - 1 - i)];
235*8fb009dcSAndroid Build Coastguard Worker for (int j = k; j < k + offset; j++) {
236*8fb009dcSAndroid Build Coastguard Worker uint32_t even = s->c[j];
237*8fb009dcSAndroid Build Coastguard Worker uint32_t odd = s->c[j + offset];
238*8fb009dcSAndroid Build Coastguard Worker s->c[j] = reduce_once(odd + even);
239*8fb009dcSAndroid Build Coastguard Worker s->c[j + offset] = reduce_montgomery((uint64_t)step_root *
240*8fb009dcSAndroid Build Coastguard Worker (uint64_t)(kPrime + even - odd));
241*8fb009dcSAndroid Build Coastguard Worker }
242*8fb009dcSAndroid Build Coastguard Worker k += 2 * offset;
243*8fb009dcSAndroid Build Coastguard Worker }
244*8fb009dcSAndroid Build Coastguard Worker }
245*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
246*8fb009dcSAndroid Build Coastguard Worker s->c[i] = reduce_montgomery((uint64_t)s->c[i] *
247*8fb009dcSAndroid Build Coastguard Worker (uint64_t)kInverseDegreeMontgomery);
248*8fb009dcSAndroid Build Coastguard Worker }
249*8fb009dcSAndroid Build Coastguard Worker }
250*8fb009dcSAndroid Build Coastguard Worker
vectork_zero(vectork * out)251*8fb009dcSAndroid Build Coastguard Worker static void vectork_zero(vectork *out) { OPENSSL_memset(out, 0, sizeof(*out)); }
252*8fb009dcSAndroid Build Coastguard Worker
vectork_add(vectork * out,const vectork * lhs,const vectork * rhs)253*8fb009dcSAndroid Build Coastguard Worker static void vectork_add(vectork *out, const vectork *lhs, const vectork *rhs) {
254*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
255*8fb009dcSAndroid Build Coastguard Worker scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]);
256*8fb009dcSAndroid Build Coastguard Worker }
257*8fb009dcSAndroid Build Coastguard Worker }
258*8fb009dcSAndroid Build Coastguard Worker
vectork_sub(vectork * out,const vectork * lhs,const vectork * rhs)259*8fb009dcSAndroid Build Coastguard Worker static void vectork_sub(vectork *out, const vectork *lhs, const vectork *rhs) {
260*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
261*8fb009dcSAndroid Build Coastguard Worker scalar_sub(&out->v[i], &lhs->v[i], &rhs->v[i]);
262*8fb009dcSAndroid Build Coastguard Worker }
263*8fb009dcSAndroid Build Coastguard Worker }
264*8fb009dcSAndroid Build Coastguard Worker
vectork_mult_scalar(vectork * out,const vectork * lhs,const scalar * rhs)265*8fb009dcSAndroid Build Coastguard Worker static void vectork_mult_scalar(vectork *out, const vectork *lhs,
266*8fb009dcSAndroid Build Coastguard Worker const scalar *rhs) {
267*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
268*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&out->v[i], &lhs->v[i], rhs);
269*8fb009dcSAndroid Build Coastguard Worker }
270*8fb009dcSAndroid Build Coastguard Worker }
271*8fb009dcSAndroid Build Coastguard Worker
vectork_ntt(vectork * a)272*8fb009dcSAndroid Build Coastguard Worker static void vectork_ntt(vectork *a) {
273*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
274*8fb009dcSAndroid Build Coastguard Worker scalar_ntt(&a->v[i]);
275*8fb009dcSAndroid Build Coastguard Worker }
276*8fb009dcSAndroid Build Coastguard Worker }
277*8fb009dcSAndroid Build Coastguard Worker
vectork_inverse_ntt(vectork * a)278*8fb009dcSAndroid Build Coastguard Worker static void vectork_inverse_ntt(vectork *a) {
279*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
280*8fb009dcSAndroid Build Coastguard Worker scalar_inverse_ntt(&a->v[i]);
281*8fb009dcSAndroid Build Coastguard Worker }
282*8fb009dcSAndroid Build Coastguard Worker }
283*8fb009dcSAndroid Build Coastguard Worker
vectorl_add(vectorl * out,const vectorl * lhs,const vectorl * rhs)284*8fb009dcSAndroid Build Coastguard Worker static void vectorl_add(vectorl *out, const vectorl *lhs, const vectorl *rhs) {
285*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
286*8fb009dcSAndroid Build Coastguard Worker scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]);
287*8fb009dcSAndroid Build Coastguard Worker }
288*8fb009dcSAndroid Build Coastguard Worker }
289*8fb009dcSAndroid Build Coastguard Worker
vectorl_mult_scalar(vectorl * out,const vectorl * lhs,const scalar * rhs)290*8fb009dcSAndroid Build Coastguard Worker static void vectorl_mult_scalar(vectorl *out, const vectorl *lhs,
291*8fb009dcSAndroid Build Coastguard Worker const scalar *rhs) {
292*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
293*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&out->v[i], &lhs->v[i], rhs);
294*8fb009dcSAndroid Build Coastguard Worker }
295*8fb009dcSAndroid Build Coastguard Worker }
296*8fb009dcSAndroid Build Coastguard Worker
vectorl_ntt(vectorl * a)297*8fb009dcSAndroid Build Coastguard Worker static void vectorl_ntt(vectorl *a) {
298*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
299*8fb009dcSAndroid Build Coastguard Worker scalar_ntt(&a->v[i]);
300*8fb009dcSAndroid Build Coastguard Worker }
301*8fb009dcSAndroid Build Coastguard Worker }
302*8fb009dcSAndroid Build Coastguard Worker
vectorl_inverse_ntt(vectorl * a)303*8fb009dcSAndroid Build Coastguard Worker static void vectorl_inverse_ntt(vectorl *a) {
304*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
305*8fb009dcSAndroid Build Coastguard Worker scalar_inverse_ntt(&a->v[i]);
306*8fb009dcSAndroid Build Coastguard Worker }
307*8fb009dcSAndroid Build Coastguard Worker }
308*8fb009dcSAndroid Build Coastguard Worker
matrix_mult(vectork * out,const matrix * m,const vectorl * a)309*8fb009dcSAndroid Build Coastguard Worker static void matrix_mult(vectork *out, const matrix *m, const vectorl *a) {
310*8fb009dcSAndroid Build Coastguard Worker vectork_zero(out);
311*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
312*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < L; j++) {
313*8fb009dcSAndroid Build Coastguard Worker scalar product;
314*8fb009dcSAndroid Build Coastguard Worker scalar_mult(&product, &m->v[i][j], &a->v[j]);
315*8fb009dcSAndroid Build Coastguard Worker scalar_add(&out->v[i], &out->v[i], &product);
316*8fb009dcSAndroid Build Coastguard Worker }
317*8fb009dcSAndroid Build Coastguard Worker }
318*8fb009dcSAndroid Build Coastguard Worker }
319*8fb009dcSAndroid Build Coastguard Worker
320*8fb009dcSAndroid Build Coastguard Worker /* Rounding & hints */
321*8fb009dcSAndroid Build Coastguard Worker
322*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 29 (`Power2Round`).
power2_round(uint32_t * r1,uint32_t * r0,uint32_t r)323*8fb009dcSAndroid Build Coastguard Worker static void power2_round(uint32_t *r1, uint32_t *r0, uint32_t r) {
324*8fb009dcSAndroid Build Coastguard Worker *r1 = r >> kDroppedBits;
325*8fb009dcSAndroid Build Coastguard Worker *r0 = r - (*r1 << kDroppedBits);
326*8fb009dcSAndroid Build Coastguard Worker
327*8fb009dcSAndroid Build Coastguard Worker uint32_t r0_adjusted = reduce_once(kPrime + *r0 - (1 << kDroppedBits));
328*8fb009dcSAndroid Build Coastguard Worker uint32_t r1_adjusted = *r1 + 1;
329*8fb009dcSAndroid Build Coastguard Worker
330*8fb009dcSAndroid Build Coastguard Worker // Mask is set iff r0 > 2^(dropped_bits - 1).
331*8fb009dcSAndroid Build Coastguard Worker crypto_word_t mask =
332*8fb009dcSAndroid Build Coastguard Worker constant_time_lt_w((uint32_t)(1 << (kDroppedBits - 1)), *r0);
333*8fb009dcSAndroid Build Coastguard Worker // r0 = mask ? r0_adjusted : r0
334*8fb009dcSAndroid Build Coastguard Worker *r0 = constant_time_select_int(mask, r0_adjusted, *r0);
335*8fb009dcSAndroid Build Coastguard Worker // r1 = mask ? r1_adjusted : r1
336*8fb009dcSAndroid Build Coastguard Worker *r1 = constant_time_select_int(mask, r1_adjusted, *r1);
337*8fb009dcSAndroid Build Coastguard Worker }
338*8fb009dcSAndroid Build Coastguard Worker
339*8fb009dcSAndroid Build Coastguard Worker // Scale back previously rounded value.
scale_power2_round(uint32_t * out,uint32_t r1)340*8fb009dcSAndroid Build Coastguard Worker static void scale_power2_round(uint32_t *out, uint32_t r1) {
341*8fb009dcSAndroid Build Coastguard Worker // Pre-condition: 0 <= r1 <= 2^10 - 1
342*8fb009dcSAndroid Build Coastguard Worker *out = r1 << kDroppedBits;
343*8fb009dcSAndroid Build Coastguard Worker // Post-condition: 0 <= out <= 2^23 - 2^13 = kPrime - 1
344*8fb009dcSAndroid Build Coastguard Worker assert(*out < kPrime);
345*8fb009dcSAndroid Build Coastguard Worker }
346*8fb009dcSAndroid Build Coastguard Worker
347*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 31 (`HighBits`).
high_bits(uint32_t x)348*8fb009dcSAndroid Build Coastguard Worker static uint32_t high_bits(uint32_t x) {
349*8fb009dcSAndroid Build Coastguard Worker // Reference description (given 0 <= x < q):
350*8fb009dcSAndroid Build Coastguard Worker //
351*8fb009dcSAndroid Build Coastguard Worker // ```
352*8fb009dcSAndroid Build Coastguard Worker // int32_t r0 = x mod+- (2 * kGamma2);
353*8fb009dcSAndroid Build Coastguard Worker // if (x - r0 == q - 1) {
354*8fb009dcSAndroid Build Coastguard Worker // return 0;
355*8fb009dcSAndroid Build Coastguard Worker // } else {
356*8fb009dcSAndroid Build Coastguard Worker // return (x - r0) / (2 * kGamma2);
357*8fb009dcSAndroid Build Coastguard Worker // }
358*8fb009dcSAndroid Build Coastguard Worker // ```
359*8fb009dcSAndroid Build Coastguard Worker //
360*8fb009dcSAndroid Build Coastguard Worker // Below is the formula taken from the reference implementation.
361*8fb009dcSAndroid Build Coastguard Worker //
362*8fb009dcSAndroid Build Coastguard Worker // Here, kGamma2 == 2^18 - 2^8
363*8fb009dcSAndroid Build Coastguard Worker // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4
364*8fb009dcSAndroid Build Coastguard Worker uint32_t r1 = (x + 127) >> 7;
365*8fb009dcSAndroid Build Coastguard Worker r1 = (r1 * 1025 + (1 << 21)) >> 22;
366*8fb009dcSAndroid Build Coastguard Worker r1 &= 15;
367*8fb009dcSAndroid Build Coastguard Worker return r1;
368*8fb009dcSAndroid Build Coastguard Worker }
369*8fb009dcSAndroid Build Coastguard Worker
370*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 30 (`Decompose`).
decompose(uint32_t * r1,int32_t * r0,uint32_t r)371*8fb009dcSAndroid Build Coastguard Worker static void decompose(uint32_t *r1, int32_t *r0, uint32_t r) {
372*8fb009dcSAndroid Build Coastguard Worker *r1 = high_bits(r);
373*8fb009dcSAndroid Build Coastguard Worker
374*8fb009dcSAndroid Build Coastguard Worker *r0 = r;
375*8fb009dcSAndroid Build Coastguard Worker *r0 -= *r1 * 2 * (int32_t)kGamma2;
376*8fb009dcSAndroid Build Coastguard Worker *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime;
377*8fb009dcSAndroid Build Coastguard Worker }
378*8fb009dcSAndroid Build Coastguard Worker
379*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 32 (`LowBits`).
low_bits(uint32_t x)380*8fb009dcSAndroid Build Coastguard Worker static int32_t low_bits(uint32_t x) {
381*8fb009dcSAndroid Build Coastguard Worker uint32_t r1;
382*8fb009dcSAndroid Build Coastguard Worker int32_t r0;
383*8fb009dcSAndroid Build Coastguard Worker decompose(&r1, &r0, x);
384*8fb009dcSAndroid Build Coastguard Worker return r0;
385*8fb009dcSAndroid Build Coastguard Worker }
386*8fb009dcSAndroid Build Coastguard Worker
387*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 33 (`MakeHint`).
make_hint(uint32_t ct0,uint32_t cs2,uint32_t w)388*8fb009dcSAndroid Build Coastguard Worker static int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) {
389*8fb009dcSAndroid Build Coastguard Worker uint32_t r_plus_z = reduce_once(kPrime + w - cs2);
390*8fb009dcSAndroid Build Coastguard Worker uint32_t r = reduce_once(r_plus_z + ct0);
391*8fb009dcSAndroid Build Coastguard Worker return high_bits(r) != high_bits(r_plus_z);
392*8fb009dcSAndroid Build Coastguard Worker }
393*8fb009dcSAndroid Build Coastguard Worker
394*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 34 (`UseHint`).
use_hint_vartime(uint32_t h,uint32_t r)395*8fb009dcSAndroid Build Coastguard Worker static uint32_t use_hint_vartime(uint32_t h, uint32_t r) {
396*8fb009dcSAndroid Build Coastguard Worker uint32_t r1;
397*8fb009dcSAndroid Build Coastguard Worker int32_t r0;
398*8fb009dcSAndroid Build Coastguard Worker decompose(&r1, &r0, r);
399*8fb009dcSAndroid Build Coastguard Worker
400*8fb009dcSAndroid Build Coastguard Worker if (h) {
401*8fb009dcSAndroid Build Coastguard Worker if (r0 > 0) {
402*8fb009dcSAndroid Build Coastguard Worker return (r1 + 1) & 15;
403*8fb009dcSAndroid Build Coastguard Worker } else {
404*8fb009dcSAndroid Build Coastguard Worker return (r1 - 1) & 15;
405*8fb009dcSAndroid Build Coastguard Worker }
406*8fb009dcSAndroid Build Coastguard Worker } else {
407*8fb009dcSAndroid Build Coastguard Worker return r1;
408*8fb009dcSAndroid Build Coastguard Worker }
409*8fb009dcSAndroid Build Coastguard Worker }
410*8fb009dcSAndroid Build Coastguard Worker
scalar_power2_round(scalar * s1,scalar * s0,const scalar * s)411*8fb009dcSAndroid Build Coastguard Worker static void scalar_power2_round(scalar *s1, scalar *s0, const scalar *s) {
412*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
413*8fb009dcSAndroid Build Coastguard Worker power2_round(&s1->c[i], &s0->c[i], s->c[i]);
414*8fb009dcSAndroid Build Coastguard Worker }
415*8fb009dcSAndroid Build Coastguard Worker }
416*8fb009dcSAndroid Build Coastguard Worker
scalar_scale_power2_round(scalar * out,const scalar * in)417*8fb009dcSAndroid Build Coastguard Worker static void scalar_scale_power2_round(scalar *out, const scalar *in) {
418*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
419*8fb009dcSAndroid Build Coastguard Worker scale_power2_round(&out->c[i], in->c[i]);
420*8fb009dcSAndroid Build Coastguard Worker }
421*8fb009dcSAndroid Build Coastguard Worker }
422*8fb009dcSAndroid Build Coastguard Worker
scalar_high_bits(scalar * out,const scalar * in)423*8fb009dcSAndroid Build Coastguard Worker static void scalar_high_bits(scalar *out, const scalar *in) {
424*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
425*8fb009dcSAndroid Build Coastguard Worker out->c[i] = high_bits(in->c[i]);
426*8fb009dcSAndroid Build Coastguard Worker }
427*8fb009dcSAndroid Build Coastguard Worker }
428*8fb009dcSAndroid Build Coastguard Worker
scalar_low_bits(scalar * out,const scalar * in)429*8fb009dcSAndroid Build Coastguard Worker static void scalar_low_bits(scalar *out, const scalar *in) {
430*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
431*8fb009dcSAndroid Build Coastguard Worker out->c[i] = low_bits(in->c[i]);
432*8fb009dcSAndroid Build Coastguard Worker }
433*8fb009dcSAndroid Build Coastguard Worker }
434*8fb009dcSAndroid Build Coastguard Worker
scalar_max(uint32_t * max,const scalar * s)435*8fb009dcSAndroid Build Coastguard Worker static void scalar_max(uint32_t *max, const scalar *s) {
436*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
437*8fb009dcSAndroid Build Coastguard Worker uint32_t abs = abs_mod_prime(s->c[i]);
438*8fb009dcSAndroid Build Coastguard Worker *max = maximum(*max, abs);
439*8fb009dcSAndroid Build Coastguard Worker }
440*8fb009dcSAndroid Build Coastguard Worker }
441*8fb009dcSAndroid Build Coastguard Worker
scalar_max_signed(uint32_t * max,const scalar * s)442*8fb009dcSAndroid Build Coastguard Worker static void scalar_max_signed(uint32_t *max, const scalar *s) {
443*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
444*8fb009dcSAndroid Build Coastguard Worker uint32_t abs = abs_signed(s->c[i]);
445*8fb009dcSAndroid Build Coastguard Worker *max = maximum(*max, abs);
446*8fb009dcSAndroid Build Coastguard Worker }
447*8fb009dcSAndroid Build Coastguard Worker }
448*8fb009dcSAndroid Build Coastguard Worker
scalar_make_hint(scalar * out,const scalar * ct0,const scalar * cs2,const scalar * w)449*8fb009dcSAndroid Build Coastguard Worker static void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2,
450*8fb009dcSAndroid Build Coastguard Worker const scalar *w) {
451*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
452*8fb009dcSAndroid Build Coastguard Worker out->c[i] = make_hint(ct0->c[i], cs2->c[i], w->c[i]);
453*8fb009dcSAndroid Build Coastguard Worker }
454*8fb009dcSAndroid Build Coastguard Worker }
455*8fb009dcSAndroid Build Coastguard Worker
scalar_use_hint_vartime(scalar * out,const scalar * h,const scalar * r)456*8fb009dcSAndroid Build Coastguard Worker static void scalar_use_hint_vartime(scalar *out, const scalar *h,
457*8fb009dcSAndroid Build Coastguard Worker const scalar *r) {
458*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
459*8fb009dcSAndroid Build Coastguard Worker out->c[i] = use_hint_vartime(h->c[i], r->c[i]);
460*8fb009dcSAndroid Build Coastguard Worker }
461*8fb009dcSAndroid Build Coastguard Worker }
462*8fb009dcSAndroid Build Coastguard Worker
vectork_power2_round(vectork * t1,vectork * t0,const vectork * t)463*8fb009dcSAndroid Build Coastguard Worker static void vectork_power2_round(vectork *t1, vectork *t0, const vectork *t) {
464*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
465*8fb009dcSAndroid Build Coastguard Worker scalar_power2_round(&t1->v[i], &t0->v[i], &t->v[i]);
466*8fb009dcSAndroid Build Coastguard Worker }
467*8fb009dcSAndroid Build Coastguard Worker }
468*8fb009dcSAndroid Build Coastguard Worker
vectork_scale_power2_round(vectork * out,const vectork * in)469*8fb009dcSAndroid Build Coastguard Worker static void vectork_scale_power2_round(vectork *out, const vectork *in) {
470*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
471*8fb009dcSAndroid Build Coastguard Worker scalar_scale_power2_round(&out->v[i], &in->v[i]);
472*8fb009dcSAndroid Build Coastguard Worker }
473*8fb009dcSAndroid Build Coastguard Worker }
474*8fb009dcSAndroid Build Coastguard Worker
vectork_high_bits(vectork * out,const vectork * in)475*8fb009dcSAndroid Build Coastguard Worker static void vectork_high_bits(vectork *out, const vectork *in) {
476*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
477*8fb009dcSAndroid Build Coastguard Worker scalar_high_bits(&out->v[i], &in->v[i]);
478*8fb009dcSAndroid Build Coastguard Worker }
479*8fb009dcSAndroid Build Coastguard Worker }
480*8fb009dcSAndroid Build Coastguard Worker
vectork_low_bits(vectork * out,const vectork * in)481*8fb009dcSAndroid Build Coastguard Worker static void vectork_low_bits(vectork *out, const vectork *in) {
482*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
483*8fb009dcSAndroid Build Coastguard Worker scalar_low_bits(&out->v[i], &in->v[i]);
484*8fb009dcSAndroid Build Coastguard Worker }
485*8fb009dcSAndroid Build Coastguard Worker }
486*8fb009dcSAndroid Build Coastguard Worker
vectork_max(const vectork * a)487*8fb009dcSAndroid Build Coastguard Worker static uint32_t vectork_max(const vectork *a) {
488*8fb009dcSAndroid Build Coastguard Worker uint32_t max = 0;
489*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
490*8fb009dcSAndroid Build Coastguard Worker scalar_max(&max, &a->v[i]);
491*8fb009dcSAndroid Build Coastguard Worker }
492*8fb009dcSAndroid Build Coastguard Worker return max;
493*8fb009dcSAndroid Build Coastguard Worker }
494*8fb009dcSAndroid Build Coastguard Worker
vectork_max_signed(const vectork * a)495*8fb009dcSAndroid Build Coastguard Worker static uint32_t vectork_max_signed(const vectork *a) {
496*8fb009dcSAndroid Build Coastguard Worker uint32_t max = 0;
497*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
498*8fb009dcSAndroid Build Coastguard Worker scalar_max_signed(&max, &a->v[i]);
499*8fb009dcSAndroid Build Coastguard Worker }
500*8fb009dcSAndroid Build Coastguard Worker return max;
501*8fb009dcSAndroid Build Coastguard Worker }
502*8fb009dcSAndroid Build Coastguard Worker
503*8fb009dcSAndroid Build Coastguard Worker // The input vector contains only zeroes and ones.
vectork_count_ones(const vectork * a)504*8fb009dcSAndroid Build Coastguard Worker static size_t vectork_count_ones(const vectork *a) {
505*8fb009dcSAndroid Build Coastguard Worker size_t count = 0;
506*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
507*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < DEGREE; j++) {
508*8fb009dcSAndroid Build Coastguard Worker count += a->v[i].c[j];
509*8fb009dcSAndroid Build Coastguard Worker }
510*8fb009dcSAndroid Build Coastguard Worker }
511*8fb009dcSAndroid Build Coastguard Worker return count;
512*8fb009dcSAndroid Build Coastguard Worker }
513*8fb009dcSAndroid Build Coastguard Worker
vectork_make_hint(vectork * out,const vectork * ct0,const vectork * cs2,const vectork * w)514*8fb009dcSAndroid Build Coastguard Worker static void vectork_make_hint(vectork *out, const vectork *ct0,
515*8fb009dcSAndroid Build Coastguard Worker const vectork *cs2, const vectork *w) {
516*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
517*8fb009dcSAndroid Build Coastguard Worker scalar_make_hint(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]);
518*8fb009dcSAndroid Build Coastguard Worker }
519*8fb009dcSAndroid Build Coastguard Worker }
520*8fb009dcSAndroid Build Coastguard Worker
vectork_use_hint_vartime(vectork * out,const vectork * h,const vectork * r)521*8fb009dcSAndroid Build Coastguard Worker static void vectork_use_hint_vartime(vectork *out, const vectork *h,
522*8fb009dcSAndroid Build Coastguard Worker const vectork *r) {
523*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
524*8fb009dcSAndroid Build Coastguard Worker scalar_use_hint_vartime(&out->v[i], &h->v[i], &r->v[i]);
525*8fb009dcSAndroid Build Coastguard Worker }
526*8fb009dcSAndroid Build Coastguard Worker }
527*8fb009dcSAndroid Build Coastguard Worker
vectorl_max(const vectorl * a)528*8fb009dcSAndroid Build Coastguard Worker static uint32_t vectorl_max(const vectorl *a) {
529*8fb009dcSAndroid Build Coastguard Worker uint32_t max = 0;
530*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
531*8fb009dcSAndroid Build Coastguard Worker scalar_max(&max, &a->v[i]);
532*8fb009dcSAndroid Build Coastguard Worker }
533*8fb009dcSAndroid Build Coastguard Worker return max;
534*8fb009dcSAndroid Build Coastguard Worker }
535*8fb009dcSAndroid Build Coastguard Worker
536*8fb009dcSAndroid Build Coastguard Worker /* Bit packing */
537*8fb009dcSAndroid Build Coastguard Worker
538*8fb009dcSAndroid Build Coastguard Worker static const uint8_t kMasks[8] = {0x01, 0x03, 0x07, 0x0f,
539*8fb009dcSAndroid Build Coastguard Worker 0x1f, 0x3f, 0x7f, 0xff};
540*8fb009dcSAndroid Build Coastguard Worker
541*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 10 (`SimpleBitPack`).
scalar_encode(uint8_t * out,const scalar * s,int bits)542*8fb009dcSAndroid Build Coastguard Worker static void scalar_encode(uint8_t *out, const scalar *s, int bits) {
543*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1);
544*8fb009dcSAndroid Build Coastguard Worker
545*8fb009dcSAndroid Build Coastguard Worker uint8_t out_byte = 0;
546*8fb009dcSAndroid Build Coastguard Worker int out_byte_bits = 0;
547*8fb009dcSAndroid Build Coastguard Worker
548*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
549*8fb009dcSAndroid Build Coastguard Worker uint32_t element = s->c[i];
550*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
551*8fb009dcSAndroid Build Coastguard Worker
552*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
553*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
554*8fb009dcSAndroid Build Coastguard Worker int out_bits_remaining = 8 - out_byte_bits;
555*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits >= out_bits_remaining) {
556*8fb009dcSAndroid Build Coastguard Worker chunk_bits = out_bits_remaining;
557*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
558*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
559*8fb009dcSAndroid Build Coastguard Worker out++;
560*8fb009dcSAndroid Build Coastguard Worker out_byte_bits = 0;
561*8fb009dcSAndroid Build Coastguard Worker out_byte = 0;
562*8fb009dcSAndroid Build Coastguard Worker } else {
563*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
564*8fb009dcSAndroid Build Coastguard Worker out_byte_bits += chunk_bits;
565*8fb009dcSAndroid Build Coastguard Worker }
566*8fb009dcSAndroid Build Coastguard Worker
567*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
568*8fb009dcSAndroid Build Coastguard Worker element >>= chunk_bits;
569*8fb009dcSAndroid Build Coastguard Worker }
570*8fb009dcSAndroid Build Coastguard Worker }
571*8fb009dcSAndroid Build Coastguard Worker
572*8fb009dcSAndroid Build Coastguard Worker if (out_byte_bits > 0) {
573*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
574*8fb009dcSAndroid Build Coastguard Worker }
575*8fb009dcSAndroid Build Coastguard Worker }
576*8fb009dcSAndroid Build Coastguard Worker
577*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 11 (`BitPack`).
scalar_encode_signed(uint8_t * out,const scalar * s,int bits,uint32_t max)578*8fb009dcSAndroid Build Coastguard Worker static void scalar_encode_signed(uint8_t *out, const scalar *s, int bits,
579*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
580*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*s->c) * 8 && bits != 1);
581*8fb009dcSAndroid Build Coastguard Worker
582*8fb009dcSAndroid Build Coastguard Worker uint8_t out_byte = 0;
583*8fb009dcSAndroid Build Coastguard Worker int out_byte_bits = 0;
584*8fb009dcSAndroid Build Coastguard Worker
585*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
586*8fb009dcSAndroid Build Coastguard Worker uint32_t element = reduce_once(kPrime + max - s->c[i]);
587*8fb009dcSAndroid Build Coastguard Worker declassify_assert(element <= 2 * max);
588*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
589*8fb009dcSAndroid Build Coastguard Worker
590*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
591*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
592*8fb009dcSAndroid Build Coastguard Worker int out_bits_remaining = 8 - out_byte_bits;
593*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits >= out_bits_remaining) {
594*8fb009dcSAndroid Build Coastguard Worker chunk_bits = out_bits_remaining;
595*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
596*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
597*8fb009dcSAndroid Build Coastguard Worker out++;
598*8fb009dcSAndroid Build Coastguard Worker out_byte_bits = 0;
599*8fb009dcSAndroid Build Coastguard Worker out_byte = 0;
600*8fb009dcSAndroid Build Coastguard Worker } else {
601*8fb009dcSAndroid Build Coastguard Worker out_byte |= (element & kMasks[chunk_bits - 1]) << out_byte_bits;
602*8fb009dcSAndroid Build Coastguard Worker out_byte_bits += chunk_bits;
603*8fb009dcSAndroid Build Coastguard Worker }
604*8fb009dcSAndroid Build Coastguard Worker
605*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
606*8fb009dcSAndroid Build Coastguard Worker element >>= chunk_bits;
607*8fb009dcSAndroid Build Coastguard Worker }
608*8fb009dcSAndroid Build Coastguard Worker }
609*8fb009dcSAndroid Build Coastguard Worker
610*8fb009dcSAndroid Build Coastguard Worker if (out_byte_bits > 0) {
611*8fb009dcSAndroid Build Coastguard Worker *out = out_byte;
612*8fb009dcSAndroid Build Coastguard Worker }
613*8fb009dcSAndroid Build Coastguard Worker }
614*8fb009dcSAndroid Build Coastguard Worker
615*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 12 (`SimpleBitUnpack`).
scalar_decode(scalar * out,const uint8_t * in,int bits)616*8fb009dcSAndroid Build Coastguard Worker static void scalar_decode(scalar *out, const uint8_t *in, int bits) {
617*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1);
618*8fb009dcSAndroid Build Coastguard Worker
619*8fb009dcSAndroid Build Coastguard Worker uint8_t in_byte = 0;
620*8fb009dcSAndroid Build Coastguard Worker int in_byte_bits_left = 0;
621*8fb009dcSAndroid Build Coastguard Worker
622*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
623*8fb009dcSAndroid Build Coastguard Worker uint32_t element = 0;
624*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
625*8fb009dcSAndroid Build Coastguard Worker
626*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
627*8fb009dcSAndroid Build Coastguard Worker if (in_byte_bits_left == 0) {
628*8fb009dcSAndroid Build Coastguard Worker in_byte = *in;
629*8fb009dcSAndroid Build Coastguard Worker in++;
630*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left = 8;
631*8fb009dcSAndroid Build Coastguard Worker }
632*8fb009dcSAndroid Build Coastguard Worker
633*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
634*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits > in_byte_bits_left) {
635*8fb009dcSAndroid Build Coastguard Worker chunk_bits = in_byte_bits_left;
636*8fb009dcSAndroid Build Coastguard Worker }
637*8fb009dcSAndroid Build Coastguard Worker
638*8fb009dcSAndroid Build Coastguard Worker element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done;
639*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left -= chunk_bits;
640*8fb009dcSAndroid Build Coastguard Worker in_byte >>= chunk_bits;
641*8fb009dcSAndroid Build Coastguard Worker
642*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
643*8fb009dcSAndroid Build Coastguard Worker }
644*8fb009dcSAndroid Build Coastguard Worker
645*8fb009dcSAndroid Build Coastguard Worker out->c[i] = element;
646*8fb009dcSAndroid Build Coastguard Worker }
647*8fb009dcSAndroid Build Coastguard Worker }
648*8fb009dcSAndroid Build Coastguard Worker
649*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 13 (`BitUnpack`).
scalar_decode_signed(scalar * out,const uint8_t * in,int bits,uint32_t max)650*8fb009dcSAndroid Build Coastguard Worker static int scalar_decode_signed(scalar *out, const uint8_t *in, int bits,
651*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
652*8fb009dcSAndroid Build Coastguard Worker assert(bits <= (int)sizeof(*out->c) * 8 && bits != 1);
653*8fb009dcSAndroid Build Coastguard Worker
654*8fb009dcSAndroid Build Coastguard Worker uint8_t in_byte = 0;
655*8fb009dcSAndroid Build Coastguard Worker int in_byte_bits_left = 0;
656*8fb009dcSAndroid Build Coastguard Worker
657*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < DEGREE; i++) {
658*8fb009dcSAndroid Build Coastguard Worker uint32_t element = 0;
659*8fb009dcSAndroid Build Coastguard Worker int element_bits_done = 0;
660*8fb009dcSAndroid Build Coastguard Worker
661*8fb009dcSAndroid Build Coastguard Worker while (element_bits_done < bits) {
662*8fb009dcSAndroid Build Coastguard Worker if (in_byte_bits_left == 0) {
663*8fb009dcSAndroid Build Coastguard Worker in_byte = *in;
664*8fb009dcSAndroid Build Coastguard Worker in++;
665*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left = 8;
666*8fb009dcSAndroid Build Coastguard Worker }
667*8fb009dcSAndroid Build Coastguard Worker
668*8fb009dcSAndroid Build Coastguard Worker int chunk_bits = bits - element_bits_done;
669*8fb009dcSAndroid Build Coastguard Worker if (chunk_bits > in_byte_bits_left) {
670*8fb009dcSAndroid Build Coastguard Worker chunk_bits = in_byte_bits_left;
671*8fb009dcSAndroid Build Coastguard Worker }
672*8fb009dcSAndroid Build Coastguard Worker
673*8fb009dcSAndroid Build Coastguard Worker element |= (in_byte & kMasks[chunk_bits - 1]) << element_bits_done;
674*8fb009dcSAndroid Build Coastguard Worker in_byte_bits_left -= chunk_bits;
675*8fb009dcSAndroid Build Coastguard Worker in_byte >>= chunk_bits;
676*8fb009dcSAndroid Build Coastguard Worker
677*8fb009dcSAndroid Build Coastguard Worker element_bits_done += chunk_bits;
678*8fb009dcSAndroid Build Coastguard Worker }
679*8fb009dcSAndroid Build Coastguard Worker
680*8fb009dcSAndroid Build Coastguard Worker // This may be only out of range in cases of invalid input, in which case it
681*8fb009dcSAndroid Build Coastguard Worker // is okay to leak the value. This function is also called with secret
682*8fb009dcSAndroid Build Coastguard Worker // input during signing, in |scalar_sample_mask|. However, in that case
683*8fb009dcSAndroid Build Coastguard Worker // (and in any case when |max| is a power of two), this case is impossible.
684*8fb009dcSAndroid Build Coastguard Worker if (constant_time_declassify_int(element > 2 * max)) {
685*8fb009dcSAndroid Build Coastguard Worker return 0;
686*8fb009dcSAndroid Build Coastguard Worker }
687*8fb009dcSAndroid Build Coastguard Worker out->c[i] = reduce_once(kPrime + max - element);
688*8fb009dcSAndroid Build Coastguard Worker }
689*8fb009dcSAndroid Build Coastguard Worker
690*8fb009dcSAndroid Build Coastguard Worker return 1;
691*8fb009dcSAndroid Build Coastguard Worker }
692*8fb009dcSAndroid Build Coastguard Worker
693*8fb009dcSAndroid Build Coastguard Worker /* Expansion functions */
694*8fb009dcSAndroid Build Coastguard Worker
695*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 24 (`RejNTTPoly`).
696*8fb009dcSAndroid Build Coastguard Worker //
697*8fb009dcSAndroid Build Coastguard Worker // Rejection samples a Keccak stream to get uniformly distributed elements. This
698*8fb009dcSAndroid Build Coastguard Worker // is used for matrix expansion and only operates on public inputs.
scalar_from_keccak_vartime(scalar * out,const uint8_t derived_seed[RHO_BYTES+2])699*8fb009dcSAndroid Build Coastguard Worker static void scalar_from_keccak_vartime(
700*8fb009dcSAndroid Build Coastguard Worker scalar *out, const uint8_t derived_seed[RHO_BYTES + 2]) {
701*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
702*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake128);
703*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, RHO_BYTES + 2);
704*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.squeeze_offset == 0);
705*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.rate_bytes == 168);
706*8fb009dcSAndroid Build Coastguard Worker static_assert(168 % 3 == 0, "block and coefficient boundaries do not align");
707*8fb009dcSAndroid Build Coastguard Worker
708*8fb009dcSAndroid Build Coastguard Worker int done = 0;
709*8fb009dcSAndroid Build Coastguard Worker while (done < DEGREE) {
710*8fb009dcSAndroid Build Coastguard Worker uint8_t block[168];
711*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
712*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(block) && done < DEGREE; i += 3) {
713*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 8 (`CoeffFromThreeBytes`).
714*8fb009dcSAndroid Build Coastguard Worker uint32_t value = (uint32_t)block[i] | ((uint32_t)block[i + 1] << 8) |
715*8fb009dcSAndroid Build Coastguard Worker (((uint32_t)block[i + 2] & 0x7f) << 16);
716*8fb009dcSAndroid Build Coastguard Worker if (value < kPrime) {
717*8fb009dcSAndroid Build Coastguard Worker out->c[done++] = value;
718*8fb009dcSAndroid Build Coastguard Worker }
719*8fb009dcSAndroid Build Coastguard Worker }
720*8fb009dcSAndroid Build Coastguard Worker }
721*8fb009dcSAndroid Build Coastguard Worker }
722*8fb009dcSAndroid Build Coastguard Worker
723*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 25 (`RejBoundedPoly`).
scalar_uniform_eta_4(scalar * out,const uint8_t derived_seed[SIGMA_BYTES+2])724*8fb009dcSAndroid Build Coastguard Worker static void scalar_uniform_eta_4(scalar *out,
725*8fb009dcSAndroid Build Coastguard Worker const uint8_t derived_seed[SIGMA_BYTES + 2]) {
726*8fb009dcSAndroid Build Coastguard Worker static_assert(ETA == 4, "This implementation is specialized for ETA == 4");
727*8fb009dcSAndroid Build Coastguard Worker
728*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
729*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
730*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, SIGMA_BYTES + 2);
731*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.squeeze_offset == 0);
732*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.rate_bytes == 136);
733*8fb009dcSAndroid Build Coastguard Worker
734*8fb009dcSAndroid Build Coastguard Worker int done = 0;
735*8fb009dcSAndroid Build Coastguard Worker while (done < DEGREE) {
736*8fb009dcSAndroid Build Coastguard Worker uint8_t block[136];
737*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
738*8fb009dcSAndroid Build Coastguard Worker for (size_t i = 0; i < sizeof(block) && done < DEGREE; ++i) {
739*8fb009dcSAndroid Build Coastguard Worker uint32_t t0 = block[i] & 0x0F;
740*8fb009dcSAndroid Build Coastguard Worker uint32_t t1 = block[i] >> 4;
741*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 9 (`CoefFromHalfByte`). Although both the input and
742*8fb009dcSAndroid Build Coastguard Worker // output here are secret, it is OK to leak when we rejected a byte.
743*8fb009dcSAndroid Build Coastguard Worker // Individual bytes of the SHAKE-256 stream are (indistiguishable from)
744*8fb009dcSAndroid Build Coastguard Worker // independent of each other and the original seed, so leaking information
745*8fb009dcSAndroid Build Coastguard Worker // about the rejected bytes does not reveal the input or output.
746*8fb009dcSAndroid Build Coastguard Worker if (constant_time_declassify_int(t0 < 9)) {
747*8fb009dcSAndroid Build Coastguard Worker out->c[done++] = reduce_once(kPrime + ETA - t0);
748*8fb009dcSAndroid Build Coastguard Worker }
749*8fb009dcSAndroid Build Coastguard Worker if (done < DEGREE && constant_time_declassify_int(t1 < 9)) {
750*8fb009dcSAndroid Build Coastguard Worker out->c[done++] = reduce_once(kPrime + ETA - t1);
751*8fb009dcSAndroid Build Coastguard Worker }
752*8fb009dcSAndroid Build Coastguard Worker }
753*8fb009dcSAndroid Build Coastguard Worker }
754*8fb009dcSAndroid Build Coastguard Worker }
755*8fb009dcSAndroid Build Coastguard Worker
756*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 28 (`ExpandMask`).
scalar_sample_mask(scalar * out,const uint8_t derived_seed[RHO_PRIME_BYTES+2])757*8fb009dcSAndroid Build Coastguard Worker static void scalar_sample_mask(
758*8fb009dcSAndroid Build Coastguard Worker scalar *out, const uint8_t derived_seed[RHO_PRIME_BYTES + 2]) {
759*8fb009dcSAndroid Build Coastguard Worker uint8_t buf[640];
760*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(buf, sizeof(buf), derived_seed, RHO_PRIME_BYTES + 2,
761*8fb009dcSAndroid Build Coastguard Worker boringssl_shake256);
762*8fb009dcSAndroid Build Coastguard Worker
763*8fb009dcSAndroid Build Coastguard Worker // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail.
764*8fb009dcSAndroid Build Coastguard Worker scalar_decode_signed(out, buf, 20, 1 << 19);
765*8fb009dcSAndroid Build Coastguard Worker }
766*8fb009dcSAndroid Build Coastguard Worker
767*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 23 (`SampleInBall`).
scalar_sample_in_ball_vartime(scalar * out,const uint8_t * seed,int len)768*8fb009dcSAndroid Build Coastguard Worker static void scalar_sample_in_ball_vartime(scalar *out, const uint8_t *seed,
769*8fb009dcSAndroid Build Coastguard Worker int len) {
770*8fb009dcSAndroid Build Coastguard Worker assert(len == 32);
771*8fb009dcSAndroid Build Coastguard Worker
772*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
773*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
774*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, seed, len);
775*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.squeeze_offset == 0);
776*8fb009dcSAndroid Build Coastguard Worker assert(keccak_ctx.rate_bytes == 136);
777*8fb009dcSAndroid Build Coastguard Worker
778*8fb009dcSAndroid Build Coastguard Worker uint8_t block[136];
779*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
780*8fb009dcSAndroid Build Coastguard Worker
781*8fb009dcSAndroid Build Coastguard Worker uint64_t signs = CRYPTO_load_u64_le(block);
782*8fb009dcSAndroid Build Coastguard Worker int offset = 8;
783*8fb009dcSAndroid Build Coastguard Worker // SampleInBall implements a Fisher–Yates shuffle, which unavoidably leaks
784*8fb009dcSAndroid Build Coastguard Worker // where the zeros are by memory access pattern. Although this leak happens
785*8fb009dcSAndroid Build Coastguard Worker // before bad signatures are rejected, this is safe. See
786*8fb009dcSAndroid Build Coastguard Worker // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/8d8f01ac_70af3f21/
787*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(block + offset, sizeof(block) - offset);
788*8fb009dcSAndroid Build Coastguard Worker
789*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(out, 0, sizeof(*out));
790*8fb009dcSAndroid Build Coastguard Worker for (size_t i = DEGREE - TAU; i < DEGREE; i++) {
791*8fb009dcSAndroid Build Coastguard Worker size_t byte;
792*8fb009dcSAndroid Build Coastguard Worker for (;;) {
793*8fb009dcSAndroid Build Coastguard Worker if (offset == 136) {
794*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
795*8fb009dcSAndroid Build Coastguard Worker // See above.
796*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(block, sizeof(block));
797*8fb009dcSAndroid Build Coastguard Worker offset = 0;
798*8fb009dcSAndroid Build Coastguard Worker }
799*8fb009dcSAndroid Build Coastguard Worker
800*8fb009dcSAndroid Build Coastguard Worker byte = block[offset++];
801*8fb009dcSAndroid Build Coastguard Worker if (byte <= i) {
802*8fb009dcSAndroid Build Coastguard Worker break;
803*8fb009dcSAndroid Build Coastguard Worker }
804*8fb009dcSAndroid Build Coastguard Worker }
805*8fb009dcSAndroid Build Coastguard Worker
806*8fb009dcSAndroid Build Coastguard Worker out->c[i] = out->c[byte];
807*8fb009dcSAndroid Build Coastguard Worker out->c[byte] = reduce_once(kPrime + 1 - 2 * (signs & 1));
808*8fb009dcSAndroid Build Coastguard Worker signs >>= 1;
809*8fb009dcSAndroid Build Coastguard Worker }
810*8fb009dcSAndroid Build Coastguard Worker }
811*8fb009dcSAndroid Build Coastguard Worker
812*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 26 (`ExpandA`).
matrix_expand(matrix * out,const uint8_t rho[RHO_BYTES])813*8fb009dcSAndroid Build Coastguard Worker static void matrix_expand(matrix *out, const uint8_t rho[RHO_BYTES]) {
814*8fb009dcSAndroid Build Coastguard Worker static_assert(K <= 0x100, "K must fit in 8 bits");
815*8fb009dcSAndroid Build Coastguard Worker static_assert(L <= 0x100, "L must fit in 8 bits");
816*8fb009dcSAndroid Build Coastguard Worker
817*8fb009dcSAndroid Build Coastguard Worker uint8_t derived_seed[RHO_BYTES + 2];
818*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(derived_seed, rho, RHO_BYTES);
819*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
820*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < L; j++) {
821*8fb009dcSAndroid Build Coastguard Worker derived_seed[RHO_BYTES + 1] = i;
822*8fb009dcSAndroid Build Coastguard Worker derived_seed[RHO_BYTES] = j;
823*8fb009dcSAndroid Build Coastguard Worker scalar_from_keccak_vartime(&out->v[i][j], derived_seed);
824*8fb009dcSAndroid Build Coastguard Worker }
825*8fb009dcSAndroid Build Coastguard Worker }
826*8fb009dcSAndroid Build Coastguard Worker }
827*8fb009dcSAndroid Build Coastguard Worker
828*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 27 (`ExpandS`).
vector_expand_short(vectorl * s1,vectork * s2,const uint8_t sigma[SIGMA_BYTES])829*8fb009dcSAndroid Build Coastguard Worker static void vector_expand_short(vectorl *s1, vectork *s2,
830*8fb009dcSAndroid Build Coastguard Worker const uint8_t sigma[SIGMA_BYTES]) {
831*8fb009dcSAndroid Build Coastguard Worker static_assert(K <= 0x100, "K must fit in 8 bits");
832*8fb009dcSAndroid Build Coastguard Worker static_assert(L <= 0x100, "L must fit in 8 bits");
833*8fb009dcSAndroid Build Coastguard Worker static_assert(K + L <= 0x100, "K+L must fit in 8 bits");
834*8fb009dcSAndroid Build Coastguard Worker
835*8fb009dcSAndroid Build Coastguard Worker uint8_t derived_seed[SIGMA_BYTES + 2];
836*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(derived_seed, sigma, SIGMA_BYTES);
837*8fb009dcSAndroid Build Coastguard Worker derived_seed[SIGMA_BYTES] = 0;
838*8fb009dcSAndroid Build Coastguard Worker derived_seed[SIGMA_BYTES + 1] = 0;
839*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
840*8fb009dcSAndroid Build Coastguard Worker scalar_uniform_eta_4(&s1->v[i], derived_seed);
841*8fb009dcSAndroid Build Coastguard Worker ++derived_seed[SIGMA_BYTES];
842*8fb009dcSAndroid Build Coastguard Worker }
843*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
844*8fb009dcSAndroid Build Coastguard Worker scalar_uniform_eta_4(&s2->v[i], derived_seed);
845*8fb009dcSAndroid Build Coastguard Worker ++derived_seed[SIGMA_BYTES];
846*8fb009dcSAndroid Build Coastguard Worker }
847*8fb009dcSAndroid Build Coastguard Worker }
848*8fb009dcSAndroid Build Coastguard Worker
849*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 28 (`ExpandMask`).
vectorl_expand_mask(vectorl * out,const uint8_t seed[RHO_PRIME_BYTES],size_t kappa)850*8fb009dcSAndroid Build Coastguard Worker static void vectorl_expand_mask(vectorl *out,
851*8fb009dcSAndroid Build Coastguard Worker const uint8_t seed[RHO_PRIME_BYTES],
852*8fb009dcSAndroid Build Coastguard Worker size_t kappa) {
853*8fb009dcSAndroid Build Coastguard Worker assert(kappa + L <= 0x10000);
854*8fb009dcSAndroid Build Coastguard Worker
855*8fb009dcSAndroid Build Coastguard Worker uint8_t derived_seed[RHO_PRIME_BYTES + 2];
856*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(derived_seed, seed, RHO_PRIME_BYTES);
857*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
858*8fb009dcSAndroid Build Coastguard Worker size_t index = kappa + i;
859*8fb009dcSAndroid Build Coastguard Worker derived_seed[RHO_PRIME_BYTES] = index & 0xFF;
860*8fb009dcSAndroid Build Coastguard Worker derived_seed[RHO_PRIME_BYTES + 1] = (index >> 8) & 0xFF;
861*8fb009dcSAndroid Build Coastguard Worker scalar_sample_mask(&out->v[i], derived_seed);
862*8fb009dcSAndroid Build Coastguard Worker }
863*8fb009dcSAndroid Build Coastguard Worker }
864*8fb009dcSAndroid Build Coastguard Worker
865*8fb009dcSAndroid Build Coastguard Worker /* Encoding */
866*8fb009dcSAndroid Build Coastguard Worker
867*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 10 (`SimpleBitPack`).
868*8fb009dcSAndroid Build Coastguard Worker //
869*8fb009dcSAndroid Build Coastguard Worker // Encodes an entire vector into 32*K*|bits| bytes. Note that since 256 (DEGREE)
870*8fb009dcSAndroid Build Coastguard Worker // is divisible by 8, the individual vector entries will always fill a whole
871*8fb009dcSAndroid Build Coastguard Worker // number of bytes, so we do not need to worry about bit packing here.
vectork_encode(uint8_t * out,const vectork * a,int bits)872*8fb009dcSAndroid Build Coastguard Worker static void vectork_encode(uint8_t *out, const vectork *a, int bits) {
873*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
874*8fb009dcSAndroid Build Coastguard Worker scalar_encode(out + i * bits * DEGREE / 8, &a->v[i], bits);
875*8fb009dcSAndroid Build Coastguard Worker }
876*8fb009dcSAndroid Build Coastguard Worker }
877*8fb009dcSAndroid Build Coastguard Worker
878*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 12 (`SimpleBitUnpack`).
vectork_decode(vectork * out,const uint8_t * in,int bits)879*8fb009dcSAndroid Build Coastguard Worker static void vectork_decode(vectork *out, const uint8_t *in, int bits) {
880*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
881*8fb009dcSAndroid Build Coastguard Worker scalar_decode(&out->v[i], in + i * bits * DEGREE / 8, bits);
882*8fb009dcSAndroid Build Coastguard Worker }
883*8fb009dcSAndroid Build Coastguard Worker }
884*8fb009dcSAndroid Build Coastguard Worker
vectork_encode_signed(uint8_t * out,const vectork * a,int bits,uint32_t max)885*8fb009dcSAndroid Build Coastguard Worker static void vectork_encode_signed(uint8_t *out, const vectork *a, int bits,
886*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
887*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
888*8fb009dcSAndroid Build Coastguard Worker scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max);
889*8fb009dcSAndroid Build Coastguard Worker }
890*8fb009dcSAndroid Build Coastguard Worker }
891*8fb009dcSAndroid Build Coastguard Worker
vectork_decode_signed(vectork * out,const uint8_t * in,int bits,uint32_t max)892*8fb009dcSAndroid Build Coastguard Worker static int vectork_decode_signed(vectork *out, const uint8_t *in, int bits,
893*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
894*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
895*8fb009dcSAndroid Build Coastguard Worker if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits,
896*8fb009dcSAndroid Build Coastguard Worker max)) {
897*8fb009dcSAndroid Build Coastguard Worker return 0;
898*8fb009dcSAndroid Build Coastguard Worker }
899*8fb009dcSAndroid Build Coastguard Worker }
900*8fb009dcSAndroid Build Coastguard Worker return 1;
901*8fb009dcSAndroid Build Coastguard Worker }
902*8fb009dcSAndroid Build Coastguard Worker
903*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 11 (`BitPack`).
904*8fb009dcSAndroid Build Coastguard Worker //
905*8fb009dcSAndroid Build Coastguard Worker // Encodes an entire vector into 32*L*|bits| bytes. Note that since 256 (DEGREE)
906*8fb009dcSAndroid Build Coastguard Worker // is divisible by 8, the individual vector entries will always fill a whole
907*8fb009dcSAndroid Build Coastguard Worker // number of bytes, so we do not need to worry about bit packing here.
vectorl_encode_signed(uint8_t * out,const vectorl * a,int bits,uint32_t max)908*8fb009dcSAndroid Build Coastguard Worker static void vectorl_encode_signed(uint8_t *out, const vectorl *a, int bits,
909*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
910*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
911*8fb009dcSAndroid Build Coastguard Worker scalar_encode_signed(out + i * bits * DEGREE / 8, &a->v[i], bits, max);
912*8fb009dcSAndroid Build Coastguard Worker }
913*8fb009dcSAndroid Build Coastguard Worker }
914*8fb009dcSAndroid Build Coastguard Worker
vectorl_decode_signed(vectorl * out,const uint8_t * in,int bits,uint32_t max)915*8fb009dcSAndroid Build Coastguard Worker static int vectorl_decode_signed(vectorl *out, const uint8_t *in, int bits,
916*8fb009dcSAndroid Build Coastguard Worker uint32_t max) {
917*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < L; i++) {
918*8fb009dcSAndroid Build Coastguard Worker if (!scalar_decode_signed(&out->v[i], in + i * bits * DEGREE / 8, bits,
919*8fb009dcSAndroid Build Coastguard Worker max)) {
920*8fb009dcSAndroid Build Coastguard Worker return 0;
921*8fb009dcSAndroid Build Coastguard Worker }
922*8fb009dcSAndroid Build Coastguard Worker }
923*8fb009dcSAndroid Build Coastguard Worker return 1;
924*8fb009dcSAndroid Build Coastguard Worker }
925*8fb009dcSAndroid Build Coastguard Worker
926*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 22 (`w1Encode`).
927*8fb009dcSAndroid Build Coastguard Worker //
928*8fb009dcSAndroid Build Coastguard Worker // The output must point to an array of 128*K bytes.
w1_encode(uint8_t * out,const vectork * w1)929*8fb009dcSAndroid Build Coastguard Worker static void w1_encode(uint8_t *out, const vectork *w1) {
930*8fb009dcSAndroid Build Coastguard Worker vectork_encode(out, w1, 4);
931*8fb009dcSAndroid Build Coastguard Worker }
932*8fb009dcSAndroid Build Coastguard Worker
933*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 14 (`HintBitPack`).
hint_bit_pack(uint8_t * out,const vectork * h)934*8fb009dcSAndroid Build Coastguard Worker static void hint_bit_pack(uint8_t *out, const vectork *h) {
935*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(out, 0, OMEGA + K);
936*8fb009dcSAndroid Build Coastguard Worker int index = 0;
937*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
938*8fb009dcSAndroid Build Coastguard Worker for (int j = 0; j < DEGREE; j++) {
939*8fb009dcSAndroid Build Coastguard Worker if (h->v[i].c[j]) {
940*8fb009dcSAndroid Build Coastguard Worker out[index++] = j;
941*8fb009dcSAndroid Build Coastguard Worker }
942*8fb009dcSAndroid Build Coastguard Worker }
943*8fb009dcSAndroid Build Coastguard Worker out[OMEGA + i] = index;
944*8fb009dcSAndroid Build Coastguard Worker }
945*8fb009dcSAndroid Build Coastguard Worker }
946*8fb009dcSAndroid Build Coastguard Worker
947*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 15 (`HintBitUnpack`).
hint_bit_unpack(vectork * h,const uint8_t * in)948*8fb009dcSAndroid Build Coastguard Worker static int hint_bit_unpack(vectork *h, const uint8_t *in) {
949*8fb009dcSAndroid Build Coastguard Worker vectork_zero(h);
950*8fb009dcSAndroid Build Coastguard Worker int index = 0;
951*8fb009dcSAndroid Build Coastguard Worker for (int i = 0; i < K; i++) {
952*8fb009dcSAndroid Build Coastguard Worker int limit = in[OMEGA + i];
953*8fb009dcSAndroid Build Coastguard Worker if (limit < index || limit > OMEGA) {
954*8fb009dcSAndroid Build Coastguard Worker return 0;
955*8fb009dcSAndroid Build Coastguard Worker }
956*8fb009dcSAndroid Build Coastguard Worker
957*8fb009dcSAndroid Build Coastguard Worker int last = -1;
958*8fb009dcSAndroid Build Coastguard Worker while (index < limit) {
959*8fb009dcSAndroid Build Coastguard Worker int byte = in[index++];
960*8fb009dcSAndroid Build Coastguard Worker if (last >= 0 && byte <= last) {
961*8fb009dcSAndroid Build Coastguard Worker return 0;
962*8fb009dcSAndroid Build Coastguard Worker }
963*8fb009dcSAndroid Build Coastguard Worker last = byte;
964*8fb009dcSAndroid Build Coastguard Worker h->v[i].c[byte] = 1;
965*8fb009dcSAndroid Build Coastguard Worker }
966*8fb009dcSAndroid Build Coastguard Worker }
967*8fb009dcSAndroid Build Coastguard Worker for (; index < OMEGA; index++) {
968*8fb009dcSAndroid Build Coastguard Worker if (in[index] != 0) {
969*8fb009dcSAndroid Build Coastguard Worker return 0;
970*8fb009dcSAndroid Build Coastguard Worker }
971*8fb009dcSAndroid Build Coastguard Worker }
972*8fb009dcSAndroid Build Coastguard Worker return 1;
973*8fb009dcSAndroid Build Coastguard Worker }
974*8fb009dcSAndroid Build Coastguard Worker
975*8fb009dcSAndroid Build Coastguard Worker struct public_key {
976*8fb009dcSAndroid Build Coastguard Worker uint8_t rho[RHO_BYTES];
977*8fb009dcSAndroid Build Coastguard Worker vectork t1;
978*8fb009dcSAndroid Build Coastguard Worker // Pre-cached value(s).
979*8fb009dcSAndroid Build Coastguard Worker uint8_t public_key_hash[TR_BYTES];
980*8fb009dcSAndroid Build Coastguard Worker };
981*8fb009dcSAndroid Build Coastguard Worker
982*8fb009dcSAndroid Build Coastguard Worker struct private_key {
983*8fb009dcSAndroid Build Coastguard Worker uint8_t rho[RHO_BYTES];
984*8fb009dcSAndroid Build Coastguard Worker uint8_t k[K_BYTES];
985*8fb009dcSAndroid Build Coastguard Worker uint8_t public_key_hash[TR_BYTES];
986*8fb009dcSAndroid Build Coastguard Worker vectorl s1;
987*8fb009dcSAndroid Build Coastguard Worker vectork s2;
988*8fb009dcSAndroid Build Coastguard Worker vectork t0;
989*8fb009dcSAndroid Build Coastguard Worker };
990*8fb009dcSAndroid Build Coastguard Worker
991*8fb009dcSAndroid Build Coastguard Worker struct signature {
992*8fb009dcSAndroid Build Coastguard Worker uint8_t c_tilde[2 * LAMBDA_BYTES];
993*8fb009dcSAndroid Build Coastguard Worker vectorl z;
994*8fb009dcSAndroid Build Coastguard Worker vectork h;
995*8fb009dcSAndroid Build Coastguard Worker };
996*8fb009dcSAndroid Build Coastguard Worker
997*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 16 (`pkEncode`).
dilithium_marshal_public_key(CBB * out,const struct public_key * pub)998*8fb009dcSAndroid Build Coastguard Worker static int dilithium_marshal_public_key(CBB *out,
999*8fb009dcSAndroid Build Coastguard Worker const struct public_key *pub) {
1000*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) {
1001*8fb009dcSAndroid Build Coastguard Worker return 0;
1002*8fb009dcSAndroid Build Coastguard Worker }
1003*8fb009dcSAndroid Build Coastguard Worker
1004*8fb009dcSAndroid Build Coastguard Worker uint8_t *vectork_output;
1005*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vectork_output, 320 * K)) {
1006*8fb009dcSAndroid Build Coastguard Worker return 0;
1007*8fb009dcSAndroid Build Coastguard Worker }
1008*8fb009dcSAndroid Build Coastguard Worker vectork_encode(vectork_output, &pub->t1, 10);
1009*8fb009dcSAndroid Build Coastguard Worker
1010*8fb009dcSAndroid Build Coastguard Worker return 1;
1011*8fb009dcSAndroid Build Coastguard Worker }
1012*8fb009dcSAndroid Build Coastguard Worker
1013*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 17 (`pkDecode`).
dilithium_parse_public_key(struct public_key * pub,CBS * in)1014*8fb009dcSAndroid Build Coastguard Worker static int dilithium_parse_public_key(struct public_key *pub, CBS *in) {
1015*8fb009dcSAndroid Build Coastguard Worker if (!CBS_copy_bytes(in, pub->rho, sizeof(pub->rho))) {
1016*8fb009dcSAndroid Build Coastguard Worker return 0;
1017*8fb009dcSAndroid Build Coastguard Worker }
1018*8fb009dcSAndroid Build Coastguard Worker
1019*8fb009dcSAndroid Build Coastguard Worker CBS t1_bytes;
1020*8fb009dcSAndroid Build Coastguard Worker if (!CBS_get_bytes(in, &t1_bytes, 320 * K)) {
1021*8fb009dcSAndroid Build Coastguard Worker return 0;
1022*8fb009dcSAndroid Build Coastguard Worker }
1023*8fb009dcSAndroid Build Coastguard Worker vectork_decode(&pub->t1, CBS_data(&t1_bytes), 10);
1024*8fb009dcSAndroid Build Coastguard Worker
1025*8fb009dcSAndroid Build Coastguard Worker return 1;
1026*8fb009dcSAndroid Build Coastguard Worker }
1027*8fb009dcSAndroid Build Coastguard Worker
1028*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 18 (`skEncode`).
dilithium_marshal_private_key(CBB * out,const struct private_key * priv)1029*8fb009dcSAndroid Build Coastguard Worker static int dilithium_marshal_private_key(CBB *out,
1030*8fb009dcSAndroid Build Coastguard Worker const struct private_key *priv) {
1031*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(out, priv->rho, sizeof(priv->rho)) ||
1032*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(out, priv->k, sizeof(priv->k)) ||
1033*8fb009dcSAndroid Build Coastguard Worker !CBB_add_bytes(out, priv->public_key_hash,
1034*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->public_key_hash))) {
1035*8fb009dcSAndroid Build Coastguard Worker return 0;
1036*8fb009dcSAndroid Build Coastguard Worker }
1037*8fb009dcSAndroid Build Coastguard Worker
1038*8fb009dcSAndroid Build Coastguard Worker uint8_t *vectorl_output;
1039*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vectorl_output, 128 * L)) {
1040*8fb009dcSAndroid Build Coastguard Worker return 0;
1041*8fb009dcSAndroid Build Coastguard Worker }
1042*8fb009dcSAndroid Build Coastguard Worker vectorl_encode_signed(vectorl_output, &priv->s1, 4, ETA);
1043*8fb009dcSAndroid Build Coastguard Worker
1044*8fb009dcSAndroid Build Coastguard Worker uint8_t *vectork_output;
1045*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vectork_output, 128 * K)) {
1046*8fb009dcSAndroid Build Coastguard Worker return 0;
1047*8fb009dcSAndroid Build Coastguard Worker }
1048*8fb009dcSAndroid Build Coastguard Worker vectork_encode_signed(vectork_output, &priv->s2, 4, ETA);
1049*8fb009dcSAndroid Build Coastguard Worker
1050*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vectork_output, 416 * K)) {
1051*8fb009dcSAndroid Build Coastguard Worker return 0;
1052*8fb009dcSAndroid Build Coastguard Worker }
1053*8fb009dcSAndroid Build Coastguard Worker vectork_encode_signed(vectork_output, &priv->t0, 13, 1 << 12);
1054*8fb009dcSAndroid Build Coastguard Worker
1055*8fb009dcSAndroid Build Coastguard Worker return 1;
1056*8fb009dcSAndroid Build Coastguard Worker }
1057*8fb009dcSAndroid Build Coastguard Worker
1058*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 19 (`skDecode`).
dilithium_parse_private_key(struct private_key * priv,CBS * in)1059*8fb009dcSAndroid Build Coastguard Worker static int dilithium_parse_private_key(struct private_key *priv, CBS *in) {
1060*8fb009dcSAndroid Build Coastguard Worker CBS s1_bytes;
1061*8fb009dcSAndroid Build Coastguard Worker CBS s2_bytes;
1062*8fb009dcSAndroid Build Coastguard Worker CBS t0_bytes;
1063*8fb009dcSAndroid Build Coastguard Worker if (!CBS_copy_bytes(in, priv->rho, sizeof(priv->rho)) ||
1064*8fb009dcSAndroid Build Coastguard Worker !CBS_copy_bytes(in, priv->k, sizeof(priv->k)) ||
1065*8fb009dcSAndroid Build Coastguard Worker !CBS_copy_bytes(in, priv->public_key_hash,
1066*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->public_key_hash)) ||
1067*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(in, &s1_bytes, 128 * L) ||
1068*8fb009dcSAndroid Build Coastguard Worker !vectorl_decode_signed(&priv->s1, CBS_data(&s1_bytes), 4, ETA) ||
1069*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(in, &s2_bytes, 128 * K) ||
1070*8fb009dcSAndroid Build Coastguard Worker !vectork_decode_signed(&priv->s2, CBS_data(&s2_bytes), 4, ETA) ||
1071*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(in, &t0_bytes, 416 * K) ||
1072*8fb009dcSAndroid Build Coastguard Worker // Note: Decoding 13 bits into (-2^12, 2^12] cannot fail.
1073*8fb009dcSAndroid Build Coastguard Worker !vectork_decode_signed(&priv->t0, CBS_data(&t0_bytes), 13, 1 << 12)) {
1074*8fb009dcSAndroid Build Coastguard Worker return 0;
1075*8fb009dcSAndroid Build Coastguard Worker }
1076*8fb009dcSAndroid Build Coastguard Worker
1077*8fb009dcSAndroid Build Coastguard Worker return 1;
1078*8fb009dcSAndroid Build Coastguard Worker }
1079*8fb009dcSAndroid Build Coastguard Worker
1080*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 20 (`sigEncode`).
dilithium_marshal_signature(CBB * out,const struct signature * sign)1081*8fb009dcSAndroid Build Coastguard Worker static int dilithium_marshal_signature(CBB *out, const struct signature *sign) {
1082*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_bytes(out, sign->c_tilde, sizeof(sign->c_tilde))) {
1083*8fb009dcSAndroid Build Coastguard Worker return 0;
1084*8fb009dcSAndroid Build Coastguard Worker }
1085*8fb009dcSAndroid Build Coastguard Worker
1086*8fb009dcSAndroid Build Coastguard Worker uint8_t *vectorl_output;
1087*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &vectorl_output, 640 * L)) {
1088*8fb009dcSAndroid Build Coastguard Worker return 0;
1089*8fb009dcSAndroid Build Coastguard Worker }
1090*8fb009dcSAndroid Build Coastguard Worker vectorl_encode_signed(vectorl_output, &sign->z, 20, 1 << 19);
1091*8fb009dcSAndroid Build Coastguard Worker
1092*8fb009dcSAndroid Build Coastguard Worker uint8_t *hint_output;
1093*8fb009dcSAndroid Build Coastguard Worker if (!CBB_add_space(out, &hint_output, OMEGA + K)) {
1094*8fb009dcSAndroid Build Coastguard Worker return 0;
1095*8fb009dcSAndroid Build Coastguard Worker }
1096*8fb009dcSAndroid Build Coastguard Worker hint_bit_pack(hint_output, &sign->h);
1097*8fb009dcSAndroid Build Coastguard Worker
1098*8fb009dcSAndroid Build Coastguard Worker return 1;
1099*8fb009dcSAndroid Build Coastguard Worker }
1100*8fb009dcSAndroid Build Coastguard Worker
1101*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 21 (`sigDecode`).
dilithium_parse_signature(struct signature * sign,CBS * in)1102*8fb009dcSAndroid Build Coastguard Worker static int dilithium_parse_signature(struct signature *sign, CBS *in) {
1103*8fb009dcSAndroid Build Coastguard Worker CBS z_bytes;
1104*8fb009dcSAndroid Build Coastguard Worker CBS hint_bytes;
1105*8fb009dcSAndroid Build Coastguard Worker if (!CBS_copy_bytes(in, sign->c_tilde, sizeof(sign->c_tilde)) ||
1106*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(in, &z_bytes, 640 * L) ||
1107*8fb009dcSAndroid Build Coastguard Worker // Note: Decoding 20 bits into (-2^19, 2^19] cannot fail.
1108*8fb009dcSAndroid Build Coastguard Worker !vectorl_decode_signed(&sign->z, CBS_data(&z_bytes), 20, 1 << 19) ||
1109*8fb009dcSAndroid Build Coastguard Worker !CBS_get_bytes(in, &hint_bytes, OMEGA + K) ||
1110*8fb009dcSAndroid Build Coastguard Worker !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) {
1111*8fb009dcSAndroid Build Coastguard Worker return 0;
1112*8fb009dcSAndroid Build Coastguard Worker };
1113*8fb009dcSAndroid Build Coastguard Worker
1114*8fb009dcSAndroid Build Coastguard Worker return 1;
1115*8fb009dcSAndroid Build Coastguard Worker }
1116*8fb009dcSAndroid Build Coastguard Worker
private_key_from_external(const struct DILITHIUM_private_key * external)1117*8fb009dcSAndroid Build Coastguard Worker static struct private_key *private_key_from_external(
1118*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_private_key *external) {
1119*8fb009dcSAndroid Build Coastguard Worker static_assert(
1120*8fb009dcSAndroid Build Coastguard Worker sizeof(struct DILITHIUM_private_key) == sizeof(struct private_key),
1121*8fb009dcSAndroid Build Coastguard Worker "Kyber private key size incorrect");
1122*8fb009dcSAndroid Build Coastguard Worker static_assert(
1123*8fb009dcSAndroid Build Coastguard Worker alignof(struct DILITHIUM_private_key) == alignof(struct private_key),
1124*8fb009dcSAndroid Build Coastguard Worker "Kyber private key align incorrect");
1125*8fb009dcSAndroid Build Coastguard Worker return (struct private_key *)external;
1126*8fb009dcSAndroid Build Coastguard Worker }
1127*8fb009dcSAndroid Build Coastguard Worker
public_key_from_external(const struct DILITHIUM_public_key * external)1128*8fb009dcSAndroid Build Coastguard Worker static struct public_key *public_key_from_external(
1129*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_public_key *external) {
1130*8fb009dcSAndroid Build Coastguard Worker static_assert(
1131*8fb009dcSAndroid Build Coastguard Worker sizeof(struct DILITHIUM_public_key) == sizeof(struct public_key),
1132*8fb009dcSAndroid Build Coastguard Worker "Dilithium public key size incorrect");
1133*8fb009dcSAndroid Build Coastguard Worker static_assert(
1134*8fb009dcSAndroid Build Coastguard Worker alignof(struct DILITHIUM_public_key) == alignof(struct public_key),
1135*8fb009dcSAndroid Build Coastguard Worker "Dilithium public key align incorrect");
1136*8fb009dcSAndroid Build Coastguard Worker return (struct public_key *)external;
1137*8fb009dcSAndroid Build Coastguard Worker }
1138*8fb009dcSAndroid Build Coastguard Worker
1139*8fb009dcSAndroid Build Coastguard Worker /* API */
1140*8fb009dcSAndroid Build Coastguard Worker
1141*8fb009dcSAndroid Build Coastguard Worker // Calls |DILITHIUM_generate_key_external_entropy| with random bytes from
1142*8fb009dcSAndroid Build Coastguard Worker // |RAND_bytes|. Returns 1 on success and 0 on failure.
DILITHIUM_generate_key(uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES],struct DILITHIUM_private_key * out_private_key)1143*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_generate_key(
1144*8fb009dcSAndroid Build Coastguard Worker uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES],
1145*8fb009dcSAndroid Build Coastguard Worker struct DILITHIUM_private_key *out_private_key) {
1146*8fb009dcSAndroid Build Coastguard Worker uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY];
1147*8fb009dcSAndroid Build Coastguard Worker RAND_bytes(entropy, sizeof(entropy));
1148*8fb009dcSAndroid Build Coastguard Worker return DILITHIUM_generate_key_external_entropy(out_encoded_public_key,
1149*8fb009dcSAndroid Build Coastguard Worker out_private_key, entropy);
1150*8fb009dcSAndroid Build Coastguard Worker }
1151*8fb009dcSAndroid Build Coastguard Worker
1152*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 1 (`ML-DSA.KeyGen`). Returns 1 on success and 0 on
1153*8fb009dcSAndroid Build Coastguard Worker // failure.
DILITHIUM_generate_key_external_entropy(uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES],struct DILITHIUM_private_key * out_private_key,const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY])1154*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_generate_key_external_entropy(
1155*8fb009dcSAndroid Build Coastguard Worker uint8_t out_encoded_public_key[DILITHIUM_PUBLIC_KEY_BYTES],
1156*8fb009dcSAndroid Build Coastguard Worker struct DILITHIUM_private_key *out_private_key,
1157*8fb009dcSAndroid Build Coastguard Worker const uint8_t entropy[DILITHIUM_GENERATE_KEY_ENTROPY]) {
1158*8fb009dcSAndroid Build Coastguard Worker int ret = 0;
1159*8fb009dcSAndroid Build Coastguard Worker
1160*8fb009dcSAndroid Build Coastguard Worker // Intermediate values, allocated on the heap to allow use when there is a
1161*8fb009dcSAndroid Build Coastguard Worker // limited amount of stack.
1162*8fb009dcSAndroid Build Coastguard Worker struct values_st {
1163*8fb009dcSAndroid Build Coastguard Worker struct public_key pub;
1164*8fb009dcSAndroid Build Coastguard Worker matrix a_ntt;
1165*8fb009dcSAndroid Build Coastguard Worker vectorl s1_ntt;
1166*8fb009dcSAndroid Build Coastguard Worker vectork t;
1167*8fb009dcSAndroid Build Coastguard Worker };
1168*8fb009dcSAndroid Build Coastguard Worker struct values_st *values = OPENSSL_malloc(sizeof(*values));
1169*8fb009dcSAndroid Build Coastguard Worker if (values == NULL) {
1170*8fb009dcSAndroid Build Coastguard Worker goto err;
1171*8fb009dcSAndroid Build Coastguard Worker }
1172*8fb009dcSAndroid Build Coastguard Worker
1173*8fb009dcSAndroid Build Coastguard Worker struct private_key *priv = private_key_from_external(out_private_key);
1174*8fb009dcSAndroid Build Coastguard Worker
1175*8fb009dcSAndroid Build Coastguard Worker uint8_t expanded_seed[RHO_BYTES + SIGMA_BYTES + K_BYTES];
1176*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(expanded_seed, sizeof(expanded_seed), entropy,
1177*8fb009dcSAndroid Build Coastguard Worker DILITHIUM_GENERATE_KEY_ENTROPY, boringssl_shake256);
1178*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const rho = expanded_seed;
1179*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const sigma = expanded_seed + RHO_BYTES;
1180*8fb009dcSAndroid Build Coastguard Worker const uint8_t *const k = expanded_seed + RHO_BYTES + SIGMA_BYTES;
1181*8fb009dcSAndroid Build Coastguard Worker // rho is public.
1182*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(rho, RHO_BYTES);
1183*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(values->pub.rho, rho, sizeof(values->pub.rho));
1184*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(priv->rho, rho, sizeof(priv->rho));
1185*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(priv->k, k, sizeof(priv->k));
1186*8fb009dcSAndroid Build Coastguard Worker
1187*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&values->a_ntt, rho);
1188*8fb009dcSAndroid Build Coastguard Worker vector_expand_short(&priv->s1, &priv->s2, sigma);
1189*8fb009dcSAndroid Build Coastguard Worker
1190*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt));
1191*8fb009dcSAndroid Build Coastguard Worker vectorl_ntt(&values->s1_ntt);
1192*8fb009dcSAndroid Build Coastguard Worker
1193*8fb009dcSAndroid Build Coastguard Worker matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt);
1194*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->t);
1195*8fb009dcSAndroid Build Coastguard Worker vectork_add(&values->t, &values->t, &priv->s2);
1196*8fb009dcSAndroid Build Coastguard Worker
1197*8fb009dcSAndroid Build Coastguard Worker vectork_power2_round(&values->pub.t1, &priv->t0, &values->t);
1198*8fb009dcSAndroid Build Coastguard Worker // t1 is public.
1199*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(&values->pub.t1, sizeof(values->pub.t1));
1200*8fb009dcSAndroid Build Coastguard Worker
1201*8fb009dcSAndroid Build Coastguard Worker CBB cbb;
1202*8fb009dcSAndroid Build Coastguard Worker CBB_init_fixed(&cbb, out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES);
1203*8fb009dcSAndroid Build Coastguard Worker if (!dilithium_marshal_public_key(&cbb, &values->pub)) {
1204*8fb009dcSAndroid Build Coastguard Worker goto err;
1205*8fb009dcSAndroid Build Coastguard Worker }
1206*8fb009dcSAndroid Build Coastguard Worker
1207*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(priv->public_key_hash, sizeof(priv->public_key_hash),
1208*8fb009dcSAndroid Build Coastguard Worker out_encoded_public_key, DILITHIUM_PUBLIC_KEY_BYTES,
1209*8fb009dcSAndroid Build Coastguard Worker boringssl_shake256);
1210*8fb009dcSAndroid Build Coastguard Worker
1211*8fb009dcSAndroid Build Coastguard Worker ret = 1;
1212*8fb009dcSAndroid Build Coastguard Worker err:
1213*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(values);
1214*8fb009dcSAndroid Build Coastguard Worker return ret;
1215*8fb009dcSAndroid Build Coastguard Worker }
1216*8fb009dcSAndroid Build Coastguard Worker
DILITHIUM_public_from_private(struct DILITHIUM_public_key * out_public_key,const struct DILITHIUM_private_key * private_key)1217*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_public_from_private(
1218*8fb009dcSAndroid Build Coastguard Worker struct DILITHIUM_public_key *out_public_key,
1219*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_private_key *private_key) {
1220*8fb009dcSAndroid Build Coastguard Worker int ret = 0;
1221*8fb009dcSAndroid Build Coastguard Worker
1222*8fb009dcSAndroid Build Coastguard Worker // Intermediate values, allocated on the heap to allow use when there is a
1223*8fb009dcSAndroid Build Coastguard Worker // limited amount of stack.
1224*8fb009dcSAndroid Build Coastguard Worker struct values_st {
1225*8fb009dcSAndroid Build Coastguard Worker matrix a_ntt;
1226*8fb009dcSAndroid Build Coastguard Worker vectorl s1_ntt;
1227*8fb009dcSAndroid Build Coastguard Worker vectork t;
1228*8fb009dcSAndroid Build Coastguard Worker vectork t0;
1229*8fb009dcSAndroid Build Coastguard Worker };
1230*8fb009dcSAndroid Build Coastguard Worker struct values_st *values = OPENSSL_malloc(sizeof(*values));
1231*8fb009dcSAndroid Build Coastguard Worker if (values == NULL) {
1232*8fb009dcSAndroid Build Coastguard Worker goto err;
1233*8fb009dcSAndroid Build Coastguard Worker }
1234*8fb009dcSAndroid Build Coastguard Worker
1235*8fb009dcSAndroid Build Coastguard Worker const struct private_key *priv = private_key_from_external(private_key);
1236*8fb009dcSAndroid Build Coastguard Worker struct public_key *pub = public_key_from_external(out_public_key);
1237*8fb009dcSAndroid Build Coastguard Worker
1238*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(pub->rho, priv->rho, sizeof(pub->rho));
1239*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(pub->public_key_hash, priv->public_key_hash,
1240*8fb009dcSAndroid Build Coastguard Worker sizeof(pub->public_key_hash));
1241*8fb009dcSAndroid Build Coastguard Worker
1242*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&values->a_ntt, priv->rho);
1243*8fb009dcSAndroid Build Coastguard Worker
1244*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt));
1245*8fb009dcSAndroid Build Coastguard Worker vectorl_ntt(&values->s1_ntt);
1246*8fb009dcSAndroid Build Coastguard Worker
1247*8fb009dcSAndroid Build Coastguard Worker matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt);
1248*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->t);
1249*8fb009dcSAndroid Build Coastguard Worker vectork_add(&values->t, &values->t, &priv->s2);
1250*8fb009dcSAndroid Build Coastguard Worker
1251*8fb009dcSAndroid Build Coastguard Worker vectork_power2_round(&pub->t1, &values->t0, &values->t);
1252*8fb009dcSAndroid Build Coastguard Worker
1253*8fb009dcSAndroid Build Coastguard Worker ret = 1;
1254*8fb009dcSAndroid Build Coastguard Worker err:
1255*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(values);
1256*8fb009dcSAndroid Build Coastguard Worker return ret;
1257*8fb009dcSAndroid Build Coastguard Worker }
1258*8fb009dcSAndroid Build Coastguard Worker
1259*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 2 (`ML-DSA.Sign`). Returns 1 on success and 0 on failure.
dilithium_sign_with_randomizer(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],const struct DILITHIUM_private_key * private_key,const uint8_t * msg,size_t msg_len,const uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES])1260*8fb009dcSAndroid Build Coastguard Worker static int dilithium_sign_with_randomizer(
1261*8fb009dcSAndroid Build Coastguard Worker uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],
1262*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_private_key *private_key, const uint8_t *msg,
1263*8fb009dcSAndroid Build Coastguard Worker size_t msg_len,
1264*8fb009dcSAndroid Build Coastguard Worker const uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES]) {
1265*8fb009dcSAndroid Build Coastguard Worker int ret = 0;
1266*8fb009dcSAndroid Build Coastguard Worker
1267*8fb009dcSAndroid Build Coastguard Worker const struct private_key *priv = private_key_from_external(private_key);
1268*8fb009dcSAndroid Build Coastguard Worker
1269*8fb009dcSAndroid Build Coastguard Worker uint8_t mu[MU_BYTES];
1270*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
1271*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1272*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, priv->public_key_hash,
1273*8fb009dcSAndroid Build Coastguard Worker sizeof(priv->public_key_hash));
1274*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len);
1275*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES);
1276*8fb009dcSAndroid Build Coastguard Worker
1277*8fb009dcSAndroid Build Coastguard Worker uint8_t rho_prime[RHO_PRIME_BYTES];
1278*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1279*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, priv->k, sizeof(priv->k));
1280*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, randomizer,
1281*8fb009dcSAndroid Build Coastguard Worker DILITHIUM_SIGNATURE_RANDOMIZER_BYTES);
1282*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES);
1283*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, rho_prime, RHO_PRIME_BYTES);
1284*8fb009dcSAndroid Build Coastguard Worker
1285*8fb009dcSAndroid Build Coastguard Worker // Intermediate values, allocated on the heap to allow use when there is a
1286*8fb009dcSAndroid Build Coastguard Worker // limited amount of stack.
1287*8fb009dcSAndroid Build Coastguard Worker struct values_st {
1288*8fb009dcSAndroid Build Coastguard Worker struct signature sign;
1289*8fb009dcSAndroid Build Coastguard Worker vectorl s1_ntt;
1290*8fb009dcSAndroid Build Coastguard Worker vectork s2_ntt;
1291*8fb009dcSAndroid Build Coastguard Worker vectork t0_ntt;
1292*8fb009dcSAndroid Build Coastguard Worker matrix a_ntt;
1293*8fb009dcSAndroid Build Coastguard Worker vectorl y;
1294*8fb009dcSAndroid Build Coastguard Worker vectorl y_ntt;
1295*8fb009dcSAndroid Build Coastguard Worker vectork w;
1296*8fb009dcSAndroid Build Coastguard Worker vectork w1;
1297*8fb009dcSAndroid Build Coastguard Worker vectorl cs1;
1298*8fb009dcSAndroid Build Coastguard Worker vectork cs2;
1299*8fb009dcSAndroid Build Coastguard Worker vectork r0;
1300*8fb009dcSAndroid Build Coastguard Worker vectork ct0;
1301*8fb009dcSAndroid Build Coastguard Worker };
1302*8fb009dcSAndroid Build Coastguard Worker struct values_st *values = OPENSSL_malloc(sizeof(*values));
1303*8fb009dcSAndroid Build Coastguard Worker if (values == NULL) {
1304*8fb009dcSAndroid Build Coastguard Worker goto err;
1305*8fb009dcSAndroid Build Coastguard Worker }
1306*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt));
1307*8fb009dcSAndroid Build Coastguard Worker vectorl_ntt(&values->s1_ntt);
1308*8fb009dcSAndroid Build Coastguard Worker
1309*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->s2_ntt, &priv->s2, sizeof(values->s2_ntt));
1310*8fb009dcSAndroid Build Coastguard Worker vectork_ntt(&values->s2_ntt);
1311*8fb009dcSAndroid Build Coastguard Worker
1312*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->t0_ntt, &priv->t0, sizeof(values->t0_ntt));
1313*8fb009dcSAndroid Build Coastguard Worker vectork_ntt(&values->t0_ntt);
1314*8fb009dcSAndroid Build Coastguard Worker
1315*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&values->a_ntt, priv->rho);
1316*8fb009dcSAndroid Build Coastguard Worker
1317*8fb009dcSAndroid Build Coastguard Worker for (size_t kappa = 0;; kappa += L) {
1318*8fb009dcSAndroid Build Coastguard Worker // TODO(bbe): y only lives long enough to compute y_ntt.
1319*8fb009dcSAndroid Build Coastguard Worker // consider using another vectorl to save memory.
1320*8fb009dcSAndroid Build Coastguard Worker vectorl_expand_mask(&values->y, rho_prime, kappa);
1321*8fb009dcSAndroid Build Coastguard Worker
1322*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->y_ntt, &values->y, sizeof(values->y_ntt));
1323*8fb009dcSAndroid Build Coastguard Worker vectorl_ntt(&values->y_ntt);
1324*8fb009dcSAndroid Build Coastguard Worker
1325*8fb009dcSAndroid Build Coastguard Worker // TODO(bbe): w only lives long enough to compute y_ntt.
1326*8fb009dcSAndroid Build Coastguard Worker // consider using another vectork to save memory.
1327*8fb009dcSAndroid Build Coastguard Worker matrix_mult(&values->w, &values->a_ntt, &values->y_ntt);
1328*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->w);
1329*8fb009dcSAndroid Build Coastguard Worker
1330*8fb009dcSAndroid Build Coastguard Worker vectork_high_bits(&values->w1, &values->w);
1331*8fb009dcSAndroid Build Coastguard Worker uint8_t w1_encoded[128 * K];
1332*8fb009dcSAndroid Build Coastguard Worker w1_encode(w1_encoded, &values->w1);
1333*8fb009dcSAndroid Build Coastguard Worker
1334*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1335*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES);
1336*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K);
1337*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde,
1338*8fb009dcSAndroid Build Coastguard Worker 2 * LAMBDA_BYTES);
1339*8fb009dcSAndroid Build Coastguard Worker
1340*8fb009dcSAndroid Build Coastguard Worker scalar c_ntt;
1341*8fb009dcSAndroid Build Coastguard Worker scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32);
1342*8fb009dcSAndroid Build Coastguard Worker scalar_ntt(&c_ntt);
1343*8fb009dcSAndroid Build Coastguard Worker
1344*8fb009dcSAndroid Build Coastguard Worker vectorl_mult_scalar(&values->cs1, &values->s1_ntt, &c_ntt);
1345*8fb009dcSAndroid Build Coastguard Worker vectorl_inverse_ntt(&values->cs1);
1346*8fb009dcSAndroid Build Coastguard Worker vectork_mult_scalar(&values->cs2, &values->s2_ntt, &c_ntt);
1347*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->cs2);
1348*8fb009dcSAndroid Build Coastguard Worker
1349*8fb009dcSAndroid Build Coastguard Worker vectorl_add(&values->sign.z, &values->y, &values->cs1);
1350*8fb009dcSAndroid Build Coastguard Worker
1351*8fb009dcSAndroid Build Coastguard Worker vectork_sub(&values->r0, &values->w, &values->cs2);
1352*8fb009dcSAndroid Build Coastguard Worker vectork_low_bits(&values->r0, &values->r0);
1353*8fb009dcSAndroid Build Coastguard Worker
1354*8fb009dcSAndroid Build Coastguard Worker // Leaking the fact that a signature was rejected is fine as the next
1355*8fb009dcSAndroid Build Coastguard Worker // attempt at a signature will be (indistinguishable from) independent of
1356*8fb009dcSAndroid Build Coastguard Worker // this one. Note, however, that we additionally leak which of the two
1357*8fb009dcSAndroid Build Coastguard Worker // branches rejected the signature. Section 5.5 of
1358*8fb009dcSAndroid Build Coastguard Worker // https://pq-crystals.org/dilithium/data/dilithium-specification-round3.pdf
1359*8fb009dcSAndroid Build Coastguard Worker // describes this leak as OK. Note we leak less than what is described by
1360*8fb009dcSAndroid Build Coastguard Worker // the paper; we do not reveal which coefficient violated the bound, and we
1361*8fb009dcSAndroid Build Coastguard Worker // hide which of the |z_max| or |r0_max| bound failed. See also
1362*8fb009dcSAndroid Build Coastguard Worker // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/2bbab0fa_d241d35a/
1363*8fb009dcSAndroid Build Coastguard Worker uint32_t z_max = vectorl_max(&values->sign.z);
1364*8fb009dcSAndroid Build Coastguard Worker uint32_t r0_max = vectork_max_signed(&values->r0);
1365*8fb009dcSAndroid Build Coastguard Worker if (constant_time_declassify_w(
1366*8fb009dcSAndroid Build Coastguard Worker constant_time_ge_w(z_max, kGamma1 - BETA) |
1367*8fb009dcSAndroid Build Coastguard Worker constant_time_ge_w(r0_max, kGamma2 - BETA))) {
1368*8fb009dcSAndroid Build Coastguard Worker continue;
1369*8fb009dcSAndroid Build Coastguard Worker }
1370*8fb009dcSAndroid Build Coastguard Worker
1371*8fb009dcSAndroid Build Coastguard Worker vectork_mult_scalar(&values->ct0, &values->t0_ntt, &c_ntt);
1372*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->ct0);
1373*8fb009dcSAndroid Build Coastguard Worker vectork_make_hint(&values->sign.h, &values->ct0, &values->cs2, &values->w);
1374*8fb009dcSAndroid Build Coastguard Worker
1375*8fb009dcSAndroid Build Coastguard Worker // See above.
1376*8fb009dcSAndroid Build Coastguard Worker uint32_t ct0_max = vectork_max(&values->ct0);
1377*8fb009dcSAndroid Build Coastguard Worker size_t h_ones = vectork_count_ones(&values->sign.h);
1378*8fb009dcSAndroid Build Coastguard Worker if (constant_time_declassify_w(constant_time_ge_w(ct0_max, kGamma2) |
1379*8fb009dcSAndroid Build Coastguard Worker constant_time_lt_w(OMEGA, h_ones))) {
1380*8fb009dcSAndroid Build Coastguard Worker continue;
1381*8fb009dcSAndroid Build Coastguard Worker }
1382*8fb009dcSAndroid Build Coastguard Worker
1383*8fb009dcSAndroid Build Coastguard Worker // Although computed with the private key, the signature is public.
1384*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(values->sign.c_tilde, sizeof(values->sign.c_tilde));
1385*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(&values->sign.z, sizeof(values->sign.z));
1386*8fb009dcSAndroid Build Coastguard Worker CONSTTIME_DECLASSIFY(&values->sign.h, sizeof(values->sign.h));
1387*8fb009dcSAndroid Build Coastguard Worker
1388*8fb009dcSAndroid Build Coastguard Worker CBB cbb;
1389*8fb009dcSAndroid Build Coastguard Worker CBB_init_fixed(&cbb, out_encoded_signature, DILITHIUM_SIGNATURE_BYTES);
1390*8fb009dcSAndroid Build Coastguard Worker if (!dilithium_marshal_signature(&cbb, &values->sign)) {
1391*8fb009dcSAndroid Build Coastguard Worker goto err;
1392*8fb009dcSAndroid Build Coastguard Worker }
1393*8fb009dcSAndroid Build Coastguard Worker
1394*8fb009dcSAndroid Build Coastguard Worker BSSL_CHECK(CBB_len(&cbb) == DILITHIUM_SIGNATURE_BYTES);
1395*8fb009dcSAndroid Build Coastguard Worker ret = 1;
1396*8fb009dcSAndroid Build Coastguard Worker break;
1397*8fb009dcSAndroid Build Coastguard Worker }
1398*8fb009dcSAndroid Build Coastguard Worker
1399*8fb009dcSAndroid Build Coastguard Worker err:
1400*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(values);
1401*8fb009dcSAndroid Build Coastguard Worker return ret;
1402*8fb009dcSAndroid Build Coastguard Worker }
1403*8fb009dcSAndroid Build Coastguard Worker
1404*8fb009dcSAndroid Build Coastguard Worker // Dilithium signature in deterministic mode. Returns 1 on success and 0 on
1405*8fb009dcSAndroid Build Coastguard Worker // failure.
DILITHIUM_sign_deterministic(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],const struct DILITHIUM_private_key * private_key,const uint8_t * msg,size_t msg_len)1406*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_sign_deterministic(
1407*8fb009dcSAndroid Build Coastguard Worker uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],
1408*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_private_key *private_key, const uint8_t *msg,
1409*8fb009dcSAndroid Build Coastguard Worker size_t msg_len) {
1410*8fb009dcSAndroid Build Coastguard Worker uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES];
1411*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memset(randomizer, 0, sizeof(randomizer));
1412*8fb009dcSAndroid Build Coastguard Worker return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg,
1413*8fb009dcSAndroid Build Coastguard Worker msg_len, randomizer);
1414*8fb009dcSAndroid Build Coastguard Worker }
1415*8fb009dcSAndroid Build Coastguard Worker
1416*8fb009dcSAndroid Build Coastguard Worker // Dilithium signature in randomized mode, filling the random bytes with
1417*8fb009dcSAndroid Build Coastguard Worker // |RAND_bytes|. Returns 1 on success and 0 on failure.
DILITHIUM_sign(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],const struct DILITHIUM_private_key * private_key,const uint8_t * msg,size_t msg_len)1418*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_sign(uint8_t out_encoded_signature[DILITHIUM_SIGNATURE_BYTES],
1419*8fb009dcSAndroid Build Coastguard Worker const struct DILITHIUM_private_key *private_key,
1420*8fb009dcSAndroid Build Coastguard Worker const uint8_t *msg, size_t msg_len) {
1421*8fb009dcSAndroid Build Coastguard Worker uint8_t randomizer[DILITHIUM_SIGNATURE_RANDOMIZER_BYTES];
1422*8fb009dcSAndroid Build Coastguard Worker RAND_bytes(randomizer, sizeof(randomizer));
1423*8fb009dcSAndroid Build Coastguard Worker return dilithium_sign_with_randomizer(out_encoded_signature, private_key, msg,
1424*8fb009dcSAndroid Build Coastguard Worker msg_len, randomizer);
1425*8fb009dcSAndroid Build Coastguard Worker }
1426*8fb009dcSAndroid Build Coastguard Worker
1427*8fb009dcSAndroid Build Coastguard Worker // FIPS 204, Algorithm 3 (`ML-DSA.Verify`).
DILITHIUM_verify(const struct DILITHIUM_public_key * public_key,const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES],const uint8_t * msg,size_t msg_len)1428*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_verify(const struct DILITHIUM_public_key *public_key,
1429*8fb009dcSAndroid Build Coastguard Worker const uint8_t encoded_signature[DILITHIUM_SIGNATURE_BYTES],
1430*8fb009dcSAndroid Build Coastguard Worker const uint8_t *msg, size_t msg_len) {
1431*8fb009dcSAndroid Build Coastguard Worker int ret = 0;
1432*8fb009dcSAndroid Build Coastguard Worker
1433*8fb009dcSAndroid Build Coastguard Worker // Intermediate values, allocated on the heap to allow use when there is a
1434*8fb009dcSAndroid Build Coastguard Worker // limited amount of stack.
1435*8fb009dcSAndroid Build Coastguard Worker struct values_st {
1436*8fb009dcSAndroid Build Coastguard Worker struct signature sign;
1437*8fb009dcSAndroid Build Coastguard Worker matrix a_ntt;
1438*8fb009dcSAndroid Build Coastguard Worker vectorl z_ntt;
1439*8fb009dcSAndroid Build Coastguard Worker vectork az_ntt;
1440*8fb009dcSAndroid Build Coastguard Worker vectork t1_ntt;
1441*8fb009dcSAndroid Build Coastguard Worker vectork ct1_ntt;
1442*8fb009dcSAndroid Build Coastguard Worker vectork w_approx;
1443*8fb009dcSAndroid Build Coastguard Worker vectork w1;
1444*8fb009dcSAndroid Build Coastguard Worker };
1445*8fb009dcSAndroid Build Coastguard Worker struct values_st *values = OPENSSL_malloc(sizeof(*values));
1446*8fb009dcSAndroid Build Coastguard Worker if (values == NULL) {
1447*8fb009dcSAndroid Build Coastguard Worker goto err;
1448*8fb009dcSAndroid Build Coastguard Worker }
1449*8fb009dcSAndroid Build Coastguard Worker
1450*8fb009dcSAndroid Build Coastguard Worker const struct public_key *pub = public_key_from_external(public_key);
1451*8fb009dcSAndroid Build Coastguard Worker
1452*8fb009dcSAndroid Build Coastguard Worker CBS cbs;
1453*8fb009dcSAndroid Build Coastguard Worker CBS_init(&cbs, encoded_signature, DILITHIUM_SIGNATURE_BYTES);
1454*8fb009dcSAndroid Build Coastguard Worker if (!dilithium_parse_signature(&values->sign, &cbs)) {
1455*8fb009dcSAndroid Build Coastguard Worker goto err;
1456*8fb009dcSAndroid Build Coastguard Worker }
1457*8fb009dcSAndroid Build Coastguard Worker
1458*8fb009dcSAndroid Build Coastguard Worker matrix_expand(&values->a_ntt, pub->rho);
1459*8fb009dcSAndroid Build Coastguard Worker
1460*8fb009dcSAndroid Build Coastguard Worker uint8_t mu[MU_BYTES];
1461*8fb009dcSAndroid Build Coastguard Worker struct BORINGSSL_keccak_st keccak_ctx;
1462*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1463*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, pub->public_key_hash,
1464*8fb009dcSAndroid Build Coastguard Worker sizeof(pub->public_key_hash));
1465*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len);
1466*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, mu, MU_BYTES);
1467*8fb009dcSAndroid Build Coastguard Worker
1468*8fb009dcSAndroid Build Coastguard Worker scalar c_ntt;
1469*8fb009dcSAndroid Build Coastguard Worker scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde, 32);
1470*8fb009dcSAndroid Build Coastguard Worker scalar_ntt(&c_ntt);
1471*8fb009dcSAndroid Build Coastguard Worker
1472*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcpy(&values->z_ntt, &values->sign.z, sizeof(values->z_ntt));
1473*8fb009dcSAndroid Build Coastguard Worker vectorl_ntt(&values->z_ntt);
1474*8fb009dcSAndroid Build Coastguard Worker
1475*8fb009dcSAndroid Build Coastguard Worker matrix_mult(&values->az_ntt, &values->a_ntt, &values->z_ntt);
1476*8fb009dcSAndroid Build Coastguard Worker
1477*8fb009dcSAndroid Build Coastguard Worker vectork_scale_power2_round(&values->t1_ntt, &pub->t1);
1478*8fb009dcSAndroid Build Coastguard Worker vectork_ntt(&values->t1_ntt);
1479*8fb009dcSAndroid Build Coastguard Worker
1480*8fb009dcSAndroid Build Coastguard Worker vectork_mult_scalar(&values->ct1_ntt, &values->t1_ntt, &c_ntt);
1481*8fb009dcSAndroid Build Coastguard Worker
1482*8fb009dcSAndroid Build Coastguard Worker vectork_sub(&values->w_approx, &values->az_ntt, &values->ct1_ntt);
1483*8fb009dcSAndroid Build Coastguard Worker vectork_inverse_ntt(&values->w_approx);
1484*8fb009dcSAndroid Build Coastguard Worker
1485*8fb009dcSAndroid Build Coastguard Worker vectork_use_hint_vartime(&values->w1, &values->sign.h, &values->w_approx);
1486*8fb009dcSAndroid Build Coastguard Worker uint8_t w1_encoded[128 * K];
1487*8fb009dcSAndroid Build Coastguard Worker w1_encode(w1_encoded, &values->w1);
1488*8fb009dcSAndroid Build Coastguard Worker
1489*8fb009dcSAndroid Build Coastguard Worker uint8_t c_tilde[2 * LAMBDA_BYTES];
1490*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1491*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, mu, MU_BYTES);
1492*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, 128 * K);
1493*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * LAMBDA_BYTES);
1494*8fb009dcSAndroid Build Coastguard Worker
1495*8fb009dcSAndroid Build Coastguard Worker uint32_t z_max = vectorl_max(&values->sign.z);
1496*8fb009dcSAndroid Build Coastguard Worker size_t h_ones = vectork_count_ones(&values->sign.h);
1497*8fb009dcSAndroid Build Coastguard Worker if (z_max < kGamma1 - BETA && h_ones <= OMEGA &&
1498*8fb009dcSAndroid Build Coastguard Worker OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * LAMBDA_BYTES) == 0) {
1499*8fb009dcSAndroid Build Coastguard Worker ret = 1;
1500*8fb009dcSAndroid Build Coastguard Worker }
1501*8fb009dcSAndroid Build Coastguard Worker
1502*8fb009dcSAndroid Build Coastguard Worker err:
1503*8fb009dcSAndroid Build Coastguard Worker OPENSSL_free(values);
1504*8fb009dcSAndroid Build Coastguard Worker return ret;
1505*8fb009dcSAndroid Build Coastguard Worker }
1506*8fb009dcSAndroid Build Coastguard Worker
1507*8fb009dcSAndroid Build Coastguard Worker /* Serialization of keys. */
1508*8fb009dcSAndroid Build Coastguard Worker
DILITHIUM_marshal_public_key(CBB * out,const struct DILITHIUM_public_key * public_key)1509*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_marshal_public_key(
1510*8fb009dcSAndroid Build Coastguard Worker CBB *out, const struct DILITHIUM_public_key *public_key) {
1511*8fb009dcSAndroid Build Coastguard Worker return dilithium_marshal_public_key(out,
1512*8fb009dcSAndroid Build Coastguard Worker public_key_from_external(public_key));
1513*8fb009dcSAndroid Build Coastguard Worker }
1514*8fb009dcSAndroid Build Coastguard Worker
DILITHIUM_parse_public_key(struct DILITHIUM_public_key * public_key,CBS * in)1515*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_parse_public_key(struct DILITHIUM_public_key *public_key,
1516*8fb009dcSAndroid Build Coastguard Worker CBS *in) {
1517*8fb009dcSAndroid Build Coastguard Worker struct public_key *pub = public_key_from_external(public_key);
1518*8fb009dcSAndroid Build Coastguard Worker CBS orig_in = *in;
1519*8fb009dcSAndroid Build Coastguard Worker if (!dilithium_parse_public_key(pub, in) || CBS_len(in) != 0) {
1520*8fb009dcSAndroid Build Coastguard Worker return 0;
1521*8fb009dcSAndroid Build Coastguard Worker }
1522*8fb009dcSAndroid Build Coastguard Worker
1523*8fb009dcSAndroid Build Coastguard Worker // Compute pre-cached values.
1524*8fb009dcSAndroid Build Coastguard Worker BORINGSSL_keccak(pub->public_key_hash, sizeof(pub->public_key_hash),
1525*8fb009dcSAndroid Build Coastguard Worker CBS_data(&orig_in), CBS_len(&orig_in), boringssl_shake256);
1526*8fb009dcSAndroid Build Coastguard Worker return 1;
1527*8fb009dcSAndroid Build Coastguard Worker }
1528*8fb009dcSAndroid Build Coastguard Worker
DILITHIUM_marshal_private_key(CBB * out,const struct DILITHIUM_private_key * private_key)1529*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_marshal_private_key(
1530*8fb009dcSAndroid Build Coastguard Worker CBB *out, const struct DILITHIUM_private_key *private_key) {
1531*8fb009dcSAndroid Build Coastguard Worker return dilithium_marshal_private_key(out,
1532*8fb009dcSAndroid Build Coastguard Worker private_key_from_external(private_key));
1533*8fb009dcSAndroid Build Coastguard Worker }
1534*8fb009dcSAndroid Build Coastguard Worker
DILITHIUM_parse_private_key(struct DILITHIUM_private_key * private_key,CBS * in)1535*8fb009dcSAndroid Build Coastguard Worker int DILITHIUM_parse_private_key(struct DILITHIUM_private_key *private_key,
1536*8fb009dcSAndroid Build Coastguard Worker CBS *in) {
1537*8fb009dcSAndroid Build Coastguard Worker struct private_key *priv = private_key_from_external(private_key);
1538*8fb009dcSAndroid Build Coastguard Worker return dilithium_parse_private_key(priv, in) && CBS_len(in) == 0;
1539*8fb009dcSAndroid Build Coastguard Worker }
1540