diff options
author | beck <> | 2025-09-05 23:30:12 +0000 |
---|---|---|
committer | beck <> | 2025-09-05 23:30:12 +0000 |
commit | 21ce890cad6ae67e0d52f7bfdc44579df2bfc032 (patch) | |
tree | 696ffc96af9e6fa399dc93af7325749db45458c5 /src/lib/libcrypto/mlkem/mlkem_internal.h | |
parent | dc98dc450acd1ba6a9a274662e55679f5c93e5fa (diff) | |
download | openbsd-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.h | 460 |
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 | */ | ||
46 | int | ||
47 | MLKEM_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 | /* | 38 | struct 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; |
57 | int | 43 | }; |
58 | MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key, | 44 | |
59 | uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len, | 45 | struct 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 | 81 | struct 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 | 91 | struct 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 | */ |
92 | int MLKEM768_generate_key( | 100 | struct 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 | */ |
102 | int MLKEM768_private_key_from_seed(const uint8_t *seed, size_t seed_len, | 109 | struct 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 | */ |
111 | void 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 | */ |
122 | void 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 | */ |
137 | int 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 | */ |
148 | int 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 | */ |
157 | int 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 | */ |
167 | int 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 | */ |
188 | int MLKEM1024_generate_key( | 185 | int 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 | */ |
198 | int MLKEM1024_private_key_from_seed( | 195 | int 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 | */ |
208 | void MLKEM1024_public_from_private(const MLKEM_private_key *private_key, | 204 | void 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 | */ |
219 | void MLKEM1024_encap(const MLKEM_public_key *public_key, | 215 | void 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 | */ |
235 | int MLKEM1024_decap(const MLKEM_private_key *private_key, | 230 | int 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 | */ |
245 | int MLKEM1024_marshal_public_key(const MLKEM_public_key *public_key, | 242 | int 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 | */ |
255 | int MLKEM1024_parse_public_key(const uint8_t *input, size_t input_len, | 251 | int 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 | */ |
266 | int MLKEM1024_parse_private_key(const uint8_t *input, size_t input_len, | 261 | int 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 | */ | ||
283 | struct 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 | */ | ||
294 | struct 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 | |||
308 | struct 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 | |||
315 | struct 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 | */ |
329 | int MLKEM768_generate_key_external_entropy( | 274 | int 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 | */ |
345 | int MLKEM768_marshal_private_key(const MLKEM_private_key *private_key, | 284 | int 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 | */ |
355 | void MLKEM768_encap_external_entropy( | 294 | void 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. |
366 | struct 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 | */ | ||
378 | struct 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 | */ | ||
393 | int 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 | 305 | int 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 | */ |
409 | int MLKEM1024_marshal_private_key( | 315 | int 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 | */ | ||
420 | void 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 | ||