Coverage Report

Created: 2025-11-17 06:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/fipsmodule/mldsa/mldsa.cc.inc
Line
Count
Source
1
// Copyright 2014 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/base.h>
16
17
#include <memory>
18
19
#include <assert.h>
20
#include <stdlib.h>
21
22
#include <openssl/bytestring.h>
23
#include <openssl/mem.h>
24
#include <openssl/rand.h>
25
26
#include "../../internal.h"
27
#include "../../mem_internal.h"
28
#include "../bcm_interface.h"
29
#include "../keccak/internal.h"
30
31
namespace mldsa {
32
namespace {
33
34
namespace fips {
35
void ensure_keygen_self_test();
36
void ensure_sign_self_test();
37
void ensure_verify_self_test();
38
}  // namespace fips
39
40
constexpr int kDegree = 256;
41
constexpr int kRhoBytes = 32;
42
constexpr int kSigmaBytes = 64;
43
constexpr int kKBytes = 32;
44
constexpr int kTrBytes = 64;
45
constexpr int kMuBytes = 64;
46
constexpr int kRhoPrimeBytes = 64;
47
48
// 2^23 - 2^13 + 1
49
constexpr uint32_t kPrime = 8380417;
50
// Inverse of -kPrime modulo 2^32
51
constexpr uint32_t kPrimeNegInverse = 4236238847;
52
constexpr int kDroppedBits = 13;
53
constexpr uint32_t kHalfPrime = (kPrime - 1) / 2;
54
// 256^-1 mod kPrime, in Montgomery form.
55
constexpr uint32_t kInverseDegreeMontgomery = 41978;
56
57
// Constants that vary depending on ML-DSA size.
58
//
59
// These are implemented as templates which take the K parameter to distinguish
60
// the ML-DSA sizes.
61
62
template <int K>
63
0
constexpr size_t public_key_bytes() {
64
0
  if constexpr (K == 6) {
65
0
    return MLDSA65_PUBLIC_KEY_BYTES;
66
0
  } else if constexpr (K == 8) {
67
0
    return MLDSA87_PUBLIC_KEY_BYTES;
68
0
  } else if constexpr (K == 4) {
69
0
    return MLDSA44_PUBLIC_KEY_BYTES;
70
0
  }
71
0
}
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::public_key_bytes<6>()
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::public_key_bytes<8>()
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::public_key_bytes<4>()
72
73
template <int K>
74
0
constexpr size_t signature_bytes() {
75
0
  if constexpr (K == 6) {
76
0
    return MLDSA65_SIGNATURE_BYTES;
77
0
  } else if constexpr (K == 8) {
78
0
    return MLDSA87_SIGNATURE_BYTES;
79
0
  } else if constexpr (K == 4) {
80
0
    return MLDSA44_SIGNATURE_BYTES;
81
0
  }
82
0
}
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::signature_bytes<6>()
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::signature_bytes<8>()
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::signature_bytes<4>()
83
84
template <int K>
85
0
constexpr int tau() {
86
0
  if constexpr (K == 6) {
87
0
    return 49;
88
0
  } else if constexpr (K == 8) {
89
0
    return 60;
90
0
  } else if constexpr (K == 4) {
91
0
    return 39;
92
0
  }
93
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::tau<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::tau<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::tau<4>()
94
95
template <int K>
96
0
constexpr int lambda_bytes() {
97
0
  if constexpr (K == 6) {
98
0
    return 192 / 8;
99
0
  } else if constexpr (K == 8) {
100
0
    return 256 / 8;
101
0
  } else if constexpr (K == 4) {
102
0
    return 128 / 8;
103
0
  }
104
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::lambda_bytes<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::lambda_bytes<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::lambda_bytes<4>()
105
106
template <int K>
107
0
constexpr int gamma1_bits() {
108
0
  if constexpr (K == 6 || K == 8) {
109
0
    return 19;
110
0
  } else if constexpr (K == 4) {
111
0
    return 17;
112
0
  }
113
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1_bits<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1_bits<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1_bits<4>()
114
115
template <int K>
116
0
constexpr int gamma1() {
117
0
  return 1 << gamma1_bits<K>();
118
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::gamma1<4>()
119
120
template <int K>
121
0
constexpr int scalar_le_gamma1_bytes() {
122
0
  return ((gamma1_bits<K>() + 1) * kDegree) / 8;
123
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::scalar_le_gamma1_bytes<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::scalar_le_gamma1_bytes<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::scalar_le_gamma1_bytes<4>()
124
125
template <int K>
126
0
constexpr uint32_t w1_coeffs_bits() {
127
0
  if constexpr (K == 6 || K == 8) {
128
0
    return 4;
129
0
  } else if constexpr (K == 4) {
130
0
    return 6;
131
0
  }
132
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_coeffs_bits<6>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_coeffs_bits<8>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_coeffs_bits<4>()
133
134
template <int K>
135
0
constexpr uint32_t w1_scalar_bytes() {
136
0
  return (w1_coeffs_bits<K>() * kDegree) / 8;
137
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_scalar_bytes<6>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_scalar_bytes<8>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_scalar_bytes<4>()
138
139
template <int K>
140
0
constexpr uint32_t w1_bytes() {
141
0
  return w1_scalar_bytes<K>() * K;
142
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_bytes<6>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_bytes<8>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::w1_bytes<4>()
143
144
template <int K>
145
0
constexpr uint32_t prime_minus_one_over_gamma2() {
146
0
  if constexpr (K == 6 || K == 8) {
147
0
    return 32;
148
0
  } else if constexpr (K == 4) {
149
0
    return 88;
150
0
  }
151
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::prime_minus_one_over_gamma2<6>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::prime_minus_one_over_gamma2<8>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::prime_minus_one_over_gamma2<4>()
152
153
template <int K>
154
0
constexpr uint32_t gamma2() {
155
0
  return (kPrime - 1) / prime_minus_one_over_gamma2<K>();
156
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::gamma2<6>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::gamma2<8>()
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::gamma2<4>()
157
158
template <int K>
159
0
constexpr int beta() {
160
0
  if constexpr (K == 6) {
161
0
    return 196;
162
0
  } else if constexpr (K == 8) {
163
0
    return 120;
164
0
  } else if constexpr (K == 4) {
165
0
    return 78;
166
0
  }
167
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::beta<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::beta<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::beta<4>()
168
169
template <int K>
170
0
constexpr int omega() {
171
0
  if constexpr (K == 6) {
172
0
    return 55;
173
0
  } else if constexpr (K == 8) {
174
0
    return 75;
175
0
  } else if constexpr (K == 4) {
176
0
    return 80;
177
0
  }
178
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::omega<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::omega<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::omega<4>()
179
180
template <int K>
181
0
constexpr int eta() {
182
0
  if constexpr (K == 6) {
183
0
    return 4;
184
0
  } else if constexpr (K == 8 || K == 4) {
185
0
    return 2;
186
0
  }
187
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::eta<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::eta<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::eta<4>()
188
189
template <int K>
190
0
constexpr int plus_minus_eta_bitlen() {
191
0
  if constexpr (K == 6) {
192
0
    return 4;
193
0
  } else if constexpr (K == 8 || K == 4) {
194
0
    return 3;
195
0
  }
196
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::plus_minus_eta_bitlen<6>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::plus_minus_eta_bitlen<8>()
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::plus_minus_eta_bitlen<4>()
197
198
// Fundamental types.
199
200
struct scalar {
201
  uint32_t c[kDegree];
202
};
203
204
template <int K>
205
struct vector {
206
  scalar v[K];
207
};
208
209
template <int K, int L>
210
struct matrix {
211
  scalar v[K][L];
212
};
213
214
/* Arithmetic */
215
216
// This bit of Python will be referenced in some of the following comments:
217
//
218
// q = 8380417
219
// # Inverse of -q modulo 2^32
220
// q_neg_inverse = 4236238847
221
// # 2^64 modulo q
222
// montgomery_square = 2365951
223
//
224
// def bitreverse(i):
225
//     ret = 0
226
//     for n in range(8):
227
//         bit = i & 1
228
//         ret <<= 1
229
//         ret |= bit
230
//         i >>= 1
231
//     return ret
232
//
233
// def montgomery_reduce(x):
234
//     a = (x * q_neg_inverse) % 2**32
235
//     b = x + a * q
236
//     assert b & 0xFFFF_FFFF == 0
237
//     c = b >> 32
238
//     assert c < q
239
//     return c
240
//
241
// def montgomery_transform(x):
242
//     return montgomery_reduce(x * montgomery_square)
243
244
// kNTTRootsMontgomery = [
245
//   montgomery_transform(pow(1753, bitreverse(i), q)) for i in range(256)
246
// ]
247
static const uint32_t kNTTRootsMontgomery[256] = {
248
    4193792, 25847,   5771523, 7861508, 237124,  7602457, 7504169, 466468,
249
    1826347, 2353451, 8021166, 6288512, 3119733, 5495562, 3111497, 2680103,
250
    2725464, 1024112, 7300517, 3585928, 7830929, 7260833, 2619752, 6271868,
251
    6262231, 4520680, 6980856, 5102745, 1757237, 8360995, 4010497, 280005,
252
    2706023, 95776,   3077325, 3530437, 6718724, 4788269, 5842901, 3915439,
253
    4519302, 5336701, 3574422, 5512770, 3539968, 8079950, 2348700, 7841118,
254
    6681150, 6736599, 3505694, 4558682, 3507263, 6239768, 6779997, 3699596,
255
    811944,  531354,  954230,  3881043, 3900724, 5823537, 2071892, 5582638,
256
    4450022, 6851714, 4702672, 5339162, 6927966, 3475950, 2176455, 6795196,
257
    7122806, 1939314, 4296819, 7380215, 5190273, 5223087, 4747489, 126922,
258
    3412210, 7396998, 2147896, 2715295, 5412772, 4686924, 7969390, 5903370,
259
    7709315, 7151892, 8357436, 7072248, 7998430, 1349076, 1852771, 6949987,
260
    5037034, 264944,  508951,  3097992, 44288,   7280319, 904516,  3958618,
261
    4656075, 8371839, 1653064, 5130689, 2389356, 8169440, 759969,  7063561,
262
    189548,  4827145, 3159746, 6529015, 5971092, 8202977, 1315589, 1341330,
263
    1285669, 6795489, 7567685, 6940675, 5361315, 4499357, 4751448, 3839961,
264
    2091667, 3407706, 2316500, 3817976, 5037939, 2244091, 5933984, 4817955,
265
    266997,  2434439, 7144689, 3513181, 4860065, 4621053, 7183191, 5187039,
266
    900702,  1859098, 909542,  819034,  495491,  6767243, 8337157, 7857917,
267
    7725090, 5257975, 2031748, 3207046, 4823422, 7855319, 7611795, 4784579,
268
    342297,  286988,  5942594, 4108315, 3437287, 5038140, 1735879, 203044,
269
    2842341, 2691481, 5790267, 1265009, 4055324, 1247620, 2486353, 1595974,
270
    4613401, 1250494, 2635921, 4832145, 5386378, 1869119, 1903435, 7329447,
271
    7047359, 1237275, 5062207, 6950192, 7929317, 1312455, 3306115, 6417775,
272
    7100756, 1917081, 5834105, 7005614, 1500165, 777191,  2235880, 3406031,
273
    7838005, 5548557, 6709241, 6533464, 5796124, 4656147, 594136,  4603424,
274
    6366809, 2432395, 2454455, 8215696, 1957272, 3369112, 185531,  7173032,
275
    5196991, 162844,  1616392, 3014001, 810149,  1652634, 4686184, 6581310,
276
    5341501, 3523897, 3866901, 269760,  2213111, 7404533, 1717735, 472078,
277
    7953734, 1723600, 6577327, 1910376, 6712985, 7276084, 8119771, 4546524,
278
    5441381, 6144432, 7959518, 6094090, 183443,  7403526, 1612842, 4834730,
279
    7826001, 3919660, 8332111, 7018208, 3937738, 1400424, 7534263, 1976782};
280
281
// Reduces x mod kPrime in constant time, where 0 <= x < 2*kPrime.
282
0
uint32_t reduce_once(uint32_t x) {
283
0
  declassify_assert(x < 2 * kPrime);
284
  // return x < kPrime ? x : x - kPrime;
285
0
  const uint32_t subtracted = x - kPrime;
286
0
  uint32_t mask = 0u - (subtracted >> 31);
287
  // Although this is a constant-time select, we omit a value barrier here.
288
  // Value barriers impede auto-vectorization (likely because it forces the
289
  // value to transit through a general-purpose register). This is a difference
290
  // of 1.4x to 1.5x in signing performance.
291
  //
292
  // We usually add value barriers to selects because Clang turns consecutive
293
  // selects with the same condition into a branch instead of CMOV/CSEL. This
294
  // condition does not occur in ML-DSA, so omitting it seems to be generally
295
  // safe. However, see |coefficient_from_nibble|.
296
0
  return (mask & x) | (~mask & subtracted);
297
0
}
298
299
// Returns the absolute value in constant time, interpreting the high bit as a
300
// sign bit.
301
0
uint32_t abs_signed(uint32_t x) {
302
  // return is_negative(x) ? -x : x;
303
0
  uint32_t mask = 0u - (x >> 31);
304
0
  return constant_time_select_32(mask, 0u - x, x);
305
0
}
306
307
// Returns the absolute value modulo kPrime.
308
0
uint32_t abs_mod_prime(uint32_t x) {
309
0
  declassify_assert(x < kPrime);
310
  // return x <= kHalfPrime ? x : kPrime - x;
311
0
  uint32_t mask = x - kHalfPrime - 1;
312
0
  mask = 0u - (mask >> 31);
313
0
  return constant_time_select_32(mask, x, kPrime - x);
314
0
}
315
316
// Returns the maximum of two values in constant time. Each value must be less
317
// than kPrime.
318
0
uint32_t maximum_reduced(uint32_t x, uint32_t y) {
319
0
  declassify_assert(x < kPrime);
320
0
  declassify_assert(y < kPrime);
321
  // return x < y ? y : x;
322
0
  uint32_t mask = x - y;
323
0
  mask = 0u - (mask >> 31);
324
0
  return constant_time_select_32(mask, y, x);
325
0
}
326
327
0
uint32_t mod_sub(uint32_t a, uint32_t b) {
328
0
  declassify_assert(a < kPrime);
329
0
  declassify_assert(b < kPrime);
330
0
  uint32_t r = a - b;
331
  // return r < 0 ? r + kPrime : r;
332
0
  uint32_t mask = 0u - (r >> 31);
333
  // See |reduce_once| for which this does not have a value barrier.
334
0
  return (mask & (r + kPrime)) | (~mask & r);
335
0
}
336
337
0
void scalar_add(scalar *out, const scalar *lhs, const scalar *rhs) {
338
0
  for (int i = 0; i < kDegree; i++) {
339
0
    out->c[i] = reduce_once(lhs->c[i] + rhs->c[i]);
340
0
  }
341
0
}
342
343
0
void scalar_sub(scalar *out, const scalar *lhs, const scalar *rhs) {
344
0
  for (int i = 0; i < kDegree; i++) {
345
0
    out->c[i] = mod_sub(lhs->c[i], rhs->c[i]);
346
0
  }
347
0
}
348
349
0
uint32_t reduce_montgomery(uint64_t x) {
350
0
  declassify_assert(x <= ((uint64_t)kPrime << 32));
351
0
  uint64_t a = (uint32_t)x * kPrimeNegInverse;
352
0
  uint64_t b = x + a * kPrime;
353
0
  declassify_assert((b & 0xffffffff) == 0);
354
0
  uint32_t c = b >> 32;
355
0
  return reduce_once(c);
356
0
}
357
358
// Multiply two scalars in the number theoretically transformed state.
359
0
void scalar_mult(scalar *out, const scalar *lhs, const scalar *rhs) {
360
0
  for (int i = 0; i < kDegree; i++) {
361
0
    out->c[i] = reduce_montgomery((uint64_t)lhs->c[i] * (uint64_t)rhs->c[i]);
362
0
  }
363
0
}
364
365
// In place number theoretic transform of a given scalar.
366
//
367
// FIPS 204, Algorithm 41 (`NTT`).
368
0
static void scalar_ntt(scalar *s) {
369
  // Step: 1, 2, 4, 8, ..., 128
370
  // Offset: 128, 64, 32, 16, ..., 1
371
0
  int offset = kDegree;
372
0
  for (int step = 1; step < kDegree; step <<= 1) {
373
0
    offset >>= 1;
374
0
    int k = 0;
375
0
    for (int i = 0; i < step; i++) {
376
0
      assert(k == 2 * offset * i);
377
0
      const uint32_t step_root = kNTTRootsMontgomery[step + i];
378
0
      for (int j = k; j < k + offset; j++) {
379
0
        uint32_t even = s->c[j];
380
        // |reduce_montgomery| works on values up to kPrime*R and R > 2*kPrime.
381
        // |step_root| < kPrime because it's static data. |s->c[...]| is <
382
        // kPrime by the invariants of that struct.
383
0
        uint32_t odd =
384
0
            reduce_montgomery((uint64_t)step_root * (uint64_t)s->c[j + offset]);
385
0
        s->c[j] = reduce_once(odd + even);
386
0
        s->c[j + offset] = mod_sub(even, odd);
387
0
      }
388
0
      k += 2 * offset;
389
0
    }
390
0
  }
391
0
}
392
393
// In place inverse number theoretic transform of a given scalar.
394
//
395
// FIPS 204, Algorithm 42 (`NTT^-1`).
396
0
void scalar_inverse_ntt(scalar *s) {
397
  // Step: 128, 64, 32, 16, ..., 1
398
  // Offset: 1, 2, 4, 8, ..., 128
399
0
  int step = kDegree;
400
0
  for (int offset = 1; offset < kDegree; offset <<= 1) {
401
0
    step >>= 1;
402
0
    int k = 0;
403
0
    for (int i = 0; i < step; i++) {
404
0
      assert(k == 2 * offset * i);
405
0
      const uint32_t step_root =
406
0
          kPrime - kNTTRootsMontgomery[step + (step - 1 - i)];
407
0
      for (int j = k; j < k + offset; j++) {
408
0
        uint32_t even = s->c[j];
409
0
        uint32_t odd = s->c[j + offset];
410
0
        s->c[j] = reduce_once(odd + even);
411
412
        // |reduce_montgomery| works on values up to kPrime*R and R > 2*kPrime.
413
        // kPrime + even < 2*kPrime because |even| < kPrime, by the invariants
414
        // of that structure. Thus kPrime + even - odd < 2*kPrime because odd >=
415
        // 0, because it's unsigned and less than kPrime. Lastly step_root <
416
        // kPrime, because |kNTTRootsMontgomery| is static data.
417
0
        s->c[j + offset] = reduce_montgomery((uint64_t)step_root *
418
0
                                             (uint64_t)(kPrime + even - odd));
419
0
      }
420
0
      k += 2 * offset;
421
0
    }
422
0
  }
423
0
  for (int i = 0; i < kDegree; i++) {
424
0
    s->c[i] = reduce_montgomery((uint64_t)s->c[i] *
425
0
                                (uint64_t)kInverseDegreeMontgomery);
426
0
  }
427
0
}
428
429
template <int X>
430
0
void vector_zero(vector<X> *out) {
431
0
  OPENSSL_memset(out, 0, sizeof(*out));
432
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_zero<6>(mldsa::(anonymous namespace)::vector<6>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_zero<8>(mldsa::(anonymous namespace)::vector<8>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_zero<4>(mldsa::(anonymous namespace)::vector<4>*)
433
434
template <int X>
435
0
void vector_add(vector<X> *out, const vector<X> *lhs, const vector<X> *rhs) {
436
0
  for (int i = 0; i < X; i++) {
437
0
    scalar_add(&out->v[i], &lhs->v[i], &rhs->v[i]);
438
0
  }
439
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_add<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_add<5>(mldsa::(anonymous namespace)::vector<5>*, mldsa::(anonymous namespace)::vector<5> const*, mldsa::(anonymous namespace)::vector<5> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_add<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_add<7>(mldsa::(anonymous namespace)::vector<7>*, mldsa::(anonymous namespace)::vector<7> const*, mldsa::(anonymous namespace)::vector<7> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_add<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::vector<4> const*)
440
441
template <int X>
442
0
void vector_sub(vector<X> *out, const vector<X> *lhs, const vector<X> *rhs) {
443
0
  for (int i = 0; i < X; i++) {
444
0
    scalar_sub(&out->v[i], &lhs->v[i], &rhs->v[i]);
445
0
  }
446
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_sub<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_sub<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_sub<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::vector<4> const*)
447
448
template <int X>
449
void vector_mult_scalar(vector<X> *out, const vector<X> *lhs,
450
0
                        const scalar *rhs) {
451
0
  for (int i = 0; i < X; i++) {
452
0
    scalar_mult(&out->v[i], &lhs->v[i], rhs);
453
0
  }
454
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_mult_scalar<5>(mldsa::(anonymous namespace)::vector<5>*, mldsa::(anonymous namespace)::vector<5> const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_mult_scalar<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_mult_scalar<7>(mldsa::(anonymous namespace)::vector<7>*, mldsa::(anonymous namespace)::vector<7> const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_mult_scalar<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_mult_scalar<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::scalar const*)
455
456
template <int X>
457
0
void vector_ntt(vector<X> *a) {
458
0
  for (int i = 0; i < X; i++) {
459
0
    scalar_ntt(&a->v[i]);
460
0
  }
461
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_ntt<5>(mldsa::(anonymous namespace)::vector<5>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_ntt<6>(mldsa::(anonymous namespace)::vector<6>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_ntt<7>(mldsa::(anonymous namespace)::vector<7>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_ntt<8>(mldsa::(anonymous namespace)::vector<8>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_ntt<4>(mldsa::(anonymous namespace)::vector<4>*)
462
463
template <int X>
464
0
void vector_inverse_ntt(vector<X> *a) {
465
0
  for (int i = 0; i < X; i++) {
466
0
    scalar_inverse_ntt(&a->v[i]);
467
0
  }
468
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_inverse_ntt<6>(mldsa::(anonymous namespace)::vector<6>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_inverse_ntt<5>(mldsa::(anonymous namespace)::vector<5>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_inverse_ntt<8>(mldsa::(anonymous namespace)::vector<8>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_inverse_ntt<7>(mldsa::(anonymous namespace)::vector<7>*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_inverse_ntt<4>(mldsa::(anonymous namespace)::vector<4>*)
469
470
template <int K, int L>
471
0
void matrix_mult(vector<K> *out, const matrix<K, L> *m, const vector<L> *a) {
472
0
  vector_zero(out);
473
0
  for (int i = 0; i < K; i++) {
474
0
    for (int j = 0; j < L; j++) {
475
0
      scalar product;
476
0
      scalar_mult(&product, &m->v[i][j], &a->v[j]);
477
0
      scalar_add(&out->v[i], &out->v[i], &product);
478
0
    }
479
0
  }
480
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_mult<6, 5>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::matrix<6, 5> const*, mldsa::(anonymous namespace)::vector<5> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_mult<8, 7>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::matrix<8, 7> const*, mldsa::(anonymous namespace)::vector<7> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_mult<4, 4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::matrix<4, 4> const*, mldsa::(anonymous namespace)::vector<4> const*)
481
482
/* Rounding & hints */
483
484
// FIPS 204, Algorithm 35 (`Power2Round`).
485
0
void power2_round(uint32_t *r1, uint32_t *r0, uint32_t r) {
486
0
  *r1 = r >> kDroppedBits;
487
0
  *r0 = r - (*r1 << kDroppedBits);
488
489
0
  uint32_t r0_adjusted = mod_sub(*r0, 1 << kDroppedBits);
490
0
  uint32_t r1_adjusted = *r1 + 1;
491
492
  // Mask is set iff r0 > 2^(dropped_bits - 1).
493
0
  crypto_word_t mask =
494
0
      constant_time_lt_w((uint32_t)(1 << (kDroppedBits - 1)), *r0);
495
  // r0 = mask ? r0_adjusted : r0
496
0
  *r0 = constant_time_select_32(mask, r0_adjusted, *r0);
497
  // r1 = mask ? r1_adjusted : r1
498
0
  *r1 = constant_time_select_32(mask, r1_adjusted, *r1);
499
0
}
500
501
// Scale back previously rounded value.
502
0
void scale_power2_round(uint32_t *out, uint32_t r1) {
503
  // Pre-condition: 0 <= r1 <= 2^10 - 1
504
0
  assert(r1 < (1u << 10));
505
506
0
  *out = r1 << kDroppedBits;
507
508
  // Post-condition: 0 <= out <= 2^23 - 2^13 = kPrime - 1
509
0
  assert(*out < kPrime);
510
0
}
511
512
// FIPS 204, Algorithm 37 (`HighBits`).
513
template <int K>
514
0
uint32_t high_bits(uint32_t x) {
515
  // Reference description (given 0 <= x < q):
516
  //
517
  // ```
518
  // int32_t r0 = x mod+- (2 * gamma2);
519
  // if (x - r0 == q - 1) {
520
  //   return 0;
521
  // } else {
522
  //   return (x - r0) / (2 * gamma2);
523
  // }
524
  // ```
525
  //
526
0
  uint32_t r1 = (x + 127) >> 7;
527
0
  if constexpr (prime_minus_one_over_gamma2<K>() == 32) {
528
    // Below is the formula taken from the reference implementation.
529
    //
530
    // Here, Gamma2 == 2^18 - 2^8
531
    // This returns ((ceil(x / 2^7) * (2^10 + 1) + 2^21) / 2^22) mod 2^4
532
0
    r1 = (r1 * 1025 + (1 << 21)) >> 22;
533
0
    r1 &= 15;
534
0
  } else if constexpr (prime_minus_one_over_gamma2<K>() == 88) {
535
    // 1488/2^24 is close enough to 1/1488 so that r1 becomes x/(2 gamma2)
536
    // rounded down.
537
0
    r1 = (r1 * 11275 + (1 << 23)) >> 24;
538
539
    // For corner-case r1 = (Q-1)/(2 gamma2) = 44, we have to set r1=0.
540
0
    r1 ^= ((uint32_t)(((int32_t)(43 - r1)) >> 31)) & r1;
541
0
  }
542
0
  return r1;
543
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::high_bits<6>(unsigned int)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::high_bits<8>(unsigned int)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::high_bits<4>(unsigned int)
544
545
// FIPS 204, Algorithm 36 (`Decompose`).
546
template <int K>
547
0
void decompose(uint32_t *r1, int32_t *r0, uint32_t r) {
548
0
  *r1 = high_bits<K>(r);
549
550
0
  *r0 = r;
551
0
  *r0 -= *r1 * 2 * (int32_t)gamma2<K>();
552
0
  *r0 -= (((int32_t)kHalfPrime - *r0) >> 31) & (int32_t)kPrime;
553
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::decompose<6>(unsigned int*, int*, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::decompose<8>(unsigned int*, int*, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::decompose<4>(unsigned int*, int*, unsigned int)
554
555
// FIPS 204, Algorithm 38 (`LowBits`).
556
template <int K>
557
0
int32_t low_bits(uint32_t x) {
558
0
  uint32_t r1;
559
0
  int32_t r0;
560
0
  decompose<K>(&r1, &r0, x);
561
0
  return r0;
562
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::low_bits<6>(unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::low_bits<8>(unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::low_bits<4>(unsigned int)
563
564
// FIPS 204, Algorithm 39 (`MakeHint`).
565
//
566
// In the spec this takes two arguments, z and r, and is called with
567
//   z = -ct0
568
//   r = w - cs2 + ct0
569
//
570
// It then computes HighBits (algorithm 37) of z and z+r. But z+r is just w -
571
// cs2, so this takes three arguments and saves an addition.
572
template <int K>
573
0
int32_t make_hint(uint32_t ct0, uint32_t cs2, uint32_t w) {
574
0
  uint32_t r_plus_z = mod_sub(w, cs2);
575
0
  uint32_t r = reduce_once(r_plus_z + ct0);
576
0
  return high_bits<K>(r) != high_bits<K>(r_plus_z);
577
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::make_hint<6>(unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::make_hint<8>(unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::make_hint<4>(unsigned int, unsigned int, unsigned int)
578
579
// FIPS 204, Algorithm 40 (`UseHint`).
580
template <int K>
581
0
uint32_t use_hint_vartime(uint32_t h, uint32_t r) {
582
0
  uint32_t r1;
583
0
  int32_t r0;
584
0
  decompose<K>(&r1, &r0, r);
585
586
0
  if (h) {
587
0
    if constexpr (prime_minus_one_over_gamma2<K>() == 32) {
588
0
      if (r0 > 0) {
589
        // (Q-1)/(2 gamma2) = m = 16, thus |mod m| in the spec turns into |&
590
        // 15|.
591
0
        return (r1 + 1) & 15;
592
0
      } else {
593
0
        return (r1 - 1) & 15;
594
0
      }
595
0
    } else {
596
      // m = 44
597
0
      static_assert(prime_minus_one_over_gamma2<K>() == 88);
598
0
      if (r0 > 0) {
599
0
        if (r1 == 43) {
600
0
          return 0;
601
0
        } else {
602
0
          return r1 + 1;
603
0
        }
604
0
      } else {
605
0
        if (r1 == 0) {
606
0
          return 43;
607
0
        } else {
608
0
          return r1 - 1;
609
0
        }
610
0
      }
611
0
    }
612
0
  }
613
0
  return r1;
614
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::use_hint_vartime<6>(unsigned int, unsigned int)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::use_hint_vartime<8>(unsigned int, unsigned int)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::use_hint_vartime<4>(unsigned int, unsigned int)
615
616
0
void scalar_power2_round(scalar *s1, scalar *s0, const scalar *s) {
617
0
  for (int i = 0; i < kDegree; i++) {
618
0
    power2_round(&s1->c[i], &s0->c[i], s->c[i]);
619
0
  }
620
0
}
621
622
0
void scalar_scale_power2_round(scalar *out, const scalar *in) {
623
0
  for (int i = 0; i < kDegree; i++) {
624
0
    scale_power2_round(&out->c[i], in->c[i]);
625
0
  }
626
0
}
627
628
template <int K>
629
0
void scalar_high_bits(scalar *out, const scalar *in) {
630
0
  for (int i = 0; i < kDegree; i++) {
631
0
    out->c[i] = high_bits<K>(in->c[i]);
632
0
  }
633
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_high_bits<6>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_high_bits<8>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_high_bits<4>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
634
635
template <int K>
636
0
void scalar_low_bits(scalar *out, const scalar *in) {
637
0
  for (int i = 0; i < kDegree; i++) {
638
0
    out->c[i] = low_bits<K>(in->c[i]);
639
0
  }
640
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_low_bits<6>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_low_bits<8>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_low_bits<4>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*)
641
642
0
void scalar_max(uint32_t *max, const scalar *s) {
643
0
  for (int i = 0; i < kDegree; i++) {
644
0
    uint32_t abs = abs_mod_prime(s->c[i]);
645
0
    *max = maximum_reduced(*max, abs);
646
0
  }
647
0
}
648
649
0
void scalar_max_signed(uint32_t *max, const scalar *s) {
650
0
  for (int i = 0; i < kDegree; i++) {
651
0
    uint32_t abs = abs_signed(s->c[i]);
652
0
    *max = maximum_reduced(*max, abs);
653
0
  }
654
0
}
655
656
template <int K>
657
void scalar_make_hint(scalar *out, const scalar *ct0, const scalar *cs2,
658
0
                      const scalar *w) {
659
0
  for (int i = 0; i < kDegree; i++) {
660
0
    out->c[i] = make_hint<K>(ct0->c[i], cs2->c[i], w->c[i]);
661
0
  }
662
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_make_hint<6>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_make_hint<8>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_make_hint<4>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
663
664
template <int K>
665
0
void scalar_use_hint_vartime(scalar *out, const scalar *h, const scalar *r) {
666
0
  for (int i = 0; i < kDegree; i++) {
667
0
    out->c[i] = use_hint_vartime<K>(h->c[i], r->c[i]);
668
0
  }
669
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_use_hint_vartime<6>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_use_hint_vartime<8>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_use_hint_vartime<4>(mldsa::(anonymous namespace)::scalar*, mldsa::(anonymous namespace)::scalar const*, mldsa::(anonymous namespace)::scalar const*)
670
671
template <int X>
672
0
void vector_power2_round(vector<X> *t1, vector<X> *t0, const vector<X> *t) {
673
0
  for (int i = 0; i < X; i++) {
674
0
    scalar_power2_round(&t1->v[i], &t0->v[i], &t->v[i]);
675
0
  }
676
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_power2_round<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_power2_round<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_power2_round<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*)
677
678
template <int X>
679
0
void vector_scale_power2_round(vector<X> *out, const vector<X> *in) {
680
0
  for (int i = 0; i < X; i++) {
681
0
    scalar_scale_power2_round(&out->v[i], &in->v[i]);
682
0
  }
683
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_scale_power2_round<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_scale_power2_round<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_scale_power2_round<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*)
684
685
template <int K>
686
0
void vector_high_bits(vector<K> *out, const vector<K> *in) {
687
0
  for (int i = 0; i < K; i++) {
688
0
    scalar_high_bits<K>(&out->v[i], &in->v[i]);
689
0
  }
690
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_high_bits<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_high_bits<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_high_bits<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*)
691
692
template <int K>
693
0
void vector_low_bits(vector<K> *out, const vector<K> *in) {
694
0
  for (int i = 0; i < K; i++) {
695
0
    scalar_low_bits<K>(&out->v[i], &in->v[i]);
696
0
  }
697
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_low_bits<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_low_bits<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_low_bits<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*)
698
699
template <int X>
700
0
uint32_t vector_max(const vector<X> *a) {
701
0
  uint32_t max = 0;
702
0
  for (int i = 0; i < X; i++) {
703
0
    scalar_max(&max, &a->v[i]);
704
0
  }
705
0
  return max;
706
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max<5>(mldsa::(anonymous namespace)::vector<5> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max<6>(mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max<7>(mldsa::(anonymous namespace)::vector<7> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max<8>(mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max<4>(mldsa::(anonymous namespace)::vector<4> const*)
707
708
template <int X>
709
0
uint32_t vector_max_signed(const vector<X> *a) {
710
0
  uint32_t max = 0;
711
0
  for (int i = 0; i < X; i++) {
712
0
    scalar_max_signed(&max, &a->v[i]);
713
0
  }
714
0
  return max;
715
0
}
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max_signed<6>(mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max_signed<8>(mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:unsigned int mldsa::(anonymous namespace)::vector_max_signed<4>(mldsa::(anonymous namespace)::vector<4> const*)
716
717
// The input vector contains only zeroes and ones.
718
template <int X>
719
0
size_t vector_count_ones(const vector<X> *a) {
720
0
  size_t count = 0;
721
0
  for (int i = 0; i < X; i++) {
722
0
    for (int j = 0; j < kDegree; j++) {
723
0
      count += a->v[i].c[j];
724
0
    }
725
0
  }
726
0
  return count;
727
0
}
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::vector_count_ones<6>(mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::vector_count_ones<8>(mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:unsigned long mldsa::(anonymous namespace)::vector_count_ones<4>(mldsa::(anonymous namespace)::vector<4> const*)
728
729
template <int K>
730
void vector_make_hint(vector<K> *out, const vector<K> *ct0,
731
0
                      const vector<K> *cs2, const vector<K> *w) {
732
0
  for (int i = 0; i < K; i++) {
733
0
    scalar_make_hint<K>(&out->v[i], &ct0->v[i], &cs2->v[i], &w->v[i]);
734
0
  }
735
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_make_hint<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_make_hint<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_make_hint<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::vector<4> const*)
736
737
template <int K>
738
void vector_use_hint_vartime(vector<K> *out, const vector<K> *h,
739
0
                             const vector<K> *r) {
740
0
  for (int i = 0; i < K; i++) {
741
0
    scalar_use_hint_vartime<K>(&out->v[i], &h->v[i], &r->v[i]);
742
0
  }
743
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_use_hint_vartime<6>(mldsa::(anonymous namespace)::vector<6>*, mldsa::(anonymous namespace)::vector<6> const*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_use_hint_vartime<8>(mldsa::(anonymous namespace)::vector<8>*, mldsa::(anonymous namespace)::vector<8> const*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_use_hint_vartime<4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4> const*, mldsa::(anonymous namespace)::vector<4> const*)
744
745
/* Bit packing */
746
747
// FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 4.
748
0
static void scalar_encode_4(uint8_t out[128], const scalar *s) {
749
  // Every two elements lands on a byte boundary.
750
0
  static_assert(kDegree % 2 == 0, "kDegree must be a multiple of 2");
751
0
  for (int i = 0; i < kDegree / 2; i++) {
752
0
    uint32_t a = s->c[2 * i];
753
0
    uint32_t b = s->c[2 * i + 1];
754
0
    declassify_assert(a < 16);
755
0
    declassify_assert(b < 16);
756
0
    out[i] = a | (b << 4);
757
0
  }
758
0
}
759
760
// FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 6.
761
0
void scalar_encode_6(uint8_t out[192], const scalar *s) {
762
  // Every four elements lands on a byte boundary.
763
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
764
0
  for (int i = 0; i < kDegree / 4; i++) {
765
0
    uint32_t a = s->c[4 * i];
766
0
    uint32_t b = s->c[4 * i + 1];
767
0
    uint32_t c = s->c[4 * i + 2];
768
0
    uint32_t d = s->c[4 * i + 3];
769
0
    declassify_assert(a < 64);
770
0
    declassify_assert(b < 64);
771
0
    declassify_assert(c < 64);
772
0
    declassify_assert(d < 64);
773
0
    out[3 * i] = a | (b << 6);
774
0
    out[3 * i + 1] = (b >> 2) | (c << 4);
775
0
    out[3 * i + 2] = (c >> 4) | (d << 2);
776
0
  }
777
0
}
778
779
// FIPS 204, Algorithm 16 (`SimpleBitPack`). Specialized to bitlen(b) = 10.
780
0
void scalar_encode_10(uint8_t out[320], const scalar *s) {
781
  // Every four elements lands on a byte boundary.
782
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
783
0
  for (int i = 0; i < kDegree / 4; i++) {
784
0
    uint32_t a = s->c[4 * i];
785
0
    uint32_t b = s->c[4 * i + 1];
786
0
    uint32_t c = s->c[4 * i + 2];
787
0
    uint32_t d = s->c[4 * i + 3];
788
0
    declassify_assert(a < 1024);
789
0
    declassify_assert(b < 1024);
790
0
    declassify_assert(c < 1024);
791
0
    declassify_assert(d < 1024);
792
0
    out[5 * i] = (uint8_t)a;
793
0
    out[5 * i + 1] = (uint8_t)((a >> 8) | (b << 2));
794
0
    out[5 * i + 2] = (uint8_t)((b >> 6) | (c << 4));
795
0
    out[5 * i + 3] = (uint8_t)((c >> 4) | (d << 6));
796
0
    out[5 * i + 4] = (uint8_t)(d >> 2);
797
0
  }
798
0
}
799
800
// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 4 and b = 4.
801
0
void scalar_encode_signed_4_4(uint8_t out[128], const scalar *s) {
802
  // Every two elements lands on a byte boundary.
803
0
  static_assert(kDegree % 2 == 0, "kDegree must be a multiple of 2");
804
0
  for (int i = 0; i < kDegree / 2; i++) {
805
0
    uint32_t a = mod_sub(4, s->c[2 * i]);
806
0
    uint32_t b = mod_sub(4, s->c[2 * i + 1]);
807
0
    declassify_assert(a < 16);
808
0
    declassify_assert(b < 16);
809
0
    out[i] = a | (b << 4);
810
0
  }
811
0
}
812
813
// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 3 and b = 2.
814
0
static void scalar_encode_signed_3_2(uint8_t out[96], const scalar *s) {
815
0
  static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8");
816
0
  for (int i = 0; i < kDegree / 8; i++) {
817
0
    uint32_t a = mod_sub(2, s->c[8 * i]);
818
0
    uint32_t b = mod_sub(2, s->c[8 * i + 1]);
819
0
    uint32_t c = mod_sub(2, s->c[8 * i + 2]);
820
0
    uint32_t d = mod_sub(2, s->c[8 * i + 3]);
821
0
    uint32_t e = mod_sub(2, s->c[8 * i + 4]);
822
0
    uint32_t f = mod_sub(2, s->c[8 * i + 5]);
823
0
    uint32_t g = mod_sub(2, s->c[8 * i + 6]);
824
0
    uint32_t h = mod_sub(2, s->c[8 * i + 7]);
825
0
    uint32_t v = (h << 21) | (g << 18) | (f << 15) | (e << 12) | (d << 9) |
826
0
                 (c << 6) | (b << 3) | a;
827
0
    uint8_t v_bytes[sizeof(v)];
828
0
    CRYPTO_store_u32_le(v_bytes, v);
829
0
    OPENSSL_memcpy(&out[i * 3], v_bytes, 3);
830
0
  }
831
0
}
832
833
// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 13 and b =
834
// 2^12.
835
0
void scalar_encode_signed_13_12(uint8_t out[416], const scalar *s) {
836
0
  static const uint32_t kMax = 1u << 12;
837
  // Every two elements lands on a byte boundary.
838
0
  static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8");
839
0
  for (int i = 0; i < kDegree / 8; i++) {
840
0
    uint32_t a = mod_sub(kMax, s->c[8 * i]);
841
0
    uint32_t b = mod_sub(kMax, s->c[8 * i + 1]);
842
0
    uint32_t c = mod_sub(kMax, s->c[8 * i + 2]);
843
0
    uint32_t d = mod_sub(kMax, s->c[8 * i + 3]);
844
0
    uint32_t e = mod_sub(kMax, s->c[8 * i + 4]);
845
0
    uint32_t f = mod_sub(kMax, s->c[8 * i + 5]);
846
0
    uint32_t g = mod_sub(kMax, s->c[8 * i + 6]);
847
0
    uint32_t h = mod_sub(kMax, s->c[8 * i + 7]);
848
0
    declassify_assert(a < (1u << 13));
849
0
    declassify_assert(b < (1u << 13));
850
0
    declassify_assert(c < (1u << 13));
851
0
    declassify_assert(d < (1u << 13));
852
0
    declassify_assert(e < (1u << 13));
853
0
    declassify_assert(f < (1u << 13));
854
0
    declassify_assert(g < (1u << 13));
855
0
    declassify_assert(h < (1u << 13));
856
0
    a |= b << 13;
857
0
    a |= c << 26;
858
0
    c >>= 6;
859
0
    c |= d << 7;
860
0
    c |= e << 20;
861
0
    e >>= 12;
862
0
    e |= f << 1;
863
0
    e |= g << 14;
864
0
    e |= h << 27;
865
0
    h >>= 5;
866
0
    CRYPTO_store_u32_le(&out[13 * i], a);
867
0
    CRYPTO_store_u32_le(&out[13 * i + 4], c);
868
0
    CRYPTO_store_u32_le(&out[13 * i + 8], e);
869
0
    out[13 * i + 12] = static_cast<uint8_t>(h);
870
0
  }
871
0
}
872
873
// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 20 and b =
874
// 2^19.
875
0
void scalar_encode_signed_20_19(uint8_t out[640], const scalar *s) {
876
0
  static const uint32_t kMax = 1u << 19;
877
  // Every two elements lands on a byte boundary.
878
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
879
0
  for (int i = 0; i < kDegree / 4; i++) {
880
0
    uint32_t a = mod_sub(kMax, s->c[4 * i]);
881
0
    uint32_t b = mod_sub(kMax, s->c[4 * i + 1]);
882
0
    uint32_t c = mod_sub(kMax, s->c[4 * i + 2]);
883
0
    uint32_t d = mod_sub(kMax, s->c[4 * i + 3]);
884
0
    declassify_assert(a < (1u << 20));
885
0
    declassify_assert(b < (1u << 20));
886
0
    declassify_assert(c < (1u << 20));
887
0
    declassify_assert(d < (1u << 20));
888
0
    a |= b << 20;
889
0
    b >>= 12;
890
0
    b |= c << 8;
891
0
    b |= d << 28;
892
0
    d >>= 4;
893
0
    CRYPTO_store_u32_le(&out[10 * i], a);
894
0
    CRYPTO_store_u32_le(&out[10 * i + 4], b);
895
0
    CRYPTO_store_u16_le(&out[10 * i + 8], static_cast<uint16_t>(d));
896
0
  }
897
0
}
898
899
// FIPS 204, Algorithm 17 (`BitPack`). Specialized to bitlen(a+b) = 18 and b =
900
// 2^17.
901
0
void scalar_encode_signed_18_17(uint8_t out[576], const scalar *s) {
902
0
  static const uint32_t kMax = 1u << 17;
903
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
904
0
  for (int i = 0; i < kDegree / 4; i++) {
905
0
    uint32_t a = mod_sub(kMax, s->c[4 * i]);
906
0
    uint32_t b = mod_sub(kMax, s->c[4 * i + 1]);
907
0
    uint32_t c = mod_sub(kMax, s->c[4 * i + 2]);
908
0
    uint32_t d = mod_sub(kMax, s->c[4 * i + 3]);
909
0
    declassify_assert(a < (1u << 18));
910
0
    declassify_assert(b < (1u << 18));
911
0
    declassify_assert(c < (1u << 18));
912
0
    declassify_assert(d < (1u << 18));
913
0
    out[9 * i] = (uint8_t)a;
914
0
    out[9 * i + 1] = (uint8_t)(a >> 8);
915
0
    out[9 * i + 2] = (uint8_t)(a >> 16) | (uint8_t)(b << 2);
916
0
    out[9 * i + 3] = (uint8_t)(b >> 6);
917
0
    out[9 * i + 4] = (uint8_t)(b >> 14) | (uint8_t)(c << 4);
918
0
    out[9 * i + 5] = (uint8_t)(c >> 4);
919
0
    out[9 * i + 6] = (uint8_t)(c >> 12) | (uint8_t)(d << 6);
920
0
    out[9 * i + 7] = (uint8_t)(d >> 2);
921
0
    out[9 * i + 8] = (uint8_t)(d >> 10);
922
0
  }
923
0
}
924
925
// FIPS 204, Algorithm 17 (`BitPack`).
926
void scalar_encode_signed(uint8_t *out, const scalar *s, int bits,
927
0
                          uint32_t max) {
928
0
  if (bits == 3) {
929
0
    assert(max == 2);
930
0
    scalar_encode_signed_3_2(out, s);
931
0
  } else if (bits == 4) {
932
0
    assert(max == 4);
933
0
    scalar_encode_signed_4_4(out, s);
934
0
  } else if (bits == 20) {
935
0
    assert(max == 1u << 19);
936
0
    scalar_encode_signed_20_19(out, s);
937
0
  } else if (bits == 18) {
938
0
    assert(max == 1u << 17);
939
0
    scalar_encode_signed_18_17(out, s);
940
0
  } else {
941
0
    assert(bits == 13);
942
0
    assert(max == 1u << 12);
943
0
    scalar_encode_signed_13_12(out, s);
944
0
  }
945
0
}
946
947
// FIPS 204, Algorithm 18 (`SimpleBitUnpack`). Specialized for bitlen(b) == 10.
948
0
void scalar_decode_10(scalar *out, const uint8_t in[320]) {
949
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
950
0
  for (int i = 0; i < kDegree / 4; i++) {
951
0
    uint32_t v = CRYPTO_load_u32_le(&in[5 * i]);
952
0
    out->c[4 * i] = v & 0x3ff;
953
0
    out->c[4 * i + 1] = (v >> 10) & 0x3ff;
954
0
    out->c[4 * i + 2] = (v >> 20) & 0x3ff;
955
0
    out->c[4 * i + 3] = (v >> 30) | (((uint32_t)in[5 * i + 4]) << 2);
956
0
  }
957
0
}
958
959
// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 4 and b =
960
// 4.
961
0
int scalar_decode_signed_4_4(scalar *out, const uint8_t in[128]) {
962
0
  static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8");
963
0
  for (int i = 0; i < kDegree / 8; i++) {
964
0
    uint32_t v = CRYPTO_load_u32_le(&in[4 * i]);
965
    // None of the nibbles may be >= 9. So if the MSB of any nibble is set, none
966
    // of the other bits may be set. First, select all the MSBs.
967
0
    const uint32_t msbs = v & 0x88888888u;
968
    // For each nibble where the MSB is set, form a mask of all the other bits.
969
0
    const uint32_t mask = (msbs >> 1) | (msbs >> 2) | (msbs >> 3);
970
    // A nibble is only out of range in the case of invalid input, in which case
971
    // it is okay to leak the value.
972
0
    if (constant_time_declassify_int((mask & v) != 0)) {
973
0
      return 0;
974
0
    }
975
976
0
    out->c[i * 8] = mod_sub(4, v & 15);
977
0
    out->c[i * 8 + 1] = mod_sub(4, (v >> 4) & 15);
978
0
    out->c[i * 8 + 2] = mod_sub(4, (v >> 8) & 15);
979
0
    out->c[i * 8 + 3] = mod_sub(4, (v >> 12) & 15);
980
0
    out->c[i * 8 + 4] = mod_sub(4, (v >> 16) & 15);
981
0
    out->c[i * 8 + 5] = mod_sub(4, (v >> 20) & 15);
982
0
    out->c[i * 8 + 6] = mod_sub(4, (v >> 24) & 15);
983
0
    out->c[i * 8 + 7] = mod_sub(4, v >> 28);
984
0
  }
985
0
  return 1;
986
0
}
987
988
// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 3 and b =
989
// 2.
990
0
static int scalar_decode_signed_3_2(scalar *out, const uint8_t in[96]) {
991
0
  uint32_t v;
992
0
  uint8_t v_bytes[sizeof(v)] = {0};
993
0
  static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8");
994
0
  for (int i = 0; i < kDegree / 8; i++) {
995
0
    OPENSSL_memcpy(v_bytes, &in[3 * i], 3);
996
0
    v = CRYPTO_load_u32_le(v_bytes);
997
    // v contains 8, 3-bit values in the lower 24 bits. None of the values may
998
    // be >= 5. So if the MSB of any triple is set, none of the other bits may
999
    // be set. First, select all the MSBs.
1000
0
    const uint32_t msbs = v & 000044444444u;
1001
    // For each triple where the MSB is set, form a mask of all the other bits.
1002
0
    const uint32_t mask = (msbs >> 1) | (msbs >> 2);
1003
    // A triple is only out of range in the case of invalid input, in which case
1004
    // it is okay to leak the value.
1005
0
    if (constant_time_declassify_int((mask & v) != 0)) {
1006
0
      return 0;
1007
0
    }
1008
1009
0
    out->c[i * 8 + 0] = mod_sub(2, (v >> 0) & 7);
1010
0
    out->c[i * 8 + 1] = mod_sub(2, (v >> 3) & 7);
1011
0
    out->c[i * 8 + 2] = mod_sub(2, (v >> 6) & 7);
1012
0
    out->c[i * 8 + 3] = mod_sub(2, (v >> 9) & 7);
1013
0
    out->c[i * 8 + 4] = mod_sub(2, (v >> 12) & 7);
1014
0
    out->c[i * 8 + 5] = mod_sub(2, (v >> 15) & 7);
1015
0
    out->c[i * 8 + 6] = mod_sub(2, (v >> 18) & 7);
1016
0
    out->c[i * 8 + 7] = mod_sub(2, v >> 21);
1017
0
  }
1018
0
  return 1;
1019
0
}
1020
1021
// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 13 and b =
1022
// 2^12.
1023
0
void scalar_decode_signed_13_12(scalar *out, const uint8_t in[416]) {
1024
0
  static const uint32_t kMax = 1u << 12;
1025
0
  static const uint32_t k13Bits = (1u << 13) - 1;
1026
0
  static const uint32_t k7Bits = (1u << 7) - 1;
1027
1028
0
  static_assert(kDegree % 8 == 0, "kDegree must be a multiple of 8");
1029
0
  for (int i = 0; i < kDegree / 8; i++) {
1030
0
    uint32_t a = CRYPTO_load_u32_le(&in[13 * i]);
1031
0
    uint32_t b = CRYPTO_load_u32_le(&in[13 * i + 4]);
1032
0
    uint32_t c = CRYPTO_load_u32_le(&in[13 * i + 8]);
1033
0
    uint8_t d = in[13 * i + 12];
1034
1035
    // It's not possible for a 13-bit number to be out of range when the max is
1036
    // 2^12.
1037
0
    out->c[i * 8] = mod_sub(kMax, a & k13Bits);
1038
0
    out->c[i * 8 + 1] = mod_sub(kMax, (a >> 13) & k13Bits);
1039
0
    out->c[i * 8 + 2] = mod_sub(kMax, (a >> 26) | ((b & k7Bits) << 6));
1040
0
    out->c[i * 8 + 3] = mod_sub(kMax, (b >> 7) & k13Bits);
1041
0
    out->c[i * 8 + 4] = mod_sub(kMax, (b >> 20) | ((c & 1) << 12));
1042
0
    out->c[i * 8 + 5] = mod_sub(kMax, (c >> 1) & k13Bits);
1043
0
    out->c[i * 8 + 6] = mod_sub(kMax, (c >> 14) & k13Bits);
1044
0
    out->c[i * 8 + 7] = mod_sub(kMax, (c >> 27) | ((uint32_t)d) << 5);
1045
0
  }
1046
0
}
1047
1048
// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 18 and b =
1049
// 2^17.
1050
0
void scalar_decode_signed_18_17(scalar *out, const uint8_t in[576]) {
1051
0
  static const uint32_t kMax = 1u << 17;
1052
1053
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
1054
0
  for (int i = 0; i < kDegree / 4; i++) {
1055
0
    uint32_t a = uint32_t{in[9 * i]} | (uint32_t{in[9 * i + 1]} << 8) |
1056
0
                 ((uint32_t{in[9 * i + 2]} & 0x3) << 16);
1057
0
    uint32_t b = (uint32_t{in[9 * i + 2]} >> 2) |
1058
0
                 (uint32_t{in[9 * i + 3]} << 6) |
1059
0
                 ((uint32_t{in[9 * i + 4]} & 0xf) << 14);
1060
0
    uint32_t c = (uint32_t{in[9 * i + 4]} >> 4) |
1061
0
                 (uint32_t{in[9 * i + 5]} << 4) |
1062
0
                 ((uint32_t{in[9 * i + 6]} & 0x3f) << 12);
1063
0
    uint32_t d = (uint32_t{in[9 * i + 6]} >> 6) |
1064
0
                 (uint32_t{in[9 * i + 7]} << 2) |
1065
0
                 (uint32_t{in[9 * i + 8]} << 10);
1066
1067
0
    out->c[i * 4] = mod_sub(kMax, a);
1068
0
    out->c[i * 4 + 1] = mod_sub(kMax, b);
1069
0
    out->c[i * 4 + 2] = mod_sub(kMax, c);
1070
0
    out->c[i * 4 + 3] = mod_sub(kMax, d);
1071
0
  }
1072
0
}
1073
1074
// FIPS 204, Algorithm 19 (`BitUnpack`). Specialized to bitlen(a+b) = 20 and b =
1075
// 2^19.
1076
0
void scalar_decode_signed_20_19(scalar *out, const uint8_t in[640]) {
1077
0
  static const uint32_t kMax = 1u << 19;
1078
0
  static const uint32_t k20Bits = (1u << 20) - 1;
1079
1080
0
  static_assert(kDegree % 4 == 0, "kDegree must be a multiple of 4");
1081
0
  for (int i = 0; i < kDegree / 4; i++) {
1082
0
    uint32_t a = CRYPTO_load_u32_le(&in[10 * i]);
1083
0
    uint32_t b = CRYPTO_load_u32_le(&in[10 * i + 4]);
1084
0
    uint16_t c = CRYPTO_load_u16_le(&in[10 * i + 8]);
1085
1086
    // It's not possible for a 20-bit number to be out of range when the max is
1087
    // 2^19.
1088
0
    out->c[i * 4] = mod_sub(kMax, a & k20Bits);
1089
0
    out->c[i * 4 + 1] = mod_sub(kMax, (a >> 20) | ((b & 0xff) << 12));
1090
0
    out->c[i * 4 + 2] = mod_sub(kMax, (b >> 8) & k20Bits);
1091
0
    out->c[i * 4 + 3] = mod_sub(kMax, (b >> 28) | ((uint32_t)c) << 4);
1092
0
  }
1093
0
}
1094
1095
// FIPS 204, Algorithm 19 (`BitUnpack`).
1096
int scalar_decode_signed(scalar *out, const uint8_t *in, int bits,
1097
0
                         uint32_t max) {
1098
0
  if (bits == 3) {
1099
0
    assert(max == 2);
1100
0
    return scalar_decode_signed_3_2(out, in);
1101
0
  } else if (bits == 4) {
1102
0
    assert(max == 4);
1103
0
    return scalar_decode_signed_4_4(out, in);
1104
0
  } else if (bits == 13) {
1105
0
    assert(max == (1u << 12));
1106
0
    scalar_decode_signed_13_12(out, in);
1107
0
    return 1;
1108
0
  } else if (bits == 18) {
1109
0
    assert(max == (1u << 17));
1110
0
    scalar_decode_signed_18_17(out, in);
1111
0
    return 1;
1112
0
  } else if (bits == 20) {
1113
0
    assert(max == (1u << 19));
1114
0
    scalar_decode_signed_20_19(out, in);
1115
0
    return 1;
1116
0
  } else {
1117
0
    abort();
1118
0
  }
1119
0
}
1120
1121
/* Expansion functions */
1122
1123
// FIPS 204, Algorithm 30 (`RejNTTPoly`).
1124
//
1125
// Rejection samples a Keccak stream to get uniformly distributed elements. This
1126
// is used for matrix expansion and only operates on public inputs.
1127
void scalar_from_keccak_vartime(scalar *out,
1128
0
                                const uint8_t derived_seed[kRhoBytes + 2]) {
1129
0
  BORINGSSL_keccak_st keccak_ctx;
1130
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake128);
1131
0
  BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, kRhoBytes + 2);
1132
0
  assert(keccak_ctx.squeeze_offset == 0);
1133
0
  assert(keccak_ctx.rate_bytes == 168);
1134
0
  static_assert(168 % 3 == 0, "block and coefficient boundaries do not align");
1135
1136
0
  int done = 0;
1137
0
  while (done < kDegree) {
1138
0
    uint8_t block[168];
1139
0
    BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
1140
0
    for (size_t i = 0; i < sizeof(block) && done < kDegree; i += 3) {
1141
      // FIPS 204, Algorithm 14 (`CoeffFromThreeBytes`).
1142
0
      uint32_t value = (uint32_t)block[i] | ((uint32_t)block[i + 1] << 8) |
1143
0
                       (((uint32_t)block[i + 2] & 0x7f) << 16);
1144
0
      if (value < kPrime) {
1145
0
        out->c[done++] = value;
1146
0
      }
1147
0
    }
1148
0
  }
1149
0
}
1150
1151
template <int ETA>
1152
static bool coefficient_from_nibble(uint32_t nibble, uint32_t *result);
1153
1154
template <>
1155
0
bool coefficient_from_nibble<4>(uint32_t nibble, uint32_t *result) {
1156
0
  if (constant_time_declassify_int(nibble < 9)) {
1157
    // Knowing bounds on |nibble| seems to tempt some versions of Clang to emit
1158
    // a branch, if we don't have a barrier in |mod_sub|.
1159
0
    *result = mod_sub(4, value_barrier_u32(nibble));
1160
0
    return true;
1161
0
  }
1162
0
  return false;
1163
0
}
1164
1165
template <>
1166
0
bool coefficient_from_nibble<2>(uint32_t nibble, uint32_t *result) {
1167
0
  if (constant_time_declassify_int(nibble < 15)) {
1168
    // Knowing bounds on |nibble| seems to tempt some versions of Clang to emit
1169
    // a branch, if we don't have a barrier in |mod_sub|.
1170
    // Constant time "nibble % 5".
1171
0
    nibble = nibble - 5 * ((205 * nibble) >> 10);
1172
0
    *result = mod_sub(2, value_barrier_u32(nibble));
1173
0
    return true;
1174
0
  }
1175
0
  return false;
1176
0
}
1177
1178
// FIPS 204, Algorithm 31 (`RejBoundedPoly`).
1179
template <int ETA>
1180
0
void scalar_uniform(scalar *out, const uint8_t derived_seed[kSigmaBytes + 2]) {
1181
0
  BORINGSSL_keccak_st keccak_ctx;
1182
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1183
0
  BORINGSSL_keccak_absorb(&keccak_ctx, derived_seed, kSigmaBytes + 2);
1184
0
  assert(keccak_ctx.squeeze_offset == 0);
1185
0
  assert(keccak_ctx.rate_bytes == 136);
1186
1187
0
  int done = 0;
1188
0
  while (done < kDegree) {
1189
0
    uint8_t block[136];
1190
0
    BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
1191
0
    for (size_t i = 0; i < sizeof(block) && done < kDegree; ++i) {
1192
0
      uint32_t t0 = block[i] & 0x0F;
1193
0
      uint32_t t1 = block[i] >> 4;
1194
      // FIPS 204, Algorithm 15 (`CoefFromHalfByte`). Although both the input
1195
      // and output here are secret, it is OK to leak when we rejected a byte.
1196
      // Individual bytes of the SHAKE-256 stream are (indistinguishable from)
1197
      // independent of each other and the original seed, so leaking information
1198
      // about the rejected bytes does not reveal the input or output.
1199
0
      uint32_t v;
1200
0
      if (coefficient_from_nibble<ETA>(t0, &v)) {
1201
0
        out->c[done++] = v;
1202
0
      }
1203
0
      if (done < kDegree && coefficient_from_nibble<ETA>(t1, &v)) {
1204
0
        out->c[done++] = v;
1205
0
      }
1206
0
    }
1207
0
  }
1208
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_uniform<4>(mldsa::(anonymous namespace)::scalar*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_uniform<2>(mldsa::(anonymous namespace)::scalar*, unsigned char const*)
1209
1210
// FIPS 204, Algorithm 34 (`ExpandMask`), but just a single step.
1211
template <int K>
1212
void scalar_sample_mask(scalar *out,
1213
0
                        const uint8_t derived_seed[kRhoPrimeBytes + 2]) {
1214
0
  uint8_t buf[scalar_le_gamma1_bytes<K>()];
1215
0
  BORINGSSL_keccak(buf, sizeof(buf), derived_seed, kRhoPrimeBytes + 2,
1216
0
                   boringssl_shake256);
1217
1218
0
  scalar_decode_signed(out, buf, gamma1_bits<K>() + 1, gamma1<K>());
1219
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_sample_mask<6>(mldsa::(anonymous namespace)::scalar*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_sample_mask<8>(mldsa::(anonymous namespace)::scalar*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::scalar_sample_mask<4>(mldsa::(anonymous namespace)::scalar*, unsigned char const*)
1220
1221
// FIPS 204, Algorithm 29 (`SampleInBall`).
1222
void scalar_sample_in_ball_vartime(scalar *out, const uint8_t *seed, int len,
1223
0
                                   int tau) {
1224
0
  BORINGSSL_keccak_st keccak_ctx;
1225
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1226
0
  BORINGSSL_keccak_absorb(&keccak_ctx, seed, len);
1227
0
  assert(keccak_ctx.squeeze_offset == 0);
1228
0
  assert(keccak_ctx.rate_bytes == 136);
1229
1230
0
  uint8_t block[136];
1231
0
  BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
1232
1233
0
  uint64_t signs = CRYPTO_load_u64_le(block);
1234
0
  int offset = 8;
1235
  // SampleInBall implements a Fisher–Yates shuffle, which unavoidably leaks
1236
  // where the zeros are by memory access pattern. Although this leak happens
1237
  // before bad signatures are rejected, this is safe. See
1238
  // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/8d8f01ac_70af3f21/
1239
0
  CONSTTIME_DECLASSIFY(block + offset, sizeof(block) - offset);
1240
1241
0
  OPENSSL_memset(out, 0, sizeof(*out));
1242
0
  for (size_t i = kDegree - tau; i < kDegree; i++) {
1243
0
    size_t byte;
1244
0
    for (;;) {
1245
0
      if (offset == 136) {
1246
0
        BORINGSSL_keccak_squeeze(&keccak_ctx, block, sizeof(block));
1247
        // See above.
1248
0
        CONSTTIME_DECLASSIFY(block, sizeof(block));
1249
0
        offset = 0;
1250
0
      }
1251
1252
0
      byte = block[offset++];
1253
0
      if (byte <= i) {
1254
0
        break;
1255
0
      }
1256
0
    }
1257
1258
0
    out->c[i] = out->c[byte];
1259
0
    out->c[byte] = mod_sub(1, 2 * (signs & 1));
1260
0
    signs >>= 1;
1261
0
  }
1262
0
}
1263
1264
// FIPS 204, Algorithm 32 (`ExpandA`).
1265
template <int K, int L>
1266
0
void matrix_expand(matrix<K, L> *out, const uint8_t rho[kRhoBytes]) {
1267
0
  static_assert(K <= 0x100, "K must fit in 8 bits");
1268
0
  static_assert(L <= 0x100, "L must fit in 8 bits");
1269
1270
0
  uint8_t derived_seed[kRhoBytes + 2];
1271
0
  OPENSSL_memcpy(derived_seed, rho, kRhoBytes);
1272
0
  for (int i = 0; i < K; i++) {
1273
0
    for (int j = 0; j < L; j++) {
1274
0
      derived_seed[kRhoBytes + 1] = (uint8_t)i;
1275
0
      derived_seed[kRhoBytes] = (uint8_t)j;
1276
0
      scalar_from_keccak_vartime(&out->v[i][j], derived_seed);
1277
0
    }
1278
0
  }
1279
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_expand<6, 5>(mldsa::(anonymous namespace)::matrix<6, 5>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_expand<8, 7>(mldsa::(anonymous namespace)::matrix<8, 7>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::matrix_expand<4, 4>(mldsa::(anonymous namespace)::matrix<4, 4>*, unsigned char const*)
1280
1281
// FIPS 204, Algorithm 33 (`ExpandS`).
1282
template <int K, int L>
1283
void vector_expand_short(vector<L> *s1, vector<K> *s2,
1284
0
                         const uint8_t sigma[kSigmaBytes]) {
1285
0
  static_assert(K <= 0x100, "K must fit in 8 bits");
1286
0
  static_assert(L <= 0x100, "L must fit in 8 bits");
1287
0
  static_assert(K + L <= 0x100, "K+L must fit in 8 bits");
1288
1289
0
  uint8_t derived_seed[kSigmaBytes + 2];
1290
0
  OPENSSL_memcpy(derived_seed, sigma, kSigmaBytes);
1291
0
  derived_seed[kSigmaBytes] = 0;
1292
0
  derived_seed[kSigmaBytes + 1] = 0;
1293
0
  for (int i = 0; i < L; i++) {
1294
0
    scalar_uniform<eta<K>()>(&s1->v[i], derived_seed);
1295
0
    ++derived_seed[kSigmaBytes];
1296
0
  }
1297
0
  for (int i = 0; i < K; i++) {
1298
0
    scalar_uniform<eta<K>()>(&s2->v[i], derived_seed);
1299
0
    ++derived_seed[kSigmaBytes];
1300
0
  }
1301
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_short<6, 5>(mldsa::(anonymous namespace)::vector<5>*, mldsa::(anonymous namespace)::vector<6>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_short<8, 7>(mldsa::(anonymous namespace)::vector<7>*, mldsa::(anonymous namespace)::vector<8>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_short<4, 4>(mldsa::(anonymous namespace)::vector<4>*, mldsa::(anonymous namespace)::vector<4>*, unsigned char const*)
1302
1303
// FIPS 204, Algorithm 34 (`ExpandMask`).
1304
template <int K, int L>
1305
void vector_expand_mask(vector<L> *out, const uint8_t seed[kRhoPrimeBytes],
1306
0
                        size_t kappa) {
1307
0
  assert(kappa + L <= 0x10000);
1308
1309
0
  uint8_t derived_seed[kRhoPrimeBytes + 2];
1310
0
  OPENSSL_memcpy(derived_seed, seed, kRhoPrimeBytes);
1311
0
  for (int i = 0; i < L; i++) {
1312
0
    size_t index = kappa + i;
1313
0
    derived_seed[kRhoPrimeBytes] = index & 0xFF;
1314
0
    derived_seed[kRhoPrimeBytes + 1] = (index >> 8) & 0xFF;
1315
0
    scalar_sample_mask<K>(&out->v[i], derived_seed);
1316
0
  }
1317
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_mask<6, 5>(mldsa::(anonymous namespace)::vector<5>*, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_mask<8, 7>(mldsa::(anonymous namespace)::vector<7>*, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_expand_mask<4, 4>(mldsa::(anonymous namespace)::vector<4>*, unsigned char const*, unsigned long)
1318
1319
/* Encoding */
1320
1321
// FIPS 204, Algorithm 16 (`SimpleBitPack`).
1322
//
1323
// Encodes an entire vector into 32*K*|bits| bytes. Note that since 256
1324
// (kDegree) is divisible by 8, the individual vector entries will always fill a
1325
// whole number of bytes, so we do not need to worry about bit packing here.
1326
template <int K>
1327
0
void vector_encode(uint8_t *out, const vector<K> *a, int bits) {
1328
0
  if (bits == 4) {
1329
0
    for (int i = 0; i < K; i++) {
1330
0
      scalar_encode_4(out + i * bits * kDegree / 8, &a->v[i]);
1331
0
    }
1332
0
  } else if (bits == 6) {
1333
0
    for (int i = 0; i < K; i++) {
1334
0
      scalar_encode_6(out + i * bits * kDegree / 8, &a->v[i]);
1335
0
    }
1336
0
  } else {
1337
0
    assert(bits == 10);
1338
0
    for (int i = 0; i < K; i++) {
1339
0
      scalar_encode_10(out + i * bits * kDegree / 8, &a->v[i]);
1340
0
    }
1341
0
  }
1342
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode<6>(unsigned char*, mldsa::(anonymous namespace)::vector<6> const*, int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode<8>(unsigned char*, mldsa::(anonymous namespace)::vector<8> const*, int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode<4>(unsigned char*, mldsa::(anonymous namespace)::vector<4> const*, int)
1343
1344
// FIPS 204, Algorithm 18 (`SimpleBitUnpack`).
1345
template <int K>
1346
0
void vector_decode_10(vector<K> *out, const uint8_t *in) {
1347
0
  for (int i = 0; i < K; i++) {
1348
0
    scalar_decode_10(&out->v[i], in + i * 10 * kDegree / 8);
1349
0
  }
1350
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_decode_10<6>(mldsa::(anonymous namespace)::vector<6>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_decode_10<8>(mldsa::(anonymous namespace)::vector<8>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_decode_10<4>(mldsa::(anonymous namespace)::vector<4>*, unsigned char const*)
1351
1352
// FIPS 204, Algorithm 17 (`BitPack`).
1353
//
1354
// Encodes an entire vector into 32*L*|bits| bytes. Note that since 256
1355
// (kDegree) is divisible by 8, the individual vector entries will always fill a
1356
// whole number of bytes, so we do not need to worry about bit packing here.
1357
template <int X>
1358
void vector_encode_signed(uint8_t *out, const vector<X> *a, int bits,
1359
0
                          uint32_t max) {
1360
0
  for (int i = 0; i < X; i++) {
1361
0
    scalar_encode_signed(out + i * bits * kDegree / 8, &a->v[i], bits, max);
1362
0
  }
1363
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode_signed<5>(unsigned char*, mldsa::(anonymous namespace)::vector<5> const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode_signed<6>(unsigned char*, mldsa::(anonymous namespace)::vector<6> const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode_signed<7>(unsigned char*, mldsa::(anonymous namespace)::vector<7> const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode_signed<8>(unsigned char*, mldsa::(anonymous namespace)::vector<8> const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::vector_encode_signed<4>(unsigned char*, mldsa::(anonymous namespace)::vector<4> const*, int, unsigned int)
1364
1365
template <int X>
1366
int vector_decode_signed(vector<X> *out, const uint8_t *in, int bits,
1367
0
                         uint32_t max) {
1368
0
  for (int i = 0; i < X; i++) {
1369
0
    if (!scalar_decode_signed(&out->v[i], in + i * bits * kDegree / 8, bits,
1370
0
                              max)) {
1371
0
      return 0;
1372
0
    }
1373
0
  }
1374
0
  return 1;
1375
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::vector_decode_signed<5>(mldsa::(anonymous namespace)::vector<5>*, unsigned char const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::vector_decode_signed<6>(mldsa::(anonymous namespace)::vector<6>*, unsigned char const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::vector_decode_signed<7>(mldsa::(anonymous namespace)::vector<7>*, unsigned char const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::vector_decode_signed<8>(mldsa::(anonymous namespace)::vector<8>*, unsigned char const*, int, unsigned int)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::vector_decode_signed<4>(mldsa::(anonymous namespace)::vector<4>*, unsigned char const*, int, unsigned int)
1376
1377
// FIPS 204, Algorithm 28 (`w1Encode`).
1378
template <int K>
1379
0
void w1_encode(uint8_t out[w1_bytes<K>()], const vector<K> *w1) {
1380
0
  vector_encode(out, w1, w1_coeffs_bits<K>());
1381
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::w1_encode<6>(unsigned char*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::w1_encode<8>(unsigned char*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::w1_encode<4>(unsigned char*, mldsa::(anonymous namespace)::vector<4> const*)
1382
1383
// FIPS 204, Algorithm 20 (`HintBitPack`).
1384
template <int K>
1385
0
void hint_bit_pack(uint8_t out[omega<K>() + K], const vector<K> *h) {
1386
0
  OPENSSL_memset(out, 0, omega<K>() + K);
1387
0
  int index = 0;
1388
0
  for (int i = 0; i < K; i++) {
1389
0
    for (int j = 0; j < kDegree; j++) {
1390
0
      if (h->v[i].c[j]) {
1391
        // h must have at most omega<K>() non-zero coefficients.
1392
0
        BSSL_CHECK(index < omega<K>());
1393
0
        out[index++] = j;
1394
0
      }
1395
0
    }
1396
0
    out[omega<K>() + i] = index;
1397
0
  }
1398
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::hint_bit_pack<6>(unsigned char*, mldsa::(anonymous namespace)::vector<6> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::hint_bit_pack<8>(unsigned char*, mldsa::(anonymous namespace)::vector<8> const*)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::hint_bit_pack<4>(unsigned char*, mldsa::(anonymous namespace)::vector<4> const*)
1399
1400
// FIPS 204, Algorithm 21 (`HintBitUnpack`).
1401
template <int K>
1402
0
int hint_bit_unpack(vector<K> *h, const uint8_t in[omega<K>() + K]) {
1403
0
  vector_zero(h);
1404
0
  int index = 0;
1405
0
  for (int i = 0; i < K; i++) {
1406
0
    const int limit = in[omega<K>() + i];
1407
0
    if (limit < index || limit > omega<K>()) {
1408
0
      return 0;
1409
0
    }
1410
1411
0
    int last = -1;
1412
0
    while (index < limit) {
1413
0
      int byte = in[index++];
1414
0
      if (last >= 0 && byte <= last) {
1415
0
        return 0;
1416
0
      }
1417
0
      last = byte;
1418
0
      static_assert(kDegree == 256,
1419
0
                    "kDegree must be 256 for this write to be in bounds");
1420
0
      h->v[i].c[byte] = 1;
1421
0
    }
1422
0
  }
1423
0
  for (; index < omega<K>(); index++) {
1424
0
    if (in[index] != 0) {
1425
0
      return 0;
1426
0
    }
1427
0
  }
1428
0
  return 1;
1429
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::hint_bit_unpack<6>(mldsa::(anonymous namespace)::vector<6>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::hint_bit_unpack<8>(mldsa::(anonymous namespace)::vector<8>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::hint_bit_unpack<4>(mldsa::(anonymous namespace)::vector<4>*, unsigned char const*)
1430
1431
template <int K>
1432
struct public_key {
1433
  uint8_t rho[kRhoBytes];
1434
  vector<K> t1;
1435
  // Pre-cached value(s).
1436
  uint8_t public_key_hash[kTrBytes];
1437
};
1438
1439
template <int K, int L>
1440
struct private_key {
1441
  public_key<K> pub;
1442
  uint8_t k[kKBytes];
1443
  vector<L> s1;
1444
  vector<K> s2;
1445
  vector<K> t0;
1446
};
1447
1448
template <int K, int L>
1449
struct signature {
1450
  uint8_t c_tilde[2 * lambda_bytes<K>()];
1451
  vector<L> z;
1452
  vector<K> h;
1453
};
1454
1455
// FIPS 204, Algorithm 22 (`pkEncode`).
1456
template <int K>
1457
0
int mldsa_marshal_public_key(CBB *out, const public_key<K> *pub) {
1458
0
  if (!CBB_add_bytes(out, pub->rho, sizeof(pub->rho))) {
1459
0
    return 0;
1460
0
  }
1461
1462
0
  uint8_t *vectork_output;
1463
0
  if (!CBB_add_space(out, &vectork_output, 320 * K)) {
1464
0
    return 0;
1465
0
  }
1466
0
  vector_encode(vectork_output, &pub->t1, 10);
1467
1468
0
  return 1;
1469
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_public_key<6>(cbb_st*, mldsa::(anonymous namespace)::public_key<6> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_public_key<8>(cbb_st*, mldsa::(anonymous namespace)::public_key<8> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_public_key<4>(cbb_st*, mldsa::(anonymous namespace)::public_key<4> const*)
1470
1471
// FIPS 204, Algorithm 23 (`pkDecode`).
1472
template <int K>
1473
0
int mldsa_parse_public_key(public_key<K> *pub, CBS *in) {
1474
0
  const CBS orig_in = *in;
1475
1476
0
  if (!CBS_copy_bytes(in, pub->rho, sizeof(pub->rho))) {
1477
0
    return 0;
1478
0
  }
1479
1480
0
  CBS t1_bytes;
1481
0
  if (!CBS_get_bytes(in, &t1_bytes, 320 * K) || CBS_len(in) != 0) {
1482
0
    return 0;
1483
0
  }
1484
0
  vector_decode_10(&pub->t1, CBS_data(&t1_bytes));
1485
1486
  // Compute pre-cached values.
1487
0
  BORINGSSL_keccak(pub->public_key_hash, sizeof(pub->public_key_hash),
1488
0
                   CBS_data(&orig_in), CBS_len(&orig_in), boringssl_shake256);
1489
1490
0
  return 1;
1491
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_public_key<6>(mldsa::(anonymous namespace)::public_key<6>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_public_key<8>(mldsa::(anonymous namespace)::public_key<8>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_public_key<4>(mldsa::(anonymous namespace)::public_key<4>*, cbs_st*)
1492
1493
// FIPS 204, Algorithm 24 (`skEncode`).
1494
template <int K, int L>
1495
0
int mldsa_marshal_private_key(CBB *out, const private_key<K, L> *priv) {
1496
0
  if (!CBB_add_bytes(out, priv->pub.rho, sizeof(priv->pub.rho)) ||
1497
0
      !CBB_add_bytes(out, priv->k, sizeof(priv->k)) ||
1498
0
      !CBB_add_bytes(out, priv->pub.public_key_hash,
1499
0
                     sizeof(priv->pub.public_key_hash))) {
1500
0
    return 0;
1501
0
  }
1502
1503
0
  constexpr size_t scalar_bytes =
1504
0
      (kDegree * plus_minus_eta_bitlen<K>() + 7) / 8;
1505
0
  uint8_t *vectorl_output;
1506
0
  if (!CBB_add_space(out, &vectorl_output, scalar_bytes * L)) {
1507
0
    return 0;
1508
0
  }
1509
0
  vector_encode_signed(vectorl_output, &priv->s1, plus_minus_eta_bitlen<K>(),
1510
0
                       eta<K>());
1511
1512
0
  uint8_t *s2_output;
1513
0
  if (!CBB_add_space(out, &s2_output, scalar_bytes * K)) {
1514
0
    return 0;
1515
0
  }
1516
0
  vector_encode_signed(s2_output, &priv->s2, plus_minus_eta_bitlen<K>(),
1517
0
                       eta<K>());
1518
1519
0
  uint8_t *t0_output;
1520
0
  if (!CBB_add_space(out, &t0_output, 416 * K)) {
1521
0
    return 0;
1522
0
  }
1523
0
  vector_encode_signed(t0_output, &priv->t0, 13, 1 << 12);
1524
1525
0
  return 1;
1526
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_private_key<6, 5>(cbb_st*, mldsa::(anonymous namespace)::private_key<6, 5> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_private_key<8, 7>(cbb_st*, mldsa::(anonymous namespace)::private_key<8, 7> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_private_key<4, 4>(cbb_st*, mldsa::(anonymous namespace)::private_key<4, 4> const*)
1527
1528
// FIPS 204, Algorithm 25 (`skDecode`). This is only used for testing. The
1529
// supported external way to construct ML-DSA keys is to use the input seed.
1530
template <int K, int L>
1531
0
int mldsa_parse_private_key(private_key<K, L> *priv, CBS *in) {
1532
0
  CBS public_key_hash, s1_bytes, s2_bytes, t0_bytes;
1533
0
  constexpr size_t scalar_bytes =
1534
0
      (kDegree * plus_minus_eta_bitlen<K>() + 7) / 8;
1535
0
  if (!CBS_copy_bytes(in, priv->pub.rho, sizeof(priv->pub.rho)) ||
1536
0
      !CBS_copy_bytes(in, priv->k, sizeof(priv->k)) ||
1537
0
      !CBS_get_bytes(in, &public_key_hash, kTrBytes) ||
1538
0
      !CBS_get_bytes(in, &s1_bytes, scalar_bytes * L) ||
1539
0
      !vector_decode_signed(&priv->s1, CBS_data(&s1_bytes),
1540
0
                            plus_minus_eta_bitlen<K>(), eta<K>()) ||
1541
0
      !CBS_get_bytes(in, &s2_bytes, scalar_bytes * K) ||
1542
0
      !vector_decode_signed(&priv->s2, CBS_data(&s2_bytes),
1543
0
                            plus_minus_eta_bitlen<K>(), eta<K>()) ||
1544
0
      !CBS_get_bytes(in, &t0_bytes, 416 * K) ||
1545
      // Note: Decoding 13 bits into (-2^12, 2^12] cannot fail.
1546
0
      !vector_decode_signed(&priv->t0, CBS_data(&t0_bytes), 13, 1 << 12)) {
1547
0
    return 0;
1548
0
  }
1549
1550
  // Compute `t1`, which is not in the `skDecode` input.
1551
0
  uint8_t unused[public_key_bytes<K>()];
1552
0
  if (!mldsa_finish_keygen(unused, priv)) {
1553
0
    return 0;
1554
0
  }
1555
1556
  // As a side effect of computing `t1`, we also compute `t0` and
1557
  // `public_key_hash`. Check they match the received bytes.
1558
0
  uint8_t t0_computed[416 * K];
1559
0
  vector_encode_signed(t0_computed, &priv->t0, 13, 1 << 12);
1560
0
  if (!CBS_mem_equal(&public_key_hash, priv->pub.public_key_hash,
1561
0
                     sizeof(priv->pub.public_key_hash)) ||
1562
0
      !CBS_mem_equal(&t0_bytes, t0_computed, sizeof(t0_computed))) {
1563
0
    return 0;
1564
0
  }
1565
1566
0
  return 1;
1567
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_private_key<6, 5>(mldsa::(anonymous namespace)::private_key<6, 5>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_private_key<8, 7>(mldsa::(anonymous namespace)::private_key<8, 7>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_private_key<4, 4>(mldsa::(anonymous namespace)::private_key<4, 4>*, cbs_st*)
1568
1569
// FIPS 204, Algorithm 26 (`sigEncode`).
1570
template <int K, int L>
1571
0
int mldsa_marshal_signature(CBB *out, const signature<K, L> *sign) {
1572
0
  if (!CBB_add_bytes(out, sign->c_tilde, sizeof(sign->c_tilde))) {
1573
0
    return 0;
1574
0
  }
1575
1576
0
  uint8_t *vectorl_output;
1577
0
  if (!CBB_add_space(out, &vectorl_output, scalar_le_gamma1_bytes<K>() * L)) {
1578
0
    return 0;
1579
0
  }
1580
0
  vector_encode_signed(vectorl_output, &sign->z, gamma1_bits<K>() + 1,
1581
0
                       gamma1<K>());
1582
1583
0
  uint8_t *hint_output;
1584
0
  if (!CBB_add_space(out, &hint_output, omega<K>() + K)) {
1585
0
    return 0;
1586
0
  }
1587
0
  hint_bit_pack(hint_output, &sign->h);
1588
1589
0
  return 1;
1590
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_signature<6, 5>(cbb_st*, mldsa::(anonymous namespace)::signature<6, 5> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_signature<8, 7>(cbb_st*, mldsa::(anonymous namespace)::signature<8, 7> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_marshal_signature<4, 4>(cbb_st*, mldsa::(anonymous namespace)::signature<4, 4> const*)
1591
1592
// FIPS 204, Algorithm 27 (`sigDecode`).
1593
template <int K, int L>
1594
0
int mldsa_parse_signature(signature<K, L> *sign, CBS *in) {
1595
0
  CBS z_bytes;
1596
0
  CBS hint_bytes;
1597
0
  if (!CBS_copy_bytes(in, sign->c_tilde, sizeof(sign->c_tilde)) ||
1598
0
      !CBS_get_bytes(in, &z_bytes, scalar_le_gamma1_bytes<K>() * L) ||
1599
      // Note: Decoding b+1 bits into (-2^b, 2^b] cannot fail.
1600
0
      !vector_decode_signed(&sign->z, CBS_data(&z_bytes), gamma1_bits<K>() + 1,
1601
0
                            gamma1<K>()) ||
1602
0
      !CBS_get_bytes(in, &hint_bytes, omega<K>() + K) ||
1603
0
      !hint_bit_unpack(&sign->h, CBS_data(&hint_bytes))) {
1604
0
    return 0;
1605
0
  };
1606
1607
0
  return 1;
1608
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_signature<6, 5>(mldsa::(anonymous namespace)::signature<6, 5>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_signature<8, 7>(mldsa::(anonymous namespace)::signature<8, 7>*, cbs_st*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_parse_signature<4, 4>(mldsa::(anonymous namespace)::signature<4, 4>*, cbs_st*)
1609
1610
// FIPS 204, Algorithm 6 (`ML-DSA.KeyGen_internal`), steps 3 and 5–11.
1611
// Returns 1 on success and 0 on failure.
1612
template <int K, int L>
1613
int mldsa_finish_keygen(uint8_t out_encoded_public_key[public_key_bytes<K>()],
1614
0
                        private_key<K, L> *priv) {
1615
  // Intermediate values, allocated on the heap to allow use when there is a
1616
  // limited amount of stack.
1617
0
  struct Values {
1618
0
    enum { kAllowUniquePtr = true };
1619
0
    matrix<K, L> a_ntt;
1620
0
    vector<L> s1_ntt;
1621
0
    vector<K> t;
1622
0
  };
1623
0
  auto values = bssl::MakeUnique<Values>();
1624
0
  if (values == nullptr) {
1625
0
    return 0;
1626
0
  }
1627
1628
  // Step 3.
1629
0
  matrix_expand(&values->a_ntt, priv->pub.rho);
1630
1631
  // Step 5.
1632
0
  OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt));
1633
0
  vector_ntt(&values->s1_ntt);
1634
1635
0
  matrix_mult(&values->t, &values->a_ntt, &values->s1_ntt);
1636
0
  vector_inverse_ntt(&values->t);
1637
0
  vector_add(&values->t, &values->t, &priv->s2);
1638
1639
  // Step 6-7.
1640
0
  vector_power2_round(&priv->pub.t1, &priv->t0, &values->t);
1641
  // t1 is public.
1642
0
  CONSTTIME_DECLASSIFY(&priv->pub.t1, sizeof(priv->pub.t1));
1643
1644
  // Step 8.
1645
0
  CBB cbb;
1646
0
  CBB_init_fixed(&cbb, out_encoded_public_key, public_key_bytes<K>());
1647
0
  if (!mldsa_marshal_public_key(&cbb, &priv->pub)) {
1648
0
    return 0;
1649
0
  }
1650
0
  assert(CBB_len(&cbb) == public_key_bytes<K>());
1651
1652
  // Step 9-11.
1653
0
  BORINGSSL_keccak(priv->pub.public_key_hash, sizeof(priv->pub.public_key_hash),
1654
0
                   out_encoded_public_key, public_key_bytes<K>(),
1655
0
                   boringssl_shake256);
1656
1657
0
  return 1;
1658
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_finish_keygen<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5>*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_finish_keygen<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7>*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_finish_keygen<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4>*)
1659
1660
// FIPS 204, Algorithm 6 (`ML-DSA.KeyGen_internal`). Returns 1 on success and 0
1661
// on failure.
1662
template <int K, int L>
1663
int mldsa_generate_key_external_entropy_no_self_test(
1664
    uint8_t out_encoded_public_key[public_key_bytes<K>()],
1665
0
    private_key<K, L> *priv, const uint8_t entropy[MLDSA_SEED_BYTES]) {
1666
  // Step 1-2.
1667
0
  uint8_t augmented_entropy[MLDSA_SEED_BYTES + 2];
1668
0
  OPENSSL_memcpy(augmented_entropy, entropy, MLDSA_SEED_BYTES);
1669
  // The k and l parameters are appended to the seed.
1670
0
  augmented_entropy[MLDSA_SEED_BYTES] = K;
1671
0
  augmented_entropy[MLDSA_SEED_BYTES + 1] = L;
1672
0
  uint8_t expanded_seed[kRhoBytes + kSigmaBytes + kKBytes];
1673
0
  BORINGSSL_keccak(expanded_seed, sizeof(expanded_seed), augmented_entropy,
1674
0
                   sizeof(augmented_entropy), boringssl_shake256);
1675
0
  const uint8_t *const rho = expanded_seed;
1676
0
  const uint8_t *const sigma = expanded_seed + kRhoBytes;
1677
0
  const uint8_t *const k = expanded_seed + kRhoBytes + kSigmaBytes;
1678
  // rho is public.
1679
0
  CONSTTIME_DECLASSIFY(rho, kRhoBytes);
1680
0
  OPENSSL_memcpy(priv->pub.rho, rho, sizeof(priv->pub.rho));
1681
0
  OPENSSL_memcpy(priv->k, k, sizeof(priv->k));
1682
  // Step 4. This is independent of A (step 3) and can be done first.
1683
0
  vector_expand_short(&priv->s1, &priv->s2, sigma);
1684
  // Steps 3 and 5-11.
1685
0
  return mldsa_finish_keygen(out_encoded_public_key, priv);
1686
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy_no_self_test<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy_no_self_test<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy_no_self_test<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4>*, unsigned char const*)
1687
1688
template <int K, int L>
1689
int mldsa_generate_key_external_entropy(
1690
    uint8_t out_encoded_public_key[public_key_bytes<K>()],
1691
0
    private_key<K, L> *priv, const uint8_t entropy[MLDSA_SEED_BYTES]) {
1692
0
  fips::ensure_keygen_self_test();
1693
0
  return mldsa_generate_key_external_entropy_no_self_test(
1694
0
      out_encoded_public_key, priv, entropy);
1695
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7>*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_generate_key_external_entropy<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4>*, unsigned char const*)
1696
1697
// FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`), using a pre-computed mu.
1698
// Returns 1 on success and 0 on failure.
1699
template <int K, int L>
1700
int mldsa_sign_mu_no_self_test(
1701
    uint8_t out_encoded_signature[signature_bytes<K>()],
1702
    const private_key<K, L> *priv, const uint8_t mu[kMuBytes],
1703
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
1704
0
  uint8_t rho_prime[kRhoPrimeBytes];
1705
0
  BORINGSSL_keccak_st keccak_ctx;
1706
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1707
0
  BORINGSSL_keccak_absorb(&keccak_ctx, priv->k, sizeof(priv->k));
1708
0
  BORINGSSL_keccak_absorb(&keccak_ctx, randomizer,
1709
0
                          BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES);
1710
0
  BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes);
1711
0
  BORINGSSL_keccak_squeeze(&keccak_ctx, rho_prime, kRhoPrimeBytes);
1712
1713
  // Intermediate values, allocated on the heap to allow use when there is a
1714
  // limited amount of stack.
1715
0
  struct Values {
1716
0
    enum { kAllowUniquePtr = true };
1717
0
    signature<K, L> sign;
1718
0
    vector<L> s1_ntt;
1719
0
    vector<K> s2_ntt;
1720
0
    vector<K> t0_ntt;
1721
0
    matrix<K, L> a_ntt;
1722
0
    vector<L> y;
1723
0
    vector<K> w;
1724
0
    vector<K> w1;
1725
0
    vector<L> cs1;
1726
0
    vector<K> cs2;
1727
0
  };
1728
0
  auto values = bssl::MakeUnique<Values>();
1729
0
  if (values == nullptr) {
1730
0
    return 0;
1731
0
  }
1732
0
  OPENSSL_memcpy(&values->s1_ntt, &priv->s1, sizeof(values->s1_ntt));
1733
0
  vector_ntt(&values->s1_ntt);
1734
1735
0
  OPENSSL_memcpy(&values->s2_ntt, &priv->s2, sizeof(values->s2_ntt));
1736
0
  vector_ntt(&values->s2_ntt);
1737
1738
0
  OPENSSL_memcpy(&values->t0_ntt, &priv->t0, sizeof(values->t0_ntt));
1739
0
  vector_ntt(&values->t0_ntt);
1740
1741
0
  matrix_expand(&values->a_ntt, priv->pub.rho);
1742
1743
  // kappa must not exceed 2**16/L = 13107. But the probability of it
1744
  // exceeding even 1000 iterations is vanishingly small.
1745
0
  for (size_t kappa = 0;; kappa += L) {
1746
0
    vector_expand_mask<K, L>(&values->y, rho_prime, kappa);
1747
1748
0
    vector<L> *y_ntt = &values->cs1;
1749
0
    OPENSSL_memcpy(y_ntt, &values->y, sizeof(*y_ntt));
1750
0
    vector_ntt(y_ntt);
1751
1752
0
    matrix_mult(&values->w, &values->a_ntt, y_ntt);
1753
0
    vector_inverse_ntt(&values->w);
1754
1755
0
    vector_high_bits(&values->w1, &values->w);
1756
0
    uint8_t w1_encoded[w1_bytes<K>()];
1757
0
    w1_encode(w1_encoded, &values->w1);
1758
1759
0
    BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1760
0
    BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes);
1761
0
    BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes<K>());
1762
0
    BORINGSSL_keccak_squeeze(&keccak_ctx, values->sign.c_tilde,
1763
0
                             2 * lambda_bytes<K>());
1764
1765
0
    scalar c_ntt;
1766
0
    scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde,
1767
0
                                  sizeof(values->sign.c_tilde), tau<K>());
1768
0
    scalar_ntt(&c_ntt);
1769
1770
0
    vector_mult_scalar(&values->cs1, &values->s1_ntt, &c_ntt);
1771
0
    vector_inverse_ntt(&values->cs1);
1772
0
    vector_mult_scalar(&values->cs2, &values->s2_ntt, &c_ntt);
1773
0
    vector_inverse_ntt(&values->cs2);
1774
1775
0
    vector_add(&values->sign.z, &values->y, &values->cs1);
1776
1777
0
    vector<K> *r0 = &values->w1;
1778
0
    vector_sub(r0, &values->w, &values->cs2);
1779
0
    vector_low_bits(r0, r0);
1780
1781
    // Leaking the fact that a signature was rejected is fine as the next
1782
    // attempt at a signature will be (indistinguishable from) independent of
1783
    // this one. Note, however, that we additionally leak which of the two
1784
    // branches rejected the signature. Section 5.5 of
1785
    // https://pq-crystals.org/dilithium/data/dilithium-specification-round3.pdf
1786
    // describes this leak as OK. Note we leak less than what is described by
1787
    // the paper; we do not reveal which coefficient violated the bound, and
1788
    // we hide which of the |z_max| or |r0_max| bound failed. See also
1789
    // https://boringssl-review.googlesource.com/c/boringssl/+/67747/comment/2bbab0fa_d241d35a/
1790
0
    uint32_t z_max = vector_max(&values->sign.z);
1791
0
    uint32_t r0_max = vector_max_signed(r0);
1792
0
    if (constant_time_declassify_w(
1793
0
            constant_time_ge_w(z_max, gamma1<K>() - beta<K>()) |
1794
0
            constant_time_ge_w(r0_max, gamma2<K>() - beta<K>()))) {
1795
#if defined(BORINGSSL_FIPS_BREAK_TESTS)
1796
      // In order to show that our self-tests trigger both restart cases in
1797
      // this loop, printf-logging is added when built in break-test mode.
1798
      printf("MLDSA signature restart case 1.\n");
1799
#endif
1800
0
      continue;
1801
0
    }
1802
1803
0
    vector<K> *ct0 = &values->w1;
1804
0
    vector_mult_scalar(ct0, &values->t0_ntt, &c_ntt);
1805
0
    vector_inverse_ntt(ct0);
1806
0
    vector_make_hint(&values->sign.h, ct0, &values->cs2, &values->w);
1807
1808
    // See above.
1809
0
    uint32_t ct0_max = vector_max(ct0);
1810
0
    size_t h_ones = vector_count_ones(&values->sign.h);
1811
0
    if (constant_time_declassify_w(constant_time_ge_w(ct0_max, gamma2<K>()) |
1812
0
                                   constant_time_lt_w(omega<K>(), h_ones))) {
1813
#if defined(BORINGSSL_FIPS_BREAK_TESTS)
1814
      // In order to show that our self-tests trigger both restart cases in
1815
      // this loop, printf-logging is added when built in break-test mode.
1816
      printf("MLDSA signature restart case 2.\n");
1817
#endif
1818
0
      continue;
1819
0
    }
1820
1821
    // Although computed with the private key, the signature is public.
1822
0
    CONSTTIME_DECLASSIFY(values->sign.c_tilde, sizeof(values->sign.c_tilde));
1823
0
    CONSTTIME_DECLASSIFY(&values->sign.z, sizeof(values->sign.z));
1824
0
    CONSTTIME_DECLASSIFY(&values->sign.h, sizeof(values->sign.h));
1825
1826
0
    CBB cbb;
1827
0
    CBB_init_fixed(&cbb, out_encoded_signature, signature_bytes<K>());
1828
0
    if (!mldsa_marshal_signature(&cbb, &values->sign)) {
1829
0
      return 0;
1830
0
    }
1831
1832
0
    BSSL_CHECK(CBB_len(&cbb) == signature_bytes<K>());
1833
0
    return 1;
1834
0
  }
1835
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu_no_self_test<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu_no_self_test<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu_no_self_test<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4> const*, unsigned char const*, unsigned char const*)
1836
1837
// FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`), using a pre-computed mu.
1838
// Returns 1 on success and 0 on failure.
1839
template <int K, int L>
1840
int mldsa_sign_mu(
1841
    uint8_t out_encoded_signature[signature_bytes<K>()],
1842
    const private_key<K, L> *priv, const uint8_t mu[kMuBytes],
1843
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
1844
0
  fips::ensure_sign_self_test();
1845
0
  return mldsa_sign_mu_no_self_test(out_encoded_signature, priv, mu,
1846
0
                                    randomizer);
1847
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_mu<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4> const*, unsigned char const*, unsigned char const*)
1848
1849
// FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`). Returns 1 on success and 0
1850
// on failure.
1851
template <int K, int L>
1852
int mldsa_sign_internal_no_self_test(
1853
    uint8_t out_encoded_signature[signature_bytes<K>()],
1854
    const private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
1855
    const uint8_t *context_prefix, size_t context_prefix_len,
1856
    const uint8_t *context, size_t context_len,
1857
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
1858
0
  uint8_t mu[kMuBytes];
1859
0
  BORINGSSL_keccak_st keccak_ctx;
1860
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1861
0
  BORINGSSL_keccak_absorb(&keccak_ctx, priv->pub.public_key_hash,
1862
0
                          sizeof(priv->pub.public_key_hash));
1863
0
  BORINGSSL_keccak_absorb(&keccak_ctx, context_prefix, context_prefix_len);
1864
0
  BORINGSSL_keccak_absorb(&keccak_ctx, context, context_len);
1865
0
  BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len);
1866
0
  BORINGSSL_keccak_squeeze(&keccak_ctx, mu, kMuBytes);
1867
1868
0
  return mldsa_sign_mu_no_self_test(out_encoded_signature, priv, mu,
1869
0
                                    randomizer);
1870
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal_no_self_test<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal_no_self_test<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal_no_self_test<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
1871
1872
// FIPS 204, Algorithm 7 (`ML-DSA.Sign_internal`). Returns 1 on success and 0
1873
// on failure.
1874
template <int K, int L>
1875
int mldsa_sign_internal(
1876
    uint8_t out_encoded_signature[signature_bytes<K>()],
1877
    const private_key<K, L> *priv, const uint8_t *msg, size_t msg_len,
1878
    const uint8_t *context_prefix, size_t context_prefix_len,
1879
    const uint8_t *context, size_t context_len,
1880
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
1881
0
  fips::ensure_sign_self_test();
1882
0
  return mldsa_sign_internal_no_self_test(
1883
0
      out_encoded_signature, priv, msg, msg_len, context_prefix,
1884
0
      context_prefix_len, context, context_len, randomizer);
1885
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal<6, 5>(unsigned char*, mldsa::(anonymous namespace)::private_key<6, 5> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal<8, 7>(unsigned char*, mldsa::(anonymous namespace)::private_key<8, 7> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_sign_internal<4, 4>(unsigned char*, mldsa::(anonymous namespace)::private_key<4, 4> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*)
1886
1887
struct prehash_context {
1888
  BORINGSSL_keccak_st keccak_ctx;
1889
};
1890
1891
template <int K>
1892
void mldsa_prehash_init(prehash_context *out_prehash_ctx,
1893
                        const public_key<K> *pub, const uint8_t *context_prefix,
1894
                        size_t context_prefix_len, const uint8_t *context,
1895
0
                        size_t context_len) {
1896
0
  BORINGSSL_keccak_init(&out_prehash_ctx->keccak_ctx, boringssl_shake256);
1897
0
  BORINGSSL_keccak_absorb(&out_prehash_ctx->keccak_ctx, pub->public_key_hash,
1898
0
                          sizeof(pub->public_key_hash));
1899
0
  BORINGSSL_keccak_absorb(&out_prehash_ctx->keccak_ctx, context_prefix,
1900
0
                          context_prefix_len);
1901
0
  BORINGSSL_keccak_absorb(&out_prehash_ctx->keccak_ctx, context, context_len);
1902
0
}
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::mldsa_prehash_init<6>(mldsa::(anonymous namespace)::prehash_context*, mldsa::(anonymous namespace)::public_key<6> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::mldsa_prehash_init<8>(mldsa::(anonymous namespace)::prehash_context*, mldsa::(anonymous namespace)::public_key<8> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:void mldsa::(anonymous namespace)::mldsa_prehash_init<4>(mldsa::(anonymous namespace)::prehash_context*, mldsa::(anonymous namespace)::public_key<4> const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
1903
1904
void mldsa_prehash_update(prehash_context *inout_prehash_ctx,
1905
0
                          const uint8_t *msg, size_t msg_len) {
1906
0
  BORINGSSL_keccak_absorb(&inout_prehash_ctx->keccak_ctx, msg, msg_len);
1907
0
}
1908
1909
void mldsa_prehash_finalize(uint8_t out_msg_rep[kMuBytes],
1910
0
                            prehash_context *inout_prehash_ctx) {
1911
0
  BORINGSSL_keccak_squeeze(&inout_prehash_ctx->keccak_ctx, out_msg_rep,
1912
0
                           kMuBytes);
1913
0
}
1914
1915
// FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`), using a pre-computed mu.
1916
// Returns 1 on success and 0 on failure.
1917
template <int K, int L>
1918
int mldsa_verify_mu_no_self_test(
1919
    const public_key<K> *pub,
1920
    const uint8_t encoded_signature[signature_bytes<K>()],
1921
0
    const uint8_t mu[kMuBytes]) {
1922
  // Intermediate values, allocated on the heap to allow use when there is a
1923
  // limited amount of stack.
1924
0
  struct Values {
1925
0
    enum { kAllowUniquePtr = true };
1926
0
    signature<K, L> sign;
1927
0
    matrix<K, L> a_ntt;
1928
0
    vector<L> z_ntt;
1929
0
    vector<K> az_ntt;
1930
0
    vector<K> ct1_ntt;
1931
0
  };
1932
0
  auto values = bssl::MakeUnique<Values>();
1933
0
  if (values == nullptr) {
1934
0
    return 0;
1935
0
  }
1936
1937
0
  CBS cbs;
1938
0
  CBS_init(&cbs, encoded_signature, signature_bytes<K>());
1939
0
  if (!mldsa_parse_signature(&values->sign, &cbs)) {
1940
0
    return 0;
1941
0
  }
1942
1943
0
  matrix_expand(&values->a_ntt, pub->rho);
1944
1945
0
  scalar c_ntt;
1946
0
  scalar_sample_in_ball_vartime(&c_ntt, values->sign.c_tilde,
1947
0
                                sizeof(values->sign.c_tilde), tau<K>());
1948
0
  scalar_ntt(&c_ntt);
1949
1950
0
  OPENSSL_memcpy(&values->z_ntt, &values->sign.z, sizeof(values->z_ntt));
1951
0
  vector_ntt(&values->z_ntt);
1952
1953
0
  matrix_mult(&values->az_ntt, &values->a_ntt, &values->z_ntt);
1954
1955
0
  vector_scale_power2_round(&values->ct1_ntt, &pub->t1);
1956
0
  vector_ntt(&values->ct1_ntt);
1957
1958
0
  vector_mult_scalar(&values->ct1_ntt, &values->ct1_ntt, &c_ntt);
1959
1960
0
  vector<K> *const w1 = &values->az_ntt;
1961
0
  vector_sub(w1, &values->az_ntt, &values->ct1_ntt);
1962
0
  vector_inverse_ntt(w1);
1963
1964
0
  vector_use_hint_vartime(w1, &values->sign.h, w1);
1965
0
  uint8_t w1_encoded[w1_bytes<K>()];
1966
0
  w1_encode(w1_encoded, w1);
1967
1968
0
  uint8_t c_tilde[2 * lambda_bytes<K>()];
1969
0
  BORINGSSL_keccak_st keccak_ctx;
1970
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
1971
0
  BORINGSSL_keccak_absorb(&keccak_ctx, mu, kMuBytes);
1972
0
  BORINGSSL_keccak_absorb(&keccak_ctx, w1_encoded, w1_bytes<K>());
1973
0
  BORINGSSL_keccak_squeeze(&keccak_ctx, c_tilde, 2 * lambda_bytes<K>());
1974
1975
0
  uint32_t z_max = vector_max(&values->sign.z);
1976
0
  return z_max < static_cast<uint32_t>(gamma1<K>() - beta<K>()) &&
1977
0
         OPENSSL_memcmp(c_tilde, values->sign.c_tilde, 2 * lambda_bytes<K>()) ==
1978
0
             0;
1979
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu_no_self_test<6, 5>(mldsa::(anonymous namespace)::public_key<6> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu_no_self_test<8, 7>(mldsa::(anonymous namespace)::public_key<8> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu_no_self_test<4, 4>(mldsa::(anonymous namespace)::public_key<4> const*, unsigned char const*, unsigned char const*)
1980
1981
// FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`), using a pre-computed mu.
1982
// Returns 1 on success and 0 on failure.
1983
template <int K, int L>
1984
int mldsa_verify_mu(const public_key<K> *pub,
1985
                    const uint8_t encoded_signature[signature_bytes<K>()],
1986
0
                    const uint8_t mu[kMuBytes]) {
1987
0
  fips::ensure_verify_self_test();
1988
0
  return mldsa_verify_mu_no_self_test<K, L>(pub, encoded_signature, mu);
1989
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu<6, 5>(mldsa::(anonymous namespace)::public_key<6> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu<8, 7>(mldsa::(anonymous namespace)::public_key<8> const*, unsigned char const*, unsigned char const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_mu<4, 4>(mldsa::(anonymous namespace)::public_key<4> const*, unsigned char const*, unsigned char const*)
1990
1991
// FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`).
1992
template <int K, int L>
1993
int mldsa_verify_internal_no_self_test(
1994
    const public_key<K> *pub,
1995
    const uint8_t encoded_signature[signature_bytes<K>()], const uint8_t *msg,
1996
    size_t msg_len, const uint8_t *context_prefix, size_t context_prefix_len,
1997
0
    const uint8_t *context, size_t context_len) {
1998
0
  uint8_t mu[kMuBytes];
1999
0
  BORINGSSL_keccak_st keccak_ctx;
2000
0
  BORINGSSL_keccak_init(&keccak_ctx, boringssl_shake256);
2001
0
  BORINGSSL_keccak_absorb(&keccak_ctx, pub->public_key_hash,
2002
0
                          sizeof(pub->public_key_hash));
2003
0
  BORINGSSL_keccak_absorb(&keccak_ctx, context_prefix, context_prefix_len);
2004
0
  BORINGSSL_keccak_absorb(&keccak_ctx, context, context_len);
2005
0
  BORINGSSL_keccak_absorb(&keccak_ctx, msg, msg_len);
2006
0
  BORINGSSL_keccak_squeeze(&keccak_ctx, mu, kMuBytes);
2007
2008
0
  return mldsa_verify_mu_no_self_test<K, L>(pub, encoded_signature, mu);
2009
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal_no_self_test<6, 5>(mldsa::(anonymous namespace)::public_key<6> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal_no_self_test<8, 7>(mldsa::(anonymous namespace)::public_key<8> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal_no_self_test<4, 4>(mldsa::(anonymous namespace)::public_key<4> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
2010
2011
// FIPS 204, Algorithm 8 (`ML-DSA.Verify_internal`).
2012
template <int K, int L>
2013
int mldsa_verify_internal(const public_key<K> *pub,
2014
                          const uint8_t encoded_signature[signature_bytes<K>()],
2015
                          const uint8_t *msg, size_t msg_len,
2016
                          const uint8_t *context_prefix,
2017
                          size_t context_prefix_len, const uint8_t *context,
2018
0
                          size_t context_len) {
2019
0
  fips::ensure_verify_self_test();
2020
0
  return mldsa_verify_internal_no_self_test<K, L>(
2021
0
      pub, encoded_signature, msg, msg_len, context_prefix, context_prefix_len,
2022
0
      context, context_len);
2023
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal<6, 5>(mldsa::(anonymous namespace)::public_key<6> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal<8, 7>(mldsa::(anonymous namespace)::public_key<8> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::mldsa_verify_internal<4, 4>(mldsa::(anonymous namespace)::public_key<4> const*, unsigned char const*, unsigned char const*, unsigned long, unsigned char const*, unsigned long, unsigned char const*, unsigned long)
2024
2025
static_assert(sizeof(MLDSA65_private_key) == sizeof(private_key<6, 5>));
2026
static_assert(alignof(MLDSA65_private_key) == alignof(private_key<6, 5>));
2027
2028
const private_key<6, 5> *private_key_from_external_65(
2029
0
    const MLDSA65_private_key *external) {
2030
0
  return reinterpret_cast<const private_key<6, 5> *>(external);
2031
0
}
2032
0
private_key<6, 5> *private_key_from_external_65(MLDSA65_private_key *external) {
2033
0
  return reinterpret_cast<private_key<6, 5> *>(external);
2034
0
}
2035
2036
static_assert(sizeof(MLDSA65_public_key) == sizeof(public_key<6>));
2037
static_assert(alignof(MLDSA65_public_key) == alignof(public_key<6>));
2038
2039
const public_key<6> *public_key_from_external_65(
2040
0
    const MLDSA65_public_key *external) {
2041
0
  return reinterpret_cast<const public_key<6> *>(external);
2042
0
}
2043
0
public_key<6> *public_key_from_external_65(MLDSA65_public_key *external) {
2044
0
  return reinterpret_cast<public_key<6> *>(external);
2045
0
}
2046
2047
0
prehash_context *prehash_context_from_external_65(MLDSA65_prehash *external) {
2048
0
  static_assert(sizeof(MLDSA65_prehash) == sizeof(prehash_context));
2049
0
  static_assert(alignof(MLDSA65_prehash) == alignof(prehash_context));
2050
0
  return reinterpret_cast<prehash_context *>(external);
2051
0
}
2052
2053
static_assert(sizeof(MLDSA87_private_key) == sizeof(private_key<8, 7>));
2054
static_assert(alignof(MLDSA87_private_key) == alignof(private_key<8, 7>));
2055
const private_key<8, 7> *private_key_from_external_87(
2056
0
    const MLDSA87_private_key *external) {
2057
0
  return reinterpret_cast<const private_key<8, 7> *>(external);
2058
0
}
2059
0
private_key<8, 7> *private_key_from_external_87(MLDSA87_private_key *external) {
2060
0
  return reinterpret_cast<private_key<8, 7> *>(external);
2061
0
}
2062
2063
static_assert(sizeof(MLDSA87_public_key) == sizeof(public_key<8>));
2064
static_assert(alignof(MLDSA87_public_key) == alignof(public_key<8>));
2065
2066
const public_key<8> *public_key_from_external_87(
2067
0
    const MLDSA87_public_key *external) {
2068
0
  return reinterpret_cast<const public_key<8> *>(external);
2069
0
}
2070
0
public_key<8> *public_key_from_external_87(MLDSA87_public_key *external) {
2071
0
  return reinterpret_cast<public_key<8> *>(external);
2072
0
}
2073
2074
0
prehash_context *prehash_context_from_external_87(MLDSA87_prehash *external) {
2075
0
  static_assert(sizeof(MLDSA87_prehash) == sizeof(prehash_context));
2076
0
  static_assert(alignof(MLDSA87_prehash) == alignof(prehash_context));
2077
0
  return reinterpret_cast<prehash_context *>(external);
2078
0
}
2079
2080
static_assert(sizeof(MLDSA44_private_key) == sizeof(private_key<4, 4>));
2081
static_assert(alignof(MLDSA44_private_key) == alignof(private_key<4, 4>));
2082
2083
const private_key<4, 4> *private_key_from_external_44(
2084
0
    const MLDSA44_private_key *external) {
2085
0
  return reinterpret_cast<const private_key<4, 4> *>(external);
2086
0
}
2087
0
private_key<4, 4> *private_key_from_external_44(MLDSA44_private_key *external) {
2088
0
  return reinterpret_cast<private_key<4, 4> *>(external);
2089
0
}
2090
2091
static_assert(sizeof(MLDSA44_public_key) == sizeof(public_key<4>));
2092
static_assert(alignof(MLDSA44_public_key) == alignof(public_key<4>));
2093
2094
const public_key<4> *public_key_from_external_44(
2095
0
    const MLDSA44_public_key *external) {
2096
0
  return reinterpret_cast<const public_key<4> *>(external);
2097
0
}
2098
0
public_key<4> *public_key_from_external_44(MLDSA44_public_key *external) {
2099
0
  return reinterpret_cast<public_key<4> *>(external);
2100
0
}
2101
2102
0
prehash_context *prehash_context_from_external_44(MLDSA44_prehash *external) {
2103
0
  static_assert(sizeof(MLDSA44_prehash) == sizeof(prehash_context));
2104
0
  static_assert(alignof(MLDSA44_prehash) == alignof(prehash_context));
2105
0
  return reinterpret_cast<prehash_context *>(external);
2106
0
}
2107
2108
namespace fips {
2109
2110
#include "fips_known_values.inc"
2111
2112
0
static int keygen_self_test() {
2113
0
  struct Values {
2114
0
    enum { kAllowUniquePtr = true };
2115
0
    private_key<6, 5> priv;
2116
0
    uint8_t pub_bytes[MLDSA65_PUBLIC_KEY_BYTES];
2117
0
    uint8_t priv_bytes[BCM_MLDSA65_PRIVATE_KEY_BYTES];
2118
0
  };
2119
0
  auto values = bssl::MakeUnique<Values>();
2120
0
  if (values == nullptr ||
2121
0
      !mldsa_generate_key_external_entropy_no_self_test(
2122
0
          values->pub_bytes, &values->priv, kGenerateKeyEntropy)) {
2123
0
    return 0;
2124
0
  }
2125
2126
0
  CBB cbb;
2127
0
  CBB_init_fixed(&cbb, values->priv_bytes, sizeof(values->priv_bytes));
2128
0
  if (!mldsa_marshal_private_key(&cbb, &values->priv)) {
2129
0
    return 0;
2130
0
  }
2131
2132
0
  static_assert(sizeof(values->pub_bytes) == sizeof(kExpectedPublicKey));
2133
0
  static_assert(sizeof(values->priv_bytes) == sizeof(kExpectedPrivateKey));
2134
0
  if (!BORINGSSL_check_test(kExpectedPublicKey, values->pub_bytes,
2135
0
                            sizeof(values->pub_bytes),
2136
0
                            "ML-DSA keygen public key") ||
2137
0
      !BORINGSSL_check_test(kExpectedPrivateKey, values->priv_bytes,
2138
0
                            sizeof(values->priv_bytes),
2139
0
                            "ML-DSA keygen private key")) {
2140
0
    return 0;
2141
0
  }
2142
2143
0
  return 1;
2144
0
}
2145
2146
0
static int sign_self_test() {
2147
0
  struct Values {
2148
0
    enum { kAllowUniquePtr = true };
2149
0
    private_key<6, 5> priv;
2150
0
    uint8_t pub_bytes[MLDSA65_PUBLIC_KEY_BYTES];
2151
0
    uint8_t sig[MLDSA65_SIGNATURE_BYTES];
2152
0
  };
2153
0
  auto values = bssl::MakeUnique<Values>();
2154
0
  if (values == nullptr ||
2155
0
      !mldsa_generate_key_external_entropy(values->pub_bytes, &values->priv,
2156
0
                                           kSignEntropy)) {
2157
0
    return 0;
2158
0
  }
2159
2160
0
  const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
2161
2162
  // This message triggers the first restart case for signing.
2163
0
  uint8_t message[4] = {0};
2164
0
  if (!mldsa_sign_internal_no_self_test(values->sig, &values->priv, message,
2165
0
                                        sizeof(message), nullptr, 0, nullptr, 0,
2166
0
                                        randomizer)) {
2167
0
    return 0;
2168
0
  }
2169
0
  static_assert(sizeof(kExpectedCase1Signature) == sizeof(values->sig));
2170
0
  if (!BORINGSSL_check_test(kExpectedCase1Signature, values->sig,
2171
0
                            sizeof(values->sig), "ML-DSA sign case 1")) {
2172
0
    return 0;
2173
0
  }
2174
2175
  // This message triggers the second restart case for signing.
2176
0
  message[0] = 123;
2177
0
  if (!mldsa_sign_internal_no_self_test(values->sig, &values->priv, message,
2178
0
                                        sizeof(message), nullptr, 0, nullptr, 0,
2179
0
                                        randomizer)) {
2180
0
    return 0;
2181
0
  }
2182
0
  static_assert(sizeof(kExpectedCase2Signature) == sizeof(values->sig));
2183
0
  if (!BORINGSSL_check_test(kExpectedCase2Signature, values->sig,
2184
0
                            sizeof(values->sig), "ML-DSA sign case 2")) {
2185
0
    return 0;
2186
0
  }
2187
2188
0
  return 1;
2189
0
}
2190
2191
0
static int verify_self_test() {
2192
0
  struct Values {
2193
0
    enum { kAllowUniquePtr = true };
2194
0
    private_key<6, 5> priv;
2195
0
    uint8_t pub_bytes[MLDSA65_PUBLIC_KEY_BYTES];
2196
0
  };
2197
0
  auto values = bssl::MakeUnique<Values>();
2198
0
  if (values == nullptr) {
2199
0
    return 0;
2200
0
  }
2201
2202
0
  if (!mldsa_generate_key_external_entropy(values->pub_bytes, &values->priv,
2203
0
                                           kSignEntropy)) {
2204
0
    return 0;
2205
0
  }
2206
2207
0
  const uint8_t message[4] = {1, 0};
2208
0
  if (!mldsa_verify_internal_no_self_test<6, 5>(
2209
0
          &values->priv.pub, kExpectedVerifySignature, message, sizeof(message),
2210
0
          nullptr, 0, nullptr, 0)) {
2211
0
    return 0;
2212
0
  }
2213
2214
0
  return 1;
2215
0
}
2216
2217
template <int K, int L>
2218
0
int check_key(const private_key<K, L> *priv) {
2219
0
  uint8_t sig[signature_bytes<K>()];
2220
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES] = {};
2221
0
  if (!mldsa_sign_internal_no_self_test(sig, priv, nullptr, 0, nullptr, 0,
2222
0
                                        nullptr, 0, randomizer)) {
2223
0
    return 0;
2224
0
  }
2225
2226
0
  if (boringssl_fips_break_test("MLDSA_PWCT")) {
2227
0
    sig[0] ^= 1;
2228
0
  }
2229
2230
0
  if (!mldsa_verify_internal_no_self_test<K, L>(&priv->pub, sig, nullptr, 0,
2231
0
                                                nullptr, 0, nullptr, 0)) {
2232
0
    return 0;
2233
0
  }
2234
0
  return 1;
2235
0
}
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::fips::check_key<6, 5>(mldsa::(anonymous namespace)::private_key<6, 5> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::fips::check_key<8, 7>(mldsa::(anonymous namespace)::private_key<8, 7> const*)
Unexecuted instantiation: bcm.cc:int mldsa::(anonymous namespace)::fips::check_key<4, 4>(mldsa::(anonymous namespace)::private_key<4, 4> const*)
2236
2237
#if defined(BORINGSSL_FIPS)
2238
2239
DEFINE_STATIC_ONCE(g_mldsa_keygen_self_test_once)
2240
2241
void ensure_keygen_self_test(void) {
2242
  CRYPTO_once(g_mldsa_keygen_self_test_once_bss_get(), []() {
2243
    if (!keygen_self_test()) {
2244
      BORINGSSL_FIPS_abort();
2245
    }
2246
  });
2247
}
2248
2249
DEFINE_STATIC_ONCE(g_mldsa_sign_self_test_once)
2250
2251
void ensure_sign_self_test(void) {
2252
  CRYPTO_once(g_mldsa_sign_self_test_once_bss_get(), []() {
2253
    if (!sign_self_test()) {
2254
      BORINGSSL_FIPS_abort();
2255
    }
2256
  });
2257
}
2258
2259
DEFINE_STATIC_ONCE(g_mldsa_verify_self_test_once)
2260
2261
void ensure_verify_self_test(void) {
2262
  CRYPTO_once(g_mldsa_verify_self_test_once_bss_get(), []() {
2263
    if (!verify_self_test()) {
2264
      BORINGSSL_FIPS_abort();
2265
    }
2266
  });
2267
}
2268
2269
#else
2270
2271
0
void ensure_keygen_self_test(void) {}
2272
0
void ensure_sign_self_test(void) {}
2273
0
void ensure_verify_self_test(void) {}
2274
2275
#endif
2276
2277
}  // namespace fips
2278
2279
}  // namespace
2280
}  // namespace mldsa
2281
2282
2283
// ML-DSA-65 specific wrappers.
2284
2285
bcm_status BCM_mldsa65_parse_public_key(MLDSA65_public_key *public_key,
2286
0
                                        CBS *in) {
2287
0
  return bcm_as_approved_status(mldsa_parse_public_key(
2288
0
      mldsa::public_key_from_external_65(public_key), in));
2289
0
}
2290
2291
bcm_status BCM_mldsa65_marshal_private_key(
2292
0
    CBB *out, const MLDSA65_private_key *private_key) {
2293
0
  return bcm_as_approved_status(mldsa_marshal_private_key(
2294
0
      out, mldsa::private_key_from_external_65(private_key)));
2295
0
}
2296
2297
bcm_status BCM_mldsa65_parse_private_key(MLDSA65_private_key *private_key,
2298
0
                                         CBS *in) {
2299
0
  return bcm_as_approved_status(
2300
0
      mldsa_parse_private_key(mldsa::private_key_from_external_65(private_key),
2301
0
                              in) &&
2302
0
      CBS_len(in) == 0);
2303
0
}
2304
2305
0
bcm_status BCM_mldsa65_check_key_fips(MLDSA65_private_key *private_key) {
2306
0
  return bcm_as_approved_status(
2307
0
      mldsa::fips::check_key(mldsa::private_key_from_external_65(private_key)));
2308
0
}
2309
2310
// Calls |MLDSA_generate_key_external_entropy| with random bytes from
2311
// |BCM_rand_bytes|.
2312
bcm_status BCM_mldsa65_generate_key(
2313
    uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES],
2314
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA65_private_key *out_private_key) {
2315
0
  BCM_rand_bytes(out_seed, MLDSA_SEED_BYTES);
2316
0
  CONSTTIME_SECRET(out_seed, MLDSA_SEED_BYTES);
2317
0
  return BCM_mldsa65_generate_key_external_entropy(out_encoded_public_key,
2318
0
                                                   out_private_key, out_seed);
2319
0
}
2320
2321
bcm_status BCM_mldsa65_private_key_from_seed(
2322
    MLDSA65_private_key *out_private_key,
2323
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2324
0
  uint8_t public_key[MLDSA65_PUBLIC_KEY_BYTES];
2325
0
  return BCM_mldsa65_generate_key_external_entropy(public_key, out_private_key,
2326
0
                                                   seed);
2327
0
}
2328
2329
bcm_status BCM_mldsa65_generate_key_external_entropy(
2330
    uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES],
2331
    MLDSA65_private_key *out_private_key,
2332
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2333
0
  return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
2334
0
      out_encoded_public_key,
2335
0
      mldsa::private_key_from_external_65(out_private_key), entropy));
2336
0
}
2337
2338
bcm_status BCM_mldsa65_generate_key_fips(
2339
    uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES],
2340
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA65_private_key *out_private_key) {
2341
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2342
0
    return bcm_status::failure;
2343
0
  }
2344
0
  if (BCM_mldsa65_generate_key(out_encoded_public_key, out_seed,
2345
0
                               out_private_key) == bcm_status::failure) {
2346
0
    return bcm_status::failure;
2347
0
  }
2348
0
  return BCM_mldsa65_check_key_fips(out_private_key);
2349
0
}
2350
2351
bcm_status BCM_mldsa65_generate_key_external_entropy_fips(
2352
    uint8_t out_encoded_public_key[MLDSA65_PUBLIC_KEY_BYTES],
2353
    MLDSA65_private_key *out_private_key,
2354
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2355
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2356
0
    return bcm_status::failure;
2357
0
  }
2358
0
  if (BCM_mldsa65_generate_key_external_entropy(out_encoded_public_key,
2359
0
                                                out_private_key, entropy) ==
2360
0
      bcm_status::failure) {
2361
0
    return bcm_status::failure;
2362
0
  }
2363
0
  return BCM_mldsa65_check_key_fips(out_private_key);
2364
0
}
2365
2366
bcm_status BCM_mldsa65_private_key_from_seed_fips(
2367
    MLDSA65_private_key *out_private_key,
2368
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2369
0
  uint8_t public_key[MLDSA65_PUBLIC_KEY_BYTES];
2370
0
  if (BCM_mldsa65_generate_key_external_entropy(public_key, out_private_key,
2371
0
                                                seed) == bcm_status::failure) {
2372
0
    return bcm_status::failure;
2373
0
  }
2374
0
  return BCM_mldsa65_check_key_fips(out_private_key);
2375
0
}
2376
2377
bcm_status BCM_mldsa65_public_from_private(
2378
    MLDSA65_public_key *out_public_key,
2379
0
    const MLDSA65_private_key *private_key) {
2380
0
  const auto *priv = mldsa::private_key_from_external_65(private_key);
2381
0
  auto *out_pub = mldsa::public_key_from_external_65(out_public_key);
2382
0
  *out_pub = priv->pub;
2383
0
  return bcm_status::approved;
2384
0
}
2385
2386
const MLDSA65_public_key *BCM_mldsa65_public_of_private(
2387
0
    const MLDSA65_private_key *private_key) {
2388
0
  return reinterpret_cast<const MLDSA65_public_key *>(
2389
0
      &mldsa::private_key_from_external_65(private_key)->pub);
2390
0
}
2391
2392
bcm_status BCM_mldsa65_sign_internal(
2393
    uint8_t out_encoded_signature[MLDSA65_SIGNATURE_BYTES],
2394
    const MLDSA65_private_key *private_key, const uint8_t *msg, size_t msg_len,
2395
    const uint8_t *context_prefix, size_t context_prefix_len,
2396
    const uint8_t *context, size_t context_len,
2397
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2398
0
  return bcm_as_approved_status(mldsa_sign_internal(
2399
0
      out_encoded_signature, mldsa::private_key_from_external_65(private_key),
2400
0
      msg, msg_len, context_prefix, context_prefix_len, context, context_len,
2401
0
      randomizer));
2402
0
}
2403
2404
bcm_status BCM_mldsa65_sign_mu_internal(
2405
    uint8_t out_encoded_signature[MLDSA65_SIGNATURE_BYTES],
2406
    const MLDSA65_private_key *private_key,
2407
    const uint8_t msg_rep[MLDSA_MU_BYTES],
2408
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2409
0
  return bcm_as_approved_status(mldsa_sign_mu(
2410
0
      out_encoded_signature, mldsa::private_key_from_external_65(private_key),
2411
0
      msg_rep, randomizer));
2412
0
}
2413
2414
// ML-DSA signature in randomized mode, filling the random bytes with
2415
// |BCM_rand_bytes|.
2416
bcm_status BCM_mldsa65_sign(
2417
    uint8_t out_encoded_signature[MLDSA65_SIGNATURE_BYTES],
2418
    const MLDSA65_private_key *private_key, const uint8_t *msg, size_t msg_len,
2419
0
    const uint8_t *context, size_t context_len) {
2420
0
  BSSL_CHECK(context_len <= 255);
2421
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2422
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2423
0
  CONSTTIME_SECRET(randomizer, sizeof(randomizer));
2424
2425
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2426
0
  return BCM_mldsa65_sign_internal(
2427
0
      out_encoded_signature, private_key, msg, msg_len, context_prefix,
2428
0
      sizeof(context_prefix), context, context_len, randomizer);
2429
0
}
2430
2431
// ML-DSA pre-hashed API: initializing a pre-hashing context.
2432
void BCM_mldsa65_prehash_init(MLDSA65_prehash *out_prehash_ctx,
2433
                              const MLDSA65_public_key *public_key,
2434
0
                              const uint8_t *context, size_t context_len) {
2435
0
  BSSL_CHECK(context_len <= 255);
2436
2437
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2438
0
  mldsa_prehash_init(mldsa::prehash_context_from_external_65(out_prehash_ctx),
2439
0
                     mldsa::public_key_from_external_65(public_key),
2440
0
                     context_prefix, sizeof(context_prefix), context,
2441
0
                     context_len);
2442
0
}
2443
2444
// ML-DSA pre-hashed API: updating a pre-hashing context with a message chunk.
2445
void BCM_mldsa65_prehash_update(MLDSA65_prehash *inout_prehash_ctx,
2446
0
                                const uint8_t *msg, size_t msg_len) {
2447
0
  mldsa_prehash_update(
2448
0
      mldsa::prehash_context_from_external_65(inout_prehash_ctx), msg, msg_len);
2449
0
}
2450
2451
// ML-DSA pre-hashed API: obtaining a message representative to sign.
2452
void BCM_mldsa65_prehash_finalize(uint8_t out_msg_rep[MLDSA_MU_BYTES],
2453
0
                                  MLDSA65_prehash *inout_prehash_ctx) {
2454
0
  mldsa_prehash_finalize(
2455
0
      out_msg_rep, mldsa::prehash_context_from_external_65(inout_prehash_ctx));
2456
0
}
2457
2458
// ML-DSA pre-hashed API: signing a message representative.
2459
bcm_status BCM_mldsa65_sign_message_representative(
2460
    uint8_t out_encoded_signature[MLDSA65_SIGNATURE_BYTES],
2461
    const MLDSA65_private_key *private_key,
2462
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2463
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2464
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2465
0
  CONSTTIME_SECRET(randomizer, sizeof(randomizer));
2466
2467
0
  return bcm_as_approved_status(mldsa_sign_mu(
2468
0
      out_encoded_signature, mldsa::private_key_from_external_65(private_key),
2469
0
      msg_rep, randomizer));
2470
0
}
2471
2472
// ML-DSA pre-hashed API: verifying a message representative.
2473
bcm_status BCM_mldsa65_verify_message_representative(
2474
    const MLDSA65_public_key *public_key,
2475
    const uint8_t signature[MLDSA65_SIGNATURE_BYTES],
2476
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2477
0
  return bcm_as_approved_status(mldsa::mldsa_verify_mu<6, 5>(
2478
0
      mldsa::public_key_from_external_65(public_key), signature, msg_rep));
2479
0
}
2480
2481
// FIPS 204, Algorithm 3 (`ML-DSA.Verify`).
2482
bcm_status BCM_mldsa65_verify(const MLDSA65_public_key *public_key,
2483
                              const uint8_t signature[MLDSA65_SIGNATURE_BYTES],
2484
                              const uint8_t *msg, size_t msg_len,
2485
0
                              const uint8_t *context, size_t context_len) {
2486
0
  BSSL_CHECK(context_len <= 255);
2487
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2488
0
  return BCM_mldsa65_verify_internal(public_key, signature, msg, msg_len,
2489
0
                                     context_prefix, sizeof(context_prefix),
2490
0
                                     context, context_len);
2491
0
}
2492
2493
bcm_status BCM_mldsa65_verify_internal(
2494
    const MLDSA65_public_key *public_key,
2495
    const uint8_t encoded_signature[MLDSA65_SIGNATURE_BYTES],
2496
    const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix,
2497
0
    size_t context_prefix_len, const uint8_t *context, size_t context_len) {
2498
0
  return bcm_as_approved_status(mldsa::mldsa_verify_internal<6, 5>(
2499
0
      mldsa::public_key_from_external_65(public_key), encoded_signature, msg,
2500
0
      msg_len, context_prefix, context_prefix_len, context, context_len));
2501
0
}
2502
2503
bcm_status BCM_mldsa65_marshal_public_key(
2504
0
    CBB *out, const MLDSA65_public_key *public_key) {
2505
0
  return bcm_as_approved_status(mldsa_marshal_public_key(
2506
0
      out, mldsa::public_key_from_external_65(public_key)));
2507
0
}
2508
2509
int BCM_mldsa65_public_keys_equal(const MLDSA65_public_key *a,
2510
0
                                  const MLDSA65_public_key *b) {
2511
0
  auto *a_pub = mldsa::public_key_from_external_65(a);
2512
0
  auto *b_pub = mldsa::public_key_from_external_65(b);
2513
  // It is sufficient to compare |public_key_hash|. When importing a public key,
2514
  // the hash must be computed. When importing a private key in expanded form
2515
  // (an internal testing-only API), the hash is provided, but we recompute it
2516
  // and check for correctness.
2517
0
  return OPENSSL_memcmp(a_pub->public_key_hash, b_pub->public_key_hash,
2518
0
                        sizeof(a_pub->public_key_hash)) == 0;
2519
0
}
2520
2521
2522
// ML-DSA-87 specific wrappers.
2523
2524
bcm_status BCM_mldsa87_parse_public_key(MLDSA87_public_key *public_key,
2525
0
                                        CBS *in) {
2526
0
  return bcm_as_approved_status(mldsa_parse_public_key(
2527
0
      mldsa::public_key_from_external_87(public_key), in));
2528
0
}
2529
2530
bcm_status BCM_mldsa87_marshal_private_key(
2531
0
    CBB *out, const MLDSA87_private_key *private_key) {
2532
0
  return bcm_as_approved_status(mldsa_marshal_private_key(
2533
0
      out, mldsa::private_key_from_external_87(private_key)));
2534
0
}
2535
2536
bcm_status BCM_mldsa87_parse_private_key(MLDSA87_private_key *private_key,
2537
0
                                         CBS *in) {
2538
0
  return bcm_as_approved_status(
2539
0
      mldsa_parse_private_key(mldsa::private_key_from_external_87(private_key),
2540
0
                              in) &&
2541
0
      CBS_len(in) == 0);
2542
0
}
2543
2544
0
bcm_status BCM_mldsa87_check_key_fips(MLDSA87_private_key *private_key) {
2545
0
  return bcm_as_approved_status(
2546
0
      mldsa::fips::check_key(mldsa::private_key_from_external_87(private_key)));
2547
0
}
2548
2549
// Calls |MLDSA_generate_key_external_entropy| with random bytes from
2550
// |BCM_rand_bytes|.
2551
bcm_status BCM_mldsa87_generate_key(
2552
    uint8_t out_encoded_public_key[MLDSA87_PUBLIC_KEY_BYTES],
2553
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA87_private_key *out_private_key) {
2554
0
  BCM_rand_bytes(out_seed, MLDSA_SEED_BYTES);
2555
0
  return BCM_mldsa87_generate_key_external_entropy(out_encoded_public_key,
2556
0
                                                   out_private_key, out_seed);
2557
0
}
2558
2559
bcm_status BCM_mldsa87_private_key_from_seed(
2560
    MLDSA87_private_key *out_private_key,
2561
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2562
0
  uint8_t public_key[MLDSA87_PUBLIC_KEY_BYTES];
2563
0
  return BCM_mldsa87_generate_key_external_entropy(public_key, out_private_key,
2564
0
                                                   seed);
2565
0
}
2566
2567
bcm_status BCM_mldsa87_generate_key_external_entropy(
2568
    uint8_t out_encoded_public_key[MLDSA87_PUBLIC_KEY_BYTES],
2569
    MLDSA87_private_key *out_private_key,
2570
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2571
0
  return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
2572
0
      out_encoded_public_key,
2573
0
      mldsa::private_key_from_external_87(out_private_key), entropy));
2574
0
}
2575
2576
bcm_status BCM_mldsa87_generate_key_fips(
2577
    uint8_t out_encoded_public_key[MLDSA87_PUBLIC_KEY_BYTES],
2578
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA87_private_key *out_private_key) {
2579
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2580
0
    return bcm_status::failure;
2581
0
  }
2582
0
  if (BCM_mldsa87_generate_key(out_encoded_public_key, out_seed,
2583
0
                               out_private_key) == bcm_status::failure) {
2584
0
    return bcm_status::failure;
2585
0
  }
2586
0
  return BCM_mldsa87_check_key_fips(out_private_key);
2587
0
}
2588
2589
bcm_status BCM_mldsa87_generate_key_external_entropy_fips(
2590
    uint8_t out_encoded_public_key[MLDSA87_PUBLIC_KEY_BYTES],
2591
    MLDSA87_private_key *out_private_key,
2592
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2593
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2594
0
    return bcm_status::failure;
2595
0
  }
2596
0
  if (BCM_mldsa87_generate_key_external_entropy(out_encoded_public_key,
2597
0
                                                out_private_key, entropy) ==
2598
0
      bcm_status::failure) {
2599
0
    return bcm_status::failure;
2600
0
  }
2601
0
  return BCM_mldsa87_check_key_fips(out_private_key);
2602
0
}
2603
2604
bcm_status BCM_mldsa87_private_key_from_seed_fips(
2605
    MLDSA87_private_key *out_private_key,
2606
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2607
0
  uint8_t public_key[MLDSA87_PUBLIC_KEY_BYTES];
2608
0
  if (BCM_mldsa87_generate_key_external_entropy(public_key, out_private_key,
2609
0
                                                seed) == bcm_status::failure) {
2610
0
    return bcm_status::failure;
2611
0
  }
2612
0
  return BCM_mldsa87_check_key_fips(out_private_key);
2613
0
}
2614
2615
bcm_status BCM_mldsa87_public_from_private(
2616
    MLDSA87_public_key *out_public_key,
2617
0
    const MLDSA87_private_key *private_key) {
2618
0
  const auto *priv = mldsa::private_key_from_external_87(private_key);
2619
0
  auto *out_pub = mldsa::public_key_from_external_87(out_public_key);
2620
0
  *out_pub = priv->pub;
2621
0
  return bcm_status::approved;
2622
0
}
2623
2624
const MLDSA87_public_key *BCM_mldsa87_public_of_private(
2625
0
    const MLDSA87_private_key *private_key) {
2626
0
  return reinterpret_cast<const MLDSA87_public_key *>(
2627
0
      &mldsa::private_key_from_external_87(private_key)->pub);
2628
0
}
2629
2630
bcm_status BCM_mldsa87_sign_internal(
2631
    uint8_t out_encoded_signature[MLDSA87_SIGNATURE_BYTES],
2632
    const MLDSA87_private_key *private_key, const uint8_t *msg, size_t msg_len,
2633
    const uint8_t *context_prefix, size_t context_prefix_len,
2634
    const uint8_t *context, size_t context_len,
2635
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2636
0
  return bcm_as_approved_status(mldsa_sign_internal(
2637
0
      out_encoded_signature, mldsa::private_key_from_external_87(private_key),
2638
0
      msg, msg_len, context_prefix, context_prefix_len, context, context_len,
2639
0
      randomizer));
2640
0
}
2641
2642
bcm_status BCM_mldsa87_sign_mu_internal(
2643
    uint8_t out_encoded_signature[MLDSA87_SIGNATURE_BYTES],
2644
    const MLDSA87_private_key *private_key,
2645
    const uint8_t msg_rep[MLDSA_MU_BYTES],
2646
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2647
0
  return bcm_as_approved_status(mldsa_sign_mu(
2648
0
      out_encoded_signature, mldsa::private_key_from_external_87(private_key),
2649
0
      msg_rep, randomizer));
2650
0
}
2651
2652
// ML-DSA signature in randomized mode, filling the random bytes with
2653
// |BCM_rand_bytes|.
2654
bcm_status BCM_mldsa87_sign(
2655
    uint8_t out_encoded_signature[MLDSA87_SIGNATURE_BYTES],
2656
    const MLDSA87_private_key *private_key, const uint8_t *msg, size_t msg_len,
2657
0
    const uint8_t *context, size_t context_len) {
2658
0
  BSSL_CHECK(context_len <= 255);
2659
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2660
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2661
2662
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2663
0
  return BCM_mldsa87_sign_internal(
2664
0
      out_encoded_signature, private_key, msg, msg_len, context_prefix,
2665
0
      sizeof(context_prefix), context, context_len, randomizer);
2666
0
}
2667
2668
// ML-DSA pre-hashed API: initializing a pre-hashing context.
2669
void BCM_mldsa87_prehash_init(MLDSA87_prehash *out_prehash_ctx,
2670
                              const MLDSA87_public_key *public_key,
2671
0
                              const uint8_t *context, size_t context_len) {
2672
0
  BSSL_CHECK(context_len <= 255);
2673
2674
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2675
0
  mldsa_prehash_init(mldsa::prehash_context_from_external_87(out_prehash_ctx),
2676
0
                     mldsa::public_key_from_external_87(public_key),
2677
0
                     context_prefix, sizeof(context_prefix), context,
2678
0
                     context_len);
2679
0
}
2680
2681
// ML-DSA pre-hashed API: updating a pre-hashing context with a message chunk.
2682
void BCM_mldsa87_prehash_update(MLDSA87_prehash *inout_prehash_ctx,
2683
0
                                const uint8_t *msg, size_t msg_len) {
2684
0
  mldsa_prehash_update(
2685
0
      mldsa::prehash_context_from_external_87(inout_prehash_ctx), msg, msg_len);
2686
0
}
2687
2688
// ML-DSA pre-hashed API: obtaining a message representative to sign.
2689
void BCM_mldsa87_prehash_finalize(uint8_t out_msg_rep[MLDSA_MU_BYTES],
2690
0
                                  MLDSA87_prehash *inout_prehash_ctx) {
2691
0
  mldsa_prehash_finalize(
2692
0
      out_msg_rep, mldsa::prehash_context_from_external_87(inout_prehash_ctx));
2693
0
}
2694
2695
// ML-DSA pre-hashed API: signing a message representative.
2696
bcm_status BCM_mldsa87_sign_message_representative(
2697
    uint8_t out_encoded_signature[MLDSA87_SIGNATURE_BYTES],
2698
    const MLDSA87_private_key *private_key,
2699
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2700
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2701
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2702
0
  CONSTTIME_SECRET(randomizer, sizeof(randomizer));
2703
2704
0
  return bcm_as_approved_status(mldsa_sign_mu(
2705
0
      out_encoded_signature, mldsa::private_key_from_external_87(private_key),
2706
0
      msg_rep, randomizer));
2707
0
}
2708
2709
// ML-DSA pre-hashed API: verifying a message representative.
2710
bcm_status BCM_mldsa87_verify_message_representative(
2711
    const MLDSA87_public_key *public_key,
2712
    const uint8_t signature[MLDSA87_SIGNATURE_BYTES],
2713
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2714
0
  return bcm_as_approved_status(mldsa::mldsa_verify_mu<8, 7>(
2715
0
      mldsa::public_key_from_external_87(public_key), signature, msg_rep));
2716
0
}
2717
2718
// FIPS 204, Algorithm 3 (`ML-DSA.Verify`).
2719
bcm_status BCM_mldsa87_verify(const MLDSA87_public_key *public_key,
2720
                              const uint8_t *signature, const uint8_t *msg,
2721
                              size_t msg_len, const uint8_t *context,
2722
0
                              size_t context_len) {
2723
0
  BSSL_CHECK(context_len <= 255);
2724
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2725
0
  return BCM_mldsa87_verify_internal(public_key, signature, msg, msg_len,
2726
0
                                     context_prefix, sizeof(context_prefix),
2727
0
                                     context, context_len);
2728
0
}
2729
2730
bcm_status BCM_mldsa87_verify_internal(
2731
    const MLDSA87_public_key *public_key,
2732
    const uint8_t encoded_signature[MLDSA87_SIGNATURE_BYTES],
2733
    const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix,
2734
0
    size_t context_prefix_len, const uint8_t *context, size_t context_len) {
2735
0
  return bcm_as_approved_status(mldsa::mldsa_verify_internal<8, 7>(
2736
0
      mldsa::public_key_from_external_87(public_key), encoded_signature, msg,
2737
0
      msg_len, context_prefix, context_prefix_len, context, context_len));
2738
0
}
2739
2740
bcm_status BCM_mldsa87_marshal_public_key(
2741
0
    CBB *out, const MLDSA87_public_key *public_key) {
2742
0
  return bcm_as_approved_status(mldsa_marshal_public_key(
2743
0
      out, mldsa::public_key_from_external_87(public_key)));
2744
0
}
2745
2746
int BCM_mldsa87_public_keys_equal(const MLDSA87_public_key *a,
2747
0
                                  const MLDSA87_public_key *b) {
2748
0
  auto *a_pub = mldsa::public_key_from_external_87(a);
2749
0
  auto *b_pub = mldsa::public_key_from_external_87(b);
2750
  // It is sufficient to compare |public_key_hash|. When importing a public key,
2751
  // the hash must be computed. When importing a private key in expanded form
2752
  // (an internal testing-only API), the hash is provided, but we recompute it
2753
  // and check for correctness.
2754
0
  return OPENSSL_memcmp(a_pub->public_key_hash, b_pub->public_key_hash,
2755
0
                        sizeof(a_pub->public_key_hash)) == 0;
2756
0
}
2757
2758
2759
// ML-DSA-44 specific wrappers.
2760
2761
bcm_status BCM_mldsa44_parse_public_key(MLDSA44_public_key *public_key,
2762
0
                                        CBS *in) {
2763
0
  return bcm_as_approved_status(mldsa_parse_public_key(
2764
0
      mldsa::public_key_from_external_44(public_key), in));
2765
0
}
2766
2767
bcm_status BCM_mldsa44_marshal_private_key(
2768
0
    CBB *out, const MLDSA44_private_key *private_key) {
2769
0
  return bcm_as_approved_status(mldsa_marshal_private_key(
2770
0
      out, mldsa::private_key_from_external_44(private_key)));
2771
0
}
2772
2773
bcm_status BCM_mldsa44_parse_private_key(MLDSA44_private_key *private_key,
2774
0
                                         CBS *in) {
2775
0
  return bcm_as_approved_status(
2776
0
      mldsa_parse_private_key(mldsa::private_key_from_external_44(private_key),
2777
0
                              in) &&
2778
0
      CBS_len(in) == 0);
2779
0
}
2780
2781
0
bcm_status BCM_mldsa44_check_key_fips(MLDSA44_private_key *private_key) {
2782
0
  return bcm_as_approved_status(
2783
0
      mldsa::fips::check_key(mldsa::private_key_from_external_44(private_key)));
2784
0
}
2785
2786
// Calls |MLDSA_generate_key_external_entropy| with random bytes from
2787
// |BCM_rand_bytes|.
2788
bcm_status BCM_mldsa44_generate_key(
2789
    uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES],
2790
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA44_private_key *out_private_key) {
2791
0
  BCM_rand_bytes(out_seed, MLDSA_SEED_BYTES);
2792
0
  return BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key,
2793
0
                                                   out_private_key, out_seed);
2794
0
}
2795
2796
bcm_status BCM_mldsa44_private_key_from_seed(
2797
    MLDSA44_private_key *out_private_key,
2798
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2799
0
  uint8_t public_key[MLDSA44_PUBLIC_KEY_BYTES];
2800
0
  return BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key,
2801
0
                                                   seed);
2802
0
}
2803
2804
bcm_status BCM_mldsa44_generate_key_external_entropy(
2805
    uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES],
2806
    MLDSA44_private_key *out_private_key,
2807
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2808
0
  return bcm_as_not_approved_status(mldsa_generate_key_external_entropy(
2809
0
      out_encoded_public_key,
2810
0
      mldsa::private_key_from_external_44(out_private_key), entropy));
2811
0
}
2812
2813
bcm_status BCM_mldsa44_generate_key_fips(
2814
    uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES],
2815
0
    uint8_t out_seed[MLDSA_SEED_BYTES], MLDSA44_private_key *out_private_key) {
2816
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2817
0
    return bcm_status::failure;
2818
0
  }
2819
0
  if (BCM_mldsa44_generate_key(out_encoded_public_key, out_seed,
2820
0
                               out_private_key) == bcm_status::failure) {
2821
0
    return bcm_status::failure;
2822
0
  }
2823
0
  return BCM_mldsa44_check_key_fips(out_private_key);
2824
0
}
2825
2826
bcm_status BCM_mldsa44_generate_key_external_entropy_fips(
2827
    uint8_t out_encoded_public_key[MLDSA44_PUBLIC_KEY_BYTES],
2828
    MLDSA44_private_key *out_private_key,
2829
0
    const uint8_t entropy[MLDSA_SEED_BYTES]) {
2830
0
  if (out_encoded_public_key == nullptr || out_private_key == nullptr) {
2831
0
    return bcm_status::failure;
2832
0
  }
2833
0
  if (BCM_mldsa44_generate_key_external_entropy(out_encoded_public_key,
2834
0
                                                out_private_key, entropy) ==
2835
0
      bcm_status::failure) {
2836
0
    return bcm_status::failure;
2837
0
  }
2838
0
  return BCM_mldsa44_check_key_fips(out_private_key);
2839
0
}
2840
2841
bcm_status BCM_mldsa44_private_key_from_seed_fips(
2842
    MLDSA44_private_key *out_private_key,
2843
0
    const uint8_t seed[MLDSA_SEED_BYTES]) {
2844
0
  uint8_t public_key[MLDSA44_PUBLIC_KEY_BYTES];
2845
0
  if (BCM_mldsa44_generate_key_external_entropy(public_key, out_private_key,
2846
0
                                                seed) == bcm_status::failure) {
2847
0
    return bcm_status::failure;
2848
0
  }
2849
0
  return BCM_mldsa44_check_key_fips(out_private_key);
2850
0
}
2851
2852
bcm_status BCM_mldsa44_public_from_private(
2853
    MLDSA44_public_key *out_public_key,
2854
0
    const MLDSA44_private_key *private_key) {
2855
0
  const auto *priv = mldsa::private_key_from_external_44(private_key);
2856
0
  auto *out_pub = mldsa::public_key_from_external_44(out_public_key);
2857
0
  *out_pub = priv->pub;
2858
0
  return bcm_status::approved;
2859
0
}
2860
2861
const MLDSA44_public_key *BCM_mldsa44_public_of_private(
2862
0
    const MLDSA44_private_key *private_key) {
2863
0
  return reinterpret_cast<const MLDSA44_public_key *>(
2864
0
      &mldsa::private_key_from_external_44(private_key)->pub);
2865
0
}
2866
2867
bcm_status BCM_mldsa44_sign_internal(
2868
    uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES],
2869
    const MLDSA44_private_key *private_key, const uint8_t *msg, size_t msg_len,
2870
    const uint8_t *context_prefix, size_t context_prefix_len,
2871
    const uint8_t *context, size_t context_len,
2872
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2873
0
  return bcm_as_approved_status(mldsa_sign_internal(
2874
0
      out_encoded_signature, mldsa::private_key_from_external_44(private_key),
2875
0
      msg, msg_len, context_prefix, context_prefix_len, context, context_len,
2876
0
      randomizer));
2877
0
}
2878
2879
bcm_status BCM_mldsa44_sign_mu_internal(
2880
    uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES],
2881
    const MLDSA44_private_key *private_key,
2882
    const uint8_t msg_rep[MLDSA_MU_BYTES],
2883
0
    const uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES]) {
2884
0
  return bcm_as_approved_status(mldsa_sign_mu(
2885
0
      out_encoded_signature, mldsa::private_key_from_external_44(private_key),
2886
0
      msg_rep, randomizer));
2887
0
}
2888
2889
// ML-DSA signature in randomized mode, filling the random bytes with
2890
// |BCM_rand_bytes|.
2891
bcm_status BCM_mldsa44_sign(
2892
    uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES],
2893
    const MLDSA44_private_key *private_key, const uint8_t *msg, size_t msg_len,
2894
0
    const uint8_t *context, size_t context_len) {
2895
0
  BSSL_CHECK(context_len <= 255);
2896
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2897
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2898
2899
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2900
0
  return BCM_mldsa44_sign_internal(
2901
0
      out_encoded_signature, private_key, msg, msg_len, context_prefix,
2902
0
      sizeof(context_prefix), context, context_len, randomizer);
2903
0
}
2904
2905
// ML-DSA pre-hashed API: initializing a pre-hashing context.
2906
void BCM_mldsa44_prehash_init(MLDSA44_prehash *out_prehash_ctx,
2907
                              const MLDSA44_public_key *public_key,
2908
0
                              const uint8_t *context, size_t context_len) {
2909
0
  BSSL_CHECK(context_len <= 255);
2910
2911
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2912
0
  mldsa_prehash_init(mldsa::prehash_context_from_external_44(out_prehash_ctx),
2913
0
                     mldsa::public_key_from_external_44(public_key),
2914
0
                     context_prefix, sizeof(context_prefix), context,
2915
0
                     context_len);
2916
0
}
2917
2918
// ML-DSA pre-hashed API: updating a pre-hashing context with a message chunk.
2919
void BCM_mldsa44_prehash_update(MLDSA44_prehash *inout_prehash_ctx,
2920
0
                                const uint8_t *msg, size_t msg_len) {
2921
0
  mldsa_prehash_update(
2922
0
      mldsa::prehash_context_from_external_44(inout_prehash_ctx), msg, msg_len);
2923
0
}
2924
2925
// ML-DSA pre-hashed API: obtaining a message representative to sign.
2926
void BCM_mldsa44_prehash_finalize(uint8_t out_msg_rep[MLDSA_MU_BYTES],
2927
0
                                  MLDSA44_prehash *inout_prehash_ctx) {
2928
0
  mldsa_prehash_finalize(
2929
0
      out_msg_rep, mldsa::prehash_context_from_external_44(inout_prehash_ctx));
2930
0
}
2931
2932
// ML-DSA pre-hashed API: signing a message representative.
2933
bcm_status BCM_mldsa44_sign_message_representative(
2934
    uint8_t out_encoded_signature[MLDSA44_SIGNATURE_BYTES],
2935
    const MLDSA44_private_key *private_key,
2936
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2937
0
  uint8_t randomizer[BCM_MLDSA_SIGNATURE_RANDOMIZER_BYTES];
2938
0
  BCM_rand_bytes(randomizer, sizeof(randomizer));
2939
0
  CONSTTIME_SECRET(randomizer, sizeof(randomizer));
2940
2941
0
  return bcm_as_approved_status(mldsa_sign_mu(
2942
0
      out_encoded_signature, mldsa::private_key_from_external_44(private_key),
2943
0
      msg_rep, randomizer));
2944
0
}
2945
2946
// ML-DSA pre-hashed API: verifying a message representative.
2947
bcm_status BCM_mldsa44_verify_message_representative(
2948
    const MLDSA44_public_key *public_key,
2949
    const uint8_t signature[MLDSA44_SIGNATURE_BYTES],
2950
0
    const uint8_t msg_rep[MLDSA_MU_BYTES]) {
2951
0
  return bcm_as_approved_status(mldsa::mldsa_verify_mu<4, 4>(
2952
0
      mldsa::public_key_from_external_44(public_key), signature, msg_rep));
2953
0
}
2954
2955
// FIPS 204, Algorithm 3 (`ML-DSA.Verify`).
2956
bcm_status BCM_mldsa44_verify(const MLDSA44_public_key *public_key,
2957
                              const uint8_t *signature, const uint8_t *msg,
2958
                              size_t msg_len, const uint8_t *context,
2959
0
                              size_t context_len) {
2960
0
  BSSL_CHECK(context_len <= 255);
2961
0
  const uint8_t context_prefix[2] = {0, static_cast<uint8_t>(context_len)};
2962
0
  return BCM_mldsa44_verify_internal(public_key, signature, msg, msg_len,
2963
0
                                     context_prefix, sizeof(context_prefix),
2964
0
                                     context, context_len);
2965
0
}
2966
2967
bcm_status BCM_mldsa44_verify_internal(
2968
    const MLDSA44_public_key *public_key,
2969
    const uint8_t encoded_signature[MLDSA44_SIGNATURE_BYTES],
2970
    const uint8_t *msg, size_t msg_len, const uint8_t *context_prefix,
2971
0
    size_t context_prefix_len, const uint8_t *context, size_t context_len) {
2972
0
  return bcm_as_approved_status(mldsa::mldsa_verify_internal<4, 4>(
2973
0
      mldsa::public_key_from_external_44(public_key), encoded_signature, msg,
2974
0
      msg_len, context_prefix, context_prefix_len, context, context_len));
2975
0
}
2976
2977
bcm_status BCM_mldsa44_marshal_public_key(
2978
0
    CBB *out, const MLDSA44_public_key *public_key) {
2979
0
  return bcm_as_approved_status(mldsa_marshal_public_key(
2980
0
      out, mldsa::public_key_from_external_44(public_key)));
2981
0
}
2982
2983
int BCM_mldsa44_public_keys_equal(const MLDSA44_public_key *a,
2984
0
                                  const MLDSA44_public_key *b) {
2985
0
  auto *a_pub = mldsa::public_key_from_external_44(a);
2986
0
  auto *b_pub = mldsa::public_key_from_external_44(b);
2987
  // It is sufficient to compare |public_key_hash|. When importing a public key,
2988
  // the hash must be computed. When importing a private key in expanded form
2989
  // (an internal testing-only API), the hash is provided, but we recompute it
2990
  // and check for correctness.
2991
0
  return OPENSSL_memcmp(a_pub->public_key_hash, b_pub->public_key_hash,
2992
0
                        sizeof(a_pub->public_key_hash)) == 0;
2993
0
}
2994
2995
0
int boringssl_self_test_mldsa() {
2996
0
  return mldsa::fips::keygen_self_test() && mldsa::fips::sign_self_test() &&
2997
0
         mldsa::fips::verify_self_test();
2998
0
}