summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem_internal.h
diff options
context:
space:
mode:
authorbeck <>2025-08-14 15:48:48 +0000
committerbeck <>2025-08-14 15:48:48 +0000
commit6452fa9fc6f33dac80ee572764b9fe29a469f8ce (patch)
tree0956ae670e4f193442bcf99d2b1fb70a43a6b5b5 /src/lib/libcrypto/mlkem/mlkem_internal.h
parent9bef27f78e41e8026f1d588e4e36e385061f3deb (diff)
downloadopenbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.tar.gz
openbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.tar.bz2
openbsd-6452fa9fc6f33dac80ee572764b9fe29a469f8ce.zip
Add a reasonable ML-KEM API for public use.
Adapt the tests to use this API. This does not yet make the symbols public in Symbols.list which will happen shortly with a bump. This includes some partial rototilling of the non-public interfaces which will be shortly continued when the internal code is deduplicated to not have multiple copies for ML-KEM 768 and ML-KEM 1024 (which is just an artifact of unravelling the boring C++ code). ok jsing@, tb@
Diffstat (limited to 'src/lib/libcrypto/mlkem/mlkem_internal.h')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem_internal.h331
1 files changed, 323 insertions, 8 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem_internal.h b/src/lib/libcrypto/mlkem/mlkem_internal.h
index 1e051970a8..776f8aac17 100644
--- a/src/lib/libcrypto/mlkem/mlkem_internal.h
+++ b/src/lib/libcrypto/mlkem/mlkem_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: mlkem_internal.h,v 1.7 2025/05/20 00:33:40 beck Exp $ */ 1/* $OpenBSD: mlkem_internal.h,v 1.8 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2023, Google Inc. 3 * Copyright (c) 2023, Google Inc.
4 * 4 *
@@ -26,6 +26,253 @@ extern "C" {
26#endif 26#endif
27 27
28__BEGIN_HIDDEN_DECLS 28__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
35/*
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
41/*
42 * |MLKEM_encap_external_entropy| behaves exactly like the public |MLKEM_encap|
43 * with the entropy provided by the caller. It is directly called internally
44 * and by tests.
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
52/*
53 * |MLKEM_generate_key_external_entropy| behaves exactly like the public
54 * |MLKEM_generate_key| with the entropy provided by the caller.
55 * It is directly called internally and by tests.
56 */
57int
58MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key,
59 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
60 const uint8_t *entropy);
61/*
62 * Marshals a private key to encoded format, used for NIST tests.
63 */
64int MLKEM_marshal_private_key(const MLKEM_private_key *private_key,
65 uint8_t **out, size_t *out_len);
66
67/*
68 * ML-KEM-768
69 *
70 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
71 * https://csrc.nist.gov/pubs/fips/204/final
72 */
73
74/*
75 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public
76 * key.
77 */
78#define MLKEM768_PUBLIC_KEY_BYTES 1184
79
80/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */
81#define MLKEM_SEED_BYTES 64
82
83/*
84 * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared
85 * secret. Although the round-3 specification has a variable-length output, the
86 * final ML-KEM construction is expected to use a fixed 32-byte output. To
87 * simplify the future transition, we apply the same restriction.
88 */
89#define MLKEM_SHARED_SECRET_BYTES 32
90
91/*
92 * MLKEM_generate_key generates a random public/private key pair, writes the
93 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
94 * the private key. If |optional_out_seed| is not NULL then the seed used to
95 * generate the private key is written to it.
96 */
97int MLKEM768_generate_key(
98 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
99 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
100 MLKEM_private_key *out_private_key);
101
102/*
103 * MLKEM768_private_key_from_seed derives a private key from a seed that was
104 * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is
105 * incorrect, otherwise it writes |*out_private_key| and returns 1.
106 */
107int MLKEM768_private_key_from_seed(const uint8_t *seed, size_t seed_len,
108 MLKEM_private_key *out_private_key);
109
110/*
111 * MLKEM_public_from_private sets |*out_public_key| to the public key that
112 * corresponds to |private_key|. (This is faster than parsing the output of
113 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key
114 * that was just generated.)
115 */
116void MLKEM768_public_from_private(const MLKEM_private_key *private_key,
117 MLKEM_public_key *out_public_key);
118
119/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
120#define MLKEM768_CIPHERTEXT_BYTES 1088
121
122/*
123 * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the
124 * ciphertext to |out_ciphertext|, and writes the random shared secret to
125 * |out_shared_secret|.
126 */
127void MLKEM768_encap(const MLKEM_public_key *public_key,
128 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
129 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
130
131/*
132 * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key|
133 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it
134 * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid,
135 * |out_shared_secret| is filled with a key that will always be the same for the
136 * same |ciphertext| and |private_key|, but which appears to be random unless
137 * one has access to |private_key|. These alternatives occur in constant time.
138 * Any subsequent symmetric encryption using |out_shared_secret| must use an
139 * authenticated encryption scheme in order to discover the decapsulation
140 * failure.
141 */
142int MLKEM768_decap(const MLKEM_private_key *private_key,
143 const uint8_t *ciphertext, size_t ciphertext_len,
144 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
145
146/* Serialisation of keys. */
147
148/*
149 * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard
150 * format for ML-KEM public keys. It returns one on success or zero on allocation
151 * error.
152 */
153int MLKEM768_marshal_public_key(const MLKEM_public_key *public_key,
154 uint8_t **output, size_t *output_len);
155
156/*
157 * MLKEM768_parse_public_key parses a public key, in the format generated by
158 * |MLKEM_marshal_public_key|, from |in| and writes the result to
159 * |out_public_key|. It returns one on success or zero on parse error or if
160 * there are trailing bytes in |in|.
161 */
162int MLKEM768_parse_public_key(const uint8_t *input, size_t input_len,
163 MLKEM_public_key *out_public_key);
164
165/*
166 * MLKEM_parse_private_key parses a private key, in the format generated by
167 * |MLKEM_marshal_private_key|, from |in| and writes the result to
168 * |out_private_key|. It returns one on success or zero on parse error or if
169 * there are trailing bytes in |in|. This formate is verbose and should be avoided.
170 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
171 */
172int MLKEM768_parse_private_key(const uint8_t *input, size_t input_len,
173 MLKEM_private_key *out_private_key);
174
175/*
176 * ML-KEM-1024
177 *
178 * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible.
179 */
180
181/*
182 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
183 * public key.
184 */
185#define MLKEM1024_PUBLIC_KEY_BYTES 1568
186
187/*
188 * MLKEM1024_generate_key generates a random public/private key pair, writes the
189 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
190 * the private key. If |optional_out_seed| is not NULL then the seed used to
191 * generate the private key is written to it.
192 */
193int MLKEM1024_generate_key(
194 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
195 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
196 MLKEM_private_key *out_private_key);
197
198/*
199 * MLKEM1024_private_key_from_seed derives a private key from a seed that was
200 * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len|
201 * is incorrect, otherwise it writes |*out_private_key| and returns 1.
202 */
203int MLKEM1024_private_key_from_seed(
204 MLKEM_private_key *out_private_key, const uint8_t *seed,
205 size_t seed_len);
206
207/*
208 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that
209 * corresponds to |private_key|. (This is faster than parsing the output of
210 * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a
211 * key that was just generated.)
212 */
213void MLKEM1024_public_from_private(const MLKEM_private_key *private_key,
214 MLKEM_public_key *out_public_key);
215
216/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
217#define MLKEM1024_CIPHERTEXT_BYTES 1568
218
219/*
220 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the
221 * ciphertext to |out_ciphertext|, and writes the random shared secret to
222 * |out_shared_secret|.
223 */
224void MLKEM1024_encap(const MLKEM_public_key *public_key,
225 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
226 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
227
228
229/*
230 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using
231 * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is
232 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid
233 * (but of the correct length), |out_shared_secret| is filled with a key that
234 * will always be the same for the same |ciphertext| and |private_key|, but
235 * which appears to be random unless one has access to |private_key|. These
236 * alternatives occur in constant time. Any subsequent symmetric encryption
237 * using |out_shared_secret| must use an authenticated encryption scheme in
238 * order to discover the decapsulation failure.
239 */
240int MLKEM1024_decap(const MLKEM_private_key *private_key,
241 const uint8_t *ciphertext, size_t ciphertext_len,
242 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES]);
243
244/*
245 * Serialisation of ML-KEM-1024 keys.
246 * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard
247 * format for ML-KEM-1024 public keys. It returns one on success or zero on
248 * allocation error.
249 */
250int MLKEM1024_marshal_public_key(const MLKEM_public_key *public_key,
251 uint8_t **output, size_t *output_len);
252
253
254/*
255 * MLKEM1024_parse_public_key parses a public key, in the format generated by
256 * |MLKEM1024_marshal_public_key|, from |in| and writes the result to
257 * |out_public_key|. It returns one on success or zero on parse error or if
258 * there are trailing bytes in |in|.
259 */
260int MLKEM1024_parse_public_key(const uint8_t *input, size_t input_len,
261 MLKEM_public_key *out_public_key);
262
263
264/*
265 * MLKEM1024_parse_private_key parses a private key, in NIST's format for
266 * private keys, from |in| and writes the result to |out_private_key|. It
267 * returns one on success or zero on parse error or if there are trailing bytes
268 * in |in|. This format is verbose and should be avoided. Private keys should be
269 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|.
270 */
271int MLKEM1024_parse_private_key(const uint8_t *input, size_t input_len,
272 MLKEM_private_key *out_private_key);
273
274
275/* XXXX Truly internal stuff below, also in need of de-duping */
29 276
30/* 277/*
31 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy 278 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy
@@ -35,6 +282,49 @@ __BEGIN_HIDDEN_DECLS
35#define MLKEM_ENCAP_ENTROPY 32 282#define MLKEM_ENCAP_ENTROPY 32
36 283
37/* 284/*
285 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this
286 * object should never leave the address space since the format is unstable.
287 */
288struct MLKEM768_public_key {
289 union {
290 uint8_t bytes[512 * (3 + 9) + 32 + 32];
291 uint16_t alignment;
292 } opaque;
293};
294
295/*
296 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
297 * object should never leave the address space since the format is unstable.
298 */
299struct MLKEM768_private_key {
300 union {
301 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
302 uint16_t alignment;
303 } opaque;
304};
305
306/* Public opaque ML-KEM key structures. */
307
308#define MLKEM_PUBLIC_KEY_UNINITIALIZED 1
309#define MLKEM_PUBLIC_KEY_INITIALIZED 2
310#define MLKEM_PRIVATE_KEY_UNINITIALIZED 3
311#define MLKEM_PRIVATE_KEY_INITIALIZED 4
312
313struct MLKEM_public_key_st {
314 uint16_t rank;
315 int state;
316 struct MLKEM768_public_key *key_768;
317 struct MLKEM1024_public_key *key_1024;
318};
319
320struct MLKEM_private_key_st {
321 uint16_t rank;
322 int state;
323 struct MLKEM768_private_key *key_768;
324 struct MLKEM1024_private_key *key_1024;
325};
326
327/*
38 * MLKEM768_generate_key_external_entropy is a deterministic function to create a 328 * MLKEM768_generate_key_external_entropy is a deterministic function to create a
39 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be 329 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be
40 * uniformly random generated. This function is should only be used for tests, 330 * uniformly random generated. This function is should only be used for tests,
@@ -43,7 +333,7 @@ __BEGIN_HIDDEN_DECLS
43 */ 333 */
44int MLKEM768_generate_key_external_entropy( 334int MLKEM768_generate_key_external_entropy(
45 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 335 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
46 struct MLKEM768_private_key *out_private_key, 336 MLKEM_private_key *out_private_key,
47 const uint8_t entropy[MLKEM_SEED_BYTES]); 337 const uint8_t entropy[MLKEM_SEED_BYTES]);
48 338
49/* 339/*
@@ -57,11 +347,11 @@ int MLKEM768_generate_key_external_entropy(
57 * format for ML-KEM private keys. It returns one on success or zero on 347 * format for ML-KEM private keys. It returns one on success or zero on
58 * allocation error. 348 * allocation error.
59 */ 349 */
60int MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key, 350int MLKEM768_marshal_private_key(const MLKEM_private_key *private_key,
61 uint8_t **out_private_key, size_t *out_private_key_len); 351 uint8_t **out_private_key, size_t *out_private_key_len);
62 352
63/* 353/*
64 * MLKEM_encap_external_entropy behaves like |MLKEM_encap|, but uses 354 * MLKEM768_encap_external_entropy behaves like |MLKEM768_encap|, but uses
65 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating 355 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating
66 * side will be able to recover |entropy| in full. This function should only be 356 * side will be able to recover |entropy| in full. This function should only be
67 * used for tests, regular callers should use the non-deterministic 357 * used for tests, regular callers should use the non-deterministic
@@ -70,9 +360,34 @@ int MLKEM768_marshal_private_key(const struct MLKEM768_private_key *private_key,
70void MLKEM768_encap_external_entropy( 360void MLKEM768_encap_external_entropy(
71 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 361 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
72 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 362 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
73 const struct MLKEM768_public_key *public_key, 363 const MLKEM_public_key *public_key,
74 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 364 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
75 365
366
367/*
368 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
369 * object should never leave the address space since the format is unstable.
370 */
371struct MLKEM1024_public_key {
372 union {
373 uint8_t bytes[512 * (4 + 16) + 32 + 32];
374 uint16_t alignment;
375 } opaque;
376};
377
378/*
379 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
380 * this object should never leave the address space since the format is
381 * unstable.
382 */
383struct MLKEM1024_private_key {
384 union {
385 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
386 uint16_t alignment;
387 } opaque;
388};
389
390
76/* 391/*
77 * MLKEM1024_generate_key_external_entropy is a deterministic function to create a 392 * MLKEM1024_generate_key_external_entropy is a deterministic function to create a
78 * pair of ML-KEM 1024 keys, using the supplied entropy. The entropy needs to be 393 * pair of ML-KEM 1024 keys, using the supplied entropy. The entropy needs to be
@@ -82,7 +397,7 @@ void MLKEM768_encap_external_entropy(
82 */ 397 */
83int MLKEM1024_generate_key_external_entropy( 398int MLKEM1024_generate_key_external_entropy(
84 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 399 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
85 struct MLKEM1024_private_key *out_private_key, 400 MLKEM_private_key *out_private_key,
86 const uint8_t entropy[MLKEM_SEED_BYTES]); 401 const uint8_t entropy[MLKEM_SEED_BYTES]);
87 402
88/* 403/*
@@ -97,7 +412,7 @@ int MLKEM1024_generate_key_external_entropy(
97 * allocation error. 412 * allocation error.
98 */ 413 */
99int MLKEM1024_marshal_private_key( 414int MLKEM1024_marshal_private_key(
100 const struct MLKEM1024_private_key *private_key, uint8_t **out_private_key, 415 const MLKEM_private_key *private_key, uint8_t **out_private_key,
101 size_t *out_private_key_len); 416 size_t *out_private_key_len);
102 417
103/* 418/*
@@ -110,7 +425,7 @@ int MLKEM1024_marshal_private_key(
110void MLKEM1024_encap_external_entropy( 425void MLKEM1024_encap_external_entropy(
111 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 426 uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
112 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 427 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
113 const struct MLKEM1024_public_key *public_key, 428 const MLKEM_public_key *public_key,
114 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 429 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]);
115 430
116__END_HIDDEN_DECLS 431__END_HIDDEN_DECLS