Coverage Report

Created: 2026-09-12 06:55

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