1 /*
2  * Copyright 2024-2025 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 #ifndef OPENSSL_HEADER_ML_KEM_H
11 # define OPENSSL_HEADER_ML_KEM_H
12 # pragma once
13 
14 # include <openssl/e_os2.h>
15 # include <openssl/bio.h>
16 # include <openssl/core_dispatch.h>
17 # include <crypto/evp.h>
18 
19 # define ML_KEM_DEGREE 256
20 /*
21  * With (q-1) an odd multiple of 256, and 17 ("zeta") as a primitive 256th root
22  * of unity, the polynomial (X^256+1) splits in Z_q[X] into 128 irreducible
23  * quadratic factors of the form (X^2 - zeta^(2i + 1)).  This is used to
24  * implement efficient multiplication in the ring R_q via the "NTT" transform.
25  */
26 # define ML_KEM_PRIME          (ML_KEM_DEGREE * 13 + 1)
27 
28 /*
29  * Various ML-KEM primitives need random input, 32-bytes at a time.  Key
30  * generation consumes two random values (d, z) with "d" plus the rank (domain
31  * separation) further expanded to two derived seeds "rho" and "sigma", with
32  * "rho" used to generate the public matrix "A", and sigma to generate the
33  * private vector "s" and error vector "e".
34  *
35  * Encapsulation also consumes one random value m, that is 32-bytes long.  The
36  * resulting shared secret "K" (also 32 bytes) and an internal random value "r"
37  * are derived from "m" concatenated with a digest of the received public key.
38  * Use of the public key hash means that the derived shared secret is
39  * "contributary", it uses randomness from both parties.
40  *
41  * The seed "rho" is appended to the public key and allows the recipient of the
42  * public key to re-compute the matrix "A" when performing encapsulation.
43  *
44  * Note that the matrix "m" we store in the public key is the transpose of the
45  * "A" matrix from FIPS 203!
46  */
47 # define ML_KEM_RANDOM_BYTES    32 /* rho, sigma, ... */
48 # define ML_KEM_SEED_BYTES      (ML_KEM_RANDOM_BYTES * 2) /* Keygen (d, z) */
49 
50 # define ML_KEM_PKHASH_BYTES        32 /* Salts the shared-secret */
51 # define ML_KEM_SHARED_SECRET_BYTES 32
52 
53 # if ML_KEM_PKHASH_BYTES != ML_KEM_RANDOM_BYTES
54 #  error "unexpected ML-KEM public key hash size"
55 # endif
56 
57 /*-
58  * The ML-KEM specification can be found in
59  * https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf
60  *
61  * Section 8, Table 2, lists the parameters for the three variants:
62  *
63  *         Variant     n     q  k  eta1  eta2  du   dv  secbits
64  *      ----------   ---  ----  -  ----  ----  --   --  -------
65  *      ML-KEM-512   256  3329  2     3     2  10    4      128
66  *      ML-KEM-768   256  3329  3     2     2  10    4      192
67  *      ML-KEM-1024  256  3329  4     2     2  11    5      256
68  *
69  * where:
70  *
71  * - "n" (ML_KEM_DEGREE above) is the fixed degree of the quotient polynomial
72  *    in the ring: "R_q" = Z[X]/(X^n + 1).
73  * - "q" (ML_KEM_PRIME above) is the fixed prime (256 * 13 + 1 = 3329) used in
74  *   all ML-KEM variants.
75  * - "k" is the row rank of the square matrix "A", with entries in R_q, that
76  *   defines the "noisy" linear equations: t = A * s + e.  Also the rank of
77  *   of the associated vectors.
78  * - "eta1" determines the amplitude of "s" and "e" vectors in key generation
79  *   and the "y" vector in ML-KEM encapsulation (K-PKE encryption).
80  * - "eta2" determines the amplitude of "e1" and "e2" noise terms in ML-KEM
81  *   encapsulation (K-PKE encryption).
82  * - "du" determines how many bits of each coefficient are retained in the
83  *   compressed form of the "u" vector in the encapsulation ciphertext.
84  * - "dv" determines how many bits of each coefficient are retained in the
85  *   compressed form of the "v" value in encapsulation ciphertext
86  * - "secbits" is required security strength of the RNG for the random inputs.
87  */
88 
89 /*
90  * Variant-specific constants and structures
91  * -----------------------------------------
92  */
93 # define EVP_PKEY_ML_KEM_512            NID_ML_KEM_512
94 # define ML_KEM_512_BITS                512
95 # define ML_KEM_512_RANK                2
96 # define ML_KEM_512_ETA1                3
97 # define ML_KEM_512_ETA2                2
98 # define ML_KEM_512_DU                  10
99 # define ML_KEM_512_DV                  4
100 # define ML_KEM_512_SECBITS             128
101 # define ML_KEM_512_SECURITY_CATEGORY   1
102 
103 # define EVP_PKEY_ML_KEM_768            NID_ML_KEM_768
104 # define ML_KEM_768_BITS                768
105 # define ML_KEM_768_RANK                3
106 # define ML_KEM_768_ETA1                2
107 # define ML_KEM_768_ETA2                2
108 # define ML_KEM_768_DU                  10
109 # define ML_KEM_768_DV                  4
110 # define ML_KEM_768_SECBITS             192
111 # define ML_KEM_768_SECURITY_CATEGORY   3
112 
113 # define EVP_PKEY_ML_KEM_1024           NID_ML_KEM_1024
114 # define ML_KEM_1024_BITS               1024
115 # define ML_KEM_1024_RANK               4
116 # define ML_KEM_1024_ETA1               2
117 # define ML_KEM_1024_ETA2               2
118 # define ML_KEM_1024_DU                 11
119 # define ML_KEM_1024_DV                 5
120 # define ML_KEM_1024_SECBITS            256
121 # define ML_KEM_1024_SECURITY_CATEGORY  5
122 
123 # define ML_KEM_KEY_RANDOM_PCT  (1 << 0)
124 # define ML_KEM_KEY_FIXED_PCT   (1 << 1)
125 # define ML_KEM_KEY_PREFER_SEED (1 << 2)
126 # define ML_KEM_KEY_RETAIN_SEED (1 << 3)
127 /* Mask to check whether PCT on import is enabled */
128 # define ML_KEM_KEY_PCT_TYPE \
129     (ML_KEM_KEY_RANDOM_PCT | ML_KEM_KEY_FIXED_PCT)
130 /* Default provider flags */
131 # define ML_KEM_KEY_PROV_FLAGS_DEFAULT \
132     (ML_KEM_KEY_RANDOM_PCT | ML_KEM_KEY_PREFER_SEED | ML_KEM_KEY_RETAIN_SEED)
133 
134 /*
135  * External variant-specific API
136  * -----------------------------
137  */
138 
139 typedef struct {
140     const char *algorithm_name;
141     size_t prvkey_bytes;
142     size_t prvalloc;
143     size_t pubkey_bytes;
144     size_t puballoc;
145     size_t ctext_bytes;
146     size_t vector_bytes;
147     size_t u_vector_bytes;
148     int evp_type;
149     int bits;
150     int rank;
151     int du;
152     int dv;
153     int secbits;
154     int security_category;
155 } ML_KEM_VINFO;
156 
157 /* Retrive global variant-specific parameters */
158 const ML_KEM_VINFO *ossl_ml_kem_get_vinfo(int evp_type);
159 
160 /* Known as ML_KEM_KEY via crypto/types.h */
161 typedef struct ossl_ml_kem_key_st {
162     /* Variant metadata, for one of ML-KEM-{512,768,1024} */
163     const ML_KEM_VINFO *vinfo;
164 
165     /*
166      * Library context, initially used to fetch the SHA3 MDs, and later for
167      * random number generation.
168      */
169     OSSL_LIB_CTX *libctx;
170 
171     /* Pre-fetched SHA3 */
172     EVP_MD *shake128_md;
173     EVP_MD *shake256_md;
174     EVP_MD *sha3_256_md;
175     EVP_MD *sha3_512_md;
176 
177     /*
178      * Pointers into variable size storage, initially all NULL. Appropriate
179      * storage is allocated once a public or private key is specified, at
180      * which point the key becomes immutable.
181      */
182     uint8_t *rho;                           /* Public matrix seed */
183     uint8_t *pkhash;                        /* Public key hash */
184     struct ossl_ml_kem_scalar_st *t;        /* Public key vector */
185     struct ossl_ml_kem_scalar_st *m;        /* Pre-computed pubkey matrix */
186     struct ossl_ml_kem_scalar_st *s;        /* Private key secret vector */
187     uint8_t *z;                             /* Private key FO failure secret */
188     uint8_t *d;                             /* Private key seed */
189     int prov_flags;                         /* prefer/retain seed and PCT flags */
190 
191     /*
192      * Fixed-size built-in buffer, which holds the |rho| and the public key
193      * |pkhash| in that order, once we have expanded key material.
194      */
195     uint8_t rho_pkhash[64];                 /* |rho| + |pkhash| */
196 
197     /*
198      * With seed-only keys, that are not yet expanded, this holds the
199      * |z| and |d| components in that order.
200      */
201     uint8_t *seedbuf;                       /* |z| + |d| temporary secure storage buffer */
202     uint8_t *encoded_dk;                    /* Unparsed P8 private key */
203 } ML_KEM_KEY;
204 
205 /* The public key is always present, when the private is */
206 # define ossl_ml_kem_key_vinfo(key)     ((key)->vinfo)
207 # define ossl_ml_kem_have_pubkey(key)   ((key)->t != NULL)
208 # define ossl_ml_kem_have_prvkey(key)   ((key)->s != NULL)
209 # define ossl_ml_kem_have_seed(key)     ((key)->d != NULL)
210 # define ossl_ml_kem_have_dkenc(key)    ((key)->encoded_dk != NULL)
211 # define ossl_ml_kem_decoded_key(key)   ((key)->encoded_dk != NULL \
212                                          || ((key)->s == NULL && (key)->d != NULL))
213 
214 /*
215  * ----- ML-KEM key lifecycle
216  */
217 
218 /*
219  * Allocate a "bare" key for given ML-KEM variant. Initially without any public
220  * or private key material.
221  */
222 ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties,
223                                 int evp_type);
224 /* Reset a key clearing all public and private key material */
225 void ossl_ml_kem_key_reset(ML_KEM_KEY *key);
226 /* Deallocate the key */
227 void ossl_ml_kem_key_free(ML_KEM_KEY *key);
228 /*
229  * Duplicate a key, optionally including some key material, per the
230  * |selection|, see <openssl/core_dispatch.h>.
231  */
232 ML_KEM_KEY *ossl_ml_kem_key_dup(const ML_KEM_KEY *key, int selection);
233 
234 /*
235  * ----- Import or generate key material.
236  */
237 
238 /*
239  * Functions that augment "bare ML-KEM keys" with key material deserialised
240  * from an input buffer. It is an error for any key material to already be
241  * present.
242  *
243  * Return 1 on success, 0 otherwise.
244  */
245 __owur
246 int ossl_ml_kem_parse_public_key(const uint8_t *in, size_t len,
247                                  ML_KEM_KEY *key);
248 __owur
249 int ossl_ml_kem_parse_private_key(const uint8_t *in, size_t len,
250                                   ML_KEM_KEY *key);
251 ML_KEM_KEY *ossl_ml_kem_set_seed(const uint8_t *seed, size_t seedlen,
252                                  ML_KEM_KEY *key);
253 __owur
254 int ossl_ml_kem_genkey(uint8_t *pubenc, size_t publen, ML_KEM_KEY *key);
255 
256 /*
257  * Perform an ML-KEM operation with a given ML-KEM key.  The key can generally
258  * be either a private or public key, with the exception of encoding a private
259  * key or performing KEM decapsulation.
260  */
261 __owur
262 int ossl_ml_kem_encode_public_key(uint8_t *out, size_t len,
263                                   const ML_KEM_KEY *key);
264 __owur
265 int ossl_ml_kem_encode_private_key(uint8_t *out, size_t len,
266                                    const ML_KEM_KEY *key);
267 __owur
268 int ossl_ml_kem_encode_seed(uint8_t *out, size_t len,
269                             const ML_KEM_KEY *key);
270 
271 __owur
272 int ossl_ml_kem_encap_seed(uint8_t *ctext, size_t clen,
273                            uint8_t *shared_secret, size_t slen,
274                            const uint8_t *entropy, size_t elen,
275                            const ML_KEM_KEY *key);
276 __owur
277 int ossl_ml_kem_encap_rand(uint8_t *ctext, size_t clen,
278                            uint8_t *shared_secret, size_t slen,
279                            const ML_KEM_KEY *key);
280 __owur
281 int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen,
282                       const uint8_t *ctext, size_t clen,
283                       const ML_KEM_KEY *key);
284 
285 /* Compare the public key hashes of two keys */
286 __owur
287 int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2);
288 
289 #endif  /* OPENSSL_HEADER_ML_KEM_H */
290