Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl40/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
    0x001, 0x6c1, 0xa14, 0xcd9, 0xa52, 0x276, 0x769, 0x350,
263
    0x426, 0x77f, 0x0c1, 0x31d, 0xae2, 0xcbc, 0x239, 0x6d2,
264
    0x128, 0x98f, 0x53b, 0x5c4, 0xbe6, 0x038, 0x8c0, 0x535,
265
    0x592, 0x82e, 0x217, 0xb42, 0x959, 0xb3f, 0x7b6, 0x335,
266
    0x121, 0x14b, 0xcb5, 0x6dc, 0x4ad, 0x900, 0x8e5, 0x807,
267
    0x28a, 0x7b9, 0x9d1, 0x278, 0xb31, 0x021, 0x528, 0x77b,
268
    0x90f, 0x59b, 0x327, 0x1c4, 0x59e, 0xb34, 0x5fe, 0x962,
269
    0xa57, 0xa39, 0x5c9, 0x288, 0x9aa, 0xc26, 0x4cb, 0x38e,
270
    0x011, 0xac9, 0x247, 0xa59, 0x665, 0x2d3, 0x8f0, 0x44c,
271
    0x581, 0xa66, 0xcd1, 0x0e9, 0x2f4, 0x86c, 0xbc7, 0xbea,
272
    0x6a7, 0x673, 0xae5, 0x6fd, 0x737, 0x3b8, 0x5b5, 0xa7f,
273
    0x3ab, 0x904, 0x985, 0x954, 0x2dd, 0x921, 0x10c, 0x281,
274
    0x630, 0x8fa, 0x7f5, 0xc94, 0x177, 0x9f5, 0x82a, 0x66d,
275
    0x427, 0x13f, 0xad5, 0x2f5, 0x833, 0x231, 0x9a2, 0xa22,
276
    0xaf4, 0x444, 0x193, 0x402, 0x477, 0x866, 0xad7, 0x376,
277
    0x6ba, 0x4bc, 0x752, 0x405, 0x83e, 0xb77, 0x375, 0x86a
278
};
279
280
/*
281
 * InverseNTTRoots = [pow(17, -bitreverse(i), p) for i in range(128)]
282
 * Listed in order of use in the inverse NTT loop (index 0 is skipped):
283
 *
284
 *  0, 64, 65, ..., 127, 32, 33, ..., 63, 16, 17, ..., 31, 8, 9, ...
285
 */
286
static const uint16_t kInverseNTTRoots[128] = {
287
    0x001, 0x497, 0x98c, 0x18a, 0x4c3, 0x8fc, 0x5af, 0x845,
288
    0x647, 0x98b, 0x22a, 0x49b, 0x88a, 0x8ff, 0xb6e, 0x8bd,
289
    0x20d, 0x2df, 0x35f, 0xad0, 0x4ce, 0xa0c, 0x22c, 0xbc2,
290
    0x8da, 0x694, 0x4d7, 0x30c, 0xb8a, 0x06d, 0x50c, 0x407,
291
    0x6d1, 0xa80, 0xbf5, 0x3e0, 0xa24, 0x3ad, 0x37c, 0x3fd,
292
    0x956, 0x282, 0x74c, 0x949, 0x5ca, 0x604, 0x21c, 0x68e,
293
    0x65a, 0x117, 0x13a, 0x495, 0xa0d, 0xc18, 0x030, 0x29b,
294
    0x780, 0x8b5, 0x411, 0xa2e, 0x69c, 0x2a8, 0xaba, 0x238,
295
    0xcf0, 0x973, 0x836, 0x0db, 0x357, 0xa79, 0x738, 0x2c8,
296
    0x2aa, 0x39f, 0x703, 0x1cd, 0x763, 0xb3d, 0x9da, 0x766,
297
    0x3f2, 0x586, 0x7d9, 0xce0, 0x1d0, 0xa89, 0x330, 0x548,
298
    0xa77, 0x4fa, 0x41c, 0x401, 0x854, 0x625, 0x04c, 0xbb6,
299
    0xbe0, 0x9cc, 0x54b, 0x1c2, 0x3a8, 0x1bf, 0xaea, 0x4d3,
300
    0x76f, 0x7cc, 0x441, 0xcc9, 0x11b, 0x73d, 0x7c6, 0x372,
301
    0xbd9, 0x62f, 0xac8, 0x045, 0x21f, 0x9e4, 0xc40, 0x582,
302
    0x8db, 0x9b1, 0x598, 0xa8b, 0x2af, 0x028, 0x2ed, 0x640
303
};
304
305
/*
306
 * Second precomputed array from Appendix A of FIPS 203 (normalised positive),
307
 * or else Python:
308
 * ModRoots = [pow(17, 2*bitreverse(i) + 1, p) for i in range(128)]
309
 */
310
static const uint16_t kModRoots[128] = {
311
    0x011, 0xcf0, 0xac9, 0x238, 0x247, 0xaba, 0xa59, 0x2a8,
312
    0x665, 0x69c, 0x2d3, 0xa2e, 0x8f0, 0x411, 0x44c, 0x8b5,
313
    0x581, 0x780, 0xa66, 0x29b, 0xcd1, 0x030, 0x0e9, 0xc18,
314
    0x2f4, 0xa0d, 0x86c, 0x495, 0xbc7, 0x13a, 0xbea, 0x117,
315
    0x6a7, 0x65a, 0x673, 0x68e, 0xae5, 0x21c, 0x6fd, 0x604,
316
    0x737, 0x5ca, 0x3b8, 0x949, 0x5b5, 0x74c, 0xa7f, 0x282,
317
    0x3ab, 0x956, 0x904, 0x3fd, 0x985, 0x37c, 0x954, 0x3ad,
318
    0x2dd, 0xa24, 0x921, 0x3e0, 0x10c, 0xbf5, 0x281, 0xa80,
319
    0x630, 0x6d1, 0x8fa, 0x407, 0x7f5, 0x50c, 0xc94, 0x06d,
320
    0x177, 0xb8a, 0x9f5, 0x30c, 0x82a, 0x4d7, 0x66d, 0x694,
321
    0x427, 0x8da, 0x13f, 0xbc2, 0xad5, 0x22c, 0x2f5, 0xa0c,
322
    0x833, 0x4ce, 0x231, 0xad0, 0x9a2, 0x35f, 0xa22, 0x2df,
323
    0xaf4, 0x20d, 0x444, 0x8bd, 0x193, 0xb6e, 0x402, 0x8ff,
324
    0x477, 0x88a, 0x866, 0x49b, 0xad7, 0x22a, 0x376, 0x98b,
325
    0x6ba, 0x647, 0x4bc, 0x845, 0x752, 0x5af, 0x405, 0x8fc,
326
    0x83e, 0x4c3, 0xb77, 0x18a, 0x375, 0x98c, 0x86a, 0x497
327
};
328
329
/*
330
 * single_keccak hashes |inlen| bytes from |in| and writes |outlen| bytes of
331
 * output to |out|. If the |md| specifies a fixed-output function, like
332
 * SHA3-256, then |outlen| must be the correct length for that function.
333
 */
334
static __owur int single_keccak(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen,
335
    EVP_MD_CTX *mdctx)
336
448k
{
337
448k
    unsigned int sz = (unsigned int)outlen;
338
339
448k
    if (!EVP_DigestUpdate(mdctx, in, inlen))
340
0
        return 0;
341
448k
    if (EVP_MD_xof(EVP_MD_CTX_get0_md(mdctx)))
342
384k
        return EVP_DigestFinalXOF(mdctx, out, outlen);
343
64.2k
    return EVP_DigestFinal_ex(mdctx, out, &sz)
344
64.2k
        && ossl_assert((size_t)sz == outlen);
345
448k
}
346
347
/*
348
 * FIPS 203, Section 4.1, equation (4.3): PRF. Takes 32+1 input bytes, and uses
349
 * SHAKE256 to produce the input to SamplePolyCBD_eta: FIPS 203, algorithm 8.
350
 */
351
static __owur int prf(uint8_t *out, size_t len, const uint8_t in[ML_KEM_RANDOM_BYTES + 1],
352
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
353
384k
{
354
384k
    return EVP_DigestInit_ex(mdctx, key->shake256_md, NULL)
355
384k
        && single_keccak(out, len, in, ML_KEM_RANDOM_BYTES + 1, mdctx);
356
384k
}
357
358
/*
359
 * FIPS 203, Section 4.1, equation (4.4): H.  SHA3-256 hash of a variable
360
 * length input, producing 32 bytes of output.
361
 */
362
static __owur int hash_h(uint8_t out[ML_KEM_PKHASH_BYTES], const uint8_t *in, size_t len,
363
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
364
360
{
365
360
    return EVP_DigestInit_ex(mdctx, key->sha3_256_md, NULL)
366
360
        && single_keccak(out, ML_KEM_PKHASH_BYTES, in, len, mdctx);
367
360
}
368
369
/* Incremental hash_h of expanded public key */
370
static int
371
hash_h_pubkey(uint8_t pkhash[ML_KEM_PKHASH_BYTES],
372
    EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
373
63.5k
{
374
63.5k
    const ML_KEM_VINFO *vinfo = key->vinfo;
375
63.5k
    const scalar *t = key->t, *end = t + vinfo->rank;
376
63.5k
    unsigned int sz;
377
378
63.5k
    if (!EVP_DigestInit_ex(mdctx, key->sha3_256_md, NULL))
379
0
        return 0;
380
381
190k
    do {
382
190k
        uint8_t buf[3 * DEGREE / 2];
383
384
190k
        scalar_encode(buf, t++, 12);
385
190k
        if (!EVP_DigestUpdate(mdctx, buf, sizeof(buf)))
386
0
            return 0;
387
190k
    } while (t < end);
388
389
63.5k
    if (!EVP_DigestUpdate(mdctx, key->rho, ML_KEM_RANDOM_BYTES))
390
0
        return 0;
391
63.5k
    return EVP_DigestFinal_ex(mdctx, pkhash, &sz)
392
63.5k
        && ossl_assert(sz == ML_KEM_PKHASH_BYTES);
393
63.5k
}
394
395
/*
396
 * FIPS 203, Section 4.1, equation (4.5): G.  SHA3-512 hash of a variable
397
 * length input, producing 64 bytes of output, in particular the seeds
398
 * (d,z) for key generation.
399
 */
400
static __owur int hash_g(uint8_t out[ML_KEM_SEED_BYTES], const uint8_t *in, size_t len,
401
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
402
63.9k
{
403
63.9k
    return EVP_DigestInit_ex(mdctx, key->sha3_512_md, NULL)
404
63.9k
        && single_keccak(out, ML_KEM_SEED_BYTES, in, len, mdctx);
405
63.9k
}
406
407
/*
408
 * FIPS 203, Section 4.1, equation (4.4): J. SHAKE256 taking a variable length
409
 * input to compute a 32-byte implicit rejection shared secret, of the same
410
 * length as the expected shared secret.  (Computed even on success to avoid
411
 * side-channel leaks).
412
 */
413
static __owur int kdf(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
414
    const uint8_t z[ML_KEM_RANDOM_BYTES],
415
    const uint8_t *ctext, size_t len,
416
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
417
189
{
418
189
    return EVP_DigestInit_ex(mdctx, key->shake256_md, NULL)
419
189
        && EVP_DigestUpdate(mdctx, z, ML_KEM_RANDOM_BYTES)
420
189
        && EVP_DigestUpdate(mdctx, ctext, len)
421
189
        && EVP_DigestFinalXOF(mdctx, out, ML_KEM_SHARED_SECRET_BYTES);
422
189
}
423
424
/*
425
 * FIPS 203, Section 4.2.2, Algorithm 7: "SampleNTT" (steps 3-17, steps 1, 2
426
 * are performed by the caller). Rejection-samples a Keccak stream to get
427
 * uniformly distributed elements in the range [0,q). This is used for matrix
428
 * expansion and only operates on public inputs.
429
 */
430
static __owur int sample_scalar(scalar *out, EVP_MD_CTX *mdctx)
431
574k
{
432
574k
    uint16_t *curr = out->c, *endout = curr + DEGREE;
433
574k
    uint8_t buf[SCALAR_SAMPLING_BUFSIZE], *in;
434
574k
    uint8_t *endin = buf + sizeof(buf);
435
574k
    uint16_t d;
436
574k
    uint8_t b1, b2, b3;
437
438
1.72M
    do {
439
1.72M
        if (!EVP_DigestSqueeze(mdctx, in = buf, sizeof(buf)))
440
0
            return 0;
441
90.0M
        do {
442
90.0M
            b1 = *in++;
443
90.0M
            b2 = *in++;
444
90.0M
            b3 = *in++;
445
446
90.0M
            if (curr >= endout)
447
192k
                break;
448
89.8M
            if ((d = ((b2 & 0x0f) << 8) + b1) < kPrime)
449
74.1M
                *curr++ = d;
450
89.8M
            if (curr >= endout)
451
381k
                break;
452
89.4M
            if ((d = (b3 << 4) + (b2 >> 4)) < kPrime)
453
72.8M
                *curr++ = d;
454
89.4M
        } while (in < endin);
455
1.72M
    } while (curr < endout);
456
574k
    return 1;
457
574k
}
458
459
/*-
460
 * reduce_once reduces 0 <= x < 2*kPrime, mod kPrime.
461
 *
462
 * Subtract |q| if the input is larger, without exposing a side-channel,
463
 * avoiding the "clangover" attack.  See |constish_time_non_zero| for a
464
 * discussion on why the value barrier is by default omitted.
465
 */
466
static __owur uint16_t reduce_once(uint16_t x)
467
1.25G
{
468
1.25G
    const uint16_t subtracted = x - kPrime;
469
1.25G
    uint16_t mask = constish_time_non_zero(subtracted >> 15);
470
471
1.25G
    return (mask & x) | (~mask & subtracted);
472
1.25G
}
473
474
/*
475
 * Constant-time reduce x mod kPrime using Barrett reduction. x must be less
476
 * than kPrime + 2 * kPrime^2.  This is sufficient to reduce a product of
477
 * two already reduced u_int16 values, in fact it is sufficient for each
478
 * to be less than 2^12, because (kPrime * (2 * kPrime + 1)) > 2^24.
479
 */
480
static __owur uint16_t reduce(uint32_t x)
481
566M
{
482
566M
    uint64_t product = (uint64_t)x * kBarrettMultiplier;
483
566M
    uint32_t quotient = (uint32_t)(product >> kBarrettShift);
484
566M
    uint32_t remainder = x - quotient * kPrime;
485
486
566M
    return reduce_once(remainder);
487
566M
}
488
489
/* Multiply a scalar by a constant. */
490
static void scalar_mult_const(scalar *s, uint16_t a)
491
1.78k
{
492
1.78k
    uint16_t *curr = s->c, *end = curr + DEGREE, tmp;
493
494
457k
    do {
495
457k
        tmp = reduce(*curr * a);
496
457k
        *curr++ = tmp;
497
457k
    } while (curr < end);
498
1.78k
}
499
500
/*-
501
 * FIPS 203, Section 4.3, Algorithm 9: "NTT".
502
 * In-place number theoretic transform of a given scalar.  Note that ML-KEM's
503
 * kPrime 3329 does not have a 512th root of unity, so this transform leaves
504
 * off the last iteration of the usual FFT code, with the 128 relevant roots of
505
 * unity being stored in NTTRoots.  This means the output should be seen as 128
506
 * elements in GF(3329^2), with the coefficients of the elements being
507
 * consecutive entries in |s->c|.
508
 */
509
static void scalar_ntt(scalar *s)
510
383k
{
511
383k
    const uint16_t *roots = kNTTRoots;
512
383k
    uint16_t *end = s->c + DEGREE;
513
383k
    int offset = DEGREE / 2;
514
515
2.68M
    do {
516
2.68M
        uint16_t *curr = s->c, *peer;
517
518
48.6M
        do {
519
48.6M
            uint16_t *pause = curr + offset, even, odd;
520
48.6M
            uint32_t zeta = *++roots;
521
522
48.6M
            peer = pause;
523
343M
            do {
524
343M
                even = *curr;
525
343M
                odd = reduce(*peer * zeta);
526
343M
                *peer++ = reduce_once(even - odd + kPrime);
527
343M
                *curr++ = reduce_once(odd + even);
528
343M
            } while (curr < pause);
529
48.6M
        } while ((curr = peer) < end);
530
2.68M
    } while ((offset >>= 1) >= 2);
531
383k
}
532
533
/*-
534
 * FIPS 203, Section 4.3, Algorithm 10: "NTT^(-1)".
535
 * In-place inverse number theoretic transform of a given scalar, with pairs of
536
 * entries of s->v being interpreted as elements of GF(3329^2). Just as with
537
 * the number theoretic transform, this leaves off the first step of the normal
538
 * iFFT to account for the fact that 3329 does not have a 512th root of unity,
539
 * using the precomputed 128 roots of unity stored in InverseNTTRoots.
540
 */
541
static void scalar_inverse_ntt(scalar *s)
542
1.78k
{
543
1.78k
    const uint16_t *roots = kInverseNTTRoots;
544
1.78k
    uint16_t *end = s->c + DEGREE;
545
1.78k
    int offset = 2;
546
547
12.5k
    do {
548
12.5k
        uint16_t *curr = s->c, *peer;
549
550
227k
        do {
551
227k
            uint16_t *pause = curr + offset, even, odd;
552
227k
            uint32_t zeta = *++roots;
553
554
227k
            peer = pause;
555
1.60M
            do {
556
1.60M
                even = *curr;
557
1.60M
                odd = *peer;
558
1.60M
                *peer++ = reduce(zeta * (even - odd + kPrime));
559
1.60M
                *curr++ = reduce_once(odd + even);
560
1.60M
            } while (curr < pause);
561
227k
        } while ((curr = peer) < end);
562
12.5k
    } while ((offset <<= 1) < DEGREE);
563
1.78k
    scalar_mult_const(s, kInverseDegree);
564
1.78k
}
565
566
/* Addition updating the LHS scalar in-place. */
567
static void scalar_add(scalar *lhs, const scalar *rhs)
568
1.60k
{
569
1.60k
    int i;
570
571
411k
    for (i = 0; i < DEGREE; i++)
572
409k
        lhs->c[i] = reduce_once(lhs->c[i] + rhs->c[i]);
573
1.60k
}
574
575
/* Subtraction updating the LHS scalar in-place. */
576
static void scalar_sub(scalar *lhs, const scalar *rhs)
577
189
{
578
189
    int i;
579
580
48.5k
    for (i = 0; i < DEGREE; i++)
581
48.3k
        lhs->c[i] = reduce_once(lhs->c[i] - rhs->c[i] + kPrime);
582
189
}
583
584
/*
585
 * Multiplying two scalars in the number theoretically transformed state. Since
586
 * 3329 does not have a 512th root of unity, this means we have to interpret
587
 * the 2*ith and (2*i+1)th entries of the scalar as elements of
588
 * GF(3329)[X]/(X^2 - 17^(2*bitreverse(i)+1)).
589
 *
590
 * The value of 17^(2*bitreverse(i)+1) mod 3329 is stored in the precomputed
591
 * ModRoots table. Note that our Barrett transform only allows us to multiply
592
 * two reduced numbers together, so we need some intermediate reduction steps,
593
 * even if an uint64_t could hold 3 multiplied numbers.
594
 */
595
static void scalar_mult(scalar *out, const scalar *lhs,
596
    const scalar *rhs)
597
1.78k
{
598
1.78k
    uint16_t *curr = out->c, *end = curr + DEGREE;
599
1.78k
    const uint16_t *lc = lhs->c, *rc = rhs->c;
600
1.78k
    const uint16_t *roots = kModRoots;
601
602
228k
    do {
603
228k
        uint32_t l0 = *lc++, r0 = *rc++;
604
228k
        uint32_t l1 = *lc++, r1 = *rc++;
605
228k
        uint32_t zetapow = *roots++;
606
607
228k
        *curr++ = reduce(l0 * r0 + reduce(l1 * r1) * zetapow);
608
228k
        *curr++ = reduce(l0 * r1 + l1 * r0);
609
228k
    } while (curr < end);
610
1.78k
}
611
612
/* Above, but add the result to an existing scalar */
613
static ossl_inline void scalar_mult_add(scalar *out, const scalar *lhs,
614
    const scalar *rhs)
615
575k
{
616
575k
    uint16_t *curr = out->c, *end = curr + DEGREE;
617
575k
    const uint16_t *lc = lhs->c, *rc = rhs->c;
618
575k
    const uint16_t *roots = kModRoots;
619
620
73.6M
    do {
621
73.6M
        uint32_t l0 = *lc++, r0 = *rc++;
622
73.6M
        uint32_t l1 = *lc++, r1 = *rc++;
623
73.6M
        uint16_t *c0 = curr++;
624
73.6M
        uint16_t *c1 = curr++;
625
73.6M
        uint32_t zetapow = *roots++;
626
627
73.6M
        *c0 = reduce(*c0 + l0 * r0 + reduce(l1 * r1) * zetapow);
628
73.6M
        *c1 = reduce(*c1 + l0 * r1 + l1 * r0);
629
73.6M
    } while (curr < end);
630
575k
}
631
632
/*-
633
 * FIPS 203, Section 4.2.1, Algorithm 5: "ByteEncode_d", for 2<=d<=12.
634
 * Here |bits| is |d|.  For efficiency, we handle the d=1 case separately.
635
 */
636
static void scalar_encode(uint8_t *out, const scalar *s, int bits)
637
384k
{
638
384k
    const uint16_t *curr = s->c, *end = curr + DEGREE;
639
384k
    uint64_t accum = 0, element;
640
384k
    int used = 0;
641
642
98.4M
    do {
643
98.4M
        element = *curr++;
644
98.4M
        if (used + bits < 64) {
645
80.0M
            accum |= element << used;
646
80.0M
            used += bits;
647
80.0M
        } else if (used + bits > 64) {
648
12.3M
            out = OPENSSL_store_u64_le(out, accum | (element << used));
649
12.3M
            accum = element >> (64 - used);
650
12.3M
            used = (used + bits) - 64;
651
12.3M
        } else {
652
6.14M
            out = OPENSSL_store_u64_le(out, accum | (element << used));
653
6.14M
            accum = 0;
654
6.14M
            used = 0;
655
6.14M
        }
656
98.4M
    } while (curr < end);
657
384k
}
658
659
/*
660
 * scalar_encode_1 is |scalar_encode| specialised for |bits| == 1.
661
 */
662
static void scalar_encode_1(uint8_t out[DEGREE / 8], const scalar *s)
663
189
{
664
189
    int i, j;
665
189
    uint8_t out_byte;
666
667
6.23k
    for (i = 0; i < DEGREE; i += 8) {
668
6.04k
        out_byte = 0;
669
54.4k
        for (j = 0; j < 8; j++)
670
48.3k
            out_byte |= bit0(s->c[i + j]) << j;
671
6.04k
        *out = out_byte;
672
6.04k
        out++;
673
6.04k
    }
674
189
}
675
676
/*-
677
 * FIPS 203, Section 4.2.1, Algorithm 6: "ByteDecode_d", for 2<=d<12.
678
 * Here |bits| is |d|.  For efficiency, we handle the d=1 and d=12 cases
679
 * separately.
680
 *
681
 * scalar_decode parses |DEGREE * bits| bits from |in| into |DEGREE| values in
682
 * |out|.
683
 */
684
static void scalar_decode(scalar *out, const uint8_t *in, int bits)
685
752
{
686
752
    uint16_t *curr = out->c, *end = curr + DEGREE;
687
752
    uint64_t accum = 0;
688
752
    int accum_bits = 0, todo = bits;
689
752
    uint16_t bitmask = (((uint16_t)1) << bits) - 1, mask = bitmask;
690
752
    uint16_t element = 0;
691
692
213k
    do {
693
213k
        if (accum_bits == 0) {
694
26.7k
            in = OPENSSL_load_u64_le(&accum, in);
695
26.7k
            accum_bits = 64;
696
26.7k
        }
697
213k
        if (todo == bits && accum_bits >= bits) {
698
            /* No partial "element", and all the required bits available */
699
171k
            *curr++ = ((uint16_t)accum) & mask;
700
171k
            accum >>= bits;
701
171k
            accum_bits -= bits;
702
171k
        } else if (accum_bits >= todo) {
703
            /* A partial "element", and all the required bits available */
704
20.8k
            *curr++ = element | ((((uint16_t)accum) & mask) << (bits - todo));
705
20.8k
            accum >>= todo;
706
20.8k
            accum_bits -= todo;
707
20.8k
            element = 0;
708
20.8k
            todo = bits;
709
20.8k
            mask = bitmask;
710
20.8k
        } else {
711
            /*
712
             * Only some of the requisite bits accumulated, store |accum_bits|
713
             * of these in |element|.  The accumulated bitcount becomes 0, but
714
             * as soon as we have more bits we'll want to merge accum_bits
715
             * fewer of them into the final |element|.
716
             *
717
             * Note that with a 64-bit accumulator and |bits| always 12 or
718
             * less, if we're here, the previous iteration had all the
719
             * requisite bits, and so there are no kept bits in |element|.
720
             */
721
20.8k
            element = ((uint16_t)accum) & mask;
722
20.8k
            todo -= accum_bits;
723
20.8k
            mask = bitmask >> accum_bits;
724
20.8k
            accum_bits = 0;
725
20.8k
        }
726
213k
    } while (curr < end);
727
752
}
728
729
static __owur int scalar_decode_12(scalar *out, const uint8_t in[3 * DEGREE / 2])
730
1.39k
{
731
1.39k
    int i;
732
1.39k
    uint16_t *c = out->c;
733
734
143k
    for (i = 0; i < DEGREE / 2; ++i) {
735
142k
        uint8_t b1 = *in++;
736
142k
        uint8_t b2 = *in++;
737
142k
        uint8_t b3 = *in++;
738
142k
        int outOfRange1 = (*c++ = b1 | ((b2 & 0x0f) << 8)) >= kPrime;
739
142k
        int outOfRange2 = (*c++ = (b2 >> 4) | (b3 << 4)) >= kPrime;
740
741
142k
        if (outOfRange1 | outOfRange2)
742
341
            return 0;
743
142k
    }
744
1.05k
    return 1;
745
1.39k
}
746
747
/*-
748
 * scalar_decode_decompress_add is a combination of decoding and decompression
749
 * both specialised for |bits| == 1, with the result added (and sum reduced) to
750
 * the output scalar.
751
 *
752
 * NOTE: this function MUST not leak an input-data-depedennt timing signal.
753
 * A timing leak in a related function in the reference Kyber implementation
754
 * made the "clangover" attack (CVE-2024-37880) possible, giving key recovery
755
 * for ML-KEM-512 in minutes, provided the attacker has access to precise
756
 * timing of a CPU performing chosen-ciphertext decap.  Admittedly this is only
757
 * a risk when private keys are reused (perhaps KEMTLS servers).
758
 */
759
static void
760
scalar_decode_decompress_add(scalar *out, const uint8_t in[DEGREE / 8])
761
402
{
762
402
    static const uint16_t half_q_plus_1 = (ML_KEM_PRIME >> 1) + 1;
763
402
    uint16_t *curr = out->c, *end = curr + DEGREE;
764
402
    uint16_t mask;
765
402
    uint8_t b;
766
767
    /*
768
     * Add |half_q_plus_1| if the bit is set, without exposing a side-channel,
769
     * avoiding the "clangover" attack.  See |constish_time_non_zero| for a
770
     * discussion on why the value barrier is by default omitted.
771
     */
772
402
#define decode_decompress_add_bit                        \
773
102k
    mask = constish_time_non_zero(bit0(b));              \
774
102k
    *curr = reduce_once(*curr + (mask & half_q_plus_1)); \
775
102k
    curr++;                                              \
776
102k
    b >>= 1
777
778
    /* Unrolled to process each byte in one iteration */
779
12.8k
    do {
780
12.8k
        b = *in++;
781
12.8k
        decode_decompress_add_bit;
782
12.8k
        decode_decompress_add_bit;
783
12.8k
        decode_decompress_add_bit;
784
12.8k
        decode_decompress_add_bit;
785
786
12.8k
        decode_decompress_add_bit;
787
12.8k
        decode_decompress_add_bit;
788
12.8k
        decode_decompress_add_bit;
789
12.8k
        decode_decompress_add_bit;
790
12.8k
    } while (curr < end);
791
402
#undef decode_decompress_add_bit
792
402
}
793
794
/*
795
 * FIPS 203, Section 4.2.1, Equation (4.7): Compress_d.
796
 *
797
 * Compresses (lossily) an input |x| mod 3329 into |bits| many bits by grouping
798
 * numbers close to each other together. The formula used is
799
 * round(2^|bits|/kPrime*x) mod 2^|bits|.
800
 * Uses Barrett reduction to achieve constant time. Since we need both the
801
 * remainder (for rounding) and the quotient (as the result), we cannot use
802
 * |reduce| here, but need to do the Barrett reduction directly.
803
 */
804
static __owur uint16_t compress(uint16_t x, int bits)
805
457k
{
806
457k
    uint32_t shifted = (uint32_t)x << bits;
807
457k
    uint64_t product = (uint64_t)shifted * kBarrettMultiplier;
808
457k
    uint32_t quotient = (uint32_t)(product >> kBarrettShift);
809
457k
    uint32_t remainder = shifted - quotient * kPrime;
810
811
    /*
812
     * Adjust the quotient to round correctly:
813
     *   0 <= remainder <= kHalfPrime round to 0
814
     *   kHalfPrime < remainder <= kPrime + kHalfPrime round to 1
815
     *   kPrime + kHalfPrime < remainder < 2 * kPrime round to 2
816
     */
817
457k
    quotient += 1 & constant_time_lt_32(kHalfPrime, remainder);
818
457k
    quotient += 1 & constant_time_lt_32(kPrime + kHalfPrime, remainder);
819
457k
    return quotient & ((1 << bits) - 1);
820
457k
}
821
822
/*
823
 * FIPS 203, Section 4.2.1, Equation (4.8): Decompress_d.
824
825
 * Decompresses |x| by using a close equi-distant representative. The formula
826
 * is round(kPrime/2^|bits|*x). Note that 2^|bits| being the divisor allows us
827
 * to implement this logic using only bit operations.
828
 */
829
static __owur uint16_t decompress(uint16_t x, int bits)
830
192k
{
831
192k
    uint32_t product = (uint32_t)x * kPrime;
832
192k
    uint32_t power = 1 << bits;
833
    /* This is |product| % power, since |power| is a power of 2. */
834
192k
    uint32_t remainder = product & (power - 1);
835
    /* This is |product| / power, since |power| is a power of 2. */
836
192k
    uint32_t lower = product >> bits;
837
838
    /*
839
     * The rounding logic works since the first half of numbers mod |power|
840
     * have a 0 as first bit, and the second half has a 1 as first bit, since
841
     * |power| is a power of 2. As a 12 bit number, |remainder| is always
842
     * positive, so we will shift in 0s for a right shift.
843
     */
844
192k
    return lower + (remainder >> (bits - 1));
845
192k
}
846
847
/*-
848
 * FIPS 203, Section 4.2.1, Equation (4.7): "Compress_d".
849
 * In-place lossy rounding of scalars to 2^d bits.
850
 */
851
static void scalar_compress(scalar *s, int bits)
852
1.78k
{
853
1.78k
    int i;
854
855
459k
    for (i = 0; i < DEGREE; i++)
856
457k
        s->c[i] = compress(s->c[i], bits);
857
1.78k
}
858
859
/*
860
 * FIPS 203, Section 4.2.1, Equation (4.8): "Decompress_d".
861
 * In-place approximate recovery of scalars from 2^d bit compression.
862
 */
863
static void scalar_decompress(scalar *s, int bits)
864
752
{
865
752
    int i;
866
867
193k
    for (i = 0; i < DEGREE; i++)
868
192k
        s->c[i] = decompress(s->c[i], bits);
869
752
}
870
871
/* Addition updating the LHS vector in-place. */
872
static void vector_add(scalar *lhs, const scalar *rhs, int rank)
873
402
{
874
1.19k
    do {
875
1.19k
        scalar_add(lhs++, rhs++);
876
1.19k
    } while (--rank > 0);
877
402
}
878
879
/*
880
 * Encodes an entire vector into 32*|rank|*|bits| bytes. Note that since 256
881
 * (DEGREE) is divisible by 8, the individual vector entries will always fill a
882
 * whole number of bytes, so we do not need to worry about bit packing here.
883
 */
884
static void vector_encode(uint8_t *out, const scalar *a, int bits, int rank)
885
64.5k
{
886
64.5k
    int stride = bits * DEGREE / 8;
887
888
258k
    for (; rank-- > 0; out += stride)
889
193k
        scalar_encode(out, a++, bits);
890
64.5k
}
891
892
/*
893
 * Decodes 32*|rank|*|bits| bytes from |in| into |out|. It returns early
894
 * if any parsed value is >= |ML_KEM_PRIME|.  The resulting scalars are
895
 * then decompressed and transformed via the NTT.
896
 *
897
 * Note: Used only in decrypt_cpa(), which returns void and so does not check
898
 * the return value of this function.  Side-channels are fine when the input
899
 * ciphertext to decap() is simply syntactically invalid.
900
 */
901
static void
902
vector_decode_decompress_ntt(scalar *out, const uint8_t *in, int bits, int rank)
903
189
{
904
189
    int stride = bits * DEGREE / 8;
905
906
752
    for (; rank-- > 0; in += stride, ++out) {
907
563
        scalar_decode(out, in, bits);
908
563
        scalar_decompress(out, bits);
909
563
        scalar_ntt(out);
910
563
    }
911
189
}
912
913
/* vector_decode(), specialised to bits == 12. */
914
static __owur int vector_decode_12(scalar *out, const uint8_t in[3 * DEGREE / 2], int rank)
915
723
{
916
723
    int stride = 3 * DEGREE / 2;
917
918
1.78k
    for (; rank-- > 0; in += stride)
919
1.39k
        if (!scalar_decode_12(out++, in))
920
341
            return 0;
921
382
    return 1;
922
723
}
923
924
/* In-place compression of each scalar component */
925
static void vector_compress(scalar *a, int bits, int rank)
926
402
{
927
1.19k
    do {
928
1.19k
        scalar_compress(a++, bits);
929
1.19k
    } while (--rank > 0);
930
402
}
931
932
/* The output scalar must not overlap with the inputs */
933
static void inner_product(scalar *out, const scalar *lhs, const scalar *rhs,
934
    int rank)
935
591
{
936
591
    scalar_mult(out, lhs, rhs);
937
1.76k
    while (--rank > 0)
938
1.17k
        scalar_mult_add(out, ++lhs, ++rhs);
939
591
}
940
941
/*
942
 * Here, the output vector must not overlap with the inputs, the result is
943
 * directly subjected to inverse NTT.
944
 */
945
static void
946
matrix_mult_intt(scalar *out, const scalar *m, const scalar *a, int rank)
947
402
{
948
402
    const scalar *ar;
949
402
    int i, j;
950
951
1.60k
    for (i = rank; i-- > 0; ++out) {
952
1.19k
        scalar_mult(out, m++, ar = a);
953
3.81k
        for (j = rank - 1; j > 0; --j)
954
2.61k
            scalar_mult_add(out, m++, ++ar);
955
1.19k
        scalar_inverse_ntt(out);
956
1.19k
    }
957
402
}
958
959
/* Here, the output vector must not overlap with the inputs */
960
static void
961
matrix_mult_transpose_add(scalar *out, const scalar *m, const scalar *a, int rank)
962
63.5k
{
963
63.5k
    const scalar *mc = m, *mr, *ar;
964
63.5k
    int i, j;
965
966
254k
    for (i = rank; i-- > 0; ++out) {
967
190k
        scalar_mult_add(out, mr = mc++, ar = a);
968
571k
        for (j = rank; --j > 0;)
969
381k
            scalar_mult_add(out, (mr += rank), ++ar);
970
190k
    }
971
63.5k
}
972
973
/*-
974
 * Expands the matrix from a seed for key generation and for encaps-CPA.
975
 * NOTE: FIPS 203 matrix "A" is the transpose of this matrix, computed
976
 * by appending the (i,j) indices to the seed in the opposite order!
977
 *
978
 * Where FIPS 203 computes t = A * s + e, we use the transpose of "m".
979
 */
980
static __owur int matrix_expand(EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
981
63.9k
{
982
63.9k
    scalar *out = key->m;
983
63.9k
    uint8_t input[ML_KEM_RANDOM_BYTES + 2];
984
63.9k
    int rank = key->vinfo->rank;
985
63.9k
    int i, j;
986
987
    /*
988
     * The seeds derived below and the sampling buffers in sample_scalar()
989
     * are not cleansed: per FIPS 203 section 3.3 the matrix A is easily
990
     * computed from the public encapsulation key and does not require any
991
     * special protections.
992
     */
993
63.9k
    memcpy(input, key->rho, ML_KEM_RANDOM_BYTES);
994
255k
    for (i = 0; i < rank; i++) {
995
765k
        for (j = 0; j < rank; j++) {
996
574k
            input[ML_KEM_RANDOM_BYTES] = i;
997
574k
            input[ML_KEM_RANDOM_BYTES + 1] = j;
998
574k
            if (!EVP_DigestInit_ex(mdctx, key->shake128_md, NULL)
999
574k
                || !EVP_DigestUpdate(mdctx, input, sizeof(input))
1000
574k
                || !sample_scalar(out++, mdctx))
1001
0
                return 0;
1002
574k
        }
1003
191k
    }
1004
63.9k
    return 1;
1005
63.9k
}
1006
1007
/*
1008
 * Algorithm 7 from the spec, with eta fixed to two and the PRF call
1009
 * included. Creates binominally distributed elements by sampling 2*|eta| bits,
1010
 * and setting the coefficient to the count of the first bits minus the count of
1011
 * the second bits, resulting in a centered binomial distribution. Since eta is
1012
 * two this gives -2/2 with a probability of 1/16, -1/1 with probability 1/4,
1013
 * and 0 with probability 3/8.
1014
 */
1015
static __owur int cbd_2(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1],
1016
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1017
382k
{
1018
382k
    uint16_t *curr = out->c, *end = curr + DEGREE;
1019
382k
    uint8_t randbuf[4 * DEGREE / 8], *r = randbuf; /* 64 * eta slots */
1020
382k
    uint16_t value, mask;
1021
382k
    uint8_t b;
1022
1023
382k
    if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) {
1024
0
        OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1025
0
        return 0;
1026
0
    }
1027
1028
48.9M
    do {
1029
48.9M
        b = *r++;
1030
1031
        /*
1032
         * Add |kPrime| if |value| underflowed.  See |constish_time_non_zero|
1033
         * for a discussion on why the value barrier is by default omitted.
1034
         * While this could have been written reduce_once(value + kPrime), this
1035
         * is one extra addition and small range of |value| tempts some
1036
         * versions of Clang to emit a branch.
1037
         */
1038
48.9M
        value = bit0(b) + bitn(1, b);
1039
48.9M
        value -= bitn(2, b) + bitn(3, b);
1040
48.9M
        mask = constish_time_non_zero(value >> 15);
1041
48.9M
        *curr++ = value + (kPrime & mask);
1042
1043
48.9M
        value = bitn(4, b) + bitn(5, b);
1044
48.9M
        value -= bitn(6, b) + bitn(7, b);
1045
48.9M
        mask = constish_time_non_zero(value >> 15);
1046
48.9M
        *curr++ = value + (kPrime & mask);
1047
48.9M
    } while (curr < end);
1048
1049
382k
    OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1050
382k
    return 1;
1051
382k
}
1052
1053
/*
1054
 * Algorithm 7 from the spec, with eta fixed to three and the PRF call
1055
 * included. Creates binominally distributed elements by sampling 3*|eta| bits,
1056
 * and setting the coefficient to the count of the first bits minus the count of
1057
 * the second bits, resulting in a centered binomial distribution.
1058
 */
1059
static __owur int cbd_3(scalar *out, uint8_t in[ML_KEM_RANDOM_BYTES + 1],
1060
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1061
1.52k
{
1062
1.52k
    uint16_t *curr = out->c, *end = curr + DEGREE;
1063
1.52k
    uint8_t randbuf[6 * DEGREE / 8], *r = randbuf; /* 64 * eta slots */
1064
1.52k
    uint8_t b1, b2, b3;
1065
1.52k
    uint16_t value, mask;
1066
1067
1.52k
    if (!prf(randbuf, sizeof(randbuf), in, mdctx, key)) {
1068
0
        OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1069
0
        return 0;
1070
0
    }
1071
1072
97.7k
    do {
1073
97.7k
        b1 = *r++;
1074
97.7k
        b2 = *r++;
1075
97.7k
        b3 = *r++;
1076
1077
        /*
1078
         * Add |kPrime| if |value| underflowed.  See |constish_time_non_zero|
1079
         * for a discussion on why the value barrier is by default omitted.
1080
         * While this could have been written reduce_once(value + kPrime), this
1081
         * is one extra addition and small range of |value| tempts some
1082
         * versions of Clang to emit a branch.
1083
         */
1084
97.7k
        value = bit0(b1) + bitn(1, b1) + bitn(2, b1);
1085
97.7k
        value -= bitn(3, b1) + bitn(4, b1) + bitn(5, b1);
1086
97.7k
        mask = constish_time_non_zero(value >> 15);
1087
97.7k
        *curr++ = value + (kPrime & mask);
1088
1089
97.7k
        value = bitn(6, b1) + bitn(7, b1) + bit0(b2);
1090
97.7k
        value -= bitn(1, b2) + bitn(2, b2) + bitn(3, b2);
1091
97.7k
        mask = constish_time_non_zero(value >> 15);
1092
97.7k
        *curr++ = value + (kPrime & mask);
1093
1094
97.7k
        value = bitn(4, b2) + bitn(5, b2) + bitn(6, b2);
1095
97.7k
        value -= bitn(7, b2) + bit0(b3) + bitn(1, b3);
1096
97.7k
        mask = constish_time_non_zero(value >> 15);
1097
97.7k
        *curr++ = value + (kPrime & mask);
1098
1099
97.7k
        value = bitn(2, b3) + bitn(3, b3) + bitn(4, b3);
1100
97.7k
        value -= bitn(5, b3) + bitn(6, b3) + bitn(7, b3);
1101
97.7k
        mask = constish_time_non_zero(value >> 15);
1102
97.7k
        *curr++ = value + (kPrime & mask);
1103
97.7k
    } while (curr < end);
1104
1105
1.52k
    OPENSSL_cleanse((void *)randbuf, sizeof(randbuf));
1106
1.52k
    return 1;
1107
1.52k
}
1108
1109
/*
1110
 * Generates a secret vector by using |cbd| with the given seed to generate
1111
 * scalar elements and incrementing |counter| for each slot of the vector.
1112
 */
1113
static __owur int gencbd_vector(scalar *out, CBD_FUNC cbd, uint8_t *counter,
1114
    const uint8_t seed[ML_KEM_RANDOM_BYTES], int rank,
1115
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1116
402
{
1117
402
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1118
402
    int ret = 0;
1119
1120
402
    memcpy(input, seed, ML_KEM_RANDOM_BYTES);
1121
1.19k
    do {
1122
1.19k
        input[ML_KEM_RANDOM_BYTES] = (*counter)++;
1123
1.19k
        if (!cbd(out++, input, mdctx, key))
1124
0
            goto end;
1125
1.19k
    } while (--rank > 0);
1126
402
    ret = 1;
1127
1128
402
end:
1129
402
    OPENSSL_cleanse((void *)input, sizeof(input));
1130
402
    return ret;
1131
402
}
1132
1133
/*
1134
 * As above plus NTT transform.
1135
 */
1136
static __owur int gencbd_vector_ntt(scalar *out, CBD_FUNC cbd, uint8_t *counter,
1137
    const uint8_t seed[ML_KEM_RANDOM_BYTES], int rank,
1138
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1139
127k
{
1140
127k
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1141
127k
    int ret = 0;
1142
1143
127k
    memcpy(input, seed, ML_KEM_RANDOM_BYTES);
1144
382k
    do {
1145
382k
        input[ML_KEM_RANDOM_BYTES] = (*counter)++;
1146
382k
        if (!cbd(out, input, mdctx, key))
1147
0
            goto end;
1148
382k
        scalar_ntt(out++);
1149
382k
    } while (--rank > 0);
1150
127k
    ret = 1;
1151
1152
127k
end:
1153
127k
    OPENSSL_cleanse((void *)input, sizeof(input));
1154
127k
    return ret;
1155
127k
}
1156
1157
/* The |ETA1| value for ML-KEM-512 is 3, the rest and all ETA2 values are 2. */
1158
33.8k
#define CBD1(evp_type) ((evp_type) == EVP_PKEY_ML_KEM_512 ? cbd_3 : cbd_2)
1159
1160
/*
1161
 * FIPS 203, Section 5.2, Algorithm 14: K-PKE.Encrypt.
1162
 *
1163
 * Encrypts a message with given randomness to the ciphertext in |out|. Without
1164
 * applying the Fujisaki-Okamoto transform this would not result in a CCA
1165
 * secure scheme, since lattice schemes are vulnerable to decryption failure
1166
 * oracles.
1167
 *
1168
 * The steps are re-ordered to make more efficient/localised use of storage.
1169
 *
1170
 * Note also that the input public key is assumed to hold a precomputed matrix
1171
 * |A| (our key->m, with the public key holding an expanded (16-bit per scalar
1172
 * coefficient) key->t vector).
1173
 *
1174
 * Caller passes storage in |tmp| for for two temporary vectors.
1175
 */
1176
static __owur int encrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
1177
    const uint8_t message[DEGREE / 8],
1178
    const uint8_t r[ML_KEM_RANDOM_BYTES], scalar *tmp,
1179
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1180
402
{
1181
402
    const ML_KEM_VINFO *vinfo = key->vinfo;
1182
402
    CBD_FUNC cbd_1 = CBD1(vinfo->evp_type);
1183
402
    int rank = vinfo->rank;
1184
    /* We can use tmp[0..rank-1] as storage for |y|, then |e1|, ... */
1185
402
    scalar *y = &tmp[0], *e1 = y, *e2 = y;
1186
    /* We can use tmp[rank]..tmp[2*rank - 1] for |u| */
1187
402
    scalar *u = &tmp[rank];
1188
402
    scalar v;
1189
402
    uint8_t input[ML_KEM_RANDOM_BYTES + 1];
1190
402
    uint8_t counter = 0;
1191
402
    int du = vinfo->du;
1192
402
    int dv = vinfo->dv;
1193
402
    int ret = 0;
1194
1195
    /* FIPS 203 "y" vector */
1196
402
    if (!gencbd_vector_ntt(y, cbd_1, &counter, r, rank, mdctx, key))
1197
0
        goto end;
1198
    /* FIPS 203 "v" scalar */
1199
402
    inner_product(&v, key->t, y, rank);
1200
402
    scalar_inverse_ntt(&v);
1201
    /* FIPS 203 "u" vector */
1202
402
    matrix_mult_intt(u, key->m, y, rank);
1203
1204
    /* All done with |y|, now free to reuse tmp[0] for FIPS 203 |e1| */
1205
402
    if (!gencbd_vector(e1, cbd_2, &counter, r, rank, mdctx, key))
1206
0
        goto end;
1207
402
    vector_add(u, e1, rank);
1208
402
    vector_compress(u, du, rank);
1209
402
    vector_encode(out, u, du, rank);
1210
1211
    /* All done with |e1|, now free to reuse tmp[0] for FIPS 203 |e2| */
1212
402
    memcpy(input, r, ML_KEM_RANDOM_BYTES);
1213
402
    input[ML_KEM_RANDOM_BYTES] = counter;
1214
402
    if (!cbd_2(e2, input, mdctx, key))
1215
0
        goto end;
1216
402
    scalar_add(&v, e2);
1217
1218
    /* Combine message with |v| */
1219
402
    scalar_decode_decompress_add(&v, message);
1220
402
    scalar_compress(&v, dv);
1221
402
    scalar_encode(out + vinfo->u_vector_bytes, &v, dv);
1222
402
    ret = 1;
1223
1224
402
end:
1225
402
    OPENSSL_cleanse((void *)input, sizeof(input));
1226
402
    OPENSSL_cleanse((void *)&v, sizeof(v));
1227
402
    return ret;
1228
402
}
1229
1230
/*
1231
 * FIPS 203, Section 5.3, Algorithm 15: K-PKE.Decrypt.
1232
 */
1233
static void
1234
decrypt_cpa(uint8_t out[ML_KEM_SHARED_SECRET_BYTES],
1235
    const uint8_t *ctext, scalar *u, const ML_KEM_KEY *key)
1236
189
{
1237
189
    const ML_KEM_VINFO *vinfo = key->vinfo;
1238
189
    scalar v, mask;
1239
189
    int rank = vinfo->rank;
1240
189
    int du = vinfo->du;
1241
189
    int dv = vinfo->dv;
1242
1243
189
    vector_decode_decompress_ntt(u, ctext, du, rank);
1244
189
    scalar_decode(&v, ctext + vinfo->u_vector_bytes, dv);
1245
189
    scalar_decompress(&v, dv);
1246
189
    inner_product(&mask, key->s, u, rank);
1247
189
    scalar_inverse_ntt(&mask);
1248
189
    scalar_sub(&v, &mask);
1249
189
    scalar_compress(&v, 1);
1250
189
    scalar_encode_1(out, &v);
1251
1252
189
    OPENSSL_cleanse((void *)&v, sizeof(v));
1253
189
    OPENSSL_cleanse((void *)&mask, sizeof(mask));
1254
189
}
1255
1256
/*-
1257
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1258
 * FIPS 203, Section 7.2, Algorithm 20: "ML-KEM.Encaps".
1259
 *
1260
 * Fills the |out| buffer with the |ek| output of "ML-KEM.KeyGen", or,
1261
 * equivalently, the |ek| input of "ML-KEM.Encaps", i.e. returns the
1262
 * wire-format of an ML-KEM public key.
1263
 */
1264
static void encode_pubkey(uint8_t *out, const ML_KEM_KEY *key)
1265
64.0k
{
1266
64.0k
    const uint8_t *rho = key->rho;
1267
64.0k
    const ML_KEM_VINFO *vinfo = key->vinfo;
1268
1269
64.0k
    vector_encode(out, key->t, 12, vinfo->rank);
1270
64.0k
    memcpy(out + vinfo->vector_bytes, rho, ML_KEM_RANDOM_BYTES);
1271
64.0k
}
1272
1273
/*-
1274
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1275
 *
1276
 * Fills the |out| buffer with the |dk| output of "ML-KEM.KeyGen".
1277
 * This matches the input format of parse_prvkey() below.
1278
 */
1279
static void encode_prvkey(uint8_t *out, const ML_KEM_KEY *key)
1280
144
{
1281
144
    const ML_KEM_VINFO *vinfo = key->vinfo;
1282
1283
144
    vector_encode(out, key->s, 12, vinfo->rank);
1284
144
    out += vinfo->vector_bytes;
1285
144
    encode_pubkey(out, key);
1286
144
    out += vinfo->pubkey_bytes;
1287
144
    memcpy(out, key->pkhash, ML_KEM_PKHASH_BYTES);
1288
144
    out += ML_KEM_PKHASH_BYTES;
1289
144
    memcpy(out, key->z, ML_KEM_RANDOM_BYTES);
1290
144
}
1291
1292
/*-
1293
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1294
 * FIPS 203, Section 7.2, Algorithm 20: "ML-KEM.Encaps".
1295
 *
1296
 * This function parses the |in| buffer as the |ek| output of "ML-KEM.KeyGen",
1297
 * or, equivalently, the |ek| input of "ML-KEM.Encaps", i.e. decodes the
1298
 * wire-format of the ML-KEM public key.
1299
 */
1300
static int parse_pubkey(const uint8_t *in, EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
1301
612
{
1302
612
    const ML_KEM_VINFO *vinfo = key->vinfo;
1303
1304
    /* Decode and check |t| */
1305
612
    if (!vector_decode_12(key->t, in, vinfo->rank)) {
1306
252
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1307
252
            "%s invalid public 't' vector",
1308
252
            vinfo->algorithm_name);
1309
252
        return 0;
1310
252
    }
1311
    /* Save the matrix |m| recovery seed |rho| */
1312
360
    memcpy(key->rho, in + vinfo->vector_bytes, ML_KEM_RANDOM_BYTES);
1313
    /*
1314
     * Pre-compute the public key hash, needed for both encap and decap.
1315
     * Also pre-compute the matrix expansion, stored with the public key.
1316
     */
1317
360
    if (!hash_h(key->pkhash, in, vinfo->pubkey_bytes, mdctx, key)
1318
360
        || !matrix_expand(mdctx, key)) {
1319
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1320
0
            "internal error while parsing %s public key",
1321
0
            vinfo->algorithm_name);
1322
0
        return 0;
1323
0
    }
1324
360
    return 1;
1325
360
}
1326
1327
/*
1328
 * FIPS 203, Section 7.1, Algorithm 19: "ML-KEM.KeyGen".
1329
 *
1330
 * Parses the |in| buffer as a |dk| output of "ML-KEM.KeyGen".
1331
 * This matches the output format of encode_prvkey() above.
1332
 */
1333
static int parse_prvkey(const uint8_t *in, EVP_MD_CTX *mdctx, ML_KEM_KEY *key)
1334
111
{
1335
111
    const ML_KEM_VINFO *vinfo = key->vinfo;
1336
1337
    /* Decode and check |s|. */
1338
111
    if (!vector_decode_12(key->s, in, vinfo->rank)) {
1339
89
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1340
89
            "%s invalid private 's' vector",
1341
89
            vinfo->algorithm_name);
1342
89
        return 0;
1343
89
    }
1344
22
    in += vinfo->vector_bytes;
1345
1346
22
    if (!parse_pubkey(in, mdctx, key))
1347
11
        return 0;
1348
11
    in += vinfo->pubkey_bytes;
1349
1350
    /* Check public key hash. */
1351
11
    if (memcmp(key->pkhash, in, ML_KEM_PKHASH_BYTES) != 0) {
1352
11
        ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY,
1353
11
            "%s public key hash mismatch",
1354
11
            vinfo->algorithm_name);
1355
11
        return 0;
1356
11
    }
1357
0
    in += ML_KEM_PKHASH_BYTES;
1358
1359
0
    memcpy(key->z, in, ML_KEM_RANDOM_BYTES);
1360
0
    return 1;
1361
11
}
1362
1363
/*
1364
 * FIPS 203, Section 6.1, Algorithm 16: "ML-KEM.KeyGen_internal".
1365
 *
1366
 * The implementation of Section 5.1, Algorithm 13, "K-PKE.KeyGen(d)" is
1367
 * inlined.
1368
 *
1369
 * The caller MUST pass a pre-allocated digest context that is not shared with
1370
 * any concurrent computation.
1371
 *
1372
 * This function optionally outputs the serialised wire-form |ek| public key
1373
 * into the provided |pubenc| buffer, and generates the content of the |rho|,
1374
 * |pkhash|, |t|, |m|, |s| and |z| components of the private |key| (which must
1375
 * have preallocated space for these).
1376
 *
1377
 * Keys are computed from a 32-byte random |d| plus the 1 byte rank for
1378
 * domain separation.  These are concatenated and hashed to produce a pair of
1379
 * 32-byte seeds public "rho", used to generate the matrix, and private "sigma",
1380
 * used to generate the secret vector |s|.
1381
 *
1382
 * The second random input |z| is copied verbatim into the Fujisaki-Okamoto
1383
 * (FO) transform "implicit-rejection" secret (the |z| component of the private
1384
 * key), which thwarts chosen-ciphertext attacks, provided decap() runs in
1385
 * constant time, with no side channel leaks, on all well-formed (valid length,
1386
 * and correctly encoded) ciphertext inputs.
1387
 */
1388
static __owur int genkey(const uint8_t seed[ML_KEM_SEED_BYTES],
1389
    EVP_MD_CTX *mdctx, uint8_t *pubenc, ML_KEM_KEY *key)
1390
33.4k
{
1391
33.4k
    uint8_t hashed[2 * ML_KEM_RANDOM_BYTES];
1392
33.4k
    const uint8_t *const sigma = hashed + ML_KEM_RANDOM_BYTES;
1393
33.4k
    uint8_t augmented_seed[ML_KEM_RANDOM_BYTES + 1];
1394
33.4k
    const ML_KEM_VINFO *vinfo = key->vinfo;
1395
33.4k
    CBD_FUNC cbd_1 = CBD1(vinfo->evp_type);
1396
33.4k
    int rank = vinfo->rank;
1397
33.4k
    uint8_t counter = 0;
1398
33.4k
    int ret = 0;
1399
1400
    /*
1401
     * Use the "d" seed salted with the rank to derive the public and private
1402
     * seeds rho and sigma.
1403
     */
1404
33.4k
    memcpy(augmented_seed, seed, ML_KEM_RANDOM_BYTES);
1405
33.4k
    augmented_seed[ML_KEM_RANDOM_BYTES] = (uint8_t)rank;
1406
33.4k
    if (!hash_g(hashed, augmented_seed, sizeof(augmented_seed), mdctx, key))
1407
0
        goto end;
1408
33.4k
    memcpy(key->rho, hashed, ML_KEM_RANDOM_BYTES);
1409
    /* The |rho| matrix seed is public */
1410
33.4k
    CONSTTIME_DECLASSIFY(key->rho, ML_KEM_RANDOM_BYTES);
1411
1412
    /* FIPS 203 |e| vector is initial value of key->t */
1413
33.4k
    if (!matrix_expand(mdctx, key)
1414
33.4k
        || !gencbd_vector_ntt(key->s, cbd_1, &counter, sigma, rank, mdctx, key)
1415
33.4k
        || !gencbd_vector_ntt(key->t, cbd_1, &counter, sigma, rank, mdctx, key))
1416
0
        goto end;
1417
1418
    /* To |e| we now add the product of transpose |m| and |s|, giving |t|. */
1419
33.4k
    matrix_mult_transpose_add(key->t, key->m, key->s, rank);
1420
    /* The |t| vector is public */
1421
33.4k
    CONSTTIME_DECLASSIFY(key->t, vinfo->rank * sizeof(scalar));
1422
1423
33.4k
    if (pubenc == NULL) {
1424
        /* Incremental digest of public key without in-full serialisation. */
1425
33.4k
        if (!hash_h_pubkey(key->pkhash, mdctx, key))
1426
0
            goto end;
1427
33.4k
    } else {
1428
0
        encode_pubkey(pubenc, key);
1429
0
        if (!hash_h(key->pkhash, pubenc, vinfo->pubkey_bytes, mdctx, key))
1430
0
            goto end;
1431
0
    }
1432
1433
    /* Save |z| portion of seed for "implicit rejection" on failure. */
1434
33.4k
    memcpy(key->z, seed + ML_KEM_RANDOM_BYTES, ML_KEM_RANDOM_BYTES);
1435
1436
    /* Save the |d| portion of the seed */
1437
33.4k
    key->d = key->z + ML_KEM_RANDOM_BYTES;
1438
33.4k
    memcpy(key->d, seed, ML_KEM_RANDOM_BYTES);
1439
1440
33.4k
    ret = 1;
1441
33.4k
end:
1442
33.4k
    OPENSSL_cleanse((void *)augmented_seed, sizeof(augmented_seed));
1443
33.4k
    OPENSSL_cleanse((void *)hashed, sizeof(hashed));
1444
33.4k
    if (ret == 0) {
1445
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1446
0
            "internal error while generating %s private key",
1447
0
            vinfo->algorithm_name);
1448
0
    }
1449
33.4k
    return ret;
1450
33.4k
}
1451
1452
/*-
1453
 * FIPS 203, Section 6.2, Algorithm 17: "ML-KEM.Encaps_internal".
1454
 * This is the deterministic version with randomness supplied externally.
1455
 *
1456
 * The caller must pass space for two vectors in |tmp|.
1457
 * The |ctext| buffer have space for the ciphertext of the ML-KEM variant
1458
 * of the provided key.
1459
 */
1460
static int encap(uint8_t *ctext, uint8_t secret[ML_KEM_SHARED_SECRET_BYTES],
1461
    const uint8_t entropy[ML_KEM_RANDOM_BYTES],
1462
    scalar *tmp, EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1463
213
{
1464
213
    uint8_t input[ML_KEM_RANDOM_BYTES + ML_KEM_PKHASH_BYTES];
1465
213
    uint8_t Kr[ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES];
1466
213
    uint8_t *r = Kr + ML_KEM_SHARED_SECRET_BYTES;
1467
213
    int ret;
1468
1469
213
    memcpy(input, entropy, ML_KEM_RANDOM_BYTES);
1470
213
    memcpy(input + ML_KEM_RANDOM_BYTES, key->pkhash, ML_KEM_PKHASH_BYTES);
1471
213
    ret = hash_g(Kr, input, sizeof(input), mdctx, key)
1472
213
        && encrypt_cpa(ctext, entropy, r, tmp, mdctx, key);
1473
213
    OPENSSL_cleanse((void *)input, sizeof(input));
1474
1475
213
    if (ret)
1476
213
        memcpy(secret, Kr, ML_KEM_SHARED_SECRET_BYTES);
1477
0
    else
1478
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1479
0
            "internal error while performing %s encapsulation",
1480
0
            key->vinfo->algorithm_name);
1481
213
    OPENSSL_cleanse((void *)Kr, sizeof(Kr));
1482
213
    return ret;
1483
213
}
1484
1485
/*
1486
 * Hash the input message |m'| and public key digest |h|
1487
 * to obtain |K| and |r|.
1488
 */
1489
static int hash_kr(uint8_t *out, uint8_t *in,
1490
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1491
92
{
1492
92
    unsigned int sz, wanted;
1493
1494
92
    wanted = ML_KEM_SHARED_SECRET_BYTES + ML_KEM_RANDOM_BYTES;
1495
92
    return (EVP_DigestInit_ex(mdctx, key->sha3_512_md, NULL)
1496
92
        && EVP_DigestUpdate(mdctx, in, ML_KEM_RANDOM_BYTES)
1497
92
        && EVP_DigestUpdate(mdctx, key->pkhash, ML_KEM_PKHASH_BYTES)
1498
92
        && EVP_DigestFinal_ex(mdctx, out, &sz)
1499
92
        && ossl_assert(sz == wanted));
1500
92
}
1501
1502
/*-
1503
 * Decap needs space for: Kbar | K | r | m'
1504
 * We slice up a single buffer to hold them all.
1505
 * We don't need to cleanse the public pkhash value.
1506
 */
1507
47
#define DECAP_BUFFER_SZ (2 * ML_KEM_SHARED_SECRET_BYTES + 2 * ML_KEM_RANDOM_BYTES)
1508
1509
/*
1510
 * FIPS 203, Section 6.3, Algorithm 18: ML-KEM.Decaps_internal
1511
 *
1512
 * Barring failure of the supporting SHA3/SHAKE primitives, this is fully
1513
 * deterministic, the randomness for the FO transform is extracted during
1514
 * private key generation.
1515
 *
1516
 * The caller must pass space for two vectors in |tmp|.
1517
 * The |ctext| and |tmp_ctext| buffers must each have space for the ciphertext
1518
 * of the key's ML-KEM variant.
1519
 */
1520
static int decap(uint8_t secret[ML_KEM_SHARED_SECRET_BYTES],
1521
    const uint8_t *ctext, uint8_t *tmp_ctext, scalar *tmp,
1522
    EVP_MD_CTX *mdctx, const ML_KEM_KEY *key)
1523
47
{
1524
47
    uint8_t buf[DECAP_BUFFER_SZ];
1525
47
    uint8_t *failure_key = buf; /* Kbar */
1526
47
    uint8_t *Kr = failure_key + ML_KEM_SHARED_SECRET_BYTES;
1527
47
    uint8_t *r = Kr + ML_KEM_SHARED_SECRET_BYTES;
1528
47
    uint8_t *m = r + ML_KEM_RANDOM_BYTES; /* m' */
1529
47
    const ML_KEM_VINFO *vinfo = key->vinfo;
1530
47
    int i;
1531
47
    uint8_t mask;
1532
1533
    /*
1534
     * If our KDF is unavailable, fail early! Otherwise, keep going ignoring
1535
     * any further errors, returning success, and whatever we got for a shared
1536
     * secret.  The decrypt_cpa() function is just arithmetic on secret data,
1537
     * so should not be subject to failure that makes its output predictable.
1538
     *
1539
     * We guard against "should never happen" catastrophic failure of the
1540
     * "pure" function |hash_g| by overwriting the shared secret with the
1541
     * content of the failure key and returning early, if nevertheless hash_g
1542
     * fails.  This is not constant-time, but a failure of |hash_g| already
1543
     * implies loss of side-channel resistance.
1544
     *
1545
     * The same action is taken, if also |encrypt_cpa| should catastrophically
1546
     * fail, due to failure of the |PRF| underlying the CBD functions.
1547
     */
1548
47
    if (!kdf(failure_key, key->z, ctext, vinfo->ctext_bytes, mdctx, key)) {
1549
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1550
0
            "internal error while performing %s decapsulation",
1551
0
            vinfo->algorithm_name);
1552
0
        OPENSSL_cleanse(buf, DECAP_BUFFER_SZ);
1553
0
        return 0;
1554
0
    }
1555
47
    decrypt_cpa(m, ctext, tmp, key);
1556
47
    if (!hash_kr(Kr, m, mdctx, key)
1557
47
        || !encrypt_cpa(tmp_ctext, m, r, tmp, mdctx, key)) {
1558
0
        memcpy(secret, failure_key, ML_KEM_SHARED_SECRET_BYTES);
1559
0
        goto end;
1560
0
    }
1561
47
    mask = constant_time_eq_int_8(0,
1562
47
        CRYPTO_memcmp(ctext, tmp_ctext, vinfo->ctext_bytes));
1563
1.55k
    for (i = 0; i < ML_KEM_SHARED_SECRET_BYTES; i++)
1564
1.50k
        secret[i] = constant_time_select_8(mask, Kr[i], failure_key[i]);
1565
47
end:
1566
47
    OPENSSL_cleanse(buf, DECAP_BUFFER_SZ);
1567
47
    return 1;
1568
47
}
1569
1570
/*
1571
 * After allocating storage for public or private key data, update the key
1572
 * component pointers to reference that storage.
1573
 *
1574
 * The caller should only store private data in `priv` *after* a successful
1575
 * (non-zero) return from this function.
1576
 */
1577
static __owur int add_storage(scalar *pub, scalar *priv,
1578
    int private, int dup, ML_KEM_KEY *key)
1579
49.1k
{
1580
49.1k
    int rank = key->vinfo->rank;
1581
1582
49.1k
    if (pub == NULL || (private && priv == NULL)) {
1583
        /*
1584
         * One of these could be allocated correctly. It is legal to call free with a NULL
1585
         * pointer, so always attempt to free both allocations here
1586
         */
1587
0
        OPENSSL_free(pub);
1588
0
        OPENSSL_secure_free(priv);
1589
0
        return 0;
1590
0
    }
1591
1592
    /*
1593
     * We're adding key material, set up rho and pkhash to point to the
1594
     * rho_pkhash buffer.  Zero the key hash when creating fresh keys.
1595
     */
1596
49.1k
    if (dup == 0)
1597
49.0k
        memset(key->rho_pkhash, 0, sizeof(key->rho_pkhash));
1598
49.1k
    key->rho = key->rho_pkhash;
1599
49.1k
    key->pkhash = key->rho_pkhash + ML_KEM_RANDOM_BYTES;
1600
49.1k
    key->d = key->z = NULL;
1601
1602
    /* A public key needs space for |t| and |m| */
1603
49.1k
    key->m = (key->t = pub) + rank;
1604
1605
    /*
1606
     * A private key also needs space for |s| and |z|.
1607
     * The |z| buffer always includes additional space for |d|, but a key's |d|
1608
     * pointer is left NULL when parsed from the NIST format, which omits that
1609
     * information.  Only keys generated from a (d, z) seed pair will have a
1610
     * non-NULL |d| pointer.
1611
     */
1612
49.1k
    if (private)
1613
48.5k
        key->z = (uint8_t *)(rank + (key->s = priv));
1614
49.1k
    return 1;
1615
49.1k
}
1616
1617
/*
1618
 * After freeing the storage associated with a key that failed to be
1619
 * constructed, reset the internal pointers back to NULL.
1620
 */
1621
void ossl_ml_kem_key_reset(ML_KEM_KEY *key)
1622
49.5k
{
1623
    /*
1624
     * seedbuf can be allocated and contain |z| and |d| if the key is
1625
     * being created from a private key encoding.  Similarly a pending
1626
     * serialised (encoded) private key may be queued up to load.
1627
     * Clear and free that data now.
1628
     */
1629
49.5k
    if (key->seedbuf != NULL)
1630
20
        OPENSSL_secure_clear_free(key->seedbuf, ML_KEM_SEED_BYTES);
1631
49.5k
    if (ossl_ml_kem_have_dkenc(key))
1632
0
        OPENSSL_secure_clear_free(key->encoded_dk, key->vinfo->prvkey_bytes);
1633
1634
    /*-
1635
     * Cleanse any sensitive data:
1636
     * - The private vector |s| is immediately followed by the FO failure
1637
     *   secret |z|, and seed |d|, we can cleanse all three in one call.
1638
     */
1639
49.5k
    if (key->t != NULL) {
1640
49.1k
        if (ossl_ml_kem_have_prvkey(key))
1641
48.5k
            OPENSSL_secure_clear_free(key->s, key->vinfo->prvalloc);
1642
49.1k
        OPENSSL_free(key->t);
1643
49.1k
    }
1644
49.5k
    key->d = key->z = key->seedbuf = key->encoded_dk = (uint8_t *)(key->s = key->m = key->t = NULL);
1645
49.5k
}
1646
1647
/*
1648
 * ----- API exported to the provider
1649
 *
1650
 * Parameters with an implicit fixed length in the internal static API of each
1651
 * variant have an explicit checked length argument at this layer.
1652
 */
1653
1654
/* Retrieve the parameters of one of the ML-KEM variants */
1655
const ML_KEM_VINFO *ossl_ml_kem_get_vinfo(int evp_type)
1656
299k
{
1657
299k
    switch (evp_type) {
1658
61.5k
    case EVP_PKEY_ML_KEM_512:
1659
61.5k
        return &vinfo_map[ML_KEM_512_VINFO];
1660
180k
    case EVP_PKEY_ML_KEM_768:
1661
180k
        return &vinfo_map[ML_KEM_768_VINFO];
1662
57.8k
    case EVP_PKEY_ML_KEM_1024:
1663
57.8k
        return &vinfo_map[ML_KEM_1024_VINFO];
1664
299k
    }
1665
0
    return NULL;
1666
299k
}
1667
1668
ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties,
1669
    int evp_type)
1670
44.0k
{
1671
44.0k
    const ML_KEM_VINFO *vinfo = ossl_ml_kem_get_vinfo(evp_type);
1672
44.0k
    ML_KEM_KEY *key;
1673
1674
44.0k
    if (vinfo == NULL) {
1675
0
        ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_PASSED_INVALID_ARGUMENT,
1676
0
            "unsupported ML-KEM key type: %d", evp_type);
1677
0
        return NULL;
1678
0
    }
1679
1680
44.0k
    if ((key = OPENSSL_malloc(sizeof(*key))) == NULL)
1681
0
        return NULL;
1682
1683
44.0k
    key->vinfo = vinfo;
1684
44.0k
    key->libctx = libctx;
1685
44.0k
    key->prov_flags = ML_KEM_KEY_PROV_FLAGS_DEFAULT;
1686
44.0k
    key->shake128_md = EVP_MD_fetch(libctx, "SHAKE128", properties);
1687
44.0k
    key->shake256_md = EVP_MD_fetch(libctx, "SHAKE256", properties);
1688
44.0k
    key->sha3_256_md = EVP_MD_fetch(libctx, "SHA3-256", properties);
1689
44.0k
    key->sha3_512_md = EVP_MD_fetch(libctx, "SHA3-512", properties);
1690
44.0k
    key->d = key->z = key->rho = key->pkhash = key->encoded_dk = key->seedbuf = NULL;
1691
44.0k
    key->s = key->m = key->t = NULL;
1692
1693
44.0k
    if (key->shake128_md != NULL
1694
44.0k
        && key->shake256_md != NULL
1695
44.0k
        && key->sha3_256_md != NULL
1696
44.0k
        && key->sha3_512_md != NULL)
1697
44.0k
        return key;
1698
1699
0
    ossl_ml_kem_key_free(key);
1700
0
    ERR_raise_data(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR,
1701
0
        "missing SHA3 digest algorithms while creating %s key",
1702
0
        vinfo->algorithm_name);
1703
0
    return NULL;
1704
44.0k
}
1705
1706
ML_KEM_KEY *ossl_ml_kem_key_dup(const ML_KEM_KEY *key, int selection)
1707
53
{
1708
53
    int ok = 0;
1709
53
    ML_KEM_KEY *ret;
1710
1711
53
    if (key == NULL)
1712
0
        return NULL;
1713
    /*
1714
     * Partially decoded keys, not yet imported or loaded, should never be
1715
     * duplicated.
1716
     */
1717
53
    if (ossl_ml_kem_decoded_key(key))
1718
0
        return NULL;
1719
1720
53
    else if ((ret = OPENSSL_memdup(key, sizeof(*key))) == NULL)
1721
0
        return NULL;
1722
1723
53
    ret->d = ret->z = ret->rho = ret->pkhash = NULL;
1724
53
    ret->s = ret->m = ret->t = NULL;
1725
1726
    /* Clear selection bits we can't fulfill */
1727
53
    if (!ossl_ml_kem_have_pubkey(key))
1728
0
        selection = 0;
1729
53
    else if (!ossl_ml_kem_have_prvkey(key))
1730
53
        selection &= ~OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
1731
0
    else if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
1732
0
        selection &= ~OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
1733
1734
53
    switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) {
1735
0
    case 0:
1736
0
        ok = 1;
1737
0
        break;
1738
53
    case OSSL_KEYMGMT_SELECT_PUBLIC_KEY:
1739
53
        ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc), NULL, 0, 1, ret);
1740
53
        break;
1741
0
    case OSSL_KEYMGMT_SELECT_PRIVATE_KEY:
1742
        /* Frees both and returns 0 if either is NULL */
1743
0
        ok = add_storage(OPENSSL_memdup(key->t, key->vinfo->puballoc),
1744
0
            OPENSSL_secure_malloc(key->vinfo->prvalloc), 1, 1, ret);
1745
0
        if (ok) {
1746
0
            memcpy(ret->s, key->s, key->vinfo->prvalloc);
1747
1748
            /* Duplicated keys retain |d|, if available */
1749
0
            if (key->d != NULL)
1750
0
                ret->d = ret->z + ML_KEM_RANDOM_BYTES;
1751
0
        }
1752
0
        break;
1753
53
    }
1754
1755
53
    if (!ok) {
1756
0
        OPENSSL_free(ret);
1757
0
        return NULL;
1758
0
    }
1759
1760
53
    EVP_MD_up_ref(ret->shake128_md);
1761
53
    EVP_MD_up_ref(ret->shake256_md);
1762
53
    EVP_MD_up_ref(ret->sha3_256_md);
1763
53
    EVP_MD_up_ref(ret->sha3_512_md);
1764
1765
53
    return ret;
1766
53
}
1767
1768
void ossl_ml_kem_key_free(ML_KEM_KEY *key)
1769
193k
{
1770
193k
    if (key == NULL)
1771
144k
        return;
1772
1773
49.2k
    EVP_MD_free(key->shake128_md);
1774
49.2k
    EVP_MD_free(key->shake256_md);
1775
49.2k
    EVP_MD_free(key->sha3_256_md);
1776
49.2k
    EVP_MD_free(key->sha3_512_md);
1777
1778
49.2k
    ossl_ml_kem_key_reset(key);
1779
49.2k
    OPENSSL_free(key);
1780
49.2k
}
1781
1782
/* Serialise the public component of an ML-KEM key */
1783
int ossl_ml_kem_encode_public_key(uint8_t *out, size_t len,
1784
    const ML_KEM_KEY *key)
1785
63.8k
{
1786
63.8k
    if (!ossl_ml_kem_have_pubkey(key)
1787
63.8k
        || len != key->vinfo->pubkey_bytes)
1788
0
        return 0;
1789
63.8k
    encode_pubkey(out, key);
1790
63.8k
    return 1;
1791
63.8k
}
1792
1793
/* Serialise an ML-KEM private key */
1794
int ossl_ml_kem_encode_private_key(uint8_t *out, size_t len,
1795
    const ML_KEM_KEY *key)
1796
144
{
1797
144
    if (!ossl_ml_kem_have_prvkey(key)
1798
144
        || len != key->vinfo->prvkey_bytes)
1799
0
        return 0;
1800
144
    encode_prvkey(out, key);
1801
144
    return 1;
1802
144
}
1803
1804
int ossl_ml_kem_encode_seed(uint8_t *out, size_t len,
1805
    const ML_KEM_KEY *key)
1806
267
{
1807
267
    if (key == NULL || key->d == NULL || len != ML_KEM_SEED_BYTES)
1808
47
        return 0;
1809
    /*
1810
     * Both in the seed buffer, and in the allocated storage, the |d| component
1811
     * of the seed is stored last, so we must copy each separately.
1812
     */
1813
220
    memcpy(out, key->d, ML_KEM_RANDOM_BYTES);
1814
220
    out += ML_KEM_RANDOM_BYTES;
1815
220
    memcpy(out, key->z, ML_KEM_RANDOM_BYTES);
1816
220
    return 1;
1817
267
}
1818
1819
/*
1820
 * Stash the seed without (yet) performing a keygen, used during decoding, to
1821
 * avoid an extra keygen if we're only going to export the key again to load
1822
 * into another provider.
1823
 */
1824
ML_KEM_KEY *ossl_ml_kem_set_seed(const uint8_t *seed, size_t seedlen, ML_KEM_KEY *key)
1825
20
{
1826
20
    if (key == NULL
1827
20
        || ossl_ml_kem_have_pubkey(key)
1828
20
        || ossl_ml_kem_have_seed(key)
1829
20
        || seedlen != ML_KEM_SEED_BYTES)
1830
0
        return NULL;
1831
1832
20
    if (key->seedbuf == NULL) {
1833
20
        key->seedbuf = OPENSSL_secure_malloc(seedlen);
1834
20
        if (key->seedbuf == NULL)
1835
0
            return NULL;
1836
20
    }
1837
1838
20
    key->z = key->seedbuf;
1839
20
    key->d = key->z + ML_KEM_RANDOM_BYTES;
1840
20
    memcpy(key->d, seed, ML_KEM_RANDOM_BYTES);
1841
20
    seed += ML_KEM_RANDOM_BYTES;
1842
20
    memcpy(key->z, seed, ML_KEM_RANDOM_BYTES);
1843
20
    return key;
1844
20
}
1845
1846
/* Parse input as a public key */
1847
int ossl_ml_kem_parse_public_key(const uint8_t *in, size_t len, ML_KEM_KEY *key)
1848
590
{
1849
590
    EVP_MD_CTX *mdctx = NULL;
1850
590
    const ML_KEM_VINFO *vinfo;
1851
590
    int ret = 0;
1852
1853
    /* Keys with key material are immutable */
1854
590
    if (key == NULL
1855
590
        || ossl_ml_kem_have_pubkey(key)
1856
590
        || ossl_ml_kem_have_dkenc(key))
1857
0
        return 0;
1858
590
    vinfo = key->vinfo;
1859
1860
590
    if (len != vinfo->pubkey_bytes
1861
590
        || (mdctx = EVP_MD_CTX_new()) == NULL)
1862
0
        return 0;
1863
1864
590
    if (add_storage(OPENSSL_malloc(vinfo->puballoc), NULL, 0, 0, key))
1865
590
        ret = parse_pubkey(in, mdctx, key);
1866
1867
590
    if (!ret)
1868
241
        ossl_ml_kem_key_reset(key);
1869
590
    EVP_MD_CTX_free(mdctx);
1870
590
    return ret;
1871
590
}
1872
1873
/* Parse input as a new private key */
1874
int ossl_ml_kem_parse_private_key(const uint8_t *in, size_t len,
1875
    ML_KEM_KEY *key)
1876
111
{
1877
111
    EVP_MD_CTX *mdctx = NULL;
1878
111
    const ML_KEM_VINFO *vinfo;
1879
111
    int ret = 0;
1880
1881
    /* Keys with key material are immutable */
1882
111
    if (key == NULL
1883
111
        || ossl_ml_kem_have_pubkey(key)
1884
111
        || ossl_ml_kem_have_dkenc(key))
1885
0
        return 0;
1886
111
    vinfo = key->vinfo;
1887
1888
111
    if (len != vinfo->prvkey_bytes
1889
111
        || (mdctx = EVP_MD_CTX_new()) == NULL)
1890
0
        return 0;
1891
1892
    /* Clear any unused seed */
1893
111
    ossl_ml_kem_key_reset(key);
1894
1895
111
    if (add_storage(OPENSSL_malloc(vinfo->puballoc),
1896
111
            OPENSSL_secure_malloc(vinfo->prvalloc), 1, 0, key))
1897
111
        ret = parse_prvkey(in, mdctx, key);
1898
1899
111
    if (!ret)
1900
111
        ossl_ml_kem_key_reset(key);
1901
111
    EVP_MD_CTX_free(mdctx);
1902
111
    return ret;
1903
111
}
1904
1905
/*
1906
 * Generate a new keypair, either from the saved seed (when non-null), or from
1907
 * the RNG.
1908
 */
1909
int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key)
1910
63.5k
{
1911
63.5k
    uint8_t seed[ML_KEM_SEED_BYTES];
1912
63.5k
    EVP_MD_CTX *mdctx = NULL;
1913
63.5k
    const ML_KEM_VINFO *vinfo;
1914
63.5k
    int ret = 0;
1915
1916
63.5k
    if (key == NULL
1917
63.5k
        || ossl_ml_kem_have_pubkey(key)
1918
63.5k
        || ossl_ml_kem_have_dkenc(key))
1919
0
        return 0;
1920
63.5k
    vinfo = key->vinfo;
1921
1922
63.5k
    if (pubenc != NULL && publen != vinfo->pubkey_bytes)
1923
0
        return 0;
1924
1925
63.5k
    if (key->seedbuf != NULL) {
1926
76
        if (!ossl_ml_kem_encode_seed(seed, sizeof(seed), key))
1927
0
            return 0;
1928
76
        ossl_ml_kem_key_reset(key);
1929
63.5k
    } else if (RAND_priv_bytes_ex(key->libctx, seed, sizeof(seed),
1930
63.5k
                   key->vinfo->secbits)
1931
63.5k
        <= 0) {
1932
0
        return 0;
1933
0
    }
1934
1935
63.5k
    if ((mdctx = EVP_MD_CTX_new()) == NULL)
1936
0
        return 0;
1937
1938
    /*
1939
     * Data derived from (d, z) defaults secret, and to avoid side-channel
1940
     * leaks should not influence control flow.
1941
     */
1942
63.5k
    CONSTTIME_SECRET(seed, ML_KEM_SEED_BYTES);
1943
1944
63.5k
    if (add_storage(OPENSSL_malloc(vinfo->puballoc),
1945
63.5k
            OPENSSL_secure_malloc(vinfo->prvalloc), 1, 0, key))
1946
63.5k
        ret = genkey(seed, mdctx, pubenc, key);
1947
63.5k
    OPENSSL_cleanse(seed, sizeof(seed));
1948
1949
    /* Declassify secret inputs and derived outputs before returning control */
1950
63.5k
    CONSTTIME_DECLASSIFY(seed, ML_KEM_SEED_BYTES);
1951
1952
63.5k
    EVP_MD_CTX_free(mdctx);
1953
63.5k
    if (!ret) {
1954
        /* Erase any partial public key output */
1955
0
        if (pubenc != NULL)
1956
0
            OPENSSL_cleanse(pubenc, vinfo->pubkey_bytes);
1957
0
        ossl_ml_kem_key_reset(key);
1958
0
        return 0;
1959
0
    }
1960
1961
    /* The public components are already declassified */
1962
63.5k
    CONSTTIME_DECLASSIFY(key->s, vinfo->rank * sizeof(scalar));
1963
63.5k
    CONSTTIME_DECLASSIFY(key->z, 2 * ML_KEM_RANDOM_BYTES);
1964
63.5k
    return 1;
1965
63.5k
}
1966
1967
/*
1968
 * FIPS 203, Section 6.2, Algorithm 17: ML-KEM.Encaps_internal
1969
 * This is the deterministic version with randomness supplied externally.
1970
 */
1971
int ossl_ml_kem_encap_seed(uint8_t *ctext, size_t clen,
1972
    uint8_t *shared_secret, size_t slen,
1973
    const uint8_t *entropy, size_t elen,
1974
    const ML_KEM_KEY *key)
1975
213
{
1976
213
    const ML_KEM_VINFO *vinfo;
1977
213
    EVP_MD_CTX *mdctx;
1978
213
    int ret = 0;
1979
1980
213
    if (key == NULL || !ossl_ml_kem_have_pubkey(key))
1981
0
        return 0;
1982
213
    vinfo = key->vinfo;
1983
1984
213
    if (ctext == NULL || clen != vinfo->ctext_bytes
1985
213
        || shared_secret == NULL || slen != ML_KEM_SHARED_SECRET_BYTES
1986
213
        || entropy == NULL || elen != ML_KEM_RANDOM_BYTES
1987
213
        || (mdctx = EVP_MD_CTX_new()) == NULL)
1988
0
        return 0;
1989
    /*
1990
     * Data derived from the encap entropy defaults secret, and to avoid
1991
     * side-channel leaks should not influence control flow.
1992
     */
1993
213
    CONSTTIME_SECRET(entropy, elen);
1994
1995
    /*-
1996
     * This avoids the need to handle allocation failures for two (max 2KB
1997
     * each) vectors, that are never retained on return from this function.
1998
     * We stack-allocate these.
1999
     */
2000
213
#define case_encap_seed(bits)                                        \
2001
213
    {                                                                \
2002
213
        scalar tmp[2 * ML_KEM_##bits##_RANK];                        \
2003
213
                                                                     \
2004
213
        ret = encap(ctext, shared_secret, entropy, tmp, mdctx, key); \
2005
213
        OPENSSL_cleanse((void *)tmp, sizeof(tmp));                   \
2006
213
    }
2007
213
    switch (vinfo->evp_type) {
2008
62
    case EVP_PKEY_ML_KEM_512:
2009
62
        case_encap_seed(512);
2010
62
        break;
2011
93
    case EVP_PKEY_ML_KEM_768:
2012
93
        case_encap_seed(768);
2013
93
        break;
2014
58
    case EVP_PKEY_ML_KEM_1024:
2015
58
        case_encap_seed(1024);
2016
58
        break;
2017
213
    }
2018
213
#undef case_encap_seed
2019
2020
    /* Erase any partial ciphertext output on failure */
2021
213
    if (!ret)
2022
0
        OPENSSL_cleanse(ctext, clen);
2023
2024
    /* Declassify secret inputs and derived outputs before returning control */
2025
213
    CONSTTIME_DECLASSIFY(entropy, elen);
2026
213
    CONSTTIME_DECLASSIFY(ctext, clen);
2027
213
    CONSTTIME_DECLASSIFY(shared_secret, slen);
2028
2029
213
    EVP_MD_CTX_free(mdctx);
2030
213
    return ret;
2031
213
}
2032
2033
int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen,
2034
    uint8_t *shared_secret, size_t slen,
2035
    const ML_KEM_KEY *key)
2036
213
{
2037
213
    uint8_t r[ML_KEM_RANDOM_BYTES];
2038
213
    int ret;
2039
2040
213
    if (key == NULL)
2041
0
        return 0;
2042
2043
213
    if (RAND_bytes_ex(key->libctx, r, ML_KEM_RANDOM_BYTES,
2044
213
            key->vinfo->secbits)
2045
213
        < 1)
2046
0
        return 0;
2047
2048
213
    ret = ossl_ml_kem_encap_seed(ctext, clen, shared_secret, slen,
2049
213
        r, sizeof(r), key);
2050
2051
213
    OPENSSL_cleanse((void *)r, sizeof(r));
2052
213
    return ret;
2053
213
}
2054
2055
int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen,
2056
    const uint8_t *ctext, size_t clen,
2057
    const ML_KEM_KEY *key)
2058
189
{
2059
189
    const ML_KEM_VINFO *vinfo;
2060
189
    EVP_MD_CTX *mdctx;
2061
189
    int ret = 0;
2062
#if defined(OPENSSL_CONSTANT_TIME_VALIDATION)
2063
    int classify_bytes = 2 * sizeof(scalar) + ML_KEM_RANDOM_BYTES;
2064
#endif
2065
2066
    /* Need a private key here */
2067
189
    if (!ossl_ml_kem_have_prvkey(key)
2068
189
        || shared_secret == NULL
2069
189
        || slen < ML_KEM_SHARED_SECRET_BYTES)
2070
0
        return 0;
2071
189
    vinfo = key->vinfo;
2072
2073
189
    if (slen != ML_KEM_SHARED_SECRET_BYTES
2074
189
        || ctext == NULL || clen != vinfo->ctext_bytes
2075
189
        || (mdctx = EVP_MD_CTX_new()) == NULL) {
2076
0
        (void)RAND_bytes_ex(key->libctx, shared_secret,
2077
0
            ML_KEM_SHARED_SECRET_BYTES, vinfo->secbits);
2078
0
        return 0;
2079
0
    }
2080
    /*
2081
     * Data derived from |s| and |z| defaults secret, and to avoid side-channel
2082
     * leaks should not influence control flow.
2083
     */
2084
189
    CONSTTIME_SECRET(key->s, classify_bytes);
2085
2086
    /*-
2087
     * This avoids the need to handle allocation failures for two (max 2KB
2088
     * each) vectors and an encoded ciphertext (max 1568 bytes), that are never
2089
     * retained on return from this function.
2090
     * We stack-allocate these.
2091
     */
2092
189
#define case_decap(bits)                                          \
2093
189
    {                                                             \
2094
189
        uint8_t cbuf[CTEXT_BYTES(bits)];                          \
2095
189
        scalar tmp[2 * ML_KEM_##bits##_RANK];                     \
2096
189
                                                                  \
2097
189
        ret = decap(shared_secret, ctext, cbuf, tmp, mdctx, key); \
2098
189
        OPENSSL_cleanse((void *)tmp, sizeof(tmp));                \
2099
189
        OPENSSL_cleanse((void *)cbuf, sizeof(cbuf));              \
2100
189
    }
2101
189
    switch (vinfo->evp_type) {
2102
62
    case EVP_PKEY_ML_KEM_512:
2103
62
        case_decap(512);
2104
62
        break;
2105
69
    case EVP_PKEY_ML_KEM_768:
2106
69
        case_decap(768);
2107
69
        break;
2108
58
    case EVP_PKEY_ML_KEM_1024:
2109
58
        case_decap(1024);
2110
58
        break;
2111
189
    }
2112
189
#undef case_decap
2113
2114
    /* Declassify secret inputs and derived outputs before returning control */
2115
189
    CONSTTIME_DECLASSIFY(key->s, classify_bytes);
2116
189
    CONSTTIME_DECLASSIFY(shared_secret, slen);
2117
189
    EVP_MD_CTX_free(mdctx);
2118
2119
189
    return ret;
2120
189
}
2121
2122
int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2)
2123
150
{
2124
    /*
2125
     * This handles any unexpected differences in the ML-KEM variant rank,
2126
     * giving different key component structures, barring SHA3-256 hash
2127
     * collisions, the keys are the same size.
2128
     */
2129
150
    if (ossl_ml_kem_have_pubkey(key1) && ossl_ml_kem_have_pubkey(key2))
2130
150
        return memcmp(key1->pkhash, key2->pkhash, ML_KEM_PKHASH_BYTES) == 0;
2131
2132
    /*
2133
     * No match if just one of the public keys is not available, otherwise both
2134
     * are unavailable, and for now such keys are considered equal.
2135
     */
2136
0
    return (!(ossl_ml_kem_have_pubkey(key1) ^ ossl_ml_kem_have_pubkey(key2)));
2137
150
}