xref: /openbsd-src/lib/libcrypto/mlkem/mlkem.h (revision ef1019e6227dff1921b5c4f12c53f342b6d7f900)
1 /*	$OpenBSD: mlkem.h,v 1.4 2024/12/19 23:52:26 tb Exp $ */
2 /*
3  * Copyright (c) 2024, Google Inc.
4  *
5  * 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  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
12  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
14  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
15  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #ifndef OPENSSL_HEADER_MLKEM_H
19 #define OPENSSL_HEADER_MLKEM_H
20 
21 #include <sys/types.h>
22 #include <stdint.h>
23 
24 #if defined(__cplusplus)
25 extern "C" {
26 #endif
27 
28 /* Hack for now */
29 struct cbs_st;
30 struct cbb_st;
31 
32 /*
33  * ML-KEM-768
34  *
35  * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
36  * https://csrc.nist.gov/pubs/fips/204/final
37  */
38 
39 /*
40  * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this
41  * object should never leave the address space since the format is unstable.
42  */
43 struct MLKEM768_public_key {
44 	union {
45 		uint8_t bytes[512 * (3 + 9) + 32 + 32];
46 		uint16_t alignment;
47 	} opaque;
48 };
49 
50 /*
51  * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
52  * object should never leave the address space since the format is unstable.
53  */
54 struct MLKEM768_private_key {
55 	union {
56 		uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
57 		uint16_t alignment;
58 	} opaque;
59 };
60 
61 /*
62  * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public
63  * key.
64  */
65 #define MLKEM768_PUBLIC_KEY_BYTES 1184
66 
67 /* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */
68 #define MLKEM_SEED_BYTES 64
69 
70 /*
71  *  MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared
72  * secret. Although the round-3 specification has a variable-length output, the
73  * final ML-KEM construction is expected to use a fixed 32-byte output. To
74  * simplify the future transition, we apply the same restriction.
75  */
76 #define MLKEM_SHARED_SECRET_BYTES 32
77 
78 /*
79  * MLKEM_generate_key generates a random public/private key pair, writes the
80  * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
81  * the private key. If |optional_out_seed| us not NULL then te seed used to
82  * generate te private key is written to it.
83  */
84 void MLKEM768_generate_key(
85     uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
86     uint8_t optional_out_seed[MLKEM_SEED_BYTES],
87     struct MLKEM768_private_key *out_private_key);
88 
89 /*
90  * MLKEM768_private_key_from_seed derives a private key from a seed that was
91  * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is
92  * incorrect, otherwise it writes |*out_private_key| and returns 1.
93  */
94 int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key,
95     const uint8_t *seed, size_t seed_len);
96 
97 /*
98  * MLKEM_public_from_private sets |*out_public_key| to the public key that
99  * corresponds to |private_key|. (This is faster than parsing the output of
100  * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key
101  * that was just generated.)
102  */
103 void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key,
104     const struct MLKEM768_private_key *private_key);
105 
106 /* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
107 #define MLKEM768_CIPHERTEXT_BYTES 1088
108 
109 /*
110  * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the
111  * ciphertext to |out_ciphertext|, and writes the random shared secret to
112  * |out_shared_secret|.
113  */
114 void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES],
115     uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
116     const struct MLKEM768_public_key *public_key);
117 
118 /*
119  * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key|
120  * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it
121  * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid,
122  * |out_shared_secret| is filled with a key that will always be the same for the
123  * same |ciphertext| and |private_key|, but which appears to be random unless
124  * one has access to |private_key|. These alternatives occur in constant time.
125  * Any subsequent symmetric encryption using |out_shared_secret| must use an
126  * authenticated encryption scheme in order to discover the decapsulation
127  * failure.
128  */
129 int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
130     const uint8_t *ciphertext, size_t ciphertext_len,
131     const struct MLKEM768_private_key *private_key);
132 
133 /* Serialisation of keys. */
134 
135 /*
136  * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard
137  * format for ML-KEM public keys. It returns one on success or zero on allocation
138  * error.
139  */
140 int MLKEM768_marshal_public_key(struct cbb_st *out,
141     const struct MLKEM768_public_key *public_key);
142 
143 /*
144  * MLKEM768_parse_public_key parses a public key, in the format generated by
145  * |MLKEM_marshal_public_key|, from |in| and writes the result to
146  * |out_public_key|. It returns one on success or zero on parse error or if
147  * there are trailing bytes in |in|.
148  */
149 int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key,
150     struct cbs_st *in);
151 
152 /*
153  * MLKEM_parse_private_key parses a private key, in the format generated by
154  * |MLKEM_marshal_private_key|, from |in| and writes the result to
155  * |out_private_key|. It returns one on success or zero on parse error or if
156  * there are trailing bytes in |in|. This formate is verbose and should be avoided.
157  * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
158  */
159 int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
160     struct cbs_st *in);
161 
162 /*
163  * ML-KEM-1024
164  *
165  * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible.
166  */
167 
168 /*
169  * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
170  * object should never leave the address space since the format is unstable.
171  */
172 struct MLKEM1024_public_key {
173 	union {
174 		uint8_t bytes[512 * (4 + 16) + 32 + 32];
175 		uint16_t alignment;
176 	} opaque;
177 };
178 
179 /*
180  * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
181  * this object should never leave the address space since the format is
182  * unstable.
183  */
184 struct MLKEM1024_private_key {
185 	union {
186 		uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
187 		uint16_t alignment;
188 	} opaque;
189 };
190 
191 /*
192  * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
193  * public key.
194  */
195 #define MLKEM1024_PUBLIC_KEY_BYTES 1568
196 
197 /*
198  * MLKEM1024_generate_key generates a random public/private key pair, writes the
199  * encoded public key to |out_encoded_public_key| and sets |out_private_key| to
200  * the private key. If |optional_out_seed| is not NULL then the seed used to
201  * generate the private key is written to it.
202  */
203 void MLKEM1024_generate_key(
204     uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES],
205     uint8_t optional_out_seed[MLKEM_SEED_BYTES],
206     struct MLKEM1024_private_key *out_private_key);
207 
208 /*
209  * MLKEM1024_private_key_from_seed derives a private key from a seed that was
210  * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len|
211  * is incorrect, otherwise it writes |*out_private_key| and returns 1.
212  */
213 int MLKEM1024_private_key_from_seed(
214     struct MLKEM1024_private_key *out_private_key, const uint8_t *seed,
215     size_t seed_len);
216 
217 /*
218  * MLKEM1024_public_from_private sets |*out_public_key| to the public key that
219  * corresponds to |private_key|. (This is faster than parsing the output of
220  * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a
221  * key that was just generated.)
222  */
223 void MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key,
224     const struct MLKEM1024_private_key *private_key);
225 
226 /* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
227 #define MLKEM1024_CIPHERTEXT_BYTES 1568
228 
229 /*
230  * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the
231  * ciphertext to |out_ciphertext|, and writes the random shared secret to
232  * |out_shared_secret|.
233  */
234 void MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES],
235     uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
236     const struct MLKEM1024_public_key *public_key);
237 
238 /*
239  * MLKEM1024_decap decrypts a shared secret from |ciphertext| using
240  * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is
241  * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid
242  * (but of the correct length), |out_shared_secret| is filled with a key that
243  * will always be the same for the same |ciphertext| and |private_key|, but
244  * which appears to be random unless one has access to |private_key|. These
245  * alternatives occur in constant time. Any subsequent symmetric encryption
246  * using |out_shared_secret| must use an authenticated encryption scheme in
247  * order to discover the decapsulation failure.
248  */
249 int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
250     const uint8_t *ciphertext, size_t ciphertext_len,
251     const struct MLKEM1024_private_key *private_key);
252 
253 /*
254  * Serialisation of ML-KEM-1024 keys.
255  * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard
256  * format for ML-KEM-1024 public keys. It returns one on success or zero on
257  * allocation error.
258  */
259 int MLKEM1024_marshal_public_key(struct cbb_st *out,
260     const struct MLKEM1024_public_key *public_key);
261 
262 /*
263  * MLKEM1024_parse_public_key parses a public key, in the format generated by
264  * |MLKEM1024_marshal_public_key|, from |in| and writes the result to
265  * |out_public_key|. It returns one on success or zero on parse error or if
266  * there are trailing bytes in |in|.
267  */
268 int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key,
269     struct cbs_st *in);
270 
271 /*
272  * MLKEM1024_parse_private_key parses a private key, in NIST's format for
273  * private keys, from |in| and writes the result to |out_private_key|. It
274  * returns one on success or zero on parse error or if there are trailing bytes
275  * in |in|. This format is verbose and should be avoided. Private keys should be
276  * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|.
277  */
278 int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key,
279     struct cbs_st *in);
280 
281 #if defined(__cplusplus)
282 }
283 #endif
284 
285 #endif  /* OPENSSL_HEADER_MLKEM_H */
286