Coverage Report

Created: 2026-10-16 07:07

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