Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/crypto/ml_kem/ml_kem.c
Line
Count
Source
1
/*
2
 * Copyright 2024-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <openssl/byteorder.h>
11
#include <openssl/rand.h>
12
#include <openssl/proverr.h>
13
#include "crypto/ml_kem.h"
14
#include "internal/common.h"
15
#include "internal/constant_time.h"
16
#include "internal/sha3.h"
17
18
#if defined(OPENSSL_CONSTANT_TIME_VALIDATION)
19
#include <valgrind/memcheck.h>
20
#endif
21
22
#if ML_KEM_SEED_BYTES != ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES
23
#error "ML-KEM keygen seed length != shared secret + random bytes length"
24
#endif
25
#if ML_KEM_SHARED_SECRET_BYTES != ML_KEM_RANDOM_BYTES
26
#error "Invalid unequal lengths of ML-KEM shared secret and random inputs"
27
#endif
28
29
#if UINT_MAX < UINT32_MAX
30
#error "Unsupported compiler: sizeof(unsigned int) < sizeof(uint32_t)"
31
#endif
32
33
/* Handy function-like bit-extraction macros */
34
49.3M
#define bit0(b) ((b) & 1)
35
344M
#define bitn(n, b) (((b) >> n) & 1)
36
37
/*
38
 * 12 bits are sufficient to losslessly represent values in [0, q-1].
39
 * INVERSE_DEGREE is (n/2)^-1 mod q; used in inverse NTT.
40
 */
41
4.03M
#define DEGREE ML_KEM_DEGREE
42
#define INVERSE_DEGREE (ML_KEM_PRIME - 2 * 13)
43
#define LOG2PRIME 12
44
#define BARRETT_SHIFT (2 * LOG2PRIME)
45
46
#ifdef SHA3_BLOCKSIZE
47
#define SHAKE128_BLOCKSIZE SHA3_BLOCKSIZE(128)
48
#endif
49
50
/*
51
 * Return whether a value that can only be 0 or 1 is non-zero, in constant time
52
 * in practice!  The return value is a mask that is all ones if true, and all
53
 * zeros otherwise (twos-complement arithmetic assumed for unsigned values).
54
 *
55
 * Although this is used in constant-time selects, we omit a value barrier
56
 * here.  Value barriers impede auto-vectorization (likely because it forces
57
 * the value to transit through a general-purpose register). On AArch64, this
58
 * is a difference of 2x.
59
 *
60
 * We usually add value barriers to selects because Clang turns consecutive
61
 * selects with the same condition into a branch instead of CMOV/CSEL. This
62
 * condition does not occur in Kyber, so omitting it seems to be safe so far,
63
 * but see |cbd_2|, |cbd_3|, where reduction needs to be specialised to the
64
 * sign of the input, rather than adding |q| in advance, and using the generic
65
 * |reduce_once|.  (David Benjamin, Chromium)
66
 */
67
#if 0
68
#define constish_time_non_zero(b) (~constant_time_is_zero(b));
69
#else
70
1.35G
#define constish_time_non_zero(b) (0u - (b))
71
#endif
72
73
/*
74
 * The scalar rejection-sampling buffer size needs to be a multiple of 12, but
75
 * is otherwise arbitrary, the preferred block size matches the internal buffer
76
 * size of SHAKE128, avoiding internal buffering and copying in SHAKE128. That
77
 * block size of (1600 - 256)/8 bytes, or 168, just happens to divide by 12!
78
 *
79
 * If the blocksize is unknown, or is not divisible by 12, 168 is used as a
80
 * fallback.
81
 */
82
#if defined(SHAKE128_BLOCKSIZE) && (SHAKE128_BLOCKSIZE) % 12 == 0
83
#define SCALAR_SAMPLING_BUFSIZE (SHAKE128_BLOCKSIZE)
84
#else
85
#define SCALAR_SAMPLING_BUFSIZE 168
86
#endif
87
88
/*
89
 * Structure of keys
90
 */
91
typedef struct ossl_ml_kem_scalar_st {
92
    /* On every function entry and exit, 0 <= c[i] < ML_KEM_PRIME. */
93
    uint16_t c[ML_KEM_DEGREE];
94
} scalar;
95
96
/* Key material allocation layout */
97
#define DECLARE_ML_KEM_PUBKEYDATA(name, rank)                  \
98
    struct name##_alloc {                                      \
99
        /* Public vector |t| */                                \
100
        scalar tbuf[(rank)];                                   \
101
        /* Pre-computed matrix |m| (FIPS 203 |A| transpose) */ \
102
        scalar mbuf[(rank) * (rank)];                          \
103
    }
104
105
#define DECLARE_ML_KEM_PRVKEYDATA(name, rank)  \
106
    struct name##_alloc {                      \
107
        scalar sbuf[rank];                     \
108
        uint8_t zbuf[2 * ML_KEM_RANDOM_BYTES]; \
109
    }
110
111
/* Declare variant-specific public and private storage */
112
#define DECLARE_ML_KEM_VARIANT_KEYDATA(bits)                        \
113
    DECLARE_ML_KEM_PUBKEYDATA(pubkey_##bits, ML_KEM_##bits##_RANK); \
114
    DECLARE_ML_KEM_PRVKEYDATA(prvkey_##bits, ML_KEM_##bits##_RANK)
115
116
DECLARE_ML_KEM_VARIANT_KEYDATA(512);
117
DECLARE_ML_KEM_VARIANT_KEYDATA(768);
118
DECLARE_ML_KEM_VARIANT_KEYDATA(1024);
119
#undef DECLARE_ML_KEM_VARIANT_KEYDATA
120
#undef DECLARE_ML_KEM_PUBKEYDATA
121
#undef DECLARE_ML_KEM_PRVKEYDATA
122
123
typedef __owur int (*CBD_FUNC)(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1],
124
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key);
125
static void scalar_encode(uint8_t *out, const scalar *s, int bits);
126
127
/*
128
 * The wire-form of a losslessly encoded vector uses 12-bits per element.
129
 *
130
 * The wire-form public key consists of the lossless encoding of the public
131
 * vector |t|, followed by the public seed |rho|.
132
 *
133
 * Our serialised private key concatenates serialisations of the private vector
134
 * |s|, the public key, the public key hash, and the failure secret |z|.
135
 */
136
#define VECTOR_BYTES(b) ((3 * DEGREE / 2) * ML_KEM_##b##_RANK)
137
#define PUBKEY_BYTES(b) (VECTOR_BYTES(b) + ML_KEM_RANDOM_BYTES)
138
#define PRVKEY_BYTES(b) (2 * PUBKEY_BYTES(b) + ML_KEM_PKHASH_BYTES)
139
140
/*
141
 * Encapsulation produces a vector "u" and a scalar "v", whose coordinates
142
 * (numbers modulo the ML-KEM prime "q") are lossily encoded using as "du" and
143
 * "dv" bits, respectively.  This encoding is the ciphertext input for
144
 * decapsulation.
145
 */
146
#define U_VECTOR_BYTES(b) ((DEGREE / 8) * ML_KEM_##b##_DU * ML_KEM_##b##_RANK)
147
#define V_SCALAR_BYTES(b) ((DEGREE / 8) * ML_KEM_##b##_DV)
148
#define CTEXT_BYTES(b) (U_VECTOR_BYTES(b) + V_SCALAR_BYTES(b))
149
150
#if defined(OPENSSL_CONSTANT_TIME_VALIDATION)
151
152
/*
153
 * CONSTTIME_SECRET takes a pointer and a number of bytes and marks that region
154
 * of memory as secret. Secret data is tracked as it flows to registers and
155
 * other parts of a memory. If secret data is used as a condition for a branch,
156
 * or as a memory index, it will trigger warnings in valgrind.
157
 */
158
#define CONSTTIME_SECRET(ptr, len) VALGRIND_MAKE_MEM_UNDEFINED(ptr, len)
159
160
/*
161
 * CONSTTIME_DECLASSIFY takes a pointer and a number of bytes and marks that
162
 * region of memory as public. Public data is not subject to constant-time
163
 * rules.
164
 */
165
#define CONSTTIME_DECLASSIFY(ptr, len) VALGRIND_MAKE_MEM_DEFINED(ptr, len)
166
167
#else
168
169
#define CONSTTIME_SECRET(ptr, len)
170
#define CONSTTIME_DECLASSIFY(ptr, len)
171
172
#endif
173
174
/*
175
 * Indices of slots in the vinfo tables below
176
 */
177
61.5k
#define ML_KEM_512_VINFO 0
178
180k
#define ML_KEM_768_VINFO 1
179
57.8k
#define ML_KEM_1024_VINFO 2
180
181
/*
182
 * Per-variant fixed parameters
183
 */
184
static const ML_KEM_VINFO vinfo_map[3] = {
185
    { "ML-KEM-512",
186
        PRVKEY_BYTES(512),
187
        sizeof(struct prvkey_512_alloc),
188
        PUBKEY_BYTES(512),
189
        sizeof(struct pubkey_512_alloc),
190
        CTEXT_BYTES(512),
191
        VECTOR_BYTES(512),
192
        U_VECTOR_BYTES(512),
193
        EVP_PKEY_ML_KEM_512,
194
        ML_KEM_512_BITS,
195
        ML_KEM_512_RANK,
196
        ML_KEM_512_DU,
197
        ML_KEM_512_DV,
198
        ML_KEM_512_SECBITS,
199
        ML_KEM_512_SECURITY_CATEGORY },
200
    { "ML-KEM-768",
201
        PRVKEY_BYTES(768),
202
        sizeof(struct prvkey_768_alloc),
203
        PUBKEY_BYTES(768),
204
        sizeof(struct pubkey_768_alloc),
205
        CTEXT_BYTES(768),
206
        VECTOR_BYTES(768),
207
        U_VECTOR_BYTES(768),
208
        EVP_PKEY_ML_KEM_768,
209
        ML_KEM_768_BITS,
210
        ML_KEM_768_RANK,
211
        ML_KEM_768_DU,
212
        ML_KEM_768_DV,
213
        ML_KEM_768_SECBITS,
214
        ML_KEM_768_SECURITY_CATEGORY },
215
    { "ML-KEM-1024",
216
        PRVKEY_BYTES(1024),
217
        sizeof(struct prvkey_1024_alloc),
218
        PUBKEY_BYTES(1024),
219
        sizeof(struct pubkey_1024_alloc),
220
        CTEXT_BYTES(1024),
221
        VECTOR_BYTES(1024),
222
        U_VECTOR_BYTES(1024),
223
        EVP_PKEY_ML_KEM_1024,
224
        ML_KEM_1024_BITS,
225
        ML_KEM_1024_RANK,
226
        ML_KEM_1024_DU,
227
        ML_KEM_1024_DV,
228
        ML_KEM_1024_SECBITS,
229
        ML_KEM_1024_SECURITY_CATEGORY }
230
};
231
232
/*
233
 * Remainders modulo `kPrime`, for sufficiently small inputs, are computed in
234
 * constant time via Barrett reduction, and a final call to reduce_once(),
235
 * which reduces inputs that are at most 2*kPrime and is also constant-time.
236
 */
237
static const int kPrime = ML_KEM_PRIME;
238
static const unsigned int kBarrettShift = BARRETT_SHIFT;
239
static const size_t kBarrettMultiplier = (1 << BARRETT_SHIFT) / ML_KEM_PRIME;
240
static const uint16_t kHalfPrime = (ML_KEM_PRIME - 1) / 2;
241
static const uint16_t kInverseDegree = INVERSE_DEGREE;
242
243
/*
244
 * Python helper:
245
 *
246
 * p = 3329
247
 * def bitreverse(i):
248
 *     ret = 0
249
 *     for n in range(7):
250
 *         bit = i & 1
251
 *         ret <<= 1
252
 *         ret |= bit
253
 *         i >>= 1
254
 *     return ret
255
 */
256
257
/*-
258
 * First precomputed array from Appendix A of FIPS 203, or else Python:
259
 * kNTTRoots = [pow(17, bitreverse(i), p) for i in range(128)]
260
 */
261
static const uint16_t kNTTRoots[128] = {
262
    1,
263
    1729,
264
    2580,
265
    3289,
266
    2642,
267
    630,
268
    1897,
269
    848,
270
    1062,
271
    1919,
272
    193,
273
    797,
274
    2786,
275
    3260,
276
    569,
277
    1746,
278
    296,
279
    2447,
280
    1339,
281
    1476,
282
    3046,
283
    56,
284
    2240,
285
    1333,
286
    1426,
287
    2094,
288
    535,
289
    2882,
290
    2393,
291
    2879,
292
    1974,
293
    821,
294
    289,
295
    331,
296
    3253,
297
    1756,
298
    1197,
299
    2304,
300
    2277,
301
    2055,
302
    650,
303
    1977,
304
    2513,
305
    632,
306
    2865,
307
    33,
308
    1320,
309
    1915,
310
    2319,
311
    1435,
312
    807,
313
    452,
314
    1438,
315
    2868,
316
    1534,
317
    2402,
318
    2647,
319
    2617,
320
    1481,
321
    648,
322
    2474,
323
    3110,
324
    1227,
325
    910,
326
    17,
327
    2761,
328
    583,
329
    2649,
330
    1637,
331
    723,
332
    2288,
333
    1100,
334
    1409,
335
    2662,
336
    3281,
337
    233,
338
    756,
339
    2156,
340
    3015,
341
    3050,
342
    1703,
343
    1651,
344
    2789,
345
    1789,
346
    1847,
347
    952,
348
    1461,
349
    2687,
350
    939,
351
    2308,
352
    2437,
353
    2388,
354
    733,
355
    2337,
356
    268,
357
    641,
358
    1584,
359
    2298,
360
    2037,
361
    3220,
362
    375,
363
    2549,
364
    2090,
365
    1645,
366
    1063,
367
    319,
368
    2773,
369
    757,
370
    2099,
371
    561,
372
    2466,
373
    2594,
374
    2804,
375
    1092,
376
    403,
377
    1026,
378
    1143,
379
    2150,
380
    2775,
381
    886,
382
    1722,
383
    1212,
384
    1874,
385
    1029,
386
    2110,
387
    2935,
388
    885,
389
    2154,
390
};
391
392
/*
393
 * InverseNTTRoots = [pow(17, -bitreverse(i), p) for i in range(128)]
394
 * Listed in order of use in the inverse NTT loop (index 0 is skipped):
395
 *
396
 *  0, 64, 65, ..., 127, 32, 33, ..., 63, 16, 17, ..., 31, 8, 9, ...
397
 */
398
static const uint16_t kInverseNTTRoots[128] = {
399
    1,
400
    1175,
401
    2444,
402
    394,
403
    1219,
404
    2300,
405
    1455,
406
    2117,
407
    1607,
408
    2443,
409
    554,
410
    1179,
411
    2186,
412
    2303,
413
    2926,
414
    2237,
415
    525,
416
    735,
417
    863,
418
    2768,
419
    1230,
420
    2572,
421
    556,
422
    3010,
423
    2266,
424
    1684,
425
    1239,
426
    780,
427
    2954,
428
    109,
429
    1292,
430
    1031,
431
    1745,
432
    2688,
433
    3061,
434
    992,
435
    2596,
436
    941,
437
    892,
438
    1021,
439
    2390,
440
    642,
441
    1868,
442
    2377,
443
    1482,
444
    1540,
445
    540,
446
    1678,
447
    1626,
448
    279,
449
    314,
450
    1173,
451
    2573,
452
    3096,
453
    48,
454
    667,
455
    1920,
456
    2229,
457
    1041,
458
    2606,
459
    1692,
460
    680,
461
    2746,
462
    568,
463
    3312,
464
    2419,
465
    2102,
466
    219,
467
    855,
468
    2681,
469
    1848,
470
    712,
471
    682,
472
    927,
473
    1795,
474
    461,
475
    1891,
476
    2877,
477
    2522,
478
    1894,
479
    1010,
480
    1414,
481
    2009,
482
    3296,
483
    464,
484
    2697,
485
    816,
486
    1352,
487
    2679,
488
    1274,
489
    1052,
490
    1025,
491
    2132,
492
    1573,
493
    76,
494
    2998,
495
    3040,
496
    2508,
497
    1355,
498
    450,
499
    936,
500
    447,
501
    2794,
502
    1235,
503
    1903,
504
    1996,
505
    1089,
506
    3273,
507
    283,
508
    1853,
509
    1990,
510
    882,
511
    3033,
512
    1583,
513
    2760,
514
    69,
515
    543,
516
    2532,
517
    3136,
518
    1410,
519
    2267,
520
    2481,
521
    1432,
522
    2699,
523
    687,
524
    40,
525
    749,
526
    1600,
527
};
528
529
/*
530
 * Second precomputed array from Appendix A of FIPS 203 (normalised positive),
531
 * or else Python:
532
 * ModRoots = [pow(17, 2*bitreverse(i) + 1, p) for i in range(128)]
533
 */
534
static const uint16_t kModRoots[128] = {
535
    17,
536
    3312,
537
    2761,
538
    568,
539
    583,
540
    2746,
541
    2649,
542
    680,
543
    1637,
544
    1692,
545
    723,
546
    2606,
547
    2288,
548
    1041,
549
    1100,
550
    2229,
551
    1409,
552
    1920,
553
    2662,
554
    667,
555
    3281,
556
    48,
557
    233,
558
    3096,
559
    756,
560
    2573,
561
    2156,
562
    1173,
563
    3015,
564
    314,
565
    3050,
566
    279,
567
    1703,
568
    1626,
569
    1651,
570
    1678,
571
    2789,
572
    540,
573
    1789,
574
    1540,
575
    1847,
576
    1482,
577
    952,
578
    2377,
579
    1461,
580
    1868,
581
    2687,
582
    642,
583
    939,
584
    2390,
585
    2308,
586
    1021,
587
    2437,
588
    892,
589
    2388,
590
    941,
591
    733,
592
    2596,
593
    2337,
594
    992,
595
    268,
596
    3061,
597
    641,
598
    2688,
599
    1584,
600
    1745,
601
    2298,
602
    1031,
603
    2037,
604
    1292,
605
    3220,
606
    109,
607
    375,
608
    2954,
609
    2549,
610
    780,
611
    2090,
612
    1239,
613
    1645,
614
    1684,
615
    1063,
616
    2266,
617
    319,
618
    3010,
619
    2773,
620
    556,
621
    757,
622
    2572,
623
    2099,
624
    1230,
625
    561,
626
    2768,
627
    2466,
628
    863,
629
    2594,
630
    735,
631
    2804,
632
    525,
633
    1092,
634
    2237,
635
    403,
636
    2926,
637
    1026,
638
    2303,
639
    1143,
640
    2186,
641
    2150,
642
    1179,
643
    2775,
644
    554,
645
    886,
646
    2443,
647
    1722,
648
    1607,
649
    1212,
650
    2117,
651
    1874,
652
    1455,
653
    1029,
654
    2300,
655
    2110,
656
    1219,
657
    2935,
658
    394,
659
    885,
660
    2444,
661
    2154,
662
    1175,
663
};
664
665
/*
666
 * single_keccak hashes |inlen| bytes from |in| and writes |outlen| bytes of
667
 * output to |out|. If the |md| specifies a fixed-output function, like
668
 * SHA3-256, then |outlen| must be the correct length for that function.
669
 */
670
static __owur int single_keccak(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen,
671
    EVP_MD_CTX *mdctx)
672
448k
{
673
448k
    unsigned int sz = (unsigned int)outlen;
674
675
448k
    if (!EVP_DigestUpdate(mdctx, in, inlen))
676
0
        return 0;
677
448k
    if (EVP_MD_xof(EVP_MD_CTX_get0_md(mdctx)))
678
384k
        return EVP_DigestFinalXOF(mdctx, out, outlen);
679
64.2k
    return EVP_DigestFinal_ex(mdctx, out, &sz)
680
64.2k
        && ossl_assert((size_t)sz == outlen);
681
448k
}
682
683
/*
684
 * FIPS 203, Section 4.1, equation (4.3): PRF. Takes 32+1 input bytes, and uses
685
 * SHAKE256 to produce the input to SamplePolyCBD_eta: FIPS 203, algorithm 8.
686
 */
687
static __owur int prf(uint8_t *out, size_t len, const uint8_t in[ML_KEM_RANDOM_BYTES + 1],
688
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
689
384k
{
690
384k
    return EVP_DigestInit_ex(mdctx, key->shake256_md, NULL)
691
384k
        && single_keccak(out, len, in, ML_KEM_RANDOM_BYTES + 1, mdctx);
692
384k
}
693
694
/*
695
 * FIPS 203, Section 4.1, equation (4.4): H.  SHA3-256 hash of a variable
696
 * length input, producing 32 bytes of output.
697
 */
698
static __owur int hash_h(uint8_t out[ML_KEM_PKHASH_BYTES], const uint8_t *in, size_t len,
699
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
700
360
{
701
360
    return EVP_DigestInit_ex(mdctx, key->sha3_256_md, NULL)
702
360
        && single_keccak(out, ML_KEM_PKHASH_BYTES, in, len, mdctx);
703
360
}
704
705
/* Incremental hash_h of expanded public key */
706
static int
707
hash_h_pubkey(uint8_t pkhash[ML_KEM_PKHASH_BYTES],
708
    EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
709
63.5k
{
710
63.5k
    const ML_KEM_VINFO *vinfo = key->vinfo;
711
63.5k
    const scalar *t = key->t, *end = t + vinfo->rank;
712
63.5k
    unsigned int sz;
713
714
63.5k
    if (!EVP_DigestInit_ex(mdctx, key->sha3_256_md, NULL))
715
0
        return 0;
716
717
190k
    do {
718
190k
        uint8_t buf[3 * DEGREE / 2];
719
720
190k
        scalar_encode(buf, t++, 12);
721
190k
        if (!EVP_DigestUpdate(mdctx, buf, sizeof(buf)))
722
0
            return 0;
723
190k
    } while (t < end);
724
725
63.5k
    if (!EVP_DigestUpdate(mdctx, key->rho, ML_KEM_RANDOM_BYTES))
726
0
        return 0;
727
63.5k
    return EVP_DigestFinal_ex(mdctx, pkhash, &sz)
728
63.5k
        && ossl_assert(sz == ML_KEM_PKHASH_BYTES);
729
63.5k
}
730
731
/*
732
 * FIPS 203, Section 4.1, equation (4.5): G.  SHA3-512 hash of a variable
733
 * length input, producing 64 bytes of output, in particular the seeds
734
 * (d,z) for key generation.
735
 */
736
static __owur int hash_g(uint8_t out[ML_KEM_SEED_BYTES], const uint8_t *in, size_t len,
737
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
738
63.9k
{
739
63.9k
    return EVP_DigestInit_ex(mdctx, key->sha3_512_md, NULL)
740
63.9k
        && single_keccak(out, ML_KEM_SEED_BYTES, in, len, mdctx);
741
63.9k
}
742
743
/*
744
 * FIPS 203, Section 4.1, equation (4.4): J. SHAKE256 taking a variable length
745
 * input to compute a 32-byte implicit rejection shared secret, of the same
746
 * length as the expected shared secret.  (Computed even on success to avoid
747
 * side-channel leaks).
748
 */
749
static __owur int kdf(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
750
    const uint8_t z[ML_KEM_RANDOM_BYTES],
751
    const uint8_t *ctext, size_t len,
752
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
753
189
{
754
189
    return EVP_DigestInit_ex(mdctx, key->shake256_md, NULL)
755
189
        && EVP_DigestUpdate(mdctx, z, ML_KEM_RANDOM_BYTES)
756
189
        && EVP_DigestUpdate(mdctx, ctext, len)
757
189
        && EVP_DigestFinalXOF(mdctx, out, ML_KEM_SHARED_SECRET_BYTES);
758
189
}
759
760
/*
761
 * FIPS 203, Section 4.2.2, Algorithm 7: "SampleNTT" (steps 3-17, steps 1, 2
762
 * are performed by the caller). Rejection-samples a Keccak stream to get
763
 * uniformly distributed elements in the range [0,q). This is used for matrix
764
 * expansion and only operates on public inputs.
765
 */
766
static __owur int sample_scalar(scalar *out, EVP_MD_CTX *mdctx)
767
574k
{
768
574k
    uint16_t *curr = out->c, *endout = curr + DEGREE;
769
574k
    uint8_t buf[SCALAR_SAMPLING_BUFSIZE], *in;
770
574k
    uint8_t *endin = buf + sizeof(buf);
771
574k
    uint16_t d;
772
574k
    uint8_t b1, b2, b3;
773
774
1.72M
    do {
775
1.72M
        if (!EVP_DigestSqueeze(mdctx, in = buf, sizeof(buf)))
776
0
            return 0;
777
90.0M
        do {
778
90.0M
            b1 = *in++;
779
90.0M
            b2 = *in++;
780
90.0M
            b3 = *in++;
781
782
90.0M
            if (curr >= endout)
783
192k
                break;
784
89.8M
            if ((d = ((b2 & 0x0f) << 8) + b1) < kPrime)
785
74.1M
                *curr++ = d;
786
89.8M
            if (curr >= endout)
787
381k
                break;
788
89.4M
            if ((d = (b3 << 4) + (b2 >> 4)) < kPrime)
789
72.8M
                *curr++ = d;
790
89.4M
        } while (in < endin);
791
1.72M
    } while (curr < endout);
792
574k
    return 1;
793
574k
}
794
795
/*-
796
 * reduce_once reduces 0 <= x < 2*kPrime, mod kPrime.
797
 *
798
 * Subtract |q| if the input is larger, without exposing a side-channel,
799
 * avoiding the "clangover" attack.  See |constish_time_non_zero| for a
800
 * discussion on why the value barrier is by default omitted.
801
 */
802
static __owur uint16_t reduce_once(uint16_t x)
803
1.25G
{
804
1.25G
    const uint16_t subtracted = x - kPrime;
805
1.25G
    uint16_t mask = constish_time_non_zero(subtracted >> 15);
806
807
1.25G
    return (mask & x) | (~mask & subtracted);
808
1.25G
}
809
810
/*
811
 * Constant-time reduce x mod kPrime using Barrett reduction. x must be less
812
 * than kPrime + 2 * kPrime^2.  This is sufficient to reduce a product of
813
 * two already reduced u_int16 values, in fact it is sufficient for each
814
 * to be less than 2^12, because (kPrime * (2 * kPrime + 1)) > 2^24.
815
 */
816
static __owur uint16_t reduce(uint32_t x)
817
566M
{
818
566M
    uint64_t product = (uint64_t)x * kBarrettMultiplier;
819
566M
    uint32_t quotient = (uint32_t)(product >> kBarrettShift);
820
566M
    uint32_t remainder = x - quotient * kPrime;
821
822
566M
    return reduce_once(remainder);
823
566M
}
824
825
/* Multiply a scalar by a constant. */
826
static void scalar_mult_const(scalar *s, uint16_t a)
827
1.78k
{
828
1.78k
    uint16_t *curr = s->c, *end = curr + DEGREE, tmp;
829
830
457k
    do {
831
457k
        tmp = reduce(*curr * a);
832
457k
        *curr++ = tmp;
833
457k
    } while (curr < end);
834
1.78k
}
835
836
/*-
837
 * FIPS 203, Section 4.3, Algorithm 9: "NTT".
838
 * In-place number theoretic transform of a given scalar.  Note that ML-KEM's
839
 * kPrime 3329 does not have a 512th root of unity, so this transform leaves
840
 * off the last iteration of the usual FFT code, with the 128 relevant roots of
841
 * unity being stored in NTTRoots.  This means the output should be seen as 128
842
 * elements in GF(3329^2), with the coefficients of the elements being
843
 * consecutive entries in |s->c|.
844
 */
845
static void scalar_ntt(scalar *s)
846
383k
{
847
383k
    const uint16_t *roots = kNTTRoots;
848
383k
    uint16_t *end = s->c + DEGREE;
849
383k
    int offset = DEGREE / 2;
850
851
2.68M
    do {
852
2.68M
        uint16_t *curr = s->c, *peer;
853
854
48.6M
        do {
855
48.6M
            uint16_t *pause = curr + offset, even, odd;
856
48.6M
            uint32_t zeta = *++roots;
857
858
48.6M
            peer = pause;
859
343M
            do {
860
343M
                even = *curr;
861
343M
                odd = reduce(*peer * zeta);
862
343M
                *peer++ = reduce_once(even - odd + kPrime);
863
343M
                *curr++ = reduce_once(odd + even);
864
343M
            } while (curr < pause);
865
48.6M
        } while ((curr = peer) < end);
866
2.68M
    } while ((offset >>= 1) >= 2);
867
383k
}
868
869
/*-
870
 * FIPS 203, Section 4.3, Algorithm 10: "NTT^(-1)".
871
 * In-place inverse number theoretic transform of a given scalar, with pairs of
872
 * entries of s->v being interpreted as elements of GF(3329^2). Just as with
873
 * the number theoretic transform, this leaves off the first step of the normal
874
 * iFFT to account for the fact that 3329 does not have a 512th root of unity,
875
 * using the precomputed 128 roots of unity stored in InverseNTTRoots.
876
 */
877
static void scalar_inverse_ntt(scalar *s)
878
1.78k
{
879
1.78k
    const uint16_t *roots = kInverseNTTRoots;
880
1.78k
    uint16_t *end = s->c + DEGREE;
881
1.78k
    int offset = 2;
882
883
12.5k
    do {
884
12.5k
        uint16_t *curr = s->c, *peer;
885
886
227k
        do {
887
227k
            uint16_t *pause = curr + offset, even, odd;
888
227k
            uint32_t zeta = *++roots;
889
890
227k
            peer = pause;
891
1.60M
            do {
892
1.60M
                even = *curr;
893
1.60M
                odd = *peer;
894
1.60M
                *peer++ = reduce(zeta * (even - odd + kPrime));
895
1.60M
                *curr++ = reduce_once(odd + even);
896
1.60M
            } while (curr < pause);
897
227k
        } while ((curr = peer) < end);
898
12.5k
    } while ((offset <<= 1) < DEGREE);
899
1.78k
    scalar_mult_const(s, kInverseDegree);
900
1.78k
}
901
902
/* Addition updating the LHS scalar in-place. */
903
static void scalar_add(scalar *lhs, const scalar *rhs)
904
1.60k
{
905
1.60k
    int i;
906
907
411k
    for (i = 0; i < DEGREE; i++)
908
409k
        lhs->c[i] = reduce_once(lhs->c[i] + rhs->c[i]);
909
1.60k
}
910
911
/* Subtraction updating the LHS scalar in-place. */
912
static void scalar_sub(scalar *lhs, const scalar *rhs)
913
189
{
914
189
    int i;
915
916
48.5k
    for (i = 0; i < DEGREE; i++)
917
48.3k
        lhs->c[i] = reduce_once(lhs->c[i] - rhs->c[i] + kPrime);
918
189
}
919
920
/*
921
 * Multiplying two scalars in the number theoretically transformed state. Since
922
 * 3329 does not have a 512th root of unity, this means we have to interpret
923
 * the 2*ith and (2*i+1)th entries of the scalar as elements of
924
 * GF(3329)[X]/(X^2 - 17^(2*bitreverse(i)+1)).
925
 *
926
 * The value of 17^(2*bitreverse(i)+1) mod 3329 is stored in the precomputed
927
 * ModRoots table. Note that our Barrett transform only allows us to multiply
928
 * two reduced numbers together, so we need some intermediate reduction steps,
929
 * even if an uint64_t could hold 3 multiplied numbers.
930
 */
931
static void scalar_mult(scalar *out, const scalar *lhs,
932
    const scalar *rhs)
933
1.78k
{
934
1.78k
    uint16_t *curr = out->c, *end = curr + DEGREE;
935
1.78k
    const uint16_t *lc = lhs->c, *rc = rhs->c;
936
1.78k
    const uint16_t *roots = kModRoots;
937
938
228k
    do {
939
228k
        uint32_t l0 = *lc++, r0 = *rc++;
940
228k
        uint32_t l1 = *lc++, r1 = *rc++;
941
228k
        uint32_t zetapow = *roots++;
942
943
228k
        *curr++ = reduce(l0 * r0 + reduce(l1 * r1) * zetapow);
944
228k
        *curr++ = reduce(l0 * r1 + l1 * r0);
945
228k
    } while (curr < end);
946
1.78k
}
947
948
/* Above, but add the result to an existing scalar */
949
static ossl_inline void scalar_mult_add(scalar *out, const scalar *lhs,
950
    const scalar *rhs)
951
575k
{
952
575k
    uint16_t *curr = out->c, *end = curr + DEGREE;
953
575k
    const uint16_t *lc = lhs->c, *rc = rhs->c;
954
575k
    const uint16_t *roots = kModRoots;
955
956
73.6M
    do {
957
73.6M
        uint32_t l0 = *lc++, r0 = *rc++;
958
73.6M
        uint32_t l1 = *lc++, r1 = *rc++;
959
73.6M
        uint16_t *c0 = curr++;
960
73.6M
        uint16_t *c1 = curr++;
961
73.6M
        uint32_t zetapow = *roots++;
962
963
73.6M
        *c0 = reduce(*c0 + l0 * r0 + reduce(l1 * r1) * zetapow);
964
73.6M
        *c1 = reduce(*c1 + l0 * r1 + l1 * r0);
965
73.6M
    } while (curr < end);
966
575k
}
967
968
/*-
969
 * FIPS 203, Section 4.2.1, Algorithm 5: "ByteEncode_d", for 2<=d<=12.
970
 * Here |bits| is |d|.  For efficiency, we handle the d=1 case separately.
971
 */
972
static void scalar_encode(uint8_t *out, const scalar *s, int bits)
973
384k
{
974
384k
    const uint16_t *curr = s->c, *end = curr + DEGREE;
975
384k
    uint64_t accum = 0, element;
976
384k
    int used = 0;
977
978
98.4M
    do {
979
98.4M
        element = *curr++;
980
98.4M
        if (used + bits < 64) {
981
80.0M
            accum |= element << used;
982
80.0M
            used += bits;
983
80.0M
        } else if (used + bits > 64) {
984
12.3M
            out = OPENSSL_store_u64_le(out, accum | (element << used));
985
12.3M
            accum = element >> (64 - used);
986
12.3M
            used = (used + bits) - 64;
987
12.3M
        } else {
988
6.14M
            out = OPENSSL_store_u64_le(out, accum | (element << used));
989
6.14M
            accum = 0;
990
6.14M
            used = 0;
991
6.14M
        }
992
98.4M
    } while (curr < end);
993
384k
}
994
995
/*
996
 * scalar_encode_1 is |scalar_encode| specialised for |bits| == 1.
997
 */
998
static void scalar_encode_1(uint8_t out[DEGREE / 8], const scalar *s)
999
189
{
1000
189
    int i, j;
1001
189
    uint8_t out_byte;
1002
1003
6.23k
    for (i = 0; i < DEGREE; i += 8) {
1004
6.04k
        out_byte = 0;
1005
54.4k
        for (j = 0; j < 8; j++)
1006
48.3k
            out_byte |= bit0(s->c[i + j]) << j;
1007
6.04k
        *out = out_byte;
1008
6.04k
        out++;
1009
6.04k
    }
1010
189
}
1011
1012
/*-
1013
 * FIPS 203, Section 4.2.1, Algorithm 6: "ByteDecode_d", for 2<=d<12.
1014
 * Here |bits| is |d|.  For efficiency, we handle the d=1 and d=12 cases
1015
 * separately.
1016
 *
1017
 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in
1018
 * |out|.
1019
 */
1020
static void scalar_decode(scalar *out, const uint8_t *in, int bits)
1021
752
{
1022
752
    uint16_t *curr = out->c, *end = curr + DEGREE;
1023
752
    uint64_t accum = 0;
1024
752
    int accum_bits = 0, todo = bits;
1025
752
    uint16_t bitmask = (((uint16_t)1) << bits) - 1, mask = bitmask;
1026
752
    uint16_t element = 0;
1027
1028
213k
    do {
1029
213k
        if (accum_bits == 0) {
1030
26.7k
            in = OPENSSL_load_u64_le(&accum, in);
1031
26.7k
            accum_bits = 64;
1032
26.7k
        }
1033
213k
        if (todo == bits && accum_bits >= bits) {
1034
            /* No partial "element", and all the required bits available */
1035
171k
            *curr++ = ((uint16_t)accum) & mask;
1036
171k
            accum >>= bits;
1037
171k
            accum_bits -= bits;
1038
171k
        } else if (accum_bits >= todo) {
1039
            /* A partial "element", and all the required bits available */
1040
20.8k
            *curr++ = element | ((((uint16_t)accum) & mask) << (bits - todo));
1041
20.8k
            accum >>= todo;
1042
20.8k
            accum_bits -= todo;
1043
20.8k
            element = 0;
1044
20.8k
            todo = bits;
1045
20.8k
            mask = bitmask;
1046
20.8k
        } else {
1047
            /*
1048
             * Only some of the requisite bits accumulated, store |accum_bits|
1049
             * of these in |element|.  The accumulated bitcount becomes 0, but
1050
             * as soon as we have more bits we'll want to merge accum_bits
1051
             * fewer of them into the final |element|.
1052
             *
1053
             * Note that with a 64-bit accumulator and |bits| always 12 or
1054
             * less, if we're here, the previous iteration had all the
1055
             * requisite bits, and so there are no kept bits in |element|.
1056
             */
1057
20.8k
            element = ((uint16_t)accum) & mask;
1058
20.8k
            todo -= accum_bits;
1059
20.8k
            mask = bitmask >> accum_bits;
1060
20.8k
            accum_bits = 0;
1061
20.8k
        }
1062
213k
    } while (curr < end);
1063
752
}
1064
1065
static __owur int scalar_decode_12(scalar *out, const uint8_t in[3 * DEGREE / 2])
1066
1.39k
{
1067
1.39k
    int i;
1068
1.39k
    uint16_t *c = out->c;
1069
1070
143k
    for (i = 0; i < DEGREE / 2; ++i) {
1071
142k
        uint8_t b1 = *in++;
1072
142k
        uint8_t b2 = *in++;
1073
142k
        uint8_t b3 = *in++;
1074
142k
        int outOfRange1 = (*c++ = b1 | ((b2 & 0x0f) << 8)) >= kPrime;
1075
142k
        int outOfRange2 = (*c++ = (b2 >> 4) | (b3 << 4)) >= kPrime;
1076
1077
142k
        if (outOfRange1 | outOfRange2)
1078
341
            return 0;
1079
142k
    }
1080
1.05k
    return 1;
1081
1.39k
}
1082
1083
/*-
1084
 * scalar_decode_decompress_add is a combination of decoding and decompression
1085
 * both specialised for |bits| == 1, with the result added (and sum reduced) to
1086
 * the output scalar.
1087
 *
1088
 * NOTE: this function MUST not leak an input-data-depedennt timing signal.
1089
 * A timing leak in a related function in the reference Kyber implementation
1090
 * made the "clangover" attack (CVE-2024-37880) possible, giving key recovery
1091
 * for ML-KEM-512 in minutes, provided the attacker has access to precise
1092
 * timing of a CPU performing chosen-ciphertext decap.  Admittedly this is only
1093
 * a risk when private keys are reused (perhaps KEMTLS servers).
1094
 */
1095
static void
1096
scalar_decode_decompress_add(scalar *out, const uint8_t in[DEGREE / 8])
1097
402
{
1098
402
    static const uint16_t half_q_plus_1 = (ML_KEM_PRIME >> 1) + 1;
1099
402
    uint16_t *curr = out->c, *end = curr + DEGREE;
1100
402
    uint16_t mask;
1101
402
    uint8_t b;
1102
1103
    /*
1104
     * Add |half_q_plus_1| if the bit is set, without exposing a side-channel,
1105
     * avoiding the "clangover" attack.  See |constish_time_non_zero| for a
1106
     * discussion on why the value barrier is by default omitted.
1107
     */
1108
402
#define decode_decompress_add_bit                        \
1109
102k
    mask = constish_time_non_zero(bit0(b));              \
1110
102k
    *curr = reduce_once(*curr + (mask & half_q_plus_1)); \
1111
102k
    curr++;                                              \
1112
102k
    b >>= 1
1113
1114
    /* Unrolled to process each byte in one iteration */
1115
12.8k
    do {
1116
12.8k
        b = *in++;
1117
12.8k
        decode_decompress_add_bit;
1118
12.8k
        decode_decompress_add_bit;
1119
12.8k
        decode_decompress_add_bit;
1120
12.8k
        decode_decompress_add_bit;
1121
1122
12.8k
        decode_decompress_add_bit;
1123
12.8k
        decode_decompress_add_bit;
1124
12.8k
        decode_decompress_add_bit;
1125
12.8k
        decode_decompress_add_bit;
1126
12.8k
    } while (curr < end);
1127
402
#undef decode_decompress_add_bit
1128
402
}
1129
1130
/*
1131
 * FIPS 203, Section 4.2.1, Equation (4.7): Compress_d.
1132
 *
1133
 * Compresses (lossily) an input |x| mod 3329 into |bits| many bits by grouping
1134
 * numbers close to each other together. The formula used is
1135
 * round(2^|bits|/kPrime*x) mod 2^|bits|.
1136
 * Uses Barrett reduction to achieve constant time. Since we need both the
1137
 * remainder (for rounding) and the quotient (as the result), we cannot use
1138
 * |reduce| here, but need to do the Barrett reduction directly.
1139
 */
1140
static __owur uint16_t compress(uint16_t x, int bits)
1141
457k
{
1142
457k
    uint32_t shifted = (uint32_t)x << bits;
1143
457k
    uint64_t product = (uint64_t)shifted * kBarrettMultiplier;
1144
457k
    uint32_t quotient = (uint32_t)(product >> kBarrettShift);
1145
457k
    uint32_t remainder = shifted - quotient * kPrime;
1146
1147
    /*
1148
     * Adjust the quotient to round correctly:
1149
     *   0 <= remainder <= kHalfPrime round to 0
1150
     *   kHalfPrime < remainder <= kPrime + kHalfPrime round to 1
1151
     *   kPrime + kHalfPrime < remainder < 2 * kPrime round to 2
1152
     */
1153
457k
    quotient += 1 & constant_time_lt_32(kHalfPrime, remainder);
1154
457k
    quotient += 1 & constant_time_lt_32(kPrime + kHalfPrime, remainder);
1155
457k
    return quotient & ((1 << bits) - 1);
1156
457k
}
1157
1158
/*
1159
 * FIPS 203, Section 4.2.1, Equation (4.8): Decompress_d.
1160
1161
 * Decompresses |x| by using a close equi-distant representative. The formula
1162
 * is round(kPrime/2^|bits|*x). Note that 2^|bits| being the divisor allows us
1163
 * to implement this logic using only bit operations.
1164
 */
1165
static __owur uint16_t decompress(uint16_t x, int bits)
1166
192k
{
1167
192k
    uint32_t product = (uint32_t)x * kPrime;
1168
192k
    uint32_t power = 1 << bits;
1169
    /* This is |product| % power, since |power| is a power of 2. */
1170
192k
    uint32_t remainder = product & (power - 1);
1171
    /* This is |product| / power, since |power| is a power of 2. */
1172
192k
    uint32_t lower = product >> bits;
1173
1174
    /*
1175
     * The rounding logic works since the first half of numbers mod |power|
1176
     * have a 0 as first bit, and the second half has a 1 as first bit, since
1177
     * |power| is a power of 2. As a 12 bit number, |remainder| is always
1178
     * positive, so we will shift in 0s for a right shift.
1179
     */
1180
192k
    return lower + (remainder >> (bits - 1));
1181
192k
}
1182
1183
/*-
1184
 * FIPS 203, Section 4.2.1, Equation (4.7): "Compress_d".
1185
 * In-place lossy rounding of scalars to 2^d bits.
1186
 */
1187
static void scalar_compress(scalar *s, int bits)
1188
1.78k
{
1189
1.78k
    int i;
1190
1191
459k
    for (i = 0; i < DEGREE; i++)
1192
457k
        s->c[i] = compress(s->c[i], bits);
1193
1.78k
}
1194
1195
/*
1196
 * FIPS 203, Section 4.2.1, Equation (4.8): "Decompress_d".
1197
 * In-place approximate recovery of scalars from 2^d bit compression.
1198
 */
1199
static void scalar_decompress(scalar *s, int bits)
1200
752
{
1201
752
    int i;
1202
1203
193k
    for (i = 0; i < DEGREE; i++)
1204
192k
        s->c[i] = decompress(s->c[i], bits);
1205
752
}
1206
1207
/* Addition updating the LHS vector in-place. */
1208
static void vector_add(scalar *lhs, const scalar *rhs, int rank)
1209
402
{
1210
1.19k
    do {
1211
1.19k
        scalar_add(lhs++, rhs++);
1212
1.19k
    } while (--rank > 0);
1213
402
}
1214
1215
/*
1216
 * Encodes an entire vector into 32*|rank|*|bits| bytes. Note that since 256
1217
 * (DEGREE) is divisible by 8, the individual vector entries will always fill a
1218
 * whole number of bytes, so we do not need to worry about bit packing here.
1219
 */
1220
static void vector_encode(uint8_t *out, const scalar *a, int bits, int rank)
1221
64.5k
{
1222
64.5k
    int stride = bits * DEGREE / 8;
1223
1224
258k
    for (; rank-- > 0; out += stride)
1225
193k
        scalar_encode(out, a++, bits);
1226
64.5k
}
1227
1228
/*
1229
 * Decodes 32*|rank|*|bits| bytes from |in| into |out|. It returns early
1230
 * if any parsed value is >= |ML_KEM_PRIME|.  The resulting scalars are
1231
 * then decompressed and transformed via the NTT.
1232
 *
1233
 * Note: Used only in decrypt_cpa(), which returns void and so does not check
1234
 * the return value of this function.  Side-channels are fine when the input
1235
 * ciphertext to decap() is simply syntactically invalid.
1236
 */
1237
static void
1238
vector_decode_decompress_ntt(scalar *out, const uint8_t *in, int bits, int rank)
1239
189
{
1240
189
    int stride = bits * DEGREE / 8;
1241
1242
752
    for (; rank-- > 0; in += stride, ++out) {
1243
563
        scalar_decode(out, in, bits);
1244
563
        scalar_decompress(out, bits);
1245
563
        scalar_ntt(out);
1246
563
    }
1247
189
}
1248
1249
/* vector_decode(), specialised to bits == 12. */
1250
static __owur int vector_decode_12(scalar *out, const uint8_t in[3 * DEGREE / 2], int rank)
1251
723
{
1252
723
    int stride = 3 * DEGREE / 2;
1253
1254
1.78k
    for (; rank-- > 0; in += stride)
1255
1.39k
        if (!scalar_decode_12(out++, in))
1256
341
            return 0;
1257
382
    return 1;
1258
723
}
1259
1260
/* In-place compression of each scalar component */
1261
static void vector_compress(scalar *a, int bits, int rank)
1262
402
{
1263
1.19k
    do {
1264
1.19k
        scalar_compress(a++, bits);
1265
1.19k
    } while (--rank > 0);
1266
402
}
1267
1268
/* The output scalar must not overlap with the inputs */
1269
static void inner_product(scalar *out, const scalar *lhs, const scalar *rhs,
1270
    int rank)
1271
591
{
1272
591
    scalar_mult(out, lhs, rhs);
1273
1.76k
    while (--rank > 0)
1274
1.17k
        scalar_mult_add(out, ++lhs, ++rhs);
1275
591
}
1276
1277
/*
1278
 * Here, the output vector must not overlap with the inputs, the result is
1279
 * directly subjected to inverse NTT.
1280
 */
1281
static void
1282
matrix_mult_intt(scalar *out, const scalar *m, const scalar *a, int rank)
1283
402
{
1284
402
    const scalar *ar;
1285
402
    int i, j;
1286
1287
1.60k
    for (i = rank; i-- > 0; ++out) {
1288
1.19k
        scalar_mult(out, m++, ar = a);
1289
3.81k
        for (j = rank - 1; j > 0; --j)
1290
2.61k
            scalar_mult_add(out, m++, ++ar);
1291
1.19k
        scalar_inverse_ntt(out);
1292
1.19k
    }
1293
402
}
1294
1295
/* Here, the output vector must not overlap with the inputs */
1296
static void
1297
matrix_mult_transpose_add(scalar *out, const scalar *m, const scalar *a, int rank)
1298
63.5k
{
1299
63.5k
    const scalar *mc = m, *mr, *ar;
1300
63.5k
    int i, j;
1301
1302
254k
    for (i = rank; i-- > 0; ++out) {
1303
190k
        scalar_mult_add(out, mr = mc++, ar = a);
1304
571k
        for (j = rank; --j > 0;)
1305
381k
            scalar_mult_add(out, (mr += rank), ++ar);
1306
190k
    }
1307
63.5k
}
1308
1309
/*-
1310
 * Expands the matrix from a seed for key generation and for encaps-CPA.
1311
 * NOTE: FIPS 203 matrix "A" is the transpose of this matrix, computed
1312
 * by appending the (i,j) indices to the seed in the opposite order!
1313
 *
1314
 * Where FIPS 203 computes t = A * s + e, we use the transpose of "m".
1315
 */
1316
static __owur int matrix_expand(EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
1317
63.9k
{
1318
63.9k
    scalar *out = key->m;
1319
63.9k
    uint8_t input[ML_KEM_RANDOM_BYTES + 2];
1320
63.9k
    int rank = key->vinfo->rank;
1321
63.9k
    int i, j;
1322
1323
    /*
1324
     * The seeds derived below and the sampling buffers in sample_scalar()
1325
     * are not cleansed: per FIPS 203 section 3.3 the matrix A is easily
1326
     * computed from the public encapsulation key and does not require any
1327
     * special protections.
1328
     */
1329
63.9k
    memcpy(input, key->rho, ML_KEM_RANDOM_BYTES);
1330
255k
    for (i = 0; i < rank; i++) {
1331
765k
        for (j = 0; j < rank; j++) {
1332
574k
            input[ML_KEM_RANDOM_BYTES] = i;
1333
574k
            input[ML_KEM_RANDOM_BYTES + 1] = j;
1334
574k
            if (!EVP_DigestInit_ex(mdctx, key->shake128_md, NULL)
1335
574k
                || !EVP_DigestUpdate(mdctx, input, sizeof(input))
1336
574k
                || !sample_scalar(out++, mdctx))
1337
0
                return 0;
1338
574k
        }
1339
191k
    }
1340
63.9k
    return 1;
1341
63.9k
}
1342
1343
/*
1344
 * Algorithm 7 from the spec, with eta fixed to two and the PRF call
1345
 * included. Creates binominally distributed elements by sampling 2*|eta| bits,
1346
 * and setting the coefficient to the count of the first bits minus the count of
1347
 * the second bits, resulting in a centered binomial distribution. Since eta is
1348
 * two this gives -2/2 with a probability of 1/16, -1/1 with probability 1/4,
1349
 * and 0 with probability 3/8.
1350
 */
1351
static __owur int cbd_2(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1],
1352
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1353
382k
{
1354
382k
    uint16_t *curr = out->c, *end = curr + DEGREE;
1355
382k
    uint8_t randbuf[4 * DEGREE / 8], *r = randbuf; /* 64 * eta slots */
1356
382k
    uint16_t value, mask;
1357
382k
    uint8_t b;
1358
1359
382k
    if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) {
1360
0
        OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1361
0
        return 0;
1362
0
    }
1363
1364
48.9M
    do {
1365
48.9M
        b = *r++;
1366
1367
        /*
1368
         * Add |kPrime| if |value| underflowed.  See |constish_time_non_zero|
1369
         * for a discussion on why the value barrier is by default omitted.
1370
         * While this could have been written reduce_once(value + kPrime), this
1371
         * is one extra addition and small range of |value| tempts some
1372
         * versions of Clang to emit a branch.
1373
         */
1374
48.9M
        value = bit0(b) + bitn(1, b);
1375
48.9M
        value -= bitn(2, b) + bitn(3, b);
1376
48.9M
        mask = constish_time_non_zero(value >> 15);
1377
48.9M
        *curr++ = value + (kPrime & mask);
1378
1379
48.9M
        value = bitn(4, b) + bitn(5, b);
1380
48.9M
        value -= bitn(6, b) + bitn(7, b);
1381
48.9M
        mask = constish_time_non_zero(value >> 15);
1382
48.9M
        *curr++ = value + (kPrime & mask);
1383
48.9M
    } while (curr < end);
1384
1385
382k
    OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1386
382k
    return 1;
1387
382k
}
1388
1389
/*
1390
 * Algorithm 7 from the spec, with eta fixed to three and the PRF call
1391
 * included. Creates binominally distributed elements by sampling 3*|eta| bits,
1392
 * and setting the coefficient to the count of the first bits minus the count of
1393
 * the second bits, resulting in a centered binomial distribution.
1394
 */
1395
static __owur int cbd_3(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1],
1396
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1397
1.52k
{
1398
1.52k
    uint16_t *curr = out->c, *end = curr + DEGREE;
1399
1.52k
    uint8_t randbuf[6 * DEGREE / 8], *r = randbuf; /* 64 * eta slots */
1400
1.52k
    uint8_t b1, b2, b3;
1401
1.52k
    uint16_t value, mask;
1402
1403
1.52k
    if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) {
1404
0
        OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1405
0
        return 0;
1406
0
    }
1407
1408
97.7k
    do {
1409
97.7k
        b1 = *r++;
1410
97.7k
        b2 = *r++;
1411
97.7k
        b3 = *r++;
1412
1413
        /*
1414
         * Add |kPrime| if |value| underflowed.  See |constish_time_non_zero|
1415
         * for a discussion on why the value barrier is by default omitted.
1416
         * While this could have been written reduce_once(value + kPrime), this
1417
         * is one extra addition and small range of |value| tempts some
1418
         * versions of Clang to emit a branch.
1419
         */
1420
97.7k
        value = bit0(b1) + bitn(1, b1) + bitn(2, b1);
1421
97.7k
        value -= bitn(3, b1) + bitn(4, b1) + bitn(5, b1);
1422
97.7k
        mask = constish_time_non_zero(value >> 15);
1423
97.7k
        *curr++ = value + (kPrime & mask);
1424
1425
97.7k
        value = bitn(6, b1) + bitn(7, b1) + bit0(b2);
1426
97.7k
        value -= bitn(1, b2) + bitn(2, b2) + bitn(3, b2);
1427
97.7k
        mask = constish_time_non_zero(value >> 15);
1428
97.7k
        *curr++ = value + (kPrime & mask);
1429
1430
97.7k
        value = bitn(4, b2) + bitn(5, b2) + bitn(6, b2);
1431
97.7k
        value -= bitn(7, b2) + bit0(b3) + bitn(1, b3);
1432
97.7k
        mask = constish_time_non_zero(value >> 15);
1433
97.7k
        *curr++ = value + (kPrime & mask);
1434
1435
97.7k
        value = bitn(2, b3) + bitn(3, b3) + bitn(4, b3);
1436
97.7k
        value -= bitn(5, b3) + bitn(6, b3) + bitn(7, b3);
1437
97.7k
        mask = constish_time_non_zero(value >> 15);
1438
97.7k
        *curr++ = value + (kPrime & mask);
1439
97.7k
    } while (curr < end);
1440
1441
1.52k
    OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1442
1.52k
    return 1;
1443
1.52k
}
1444
1445
/*
1446
 * Generates a secret vector by using |cbd| with the given seed to generate
1447
 * scalar elements and incrementing |counter| for each slot of the vector.
1448
 */
1449
static __owur int gencbd_vector(scalar *out, CBD_FUNC cbd, uint8_t *counter,
1450
    const uint8_t seed[ML_KEM_RANDOM_BYTES], int rank,
1451
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1452
402
{
1453
402
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1454
402
    int ret = 0;
1455
1456
402
    memcpy(input, seed, ML_KEM_RANDOM_BYTES);
1457
1.19k
    do {
1458
1.19k
        input[ML_KEM_RANDOM_BYTES] = (*counter)++;
1459
1.19k
        if (!cbd(out++, input, mdctx, key))
1460
0
            goto end;
1461
1.19k
    } while (--rank > 0);
1462
402
    ret = 1;
1463
1464
402
end:
1465
402
    OPENSSL_cleanse((void *)input, sizeof(input));
1466
402
    return ret;
1467
402
}
1468
1469
/*
1470
 * As above plus NTT transform.
1471
 */
1472
static __owur int gencbd_vector_ntt(scalar *out, CBD_FUNC cbd, uint8_t *counter,
1473
    const uint8_t seed[ML_KEM_RANDOM_BYTES], int rank,
1474
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1475
127k
{
1476
127k
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1477
127k
    int ret = 0;
1478
1479
127k
    memcpy(input, seed, ML_KEM_RANDOM_BYTES);
1480
382k
    do {
1481
382k
        input[ML_KEM_RANDOM_BYTES] = (*counter)++;
1482
382k
        if (!cbd(out, input, mdctx, key))
1483
0
            goto end;
1484
382k
        scalar_ntt(out++);
1485
382k
    } while (--rank > 0);
1486
127k
    ret = 1;
1487
1488
127k
end:
1489
127k
    OPENSSL_cleanse((void *)input, sizeof(input));
1490
127k
    return ret;
1491
127k
}
1492
1493
/* The |ETA1| value for ML-KEM-512 is 3, the rest and all ETA2 values are 2. */
1494
30.5k
#define CBD1(evp_type) ((evp_type) == EVP_PKEY_ML_KEM_512 ? cbd_3 : cbd_2)
1495
1496
/*
1497
 * FIPS 203, Section 5.2, Algorithm 14: K-PKE.Encrypt.
1498
 *
1499
 * Encrypts a message with given randomness to the ciphertext in |out|. Without
1500
 * applying the Fujisaki-Okamoto transform this would not result in a CCA
1501
 * secure scheme, since lattice schemes are vulnerable to decryption failure
1502
 * oracles.
1503
 *
1504
 * The steps are re-ordered to make more efficient/localised use of storage.
1505
 *
1506
 * Note also that the input public key is assumed to hold a precomputed matrix
1507
 * |A| (our key->m, with the public key holding an expanded (16-bit per scalar
1508
 * coefficient) key->t vector).
1509
 *
1510
 * Caller passes storage in |tmp| for for two temporary vectors.
1511
 */
1512
static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
1513
    const uint8_t message[DEGREE / 8],
1514
    const uint8_t r[ML_KEM_RANDOM_BYTES], scalar *tmp,
1515
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1516
402
{
1517
402
    const ML_KEM_VINFO *vinfo = key->vinfo;
1518
402
    CBD_FUNC cbd_1 = CBD1(vinfo->evp_type);
1519
402
    int rank = vinfo->rank;
1520
    /* We can use tmp[0..rank-1] as storage for |y|, then |e1|, ... */
1521
402
    scalar *y = &tmp[0], *e1 = y, *e2 = y;
1522
    /* We can use tmp[rank]..tmp[2*rank - 1] for |u| */
1523
402
    scalar *u = &tmp[rank];
1524
402
    scalar v;
1525
402
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1526
402
    uint8_t counter = 0;
1527
402
    int du = vinfo->du;
1528
402
    int dv = vinfo->dv;
1529
402
    int ret = 0;
1530
1531
    /* FIPS 203 "y" vector */
1532
402
    if (!gencbd_vector_ntt(y, cbd_1, &counter, r, rank, mdctx, key))
1533
0
        goto end;
1534
    /* FIPS 203 "v" scalar */
1535
402
    inner_product(&v, key->t, y, rank);
1536
402
    scalar_inverse_ntt(&v);
1537
    /* FIPS 203 "u" vector */
1538
402
    matrix_mult_intt(u, key->m, y, rank);
1539
1540
    /* All done with |y|, now free to reuse tmp[0] for FIPS 203 |e1| */
1541
402
    if (!gencbd_vector(e1, cbd_2, &counter, r, rank, mdctx, key))
1542
0
        goto end;
1543
402
    vector_add(u, e1, rank);
1544
402
    vector_compress(u, du, rank);
1545
402
    vector_encode(out, u, du, rank);
1546
1547
    /* All done with |e1|, now free to reuse tmp[0] for FIPS 203 |e2| */
1548
402
    memcpy(input, r, ML_KEM_RANDOM_BYTES);
1549
402
    input[ML_KEM_RANDOM_BYTES] = counter;
1550
402
    if (!cbd_2(e2, input, mdctx, key))
1551
0
        goto end;
1552
402
    scalar_add(&v, e2);
1553
1554
    /* Combine message with |v| */
1555
402
    scalar_decode_decompress_add(&v, message);
1556
402
    scalar_compress(&v, dv);
1557
402
    scalar_encode(out + vinfo->u_vector_bytes, &v, dv);
1558
402
    ret = 1;
1559
1560
402
end:
1561
402
    OPENSSL_cleanse((void *)input, sizeof(input));
1562
402
    OPENSSL_cleanse((void *)&v, sizeof(v));
1563
402
    return ret;
1564
402
}
1565
1566
/*
1567
 * FIPS 203, Section 5.3, Algorithm 15: K-PKE.Decrypt.
1568
 */
1569
static void
1570
decrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
1571
    const uint8_t *ctext, scalar *u, const ML_KEM_KEY *key)
1572
189
{
1573
189
    const ML_KEM_VINFO *vinfo = key->vinfo;
1574
189
    scalar v, mask;
1575
189
    int rank = vinfo->rank;
1576
189
    int du = vinfo->du;
1577
189
    int dv = vinfo->dv;
1578
1579
189
    vector_decode_decompress_ntt(u, ctext, du, rank);
1580
189
    scalar_decode(&v, ctext + vinfo->u_vector_bytes, dv);
1581
189
    scalar_decompress(&v, dv);
1582
189
    inner_product(&mask, key->s, u, rank);
1583
189
    scalar_inverse_ntt(&mask);
1584
189
    scalar_sub(&v, &mask);
1585
189
    scalar_compress(&v, 1);
1586
189
    scalar_encode_1(out, &v);
1587
1588
189
    OPENSSL_cleanse((void *)&v, sizeof(v));
1589
189
    OPENSSL_cleanse((void *)&mask, sizeof(mask));
1590
189
}
1591
1592
/*-
1593
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1594
 * FIPS 203, Section 7.2, Algorithm 20: "ML-KEM.Encaps".
1595
 *
1596
 * Fills the |out| buffer with the |ek| output of "ML-KEM.KeyGen", or,
1597
 * equivalently, the |ek| input of "ML-KEM.Encaps", i.e. returns the
1598
 * wire-format of an ML-KEM public key.
1599
 */
1600
static void encode_pubkey(uint8_t *out, const ML_KEM_KEY *key)
1601
64.0k
{
1602
64.0k
    const uint8_t *rho = key->rho;
1603
64.0k
    const ML_KEM_VINFO *vinfo = key->vinfo;
1604
1605
64.0k
    vector_encode(out, key->t, 12, vinfo->rank);
1606
64.0k
    memcpy(out + vinfo->vector_bytes, rho, ML_KEM_RANDOM_BYTES);
1607
64.0k
}
1608
1609
/*-
1610
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1611
 *
1612
 * Fills the |out| buffer with the |dk| output of "ML-KEM.KeyGen".
1613
 * This matches the input format of parse_prvkey() below.
1614
 */
1615
static void encode_prvkey(uint8_t *out, const ML_KEM_KEY *key)
1616
144
{
1617
144
    const ML_KEM_VINFO *vinfo = key->vinfo;
1618
1619
144
    vector_encode(out, key->s, 12, vinfo->rank);
1620
144
    out += vinfo->vector_bytes;
1621
144
    encode_pubkey(out, key);
1622
144
    out += vinfo->pubkey_bytes;
1623
144
    memcpy(out, key->pkhash, ML_KEM_PKHASH_BYTES);
1624
144
    out += ML_KEM_PKHASH_BYTES;
1625
144
    memcpy(out, key->z, ML_KEM_RANDOM_BYTES);
1626
144
}
1627
1628
/*-
1629
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1630
 * FIPS 203, Section 7.2, Algorithm 20: "ML-KEM.Encaps".
1631
 *
1632
 * This function parses the |in| buffer as the |ek| output of "ML-KEM.KeyGen",
1633
 * or, equivalently, the |ek| input of "ML-KEM.Encaps", i.e. decodes the
1634
 * wire-format of the ML-KEM public key.
1635
 */
1636
static int parse_pubkey(const uint8_t *in, EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
1637
612
{
1638
612
    const ML_KEM_VINFO *vinfo = key->vinfo;
1639
1640
    /* Decode and check |t| */
1641
612
    if (!vector_decode_12(key->t, in, vinfo->rank)) {
1642
252
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1643
252
            "%s invalid public 't' vector",
1644
252
            vinfo->algorithm_name);
1645
252
        return 0;
1646
252
    }
1647
    /* Save the matrix |m| recovery seed |rho| */
1648
360
    memcpy(key->rho, in + vinfo->vector_bytes, ML_KEM_RANDOM_BYTES);
1649
    /*
1650
     * Pre-compute the public key hash, needed for both encap and decap.
1651
     * Also pre-compute the matrix expansion, stored with the public key.
1652
     */
1653
360
    if (!hash_h(key->pkhash, in, vinfo->pubkey_bytes, mdctx, key)
1654
360
        || !matrix_expand(mdctx, key)) {
1655
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1656
0
            "internal error while parsing %s public key",
1657
0
            vinfo->algorithm_name);
1658
0
        return 0;
1659
0
    }
1660
360
    return 1;
1661
360
}
1662
1663
/*
1664
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1665
 *
1666
 * Parses the |in| buffer as a |dk| output of "ML-KEM.KeyGen".
1667
 * This matches the output format of encode_prvkey() above.
1668
 */
1669
static int parse_prvkey(const uint8_t *in, EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
1670
111
{
1671
111
    const ML_KEM_VINFO *vinfo = key->vinfo;
1672
1673
    /* Decode and check |s|. */
1674
111
    if (!vector_decode_12(key->s, in, vinfo->rank)) {
1675
89
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1676
89
            "%s invalid private 's' vector",
1677
89
            vinfo->algorithm_name);
1678
89
        return 0;
1679
89
    }
1680
22
    in += vinfo->vector_bytes;
1681
1682
22
    if (!parse_pubkey(in, mdctx, key))
1683
11
        return 0;
1684
11
    in += vinfo->pubkey_bytes;
1685
1686
    /* Check public key hash. */
1687
11
    if (memcmp(key->pkhash, in, ML_KEM_PKHASH_BYTES) != 0) {
1688
11
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1689
11
            "%s public key hash mismatch",
1690
11
            vinfo->algorithm_name);
1691
11
        return 0;
1692
11
    }
1693
0
    in += ML_KEM_PKHASH_BYTES;
1694
1695
0
    memcpy(key->z, in, ML_KEM_RANDOM_BYTES);
1696
0
    return 1;
1697
11
}
1698
1699
/*
1700
 * FIPS 203, Section 6.1, Algorithm 16: "ML-KEM.KeyGen_internal".
1701
 *
1702
 * The implementation of Section 5.1, Algorithm 13, "K-PKE.KeyGen(d)" is
1703
 * inlined.
1704
 *
1705
 * The caller MUST pass a pre-allocated digest context that is not shared with
1706
 * any concurrent computation.
1707
 *
1708
 * This function optionally outputs the serialised wire-form |ek| public key
1709
 * into the provided |pubenc| buffer, and generates the content of the |rho|,
1710
 * |pkhash|, |t|, |m|, |s| and |z| components of the private |key| (which must
1711
 * have preallocated space for these).
1712
 *
1713
 * Keys are computed from a 32-byte random |d| plus the 1 byte rank for
1714
 * domain separation.  These are concatenated and hashed to produce a pair of
1715
 * 32-byte seeds public "rho", used to generate the matrix, and private "sigma",
1716
 * used to generate the secret vector |s|.
1717
 *
1718
 * The second random input |z| is copied verbatim into the Fujisaki-Okamoto
1719
 * (FO) transform "implicit-rejection" secret (the |z| component of the private
1720
 * key), which thwarts chosen-ciphertext attacks, provided decap() runs in
1721
 * constant time, with no side channel leaks, on all well-formed (valid length,
1722
 * and correctly encoded) ciphertext inputs.
1723
 */
1724
static __owur int genkey(const uint8_t seed[ML_KEM_SEED_BYTES],
1725
    EVP_MD_CTX *mdctx, uint8_t *pubenc, ML_KEM_KEY *key)
1726
30.1k
{
1727
30.1k
    uint8_t hashed[2 * ML_KEM_RANDOM_BYTES];
1728
30.1k
    const uint8_t *const sigma = hashed + ML_KEM_RANDOM_BYTES;
1729
30.1k
    uint8_t augmented_seed[ML_KEM_RANDOM_BYTES + 1];
1730
30.1k
    const ML_KEM_VINFO *vinfo = key->vinfo;
1731
30.1k
    CBD_FUNC cbd_1 = CBD1(vinfo->evp_type);
1732
30.1k
    int rank = vinfo->rank;
1733
30.1k
    uint8_t counter = 0;
1734
30.1k
    int ret = 0;
1735
1736
    /*
1737
     * Use the "d" seed salted with the rank to derive the public and private
1738
     * seeds rho and sigma.
1739
     */
1740
30.1k
    memcpy(augmented_seed, seed, ML_KEM_RANDOM_BYTES);
1741
30.1k
    augmented_seed[ML_KEM_RANDOM_BYTES] = (uint8_t)rank;
1742
30.1k
    if (!hash_g(hashed, augmented_seed, sizeof(augmented_seed), mdctx, key))
1743
0
        goto end;
1744
30.1k
    memcpy(key->rho, hashed, ML_KEM_RANDOM_BYTES);
1745
    /* The |rho| matrix seed is public */
1746
30.1k
    CONSTTIME_DECLASSIFY(key->rho, ML_KEM_RANDOM_BYTES);
1747
1748
    /* FIPS 203 |e| vector is initial value of key->t */
1749
30.1k
    if (!matrix_expand(mdctx, key)
1750
30.1k
        || !gencbd_vector_ntt(key->s, cbd_1, &counter, sigma, rank, mdctx, key)
1751
30.1k
        || !gencbd_vector_ntt(key->t, cbd_1, &counter, sigma, rank, mdctx, key))
1752
0
        goto end;
1753
1754
    /* To |e| we now add the product of transpose |m| and |s|, giving |t|. */
1755
30.1k
    matrix_mult_transpose_add(key->t, key->m, key->s, rank);
1756
    /* The |t| vector is public */
1757
30.1k
    CONSTTIME_DECLASSIFY(key->t, vinfo->rank * sizeof(scalar));
1758
1759
30.1k
    if (pubenc == NULL) {
1760
        /* Incremental digest of public key without in-full serialisation. */
1761
30.1k
        if (!hash_h_pubkey(key->pkhash, mdctx, key))
1762
0
            goto end;
1763
30.1k
    } else {
1764
0
        encode_pubkey(pubenc, key);
1765
0
        if (!hash_h(key->pkhash, pubenc, vinfo->pubkey_bytes, mdctx, key))
1766
0
            goto end;
1767
0
    }
1768
1769
    /* Save |z| portion of seed for "implicit rejection" on failure. */
1770
30.1k
    memcpy(key->z, seed + ML_KEM_RANDOM_BYTES, ML_KEM_RANDOM_BYTES);
1771
1772
    /* Optionally save the |d| portion of the seed */
1773
30.1k
    key->d = key->z + ML_KEM_RANDOM_BYTES;
1774
30.1k
    if (key->prov_flags & ML_KEM_KEY_RETAIN_SEED) {
1775
30.1k
        memcpy(key->d, seed, ML_KEM_RANDOM_BYTES);
1776
30.1k
    } else {
1777
0
        OPENSSL_cleanse(key->d, ML_KEM_RANDOM_BYTES);
1778
0
        key->d = NULL;
1779
0
    }
1780
1781
30.1k
    ret = 1;
1782
30.1k
end:
1783
30.1k
    OPENSSL_cleanse((void *)augmented_seed, sizeof(augmented_seed));
1784
30.1k
    OPENSSL_cleanse((void *)hashed, sizeof(hashed));
1785
30.1k
    if (ret == 0) {
1786
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1787
0
            "internal error while generating %s private key",
1788
0
            vinfo->algorithm_name);
1789
0
    }
1790
30.1k
    return ret;
1791
30.1k
}
1792
1793
/*-
1794
 * FIPS 203, Section 6.2, Algorithm 17: "ML-KEM.Encaps_internal".
1795
 * This is the deterministic version with randomness supplied externally.
1796
 *
1797
 * The caller must pass space for two vectors in |tmp|.
1798
 * The |ctext| buffer have space for the ciphertext of the ML-KEM variant
1799
 * of the provided key.
1800
 */
1801
static int encap(uint8_t *ctext, uint8_t secret[ML_KEM_SHARED_SECRET_BYTES],
1802
    const uint8_t entropy[ML_KEM_RANDOM_BYTES],
1803
    scalar *tmp, EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1804
213
{
1805
213
    uint8_t input[ML_KEM_RANDOM_BYTES + ML_KEM_PKHASH_BYTES];
1806
213
    uint8_t Kr[ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES];
1807
213
    uint8_t *r = Kr + ML_KEM_SHARED_SECRET_BYTES;
1808
213
    int ret;
1809
1810
213
    memcpy(input, entropy, ML_KEM_RANDOM_BYTES);
1811
213
    memcpy(input + ML_KEM_RANDOM_BYTES, key->pkhash, ML_KEM_PKHASH_BYTES);
1812
213
    ret = hash_g(Kr, input, sizeof(input), mdctx, key)
1813
213
        && encrypt_cpa(ctext, entropy, r, tmp, mdctx, key);
1814
213
    OPENSSL_cleanse((void *)input, sizeof(input));
1815
1816
213
    if (ret)
1817
213
        memcpy(secret, Kr, ML_KEM_SHARED_SECRET_BYTES);
1818
0
    else
1819
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1820
0
            "internal error while performing %s encapsulation",
1821
0
            key->vinfo->algorithm_name);
1822
213
    OPENSSL_cleanse((void *)Kr, sizeof(Kr));
1823
213
    return ret;
1824
213
}
1825
1826
/*
1827
 * FIPS 203, Section 6.3, Algorithm 18: ML-KEM.Decaps_internal
1828
 *
1829
 * Barring failure of the supporting SHA3/SHAKE primitives, this is fully
1830
 * deterministic, the randomness for the FO transform is extracted during
1831
 * private key generation.
1832
 *
1833
 * The caller must pass space for two vectors in |tmp|.
1834
 * The |ctext| and |tmp_ctext| buffers must each have space for the ciphertext
1835
 * of the key's ML-KEM variant.
1836
 */
1837
static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES],
1838
    const uint8_t *ctext, uint8_t *tmp_ctext, scalar *tmp,
1839
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1840
97
{
1841
97
    uint8_t decrypted[ML_KEM_SHARED_SECRET_BYTES + ML_KEM_PKHASH_BYTES];
1842
97
    uint8_t failure_key[ML_KEM_RANDOM_BYTES];
1843
97
    uint8_t Kr[ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES];
1844
97
    uint8_t *r = Kr + ML_KEM_SHARED_SECRET_BYTES;
1845
97
    const uint8_t *pkhash = key->pkhash;
1846
97
    const ML_KEM_VINFO *vinfo = key->vinfo;
1847
97
    int i;
1848
97
    uint8_t mask;
1849
1850
    /*
1851
     * If our KDF is unavailable, fail early! Otherwise, keep going ignoring
1852
     * any further errors, returning success, and whatever we got for a shared
1853
     * secret.  The decrypt_cpa() function is just arithmetic on secret data,
1854
     * so should not be subject to failure that makes its output predictable.
1855
     *
1856
     * We guard against "should never happen" catastrophic failure of the
1857
     * "pure" function |hash_g| by overwriting the shared secret with the
1858
     * content of the failure key and returning early, if nevertheless hash_g
1859
     * fails.  This is not constant-time, but a failure of |hash_g| already
1860
     * implies loss of side-channel resistance.
1861
     *
1862
     * The same action is taken, if also |encrypt_cpa| should catastrophically
1863
     * fail, due to failure of the |PRF| underlying the CBD functions.
1864
     */
1865
97
    if (!kdf(failure_key, key->z, ctext, vinfo->ctext_bytes, mdctx, key)) {
1866
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1867
0
            "internal error while performing %s decapsulation",
1868
0
            vinfo->algorithm_name);
1869
0
        OPENSSL_cleanse(failure_key, sizeof(failure_key));
1870
0
        return 0;
1871
0
    }
1872
97
    decrypt_cpa(decrypted, ctext, tmp, key);
1873
97
    memcpy(decrypted + ML_KEM_SHARED_SECRET_BYTES, pkhash, ML_KEM_PKHASH_BYTES);
1874
97
    if (!hash_g(Kr, decrypted, sizeof(decrypted), mdctx, key)
1875
97
        || !encrypt_cpa(tmp_ctext, decrypted, r, tmp, mdctx, key)) {
1876
0
        memcpy(secret, failure_key, ML_KEM_SHARED_SECRET_BYTES);
1877
0
        OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES);
1878
0
        OPENSSL_cleanse(Kr, sizeof(Kr));
1879
0
        OPENSSL_cleanse(failure_key, sizeof(failure_key));
1880
0
        return 1;
1881
0
    }
1882
97
    mask = constant_time_eq_int_8(0,
1883
97
        CRYPTO_memcmp(ctext, tmp_ctext, vinfo->ctext_bytes));
1884
3.20k
    for (i = 0; i < ML_KEM_SHARED_SECRET_BYTES; i++)
1885
3.10k
        secret[i] = constant_time_select_8(mask, Kr[i], failure_key[i]);
1886
97
    OPENSSL_cleanse(decrypted, ML_KEM_SHARED_SECRET_BYTES);
1887
97
    OPENSSL_cleanse(Kr, sizeof(Kr));
1888
97
    OPENSSL_cleanse(failure_key, sizeof(failure_key));
1889
97
    return 1;
1890
97
}
1891
1892
/*
1893
 * After allocating storage for public or private key data, update the key
1894
 * component pointers to reference that storage.
1895
 *
1896
 * The caller should only store private data in `priv` *after* a successful
1897
 * (non-zero) return from this function.
1898
 */
1899
static __owur int add_storage(scalar *pub, scalar *priv,
1900
    int private, int dup, ML_KEM_KEY *key)
1901
49.1k
{
1902
49.1k
    int rank = key->vinfo->rank;
1903
1904
49.1k
    if (pub == NULL || (private && priv == NULL)) {
1905
        /*
1906
         * One of these could be allocated correctly. It is legal to call free with a NULL
1907
         * pointer, so always attempt to free both allocations here
1908
         */
1909
0
        OPENSSL_free(pub);
1910
0
        OPENSSL_secure_free(priv);
1911
0
        return 0;
1912
0
    }
1913
1914
    /*
1915
     * We're adding key material, set up rho and pkhash to point to the
1916
     * rho_pkhash buffer.  Zero the key hash when creating fresh keys.
1917
     */
1918
49.1k
    if (dup == 0)
1919
49.0k
        memset(key->rho_pkhash, 0, sizeof(key->rho_pkhash));
1920
49.1k
    key->rho = key->rho_pkhash;
1921
49.1k
    key->pkhash = key->rho_pkhash + ML_KEM_RANDOM_BYTES;
1922
49.1k
    key->d = key->z = NULL;
1923
1924
    /* A public key needs space for |t| and |m| */
1925
49.1k
    key->m = (key->t = pub) + rank;
1926
1927
    /*
1928
     * A private key also needs space for |s| and |z|.
1929
     * The |z| buffer always includes additional space for |d|, but a key's |d|
1930
     * pointer is left NULL when parsed from the NIST format, which omits that
1931
     * information.  Only keys generated from a (d, z) seed pair will have a
1932
     * non-NULL |d| pointer.
1933
     */
1934
49.1k
    if (private)
1935
48.5k
        key->z = (uint8_t *)(rank + (key->s = priv));
1936
49.1k
    return 1;
1937
49.1k
}
1938
1939
/*
1940
 * After freeing the storage associated with a key that failed to be
1941
 * constructed, reset the internal pointers back to NULL.
1942
 */
1943
void ossl_ml_kem_key_reset(ML_KEM_KEY *key)
1944
49.5k
{
1945
    /*
1946
     * seedbuf can be allocated and contain |z| and |d| if the key is
1947
     * being created from a private key encoding.  Similarly a pending
1948
     * serialised (encoded) private key may be queued up to load.
1949
     * Clear and free that data now.
1950
     */
1951
49.5k
    if (key->seedbuf != NULL)
1952
20
        OPENSSL_secure_clear_free(key->seedbuf, ML_KEM_SEED_BYTES);
1953
49.5k
    if (ossl_ml_kem_have_dkenc(key))
1954
0
        OPENSSL_secure_clear_free(key->encoded_dk, key->vinfo->prvkey_bytes);
1955
1956
    /*-
1957
     * Cleanse any sensitive data:
1958
     * - The private vector |s| is immediately followed by the FO failure
1959
     *   secret |z|, and seed |d|, we can cleanse all three in one call.
1960
     */
1961
49.5k
    if (key->t != NULL) {
1962
49.1k
        if (ossl_ml_kem_have_prvkey(key))
1963
48.5k
            OPENSSL_secure_clear_free(key->s, key->vinfo->prvalloc);
1964
49.1k
        OPENSSL_free(key->t);
1965
49.1k
    }
1966
49.5k
    key->d = key->z = key->seedbuf = key->encoded_dk = (uint8_t *)(key->s = key->m = key->t = NULL);
1967
49.5k
}
1968
1969
/*
1970
 * ----- API exported to the provider
1971
 *
1972
 * Parameters with an implicit fixed length in the internal static API of each
1973
 * variant have an explicit checked length argument at this layer.
1974
 */
1975
1976
/* Retrieve the parameters of one of the ML-KEM variants */
1977
const ML_KEM_VINFO *ossl_ml_kem_get_vinfo(int evp_type)
1978
299k
{
1979
299k
    switch (evp_type) {
1980
61.5k
    case EVP_PKEY_ML_KEM_512:
1981
61.5k
        return &vinfo_map[ML_KEM_512_VINFO];
1982
180k
    case EVP_PKEY_ML_KEM_768:
1983
180k
        return &vinfo_map[ML_KEM_768_VINFO];
1984
57.8k
    case EVP_PKEY_ML_KEM_1024:
1985
57.8k
        return &vinfo_map[ML_KEM_1024_VINFO];
1986
299k
    }
1987
0
    return NULL;
1988
299k
}
1989
1990
ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties,
1991
    int evp_type)
1992
44.0k
{
1993
44.0k
    const ML_KEM_VINFO *vinfo = ossl_ml_kem_get_vinfo(evp_type);
1994
44.0k
    ML_KEM_KEY *key;
1995
1996
44.0k
    if (vinfo == NULL) {
1997
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
1998
0
            "unsupported ML-KEM key type: %d", evp_type);
1999
0
        return NULL;
2000
0
    }
2001
2002
44.0k
    if ((key = OPENSSL_malloc(sizeof(*key))) == NULL)
2003
0
        return NULL;
2004
2005
44.0k
    key->vinfo = vinfo;
2006
44.0k
    key->libctx = libctx;
2007
44.0k
    key->prov_flags = ML_KEM_KEY_PROV_FLAGS_DEFAULT;
2008
44.0k
    key->shake128_md = EVP_MD_fetch(libctx, "SHAKE128", properties);
2009
44.0k
    key->shake256_md = EVP_MD_fetch(libctx, "SHAKE256", properties);
2010
44.0k
    key->sha3_256_md = EVP_MD_fetch(libctx, "SHA3-256", properties);
2011
44.0k
    key->sha3_512_md = EVP_MD_fetch(libctx, "SHA3-512", properties);
2012
44.0k
    key->d = key->z = key->rho = key->pkhash = key->encoded_dk = key->seedbuf = NULL;
2013
44.0k
    key->s = key->m = key->t = NULL;
2014
2015
44.0k
    if (key->shake128_md != NULL
2016
44.0k
        && key->shake256_md != NULL
2017
44.0k
        && key->sha3_256_md != NULL
2018
44.0k
        && key->sha3_512_md != NULL)
2019
44.0k
        return key;
2020
2021
0
    ossl_ml_kem_key_free(key);
2022
0
    ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
2023
0
        "missing SHA3 digest algorithms while creating %s key",
2024
0
        vinfo->algorithm_name);
2025
0
    return NULL;
2026
44.0k
}
2027
2028
ML_KEM_KEY *ossl_ml_kem_key_dup(const ML_KEM_KEY *key, int selection)
2029
53
{
2030
53
    int ok = 0;
2031
53
    ML_KEM_KEY *ret;
2032
2033
53
    if (key == NULL)
2034
0
        return NULL;
2035
    /*
2036
     * Partially decoded keys, not yet imported or loaded, should never be
2037
     * duplicated.
2038
     */
2039
53
    if (ossl_ml_kem_decoded_key(key))
2040
0
        return NULL;
2041
2042
53
    else if ((ret = OPENSSL_memdup(key, sizeof(*key))) == NULL)
2043
0
        return NULL;
2044
2045
53
    ret->d = ret->z = ret->rho = ret->pkhash = NULL;
2046
53
    ret->s = ret->m = ret->t = NULL;
2047
2048
    /* Clear selection bits we can't fulfill */
2049
53
    if (!ossl_ml_kem_have_pubkey(key))
2050
0
        selection = 0;
2051
53
    else if (!ossl_ml_kem_have_prvkey(key))
2052
53
        selection &= ~OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
2053
0
    else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
2054
0
        selection &= ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
2055
2056
53
    switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) {
2057
0
    case 0:
2058
0
        ok = 1;
2059
0
        break;
2060
53
    case OSSL_KEYMGMT_SELECT_PUBLIC_KEY:
2061
53
        ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc), NULL, 0, 1, ret);
2062
53
        break;
2063
0
    case OSSL_KEYMGMT_SELECT_PRIVATE_KEY:
2064
        /* Frees both and returns 0 if either is NULL */
2065
0
        ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc),
2066
0
            OPENSSL_secure_malloc(key->vinfo->prvalloc), 1, 1, ret);
2067
0
        if (ok) {
2068
0
            memcpy(ret->s, key->s, key->vinfo->prvalloc);
2069
2070
            /* Duplicated keys retain |d|, if available */
2071
0
            if (key->d != NULL)
2072
0
                ret->d = ret->z + ML_KEM_RANDOM_BYTES;
2073
0
        }
2074
0
        break;
2075
53
    }
2076
2077
53
    if (!ok) {
2078
0
        OPENSSL_free(ret);
2079
0
        return NULL;
2080
0
    }
2081
2082
53
    EVP_MD_up_ref(ret->shake128_md);
2083
53
    EVP_MD_up_ref(ret->shake256_md);
2084
53
    EVP_MD_up_ref(ret->sha3_256_md);
2085
53
    EVP_MD_up_ref(ret->sha3_512_md);
2086
2087
53
    return ret;
2088
53
}
2089
2090
void ossl_ml_kem_key_free(ML_KEM_KEY *key)
2091
193k
{
2092
193k
    if (key == NULL)
2093
144k
        return;
2094
2095
49.2k
    EVP_MD_free(key->shake128_md);
2096
49.2k
    EVP_MD_free(key->shake256_md);
2097
49.2k
    EVP_MD_free(key->sha3_256_md);
2098
49.2k
    EVP_MD_free(key->sha3_512_md);
2099
2100
49.2k
    ossl_ml_kem_key_reset(key);
2101
49.2k
    OPENSSL_free(key);
2102
49.2k
}
2103
2104
/* Serialise the public component of an ML-KEM key */
2105
int ossl_ml_kem_encode_public_key(uint8_t *out, size_t len,
2106
    const ML_KEM_KEY *key)
2107
63.8k
{
2108
63.8k
    if (!ossl_ml_kem_have_pubkey(key)
2109
63.8k
        || len != key->vinfo->pubkey_bytes)
2110
0
        return 0;
2111
63.8k
    encode_pubkey(out, key);
2112
63.8k
    return 1;
2113
63.8k
}
2114
2115
/* Serialise an ML-KEM private key */
2116
int ossl_ml_kem_encode_private_key(uint8_t *out, size_t len,
2117
    const ML_KEM_KEY *key)
2118
144
{
2119
144
    if (!ossl_ml_kem_have_prvkey(key)
2120
144
        || len != key->vinfo->prvkey_bytes)
2121
0
        return 0;
2122
144
    encode_prvkey(out, key);
2123
144
    return 1;
2124
144
}
2125
2126
int ossl_ml_kem_encode_seed(uint8_t *out, size_t len,
2127
    const ML_KEM_KEY *key)
2128
267
{
2129
267
    if (key == NULL || key->d == NULL || len != ML_KEM_SEED_BYTES)
2130
47
        return 0;
2131
    /*
2132
     * Both in the seed buffer, and in the allocated storage, the |d| component
2133
     * of the seed is stored last, so we must copy each separately.
2134
     */
2135
220
    memcpy(out, key->d, ML_KEM_RANDOM_BYTES);
2136
220
    out += ML_KEM_RANDOM_BYTES;
2137
220
    memcpy(out, key->z, ML_KEM_RANDOM_BYTES);
2138
220
    return 1;
2139
267
}
2140
2141
/*
2142
 * Stash the seed without (yet) performing a keygen, used during decoding, to
2143
 * avoid an extra keygen if we're only going to export the key again to load
2144
 * into another provider.
2145
 */
2146
ML_KEM_KEY *ossl_ml_kem_set_seed(const uint8_t *seed, size_t seedlen, ML_KEM_KEY *key)
2147
20
{
2148
20
    if (key == NULL
2149
20
        || ossl_ml_kem_have_pubkey(key)
2150
20
        || ossl_ml_kem_have_seed(key)
2151
20
        || seedlen != ML_KEM_SEED_BYTES)
2152
0
        return NULL;
2153
2154
20
    if (key->seedbuf == NULL) {
2155
20
        key->seedbuf = OPENSSL_secure_malloc(seedlen);
2156
20
        if (key->seedbuf == NULL)
2157
0
            return NULL;
2158
20
    }
2159
2160
20
    key->z = key->seedbuf;
2161
20
    key->d = key->z + ML_KEM_RANDOM_BYTES;
2162
20
    memcpy(key->d, seed, ML_KEM_RANDOM_BYTES);
2163
20
    seed += ML_KEM_RANDOM_BYTES;
2164
20
    memcpy(key->z, seed, ML_KEM_RANDOM_BYTES);
2165
20
    return key;
2166
20
}
2167
2168
/* Parse input as a public key */
2169
int ossl_ml_kem_parse_public_key(const uint8_t *in, size_t len, ML_KEM_KEY *key)
2170
590
{
2171
590
    EVP_MD_CTX *mdctx = NULL;
2172
590
    const ML_KEM_VINFO *vinfo;
2173
590
    int ret = 0;
2174
2175
    /* Keys with key material are immutable */
2176
590
    if (key == NULL
2177
590
        || ossl_ml_kem_have_pubkey(key)
2178
590
        || ossl_ml_kem_have_dkenc(key))
2179
0
        return 0;
2180
590
    vinfo = key->vinfo;
2181
2182
590
    if (len != vinfo->pubkey_bytes
2183
590
        || (mdctx = EVP_MD_CTX_new()) == NULL)
2184
0
        return 0;
2185
2186
590
    if (add_storage(OPENSSL_malloc(vinfo->puballoc), NULL, 0, 0, key))
2187
590
        ret = parse_pubkey(in, mdctx, key);
2188
2189
590
    if (!ret)
2190
241
        ossl_ml_kem_key_reset(key);
2191
590
    EVP_MD_CTX_free(mdctx);
2192
590
    return ret;
2193
590
}
2194
2195
/* Parse input as a new private key */
2196
int ossl_ml_kem_parse_private_key(const uint8_t *in, size_t len,
2197
    ML_KEM_KEY *key)
2198
111
{
2199
111
    EVP_MD_CTX *mdctx = NULL;
2200
111
    const ML_KEM_VINFO *vinfo;
2201
111
    int ret = 0;
2202
2203
    /* Keys with key material are immutable */
2204
111
    if (key == NULL
2205
111
        || ossl_ml_kem_have_pubkey(key)
2206
111
        || ossl_ml_kem_have_dkenc(key))
2207
0
        return 0;
2208
111
    vinfo = key->vinfo;
2209
2210
111
    if (len != vinfo->prvkey_bytes
2211
111
        || (mdctx = EVP_MD_CTX_new()) == NULL)
2212
0
        return 0;
2213
2214
    /* Clear any unused seed */
2215
111
    ossl_ml_kem_key_reset(key);
2216
2217
111
    if (add_storage(OPENSSL_malloc(vinfo->puballoc),
2218
111
            OPENSSL_secure_malloc(vinfo->prvalloc), 1, 0, key))
2219
111
        ret = parse_prvkey(in, mdctx, key);
2220
2221
111
    if (!ret)
2222
111
        ossl_ml_kem_key_reset(key);
2223
111
    EVP_MD_CTX_free(mdctx);
2224
111
    return ret;
2225
111
}
2226
2227
/*
2228
 * Generate a new keypair, either from the saved seed (when non-null), or from
2229
 * the RNG.
2230
 */
2231
int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key)
2232
63.5k
{
2233
63.5k
    uint8_t seed[ML_KEM_SEED_BYTES];
2234
63.5k
    EVP_MD_CTX *mdctx = NULL;
2235
63.5k
    const ML_KEM_VINFO *vinfo;
2236
63.5k
    int ret = 0;
2237
2238
63.5k
    if (key == NULL
2239
63.5k
        || ossl_ml_kem_have_pubkey(key)
2240
63.5k
        || ossl_ml_kem_have_dkenc(key))
2241
0
        return 0;
2242
63.5k
    vinfo = key->vinfo;
2243
2244
63.5k
    if (pubenc != NULL && publen != vinfo->pubkey_bytes)
2245
0
        return 0;
2246
2247
63.5k
    if (key->seedbuf != NULL) {
2248
76
        if (!ossl_ml_kem_encode_seed(seed, sizeof(seed), key))
2249
0
            return 0;
2250
76
        ossl_ml_kem_key_reset(key);
2251
63.5k
    } else if (RAND_priv_bytes_ex(key->libctx, seed, sizeof(seed),
2252
63.5k
                   key->vinfo->secbits)
2253
63.5k
        <= 0) {
2254
0
        return 0;
2255
0
    }
2256
2257
63.5k
    if ((mdctx = EVP_MD_CTX_new()) == NULL)
2258
0
        return 0;
2259
2260
    /*
2261
     * Data derived from (d, z) defaults secret, and to avoid side-channel
2262
     * leaks should not influence control flow.
2263
     */
2264
63.5k
    CONSTTIME_SECRET(seed, ML_KEM_SEED_BYTES);
2265
2266
63.5k
    if (add_storage(OPENSSL_malloc(vinfo->puballoc),
2267
63.5k
            OPENSSL_secure_malloc(vinfo->prvalloc), 1, 0, key))
2268
63.5k
        ret = genkey(seed, mdctx, pubenc, key);
2269
63.5k
    OPENSSL_cleanse(seed, sizeof(seed));
2270
2271
    /* Declassify secret inputs and derived outputs before returning control */
2272
63.5k
    CONSTTIME_DECLASSIFY(seed, ML_KEM_SEED_BYTES);
2273
2274
63.5k
    EVP_MD_CTX_free(mdctx);
2275
63.5k
    if (!ret) {
2276
        /* Erase any partial public key output */
2277
0
        if (pubenc != NULL)
2278
0
            OPENSSL_cleanse(pubenc, vinfo->pubkey_bytes);
2279
0
        ossl_ml_kem_key_reset(key);
2280
0
        return 0;
2281
0
    }
2282
2283
    /* The public components are already declassified */
2284
63.5k
    CONSTTIME_DECLASSIFY(key->s, vinfo->rank * sizeof(scalar));
2285
63.5k
    CONSTTIME_DECLASSIFY(key->z, 2 * ML_KEM_RANDOM_BYTES);
2286
63.5k
    return 1;
2287
63.5k
}
2288
2289
/*
2290
 * FIPS 203, Section 6.2, Algorithm 17: ML-KEM.Encaps_internal
2291
 * This is the deterministic version with randomness supplied externally.
2292
 */
2293
int ossl_ml_kem_encap_seed(uint8_t *ctext, size_t clen,
2294
    uint8_t *shared_secret, size_t slen,
2295
    const uint8_t *entropy, size_t elen,
2296
    const ML_KEM_KEY *key)
2297
213
{
2298
213
    const ML_KEM_VINFO *vinfo;
2299
213
    EVP_MD_CTX *mdctx;
2300
213
    int ret = 0;
2301
2302
213
    if (key == NULL || !ossl_ml_kem_have_pubkey(key))
2303
0
        return 0;
2304
213
    vinfo = key->vinfo;
2305
2306
213
    if (ctext == NULL || clen != vinfo->ctext_bytes
2307
213
        || shared_secret == NULL || slen != ML_KEM_SHARED_SECRET_BYTES
2308
213
        || entropy == NULL || elen != ML_KEM_RANDOM_BYTES
2309
213
        || (mdctx = EVP_MD_CTX_new()) == NULL)
2310
0
        return 0;
2311
    /*
2312
     * Data derived from the encap entropy defaults secret, and to avoid
2313
     * side-channel leaks should not influence control flow.
2314
     */
2315
213
    CONSTTIME_SECRET(entropy, elen);
2316
2317
    /*-
2318
     * This avoids the need to handle allocation failures for two (max 2KB
2319
     * each) vectors, that are never retained on return from this function.
2320
     * We stack-allocate these.
2321
     */
2322
213
#define case_encap_seed(bits)                                        \
2323
213
    case EVP_PKEY_ML_KEM_##bits: {                                   \
2324
213
        scalar tmp[2 * ML_KEM_##bits##_RANK];                        \
2325
213
                                                                     \
2326
213
        ret = encap(ctext, shared_secret, entropy, tmp, mdctx, key); \
2327
213
        OPENSSL_cleanse((void *)tmp, sizeof(tmp));                   \
2328
213
        break;                                                       \
2329
213
    }
2330
213
    switch (vinfo->evp_type) {
2331
62
        case_encap_seed(512);
2332
93
        case_encap_seed(768);
2333
58
        case_encap_seed(1024);
2334
213
    }
2335
213
#undef case_encap_seed
2336
2337
    /* Erase any partial ciphertext output on failure */
2338
213
    if (!ret)
2339
0
        OPENSSL_cleanse(ctext, clen);
2340
2341
    /* Declassify secret inputs and derived outputs before returning control */
2342
213
    CONSTTIME_DECLASSIFY(entropy, elen);
2343
213
    CONSTTIME_DECLASSIFY(ctext, clen);
2344
213
    CONSTTIME_DECLASSIFY(shared_secret, slen);
2345
2346
213
    EVP_MD_CTX_free(mdctx);
2347
213
    return ret;
2348
213
}
2349
2350
int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen,
2351
    uint8_t *shared_secret, size_t slen,
2352
    const ML_KEM_KEY *key)
2353
213
{
2354
213
    uint8_t r[ML_KEM_RANDOM_BYTES];
2355
213
    int ret;
2356
2357
213
    if (key == NULL)
2358
0
        return 0;
2359
2360
213
    if (RAND_bytes_ex(key->libctx, r, ML_KEM_RANDOM_BYTES,
2361
213
            key->vinfo->secbits)
2362
213
        < 1)
2363
0
        return 0;
2364
2365
213
    ret = ossl_ml_kem_encap_seed(ctext, clen, shared_secret, slen,
2366
213
        r, sizeof(r), key);
2367
2368
213
    OPENSSL_cleanse((void *)r, sizeof(r));
2369
213
    return ret;
2370
213
}
2371
2372
int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen,
2373
    const uint8_t *ctext, size_t clen,
2374
    const ML_KEM_KEY *key)
2375
189
{
2376
189
    const ML_KEM_VINFO *vinfo;
2377
189
    EVP_MD_CTX *mdctx;
2378
189
    int ret = 0;
2379
#if defined(OPENSSL_CONSTANT_TIME_VALIDATION)
2380
    int classify_bytes;
2381
#endif
2382
2383
    /* Need a private key here */
2384
189
    if (!ossl_ml_kem_have_prvkey(key)
2385
189
        || shared_secret == NULL
2386
189
        || slen < ML_KEM_SHARED_SECRET_BYTES)
2387
0
        return 0;
2388
189
    vinfo = key->vinfo;
2389
2390
189
    if (slen != ML_KEM_SHARED_SECRET_BYTES
2391
189
        || ctext == NULL || clen != vinfo->ctext_bytes
2392
189
        || (mdctx = EVP_MD_CTX_new()) == NULL) {
2393
0
        (void)RAND_bytes_ex(key->libctx, shared_secret,
2394
0
            ML_KEM_SHARED_SECRET_BYTES, vinfo->secbits);
2395
0
        return 0;
2396
0
    }
2397
#if defined(OPENSSL_CONSTANT_TIME_VALIDATION)
2398
    /*
2399
     * Data derived from |s| and |z| defaults secret, and to avoid side-channel
2400
     * leaks should not influence control flow.
2401
     */
2402
    classify_bytes = 2 * sizeof(scalar) + ML_KEM_RANDOM_BYTES;
2403
    CONSTTIME_SECRET(key->s, classify_bytes);
2404
#endif
2405
2406
    /*-
2407
     * This avoids the need to handle allocation failures for two (max 2KB
2408
     * each) vectors and an encoded ciphertext (max 1568 bytes), that are never
2409
     * retained on return from this function.
2410
     * We stack-allocate these.
2411
     */
2412
189
#define case_decap(bits)                                          \
2413
189
    case EVP_PKEY_ML_KEM_##bits: {                                \
2414
189
        uint8_t cbuf[CTEXT_BYTES(bits)];                          \
2415
189
        scalar tmp[2 * ML_KEM_##bits##_RANK];                     \
2416
189
                                                                  \
2417
189
        ret = decap(shared_secret, ctext, cbuf, tmp, mdctx, key); \
2418
189
        OPENSSL_cleanse((void *)tmp, sizeof(tmp));                \
2419
189
        OPENSSL_cleanse((void *)cbuf, sizeof(cbuf));              \
2420
189
        break;                                                    \
2421
189
    }
2422
189
    switch (vinfo->evp_type) {
2423
62
        case_decap(512);
2424
69
        case_decap(768);
2425
58
        case_decap(1024);
2426
189
    }
2427
2428
    /* Declassify secret inputs and derived outputs before returning control */
2429
189
    CONSTTIME_DECLASSIFY(key->s, classify_bytes);
2430
189
    CONSTTIME_DECLASSIFY(shared_secret, slen);
2431
189
    EVP_MD_CTX_free(mdctx);
2432
2433
189
    return ret;
2434
189
#undef case_decap
2435
189
}
2436
2437
int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2)
2438
150
{
2439
    /*
2440
     * This handles any unexpected differences in the ML-KEM variant rank,
2441
     * giving different key component structures, barring SHA3-256 hash
2442
     * collisions, the keys are the same size.
2443
     */
2444
150
    if (ossl_ml_kem_have_pubkey(key1) && ossl_ml_kem_have_pubkey(key2))
2445
150
        return memcmp(key1->pkhash, key2->pkhash, ML_KEM_PKHASH_BYTES) == 0;
2446
2447
    /*
2448
     * No match if just one of the public keys is not available, otherwise both
2449
     * are unavailable, and for now such keys are considered equal.
2450
     */
2451
0
    return (!(ossl_ml_kem_have_pubkey(key1) ^ ossl_ml_kem_have_pubkey(key2)));
2452
150
}