diff options
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 | ||