summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem_internal.h
diff options
context:
space:
mode:
authorbeck <>2025-09-05 23:30:12 +0000
committerbeck <>2025-09-05 23:30:12 +0000
commit21ce890cad6ae67e0d52f7bfdc44579df2bfc032 (patch)
tree696ffc96af9e6fa399dc93af7325749db45458c5 /src/lib/libcrypto/mlkem/mlkem_internal.h
parentdc98dc450acd1ba6a9a274662e55679f5c93e5fa (diff)
downloadopenbsd-21ce890cad6ae67e0d52f7bfdc44579df2bfc032.tar.gz
openbsd-21ce890cad6ae67e0d52f7bfdc44579df2bfc032.tar.bz2
openbsd-21ce890cad6ae67e0d52f7bfdc44579df2bfc032.zip
Deduplicate the mlkem 768 and mlkem 1024 code.
This moves everything not public to mlkem_internal.c removing the old files and doing some further cleanup on the way. With this landed mlkem is out of my stack and can be changed without breaking my subsequent changes ok tb@
Diffstat (limited to 'src/lib/libcrypto/mlkem/mlkem_internal.h')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem_internal.h460
1 files changed, 177 insertions, 283 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem_internal.h b/src/lib/libcrypto/mlkem/mlkem_internal.h
index 7e6c313aa9..2b3157256e 100644
--- a/src/lib/libcrypto/mlkem/mlkem_internal.h
+++ b/src/lib/libcrypto/mlkem/mlkem_internal.h
@@ -1,6 +1,7 @@
1/* $OpenBSD: mlkem_internal.h,v 1.9 2025/08/19 21:37:08 tb Exp $ */ 1/* $OpenBSD: mlkem_internal.h,v 1.10 2025/09/05 23:30:12 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2023, Google Inc. 3 * Copyright (c) 2023, Google Inc.
4 * Copyright (c) 2025, Bob Beck <beck@obtuse.com>
4 * 5 *
5 * Permission to use, copy, modify, and/or distribute this software for any 6 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -26,402 +27,295 @@ extern "C" {
26#endif 27#endif
27 28
28__BEGIN_HIDDEN_DECLS 29__BEGIN_HIDDEN_DECLS
29/*
30 * MLKEM_SEED_LENGTH is the number of bytes in an ML-KEM seed. An ML-KEM
31 * seed is normally used to represent a private key.
32 */
33#define MLKEM_SEED_LENGTH 64
34 30
35/* 31/* Public opaque ML-KEM key structures. */
36 * MLKEM_SHARED_SECRET_LENGTH is the number of bytes in an ML-KEM shared
37 * secret.
38 */
39#define MLKEM_SHARED_SECRET_LENGTH 32
40 32
41/* 33#define MLKEM_PUBLIC_KEY_UNINITIALIZED 1
42 * |MLKEM_encap_external_entropy| behaves exactly like the public |MLKEM_encap| 34#define MLKEM_PUBLIC_KEY_INITIALIZED 2
43 * with the entropy provided by the caller. It is directly called internally 35#define MLKEM_PRIVATE_KEY_UNINITIALIZED 3
44 * and by tests. 36#define MLKEM_PRIVATE_KEY_INITIALIZED 4
45 */
46int
47MLKEM_encap_external_entropy(const MLKEM_public_key *public_key,
48 const uint8_t *entropy, uint8_t **out_ciphertext,
49 size_t *out_ciphertext_len, uint8_t **out_shared_secret,
50 size_t *out_shared_secret_len);
51 37
52/* 38struct MLKEM_public_key_st {
53 * |MLKEM_generate_key_external_entropy| behaves exactly like the public 39 uint16_t rank;
54 * |MLKEM_generate_key| with the entropy provided by the caller. 40 int state;
55 * It is directly called internally and by tests. 41 struct MLKEM768_public_key *key_768;
56 */ 42 struct MLKEM1024_public_key *key_1024;
57int 43};
58MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key, 44
59 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len, 45struct MLKEM_private_key_st {
60 const uint8_t *entropy); 46 uint16_t rank;
47 int state;
48 struct MLKEM768_private_key *key_768;
49 struct MLKEM1024_private_key *key_1024;
50};
61 51
62/* 52/*
63 * ML-KEM-768 53 * ML-KEM-768 and ML-KEM-1024
64 * 54 *
65 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from 55 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
66 * https://csrc.nist.gov/pubs/fips/204/final 56 * https://csrc.nist.gov/pubs/fips/204/final
57 *
58 * You should prefer ML-KEM-768 where possible. ML-KEM-1024 is larger and exists
59 * for people who are obsessed with more 'bits of crypto', and who are also
60 * lacking the knowledge to realize that anything that can count to 256 bits
61 * must likely use an equivalent amount of energy to that of an entire star to
62 * do so.
63 *
64 * ML-KEM-768 is adequate to protect against a future cryptographically relevant
65 * quantum computer, VIC 20, abacus, or carefully calibrated reference dog. I
66 * for one plan on welcoming our new Kardashev-II civilization overlords with
67 * open arms. In the meantime will not waste bytes on the wire by to adding
68 * the fear of the possible future existence of a cryptographically relevant
69 * Dyson sphere to the aforementioned list of fear-inducing future
70 * cryptographically relevant hypotheticals.
71 *
72 * If your carefully calibrated reference dog notices the sun starting to dim,
73 * you might need ML-KEM-1024, but you probably have bigger concerns than
74 * the decryption of your stored past TLS sessions at that point.
67 */ 75 */
68 76
69/* 77/*
70 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 78 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
71 * key. 79 * object should never leave the address space since the format is unstable.
72 */ 80 */
73#define MLKEM768_PUBLIC_KEY_BYTES 1184 81struct MLKEM1024_public_key {
74 82 uint8_t bytes[512 * (4 + 16) + 32 + 32];
75/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ 83 uint16_t alignment;
76#define MLKEM_SEED_BYTES 64 84};
77 85
78/* 86/*
79 * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared 87 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
80 * secret. Although the round-3 specification has a variable-length output, the 88 * this object should never leave the address space since the format is
81 * final ML-KEM construction is expected to use a fixed 32-byte output. To 89 * unstable.
82 * simplify the future transition, we apply the same restriction.
83 */ 90 */
84#define MLKEM_SHARED_SECRET_BYTES 32 91struct MLKEM1024_private_key {
92 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
93 uint16_t alignment;
94};
85 95
86/* 96/*
87 * MLKEM_generate_key generates a random public/private key pair, writes the 97 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this
88 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 98 * object should never leave the address space since the format is unstable.
89 * the private key. If |optional_out_seed| is not NULL then the seed used to
90 * generate the private key is written to it.
91 */ 99 */
92int MLKEM768_generate_key( 100struct MLKEM768_public_key {
93 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 101 uint8_t bytes[512 * (3 + 9) + 32 + 32];
94 uint8_t optional_out_seed[MLKEM_SEED_BYTES], 102 uint16_t alignment;
95 MLKEM_private_key *out_private_key); 103};
96 104
97/* 105/*
98 * MLKEM768_private_key_from_seed derives a private key from a seed that was 106 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
99 * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is 107 * object should never leave the address space since the format is unstable.
100 * incorrect, otherwise it writes |*out_private_key| and returns 1.
101 */ 108 */
102int MLKEM768_private_key_from_seed(const uint8_t *seed, size_t seed_len, 109struct MLKEM768_private_key {
103 MLKEM_private_key *out_private_key); 110 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
111 uint16_t alignment;
112};
104 113
105/* 114/*
106 * MLKEM_public_from_private sets |*out_public_key| to the public key that 115 * MLKEM_SEED_LENGTH is the number of bytes in an ML-KEM seed. An ML-KEM
107 * corresponds to |private_key|. (This is faster than parsing the output of 116 * seed is normally used to represent a private key.
108 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key
109 * that was just generated.)
110 */ 117 */
111void MLKEM768_public_from_private(const MLKEM_private_key *private_key, 118#define MLKEM_SEED_LENGTH 64
112 MLKEM_public_key *out_public_key);
113
114/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
115#define MLKEM768_CIPHERTEXT_BYTES 1088
116 119
117/* 120/*
118 * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the 121 * MLKEM_SHARED_SECRET_LENGTH is the number of bytes in an ML-KEM shared
119 * ciphertext to |out_ciphertext|, and writes the random shared secret to 122 * secret.
120 * |out_shared_secret|.
121 */ 123 */
122void MLKEM768_encap(const MLKEM_public_key *public_key, 124#define MLKEM_SHARED_SECRET_LENGTH 32
123 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
124 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
125 125
126/* 126/*
127 * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key| 127 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy
128 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it 128 * necessary to encapsulate a secret. The entropy will be leaked to the
129 * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid, 129 * decapsulating party.
130 * |out_shared_secret| is filled with a key that will always be the same for the
131 * same |ciphertext| and |private_key|, but which appears to be random unless
132 * one has access to |private_key|. These alternatives occur in constant time.
133 * Any subsequent symmetric encryption using |out_shared_secret| must use an
134 * authenticated encryption scheme in order to discover the decapsulation
135 * failure.
136 */ 130 */
137int MLKEM768_decap(const MLKEM_private_key *private_key, 131#define MLKEM_ENCAP_ENTROPY 32
138 const uint8_t *ciphertext, size_t ciphertext_len,
139 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
140 132
141/* Serialisation of keys. */ 133/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
134#define MLKEM1024_CIPHERTEXT_BYTES 1568
135
136/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
137#define MLKEM768_CIPHERTEXT_BYTES 1088
142 138
143/* 139/*
144 * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard 140 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public
145 * format for ML-KEM public keys. It returns one on success or zero on allocation 141 * key.
146 * error.
147 */ 142 */
148int MLKEM768_marshal_public_key(const MLKEM_public_key *public_key, 143#define MLKEM768_PUBLIC_KEY_BYTES 1184
149 uint8_t **output, size_t *output_len);
150 144
151/* 145/*
152 * MLKEM768_parse_public_key parses a public key, in the format generated by 146 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
153 * |MLKEM_marshal_public_key|, from |in| and writes the result to 147 * public key.
154 * |out_public_key|. It returns one on success or zero on parse error or if
155 * there are trailing bytes in |in|.
156 */ 148 */
157int MLKEM768_parse_public_key(const uint8_t *input, size_t input_len, 149#define MLKEM1024_PUBLIC_KEY_BYTES 1568
158 MLKEM_public_key *out_public_key);
159 150
160/* 151/*
161 * MLKEM_parse_private_key parses a private key, in the format generated by 152 * MLKEM768_PRIVATE_KEY_BYTES is the length of the data produced by
162 * |MLKEM_marshal_private_key|, from |in| and writes the result to 153 * |marshal_private_key| for a RANK768 MLKEM_private_key.
163 * |out_private_key|. It returns one on success or zero on parse error or if
164 * there are trailing bytes in |in|. This formate is verbose and should be avoided.
165 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
166 */ 154 */
167int MLKEM768_parse_private_key(const uint8_t *input, size_t input_len, 155#define MLKEM768_PRIVATE_KEY_BYTES 2400
168 MLKEM_private_key *out_private_key);
169 156
170/* 157/*
171 * ML-KEM-1024 158 * MLKEM1024_PRIVATE_KEY_BYTES is the length of the data produced by
172 * 159 * |marshal_private_key| for a RANK1024 MLKEM_private_key.
173 * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible.
174 */ 160 */
161#define MLKEM1024_PRIVATE_KEY_BYTES 3168
175 162
176/* 163/*
177 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024 164 * Internal MLKEM 768 and MLKEM 1024 functions come largely from BoringSSL, but
178 * public key. 165 * converted to C from templated C++. Due to this history, most internal
166 * functions do not allocate, and are expected to be handed memory allocated by
167 * the caller. The caller is generally expected to know what sizes to allocate
168 * based upon the rank of the key (either public or private) that they are
169 * starting with. This avoids the need to handle memory allocation failures
170 * (which boring in C++ just crashes by choice) deep in the implementation, as
171 * what is needed is allocated up front in the public facing functions, and
172 * failure is handled there.
179 */ 173 */
180#define MLKEM1024_PUBLIC_KEY_BYTES 1568 174
175/* Key generation. */
181 176
182/* 177/*
183 * MLKEM1024_generate_key generates a random public/private key pair, writes the 178 * mlkem_generate_key generates a random public/private key pair, writes the
184 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 179 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
185 * the private key. If |optional_out_seed| is not NULL then the seed used to 180 * the private key. If |optional_out_seed| is not NULL then the seed used to
186 * generate the private key is written to it. 181 * generate the private key is written to it. The caller is responsible for
182 * ensuring that |out_encoded_public_key| and |out_optonal_seed| point to
183 * enough memory to contain a key and seed for the rank of |out_private_key|.
187 */ 184 */
188int MLKEM1024_generate_key( 185int mlkem_generate_key(uint8_t *out_encoded_public_key,
189 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 186 uint8_t *optional_out_seed, MLKEM_private_key *out_private_key);
190 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
191 MLKEM_private_key *out_private_key);
192 187
193/* 188/*
194 * MLKEM1024_private_key_from_seed derives a private key from a seed that was 189 * mlkem_private_key_from_seed modifies |out_private_key| to generate a key of
195 * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len| 190 * the rank of |*out_private_key| from a seed that was generated by
196 * is incorrect, otherwise it writes |*out_private_key| and returns 1. 191 * |mlkem_generate_key|. It fails and returns 0 if |seed_len| is incorrect, or
192 * if |*out_private_key| has not been initialized. otherwise it writes to
193 * |*out_private_key| and returns 1.
197 */ 194 */
198int MLKEM1024_private_key_from_seed( 195int mlkem_private_key_from_seed(const uint8_t *seed, size_t seed_len,
199 MLKEM_private_key *out_private_key, const uint8_t *seed, 196 MLKEM_private_key *out_private_key);
200 size_t seed_len);
201 197
202/* 198/*
203 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that 199 * mlkem_public_from_private sets |*out_public_key| to the public key that
204 * corresponds to |private_key|. (This is faster than parsing the output of 200 * corresponds to |*private_key|. (This is faster than parsing the output of
205 * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a 201 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key
206 * key that was just generated.) 202 * that was just generated.)
207 */ 203 */
208void MLKEM1024_public_from_private(const MLKEM_private_key *private_key, 204void mlkem_public_from_private(const MLKEM_private_key *private_key,
209 MLKEM_public_key *out_public_key); 205 MLKEM_public_key *out_public_key);
210 206
211/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */ 207
212#define MLKEM1024_CIPHERTEXT_BYTES 1568 208/* Encapsulation and decapsulation of secrets. */
213 209
214/* 210/*
215 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the 211 * mlkem_encap encrypts a random shared secret for |public_key|, writes the
216 * ciphertext to |out_ciphertext|, and writes the random shared secret to 212 * ciphertext to |out_ciphertext|, and writes the random shared secret to
217 * |out_shared_secret|. 213 * |out_shared_secret|.
218 */ 214 */
219void MLKEM1024_encap(const MLKEM_public_key *public_key, 215void mlkem_encap(const MLKEM_public_key *public_key,
220 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 216 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
221 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]); 217 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH]);
222
223 218
224/* 219/*
225 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using 220 * mlkem_decap decrypts a shared secret from |ciphertext| using |private_key|
226 * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is 221 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it
227 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid 222 * returns 0, otherwise it returns 1. If |ciphertext| is invalid,
228 * (but of the correct length), |out_shared_secret| is filled with a key that 223 * |out_shared_secret| is filled with a key that will always be the same for the
229 * will always be the same for the same |ciphertext| and |private_key|, but 224 * same |ciphertext| and |private_key|, but which appears to be random unless
230 * which appears to be random unless one has access to |private_key|. These 225 * one has access to |private_key|. These alternatives occur in constant time.
231 * alternatives occur in constant time. Any subsequent symmetric encryption 226 * Any subsequent symmetric encryption using |out_shared_secret| must use an
232 * using |out_shared_secret| must use an authenticated encryption scheme in 227 * authenticated encryption scheme in order to discover the decapsulation
233 * order to discover the decapsulation failure. 228 * failure.
234 */ 229 */
235int MLKEM1024_decap(const MLKEM_private_key *private_key, 230int mlkem_decap(const MLKEM_private_key *private_key,
236 const uint8_t *ciphertext, size_t ciphertext_len, 231 const uint8_t *ciphertext, size_t ciphertext_len,
237 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]); 232 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH]);
233
234
235/* Serialisation of keys. */
238 236
239/* 237/*
240 * Serialisation of ML-KEM-1024 keys. 238 * mlkem_marshal_public_key serializes |public_key| to |output| in the standard
241 * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard 239 * format for ML-KEM public keys. It returns one on success or zero on allocation
242 * format for ML-KEM-1024 public keys. It returns one on success or zero on 240 * error.
243 * allocation error.
244 */ 241 */
245int MLKEM1024_marshal_public_key(const MLKEM_public_key *public_key, 242int mlkem_marshal_public_key(const MLKEM_public_key *public_key,
246 uint8_t **output, size_t *output_len); 243 uint8_t **output, size_t *output_len);
247 244
248
249/* 245/*
250 * MLKEM1024_parse_public_key parses a public key, in the format generated by 246 * mlkem_parse_public_key parses a public key, in the format generated by
251 * |MLKEM1024_marshal_public_key|, from |in| and writes the result to 247 * |MLKEM_marshal_public_key|, from |input| and writes the result to
252 * |out_public_key|. It returns one on success or zero on parse error or if 248 * |out_public_key|. It returns one on success or zero on parse error or if
253 * there are trailing bytes in |in|. 249 * there are trailing bytes in |input|.
254 */ 250 */
255int MLKEM1024_parse_public_key(const uint8_t *input, size_t input_len, 251int mlkem_parse_public_key(const uint8_t *input, size_t input_len,
256 MLKEM_public_key *out_public_key); 252 MLKEM_public_key *out_public_key);
257 253
258
259/* 254/*
260 * MLKEM1024_parse_private_key parses a private key, in NIST's format for 255 * mlkem_parse_private_key parses a private key, in the format generated by
261 * private keys, from |in| and writes the result to |out_private_key|. It 256 * |MLKEM_marshal_private_key|, from |input| and writes the result to
262 * returns one on success or zero on parse error or if there are trailing bytes 257 * |out_private_key|. It returns one on success or zero on parse error or if
263 * in |in|. This format is verbose and should be avoided. Private keys should be 258 * there are trailing bytes in |input|. This formate is verbose and should be avoided.
264 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|. 259 * Private keys should be stored as seeds and parsed using |mlkem_private_key_from_seed|.
265 */ 260 */
266int MLKEM1024_parse_private_key(const uint8_t *input, size_t input_len, 261int mlkem_parse_private_key(const uint8_t *input, size_t input_len,
267 MLKEM_private_key *out_private_key); 262 MLKEM_private_key *out_private_key);
268
269
270/* XXXX Truly internal stuff below, also in need of de-duping */
271 263
272/*
273 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy
274 * necessary to encapsulate a secret. The entropy will be leaked to the
275 * decapsulating party.
276 */
277#define MLKEM_ENCAP_ENTROPY 32
278 264
279/* 265/* Functions that are only used for test purposes. */
280 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this
281 * object should never leave the address space since the format is unstable.
282 */
283struct MLKEM768_public_key {
284 union {
285 uint8_t bytes[512 * (3 + 9) + 32 + 32];
286 uint16_t alignment;
287 } opaque;
288};
289 266
290/* 267/*
291 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this 268 * mlkem_generate_key_external_entropy is a deterministic function to create a
292 * object should never leave the address space since the format is unstable.
293 */
294struct MLKEM768_private_key {
295 union {
296 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
297 uint16_t alignment;
298 } opaque;
299};
300
301/* Public opaque ML-KEM key structures. */
302
303#define MLKEM_PUBLIC_KEY_UNINITIALIZED 1
304#define MLKEM_PUBLIC_KEY_INITIALIZED 2
305#define MLKEM_PRIVATE_KEY_UNINITIALIZED 3
306#define MLKEM_PRIVATE_KEY_INITIALIZED 4
307
308struct MLKEM_public_key_st {
309 uint16_t rank;
310 int state;
311 struct MLKEM768_public_key *key_768;
312 struct MLKEM1024_public_key *key_1024;
313};
314
315struct MLKEM_private_key_st {
316 uint16_t rank;
317 int state;
318 struct MLKEM768_private_key *key_768;
319 struct MLKEM1024_private_key *key_1024;
320};
321
322/*
323 * MLKEM768_generate_key_external_entropy is a deterministic function to create a
324 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be 269 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be
325 * uniformly random generated. This function is should only be used for tests, 270 * uniformly random generated. This function is should only be used for tests,
326 * regular callers should use the non-deterministic |MLKEM_generate_key| 271 * regular callers should use the non-deterministic |MLKEM_generate_key|
327 * directly. 272 * directly.
328 */ 273 */
329int MLKEM768_generate_key_external_entropy( 274int mlkem_generate_key_external_entropy(
330 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 275 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
331 MLKEM_private_key *out_private_key, 276 MLKEM_private_key *out_private_key,
332 const uint8_t entropy[MLKEM_SEED_BYTES]); 277 const uint8_t entropy[MLKEM_SEED_LENGTH]);
333
334/*
335 * MLKEM768_PRIVATE_KEY_BYTES is the length of the data produced by
336 * |MLKEM768_marshal_private_key|.
337 */
338#define MLKEM768_PRIVATE_KEY_BYTES 2400
339 278
340/* 279/*
341 * MLKEM768_marshal_private_key serializes |private_key| to |out| in the standard 280 * mlkem_marshal_private_key serializes |private_key| to |out_private_key| in the standard
342 * format for ML-KEM private keys. It returns one on success or zero on 281 * format for ML-KEM private keys. It returns one on success or zero on
343 * allocation error. 282 * allocation error.
344 */ 283 */
345int MLKEM768_marshal_private_key(const MLKEM_private_key *private_key, 284int mlkem_marshal_private_key(const MLKEM_private_key *private_key,
346 uint8_t **out_private_key, size_t *out_private_key_len); 285 uint8_t **out_private_key, size_t *out_private_key_len);
347 286
348/* 287/*
349 * MLKEM768_encap_external_entropy behaves like |MLKEM768_encap|, but uses 288 * mlkem_encap_external_entropy behaves like |mlkem_encap|, but uses
350 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating 289 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating
351 * side will be able to recover |entropy| in full. This function should only be 290 * side will be able to recover |entropy| in full. This function should only be
352 * used for tests, regular callers should use the non-deterministic 291 * used for tests, regular callers should use the non-deterministic
353 * |MLKEM_encap| directly. 292 * |MLKEM_encap| directly.
354 */ 293 */
355void MLKEM768_encap_external_entropy( 294void mlkem_encap_external_entropy(
356 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 295 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
357 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 296 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH],
358 const MLKEM_public_key *public_key, 297 const MLKEM_public_key *public_key,
359 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 298 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
360 299
361
362/* 300/*
363 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this 301 * |MLKEM_encap_external_entropy| behaves exactly like the public |MLKEM_encap|
364 * object should never leave the address space since the format is unstable. 302 * with the entropy provided by the caller. It is directly called internally
365 */ 303 * and by tests.
366struct MLKEM1024_public_key {
367 union {
368 uint8_t bytes[512 * (4 + 16) + 32 + 32];
369 uint16_t alignment;
370 } opaque;
371};
372
373/*
374 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
375 * this object should never leave the address space since the format is
376 * unstable.
377 */
378struct MLKEM1024_private_key {
379 union {
380 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
381 uint16_t alignment;
382 } opaque;
383};
384
385
386/*
387 * MLKEM1024_generate_key_external_entropy is a deterministic function to create a
388 * pair of ML-KEM 1024 keys, using the supplied entropy. The entropy needs to be
389 * uniformly random generated. This function is should only be used for tests,
390 * regular callers should use the non-deterministic |MLKEM_generate_key|
391 * directly.
392 */
393int MLKEM1024_generate_key_external_entropy(
394 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
395 MLKEM_private_key *out_private_key,
396 const uint8_t entropy[MLKEM_SEED_BYTES]);
397
398/*
399 * MLKEM1024_PRIVATE_KEY_BYTES is the length of the data produced by
400 * |MLKEM1024_marshal_private_key|.
401 */ 304 */
402#define MLKEM1024_PRIVATE_KEY_BYTES 3168 305int MLKEM_encap_external_entropy(const MLKEM_public_key *public_key,
306 const uint8_t *entropy, uint8_t **out_ciphertext,
307 size_t *out_ciphertext_len, uint8_t **out_shared_secret,
308 size_t *out_shared_secret_len);
403 309
404/* 310/*
405 * MLKEM1024_marshal_private_key serializes |private_key| to |out| in the 311 * |MLKEM_generate_key_external_entropy| behaves exactly like the public
406 * standard format for ML-KEM private keys. It returns one on success or zero on 312 * |MLKEM_generate_key| with the entropy provided by the caller.
407 * allocation error. 313 * It is directly called internally and by tests.
408 */ 314 */
409int MLKEM1024_marshal_private_key( 315int MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key,
410 const MLKEM_private_key *private_key, uint8_t **out_private_key, 316 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
411 size_t *out_private_key_len); 317 const uint8_t *entropy);
412 318
413/*
414 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses
415 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating
416 * side will be able to recover |entropy| in full. This function should only be
417 * used for tests, regular callers should use the non-deterministic
418 * |MLKEM_encap| directly.
419 */
420void MLKEM1024_encap_external_entropy(
421 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
422 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
423 const MLKEM_public_key *public_key,
424 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
425 319
426__END_HIDDEN_DECLS 320__END_HIDDEN_DECLS
427 321