summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/mlkem/mlkem.h')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem.h329
1 files changed, 139 insertions, 190 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem.h b/src/lib/libcrypto/mlkem/mlkem.h
index a2c5d7fed0..31d4858195 100644
--- a/src/lib/libcrypto/mlkem/mlkem.h
+++ b/src/lib/libcrypto/mlkem/mlkem.h
@@ -1,6 +1,6 @@
1/* $OpenBSD: mlkem.h,v 1.6 2025/05/19 06:47:40 beck Exp $ */ 1/* $OpenBSD: mlkem.h,v 1.7 2025/08/14 15:48:48 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2024, Google Inc. 3 * Copyright (c) 2025 Bob Beck <beck@obtuse.com>
4 * 4 *
5 * Permission to use, copy, modify, and/or distribute this software for any 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 6 * purpose with or without fee is hereby granted, provided that the above
@@ -26,253 +26,202 @@ extern "C" {
26#endif 26#endif
27 27
28/* 28/*
29 * ML-KEM-768 29 * ML-KEM constants
30 *
31 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from
32 * https://csrc.nist.gov/pubs/fips/204/final
33 */ 30 */
34 31
35/* 32#define RANK768 3
36 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this 33#define RANK1024 4
37 * object should never leave the address space since the format is unstable.
38 */
39struct MLKEM768_public_key {
40 union {
41 uint8_t bytes[512 * (3 + 9) + 32 + 32];
42 uint16_t alignment;
43 } opaque;
44};
45
46/*
47 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this
48 * object should never leave the address space since the format is unstable.
49 */
50struct MLKEM768_private_key {
51 union {
52 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
53 uint16_t alignment;
54 } opaque;
55};
56 34
57/* 35/*
58 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 36 * ML-KEM keys
59 * key.
60 */ 37 */
61#define MLKEM768_PUBLIC_KEY_BYTES 1184
62 38
63/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ 39typedef struct MLKEM_private_key_st MLKEM_private_key;
64#define MLKEM_SEED_BYTES 64 40typedef struct MLKEM_public_key_st MLKEM_public_key;
65 41
66/* 42/*
67 * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared 43 * MLKEM_private_key_new allocates a new uninitialized ML-KEM private key for
68 * secret. Although the round-3 specification has a variable-length output, the 44 * |rank|, which must be RANK768 or RANK1024. It returns a pointer to an
69 * final ML-KEM construction is expected to use a fixed 32-byte output. To 45 * allocated structure suitable for holding a generated private key of the
70 * simplify the future transition, we apply the same restriction. 46 * corresponding rank on success, NULL is returned on failure. The caller is
47 * responsible for deallocating the resulting key with |MLKEM_private_key_free|.
71 */ 48 */
72#define MLKEM_SHARED_SECRET_BYTES 32 49MLKEM_private_key *MLKEM_private_key_new(int rank);
73 50
74/* 51/*
75 * MLKEM_generate_key generates a random public/private key pair, writes the 52 * MLKEM_private_key_free zeroes and frees all memory for |key| if |key| is
76 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 53 * non NULL. If |key| is NULL it does nothing and returns.
77 * the private key. If |optional_out_seed| is not NULL then the seed used to
78 * generate the private key is written to it.
79 */ 54 */
80int MLKEM768_generate_key( 55void MLKEM_private_key_free(MLKEM_private_key *key);
81 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES],
82 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
83 struct MLKEM768_private_key *out_private_key);
84 56
85/* 57/*
86 * MLKEM768_private_key_from_seed derives a private key from a seed that was 58 * MLKEM_private_key_encoded_length the number of bytes used by the encoded form
87 * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is 59 * of |key|. Thie corresponds to the length of the buffer allocated for the
88 * incorrect, otherwise it writes |*out_private_key| and returns 1. 60 * encoded_public_key from |MLKEM_marshal_private_key|. Zero is returned if
61 * |key| is NULL or has an invalid rank.
89 */ 62 */
90int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, 63size_t MLKEM_private_key_encoded_length(const MLKEM_private_key *key);
91 const uint8_t *seed, size_t seed_len);
92 64
93/* 65/*
94 * MLKEM_public_from_private sets |*out_public_key| to the public key that 66 * MLKEM_private_key_ciphertext_length returns the number of bytes of ciphertext
95 * corresponds to |private_key|. (This is faster than parsing the output of 67 * required to decrypt a shared secret with |key| using |MLKEM_decap|. Zero is
96 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key 68 * returned if |key| is NULL or has an invalid rank.
97 * that was just generated.)
98 */ 69 */
99void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, 70size_t MLKEM_private_key_ciphertext_length(const MLKEM_private_key *key);
100 const struct MLKEM768_private_key *private_key);
101
102/* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */
103#define MLKEM768_CIPHERTEXT_BYTES 1088
104 71
105/* 72/*
106 * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the 73 * MLKEM_public_key_new allocates a new uninitialized ML-KEM public key for
107 * ciphertext to |out_ciphertext|, and writes the random shared secret to 74 * |rank|, which must be RANK768 or RANK1024. It returns a pointer to an
108 * |out_shared_secret|. 75 * allocated structure suitable for holding a generated public key of the
76 * corresponding rank on success, NULL is returned on failure. The caller is
77 * responsible for deallocating the resulting key with |MLKEM_public_key_free|.
109 */ 78 */
110void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 79MLKEM_public_key *MLKEM_public_key_new(int rank);
111 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
112 const struct MLKEM768_public_key *public_key);
113 80
114/* 81/*
115 * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key| 82 * MLKEM_public_key_free zeros and deallocates all memory for |key| if |key| is
116 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it 83 * non NULL. If |key| is NULL it does nothing and returns.
117 * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid,
118 * |out_shared_secret| is filled with a key that will always be the same for the
119 * same |ciphertext| and |private_key|, but which appears to be random unless
120 * one has access to |private_key|. These alternatives occur in constant time.
121 * Any subsequent symmetric encryption using |out_shared_secret| must use an
122 * authenticated encryption scheme in order to discover the decapsulation
123 * failure.
124 */ 84 */
125int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 85void MLKEM_public_key_free(MLKEM_public_key *key);
126 const uint8_t *ciphertext, size_t ciphertext_len,
127 const struct MLKEM768_private_key *private_key);
128
129/* Serialisation of keys. */
130 86
131/* 87/*
132 * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard 88 * MLKEM_public_key_encoded_length the number of bytes used by the encoded form
133 * format for ML-KEM public keys. It returns one on success or zero on allocation 89 * of |key|. Thie corresponds to the length of the buffer allocated for the
134 * error. 90 * encoded_public_key from |MLKEM_generate_key| or |MLKEM_marshal_public_key|.
91 * Zero is returned if |key| is NULL or has an invalid rank.
135 */ 92 */
136int MLKEM768_marshal_public_key(uint8_t **output, size_t *output_len, 93size_t MLKEM_public_key_encoded_length(const MLKEM_public_key *key);
137 const struct MLKEM768_public_key *public_key);
138 94
139/* 95/*
140 * MLKEM768_parse_public_key parses a public key, in the format generated by 96 * MLKEM_public_key_cipertext_length returns the number of bytes produced as the
141 * |MLKEM_marshal_public_key|, from |in| and writes the result to 97 * ciphertext when encrypting a shared secret with |key| using |MLKEM_encap|. Zero
142 * |out_public_key|. It returns one on success or zero on parse error or if 98 * is returned if |key| is NULL or has an invalid rank.
143 * there are trailing bytes in |in|.
144 */ 99 */
145int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, 100size_t MLKEM_public_key_ciphertext_length(const MLKEM_public_key *key);
146 const uint8_t *input, size_t input_len);
147 101
148/* 102/*
149 * MLKEM_parse_private_key parses a private key, in the format generated by 103 * ML-KEM operations
150 * |MLKEM_marshal_private_key|, from |in| and writes the result to
151 * |out_private_key|. It returns one on success or zero on parse error or if
152 * there are trailing bytes in |in|. This formate is verbose and should be avoided.
153 * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|.
154 */ 104 */
155int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
156 const uint8_t *input, size_t input_len);
157 105
158/* 106/*
159 * ML-KEM-1024 107 * MLKEM_generate_key generates a random private/public key pair, initializing
108 * |private_key|. It returns one on success, and zero on failure or error.
109 * |private_key| must be a new uninitialized key. |*out_encoded_public_key| and
110 * |*out_optional_seed|, if provided, must have the value of NULL. On success, a
111 * pointer to the encoded public key of the correct size for |key| is returned
112 * in |out_encoded_public_key|, and the length in bytes of
113 * |*out_encoded_public_key| is returned in |out_encoded_public_key_len|. If
114 * |out_optional_seed| is not NULL, a pointer to the seed used to generate the
115 * private key is returned in |*out_optional_seed| and the length in bytes of
116 * the seed is returned in |*out_optional_seed_len|. The caller is responsible
117 * for freeing the values returned in |out_encoded_public_key|, and
118 * |out_optional_seed|.
160 * 119 *
161 * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible. 120 * In the event a private key needs to be saved, The normal best practice is to
162 */ 121 * save |out_optional_seed| as the private key, along with the ML-KEM rank value.
163 122 * An MLKEM_private_key of the correct rank can then be constructed using
164/* 123 * |MLKEM_private_key_from_seed|.
165 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this
166 * object should never leave the address space since the format is unstable.
167 */
168struct MLKEM1024_public_key {
169 union {
170 uint8_t bytes[512 * (4 + 16) + 32 + 32];
171 uint16_t alignment;
172 } opaque;
173};
174
175/*
176 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of
177 * this object should never leave the address space since the format is
178 * unstable.
179 */
180struct MLKEM1024_private_key {
181 union {
182 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32];
183 uint16_t alignment;
184 } opaque;
185};
186
187/*
188 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024
189 * public key.
190 */ 124 */
191#define MLKEM1024_PUBLIC_KEY_BYTES 1568 125int MLKEM_generate_key(MLKEM_private_key *private_key,
126 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len,
127 uint8_t **out_optional_seed, size_t *out_optional_seed_len);
192 128
193/* 129/*
194 * MLKEM1024_generate_key generates a random public/private key pair, writes the 130 * MLKEM_private_key_from_seed derives a private key from a seed that was
195 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 131 * generated by |MLKEM_generate_key| initializing |private_key|. It returns one
196 * the private key. If |optional_out_seed| is not NULL then the seed used to 132 * on success, and zero on failure or error. |private_key| must be a new
197 * generate the private key is written to it. 133 * uninitialized key. |seed_len| must be MLKEM_SEED_LENGTH.
134 *
135 * For |private_key| to match the key generated by |MLKEM_generate_key|,
136 * |private_key| must have been created with the same rank as used when generating
137 * the key.
198 */ 138 */
199int MLKEM1024_generate_key( 139int MLKEM_private_key_from_seed(MLKEM_private_key *private_key,
200 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 140 const uint8_t *seed, size_t seed_len);
201 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
202 struct MLKEM1024_private_key *out_private_key);
203 141
204/* 142/*
205 * MLKEM1024_private_key_from_seed derives a private key from a seed that was 143 * MLKEM_public_from_private initializes |public_key| with the public key that
206 * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len| 144 * corresponds to |private_key|. It returns one on success and zero on
207 * is incorrect, otherwise it writes |*out_private_key| and returns 1. 145 * error. This is faster than parsing the output of |MLKEM_generate_key| if, for
146 * some reason, you need to encapsulate to a key that was just
147 * generated. |private key| must be a new uninitialized key, of the same rank as
148 * |public_key|.
208 */ 149 */
209int MLKEM1024_private_key_from_seed( 150int MLKEM_public_from_private(const MLKEM_private_key *private_key,
210 struct MLKEM1024_private_key *out_private_key, const uint8_t *seed, 151 MLKEM_public_key *public_key);
211 size_t seed_len);
212 152
213/* 153/*
214 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that 154 * MLKEM_encap encrypts a random shared secret for an initialized
215 * corresponds to |private_key|. (This is faster than parsing the output of 155 * |public_key|. It returns one on success, and zero on failure or error. |*out
216 * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a 156 * ciphertext| and |*out_shared_secret| must have the value NULL. On success, a
217 * key that was just generated.) 157 * pointer to the ciphertext of the correct size for |key| is returned in
158 * |out_ciphertext|, the length in bytes of |*out_ciphertext| is returned in
159 * |*out_ciphertext_len|, a pointer to the random shared secret is returned in
160 * |out_shared_secret|, and the length in bytes of |*out_shared_secret| is
161 * returned in |*out_ciphtertext_len|. The caller is responsible for zeroing and
162 * freeing the values returned in |out_ciphertext| and |out_shared_secret|
218 */ 163 */
219void MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key, 164int MLKEM_encap(const MLKEM_public_key *public_key,
220 const struct MLKEM1024_private_key *private_key); 165 uint8_t **out_ciphertext, size_t *out_ciphertext_len,
221 166 uint8_t **out_shared_secret, size_t *out_shared_secret_len);
222/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
223#define MLKEM1024_CIPHERTEXT_BYTES 1568
224 167
225/* 168/*
226 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the 169 * MLKEM_decap decrypts a shared secret from |ciphertext| using an initialized
227 * ciphertext to |out_ciphertext|, and writes the random shared secret to 170 * |private_key|. It returns a pointer to the shared secret|out_shared_secret|
228 * |out_shared_secret|. 171 * and the length in bytes of |*out_shared_secret| in |*out_shared_secret_len|.
229 */ 172 *
230void MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 173 * If |ciphertext_len| is incorrect for |private_key|, |*out_shared_secret| is
231 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 174 * not NULL, or memory can not be allocated, it returns zero, otherwise it
232 const struct MLKEM1024_public_key *public_key); 175 * returns one. If |ciphertext| is invalid, a pointer is returned in
233 176 * |out_shared_secret| pointing to a key that will always be the same for the
234/* 177 * same |ciphertext| and |private_key|, but which appears to be random unless
235 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using 178 * one has access to |private_key|. These alternatives occur in constant time.
236 * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is 179 * Any subsequent symmetric encryption using |out_shared_secret| must use an
237 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid 180 * authenticated encryption scheme in order to discover the decapsulation
238 * (but of the correct length), |out_shared_secret| is filled with a key that 181 * failure. The caller is responsible for zeroing and freeing the value returned
239 * will always be the same for the same |ciphertext| and |private_key|, but 182 * in |out_shared_secret|.
240 * which appears to be random unless one has access to |private_key|. These
241 * alternatives occur in constant time. Any subsequent symmetric encryption
242 * using |out_shared_secret| must use an authenticated encryption scheme in
243 * order to discover the decapsulation failure.
244 */ 183 */
245int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 184int MLKEM_decap(const MLKEM_private_key *private_key,
246 const uint8_t *ciphertext, size_t ciphertext_len, 185 const uint8_t *ciphertext, size_t ciphertext_len,
247 const struct MLKEM1024_private_key *private_key); 186 uint8_t **out_shared_secret, size_t *out_shared_secret_len);
187
188/* Serialization of ML-KEM keys. */
248 189
249/* 190/*
250 * Serialisation of ML-KEM-1024 keys. 191 * MLKEM_marshal_public_key serializes an initialized |public_key| in the
251 * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard 192 * standard format for ML-KEM public keys. It returns one on success or zero on
252 * format for ML-KEM-1024 public keys. It returns one on success or zero on 193 * allocation error or failure. |*out| must have the value NULL. On success a
253 * allocation error. 194 * pointer is returned in |out| to the encoded public key matching |public_key|,
195 * and a pointer to the length in bytes of the encoded public key is stored in
196 * |out_len|. The caller is responsible for freeing the values returned in
197 * |out|.
254 */ 198 */
255int MLKEM1024_marshal_public_key(uint8_t **output, size_t *output_len, 199int MLKEM_marshal_public_key(const MLKEM_public_key *public_key, uint8_t **out,
256 const struct MLKEM1024_public_key *public_key); 200 size_t *out_len);
257 201
258/* 202/*
259 * MLKEM1024_parse_public_key parses a public key, in the format generated by 203 * MLKEM_parse_public_key parses a public key, in the format generated by
260 * |MLKEM1024_marshal_public_key|, from |in| and writes the result to 204 * |MLKEM_marshal_public_key|, from |in|. It returns one on success or zero on
261 * |out_public_key|. It returns one on success or zero on parse error or if 205 * error or failure. |public_key| must be a new uninitialized key. |in_len| must
262 * there are trailing bytes in |in|. 206 * be the correct length for the encoded format of |public_key. On success
207 * |public_key| is initialized to the value parsed from |in|.
263 */ 208 */
264int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key, 209int MLKEM_parse_public_key(MLKEM_public_key *public_key, const uint8_t *in,
265 const uint8_t *input, size_t input_len); 210 size_t in_len);
266 211
267/* 212/*
268 * MLKEM1024_parse_private_key parses a private key, in NIST's format for 213 * MLKEM_parse_private_key parses a private key, in the format generated by
269 * private keys, from |in| and writes the result to |out_private_key|. It 214 * |MLKEM_marshal_private_key|, from |in|. It returns one on success or zero on
270 * returns one on success or zero on parse error or if there are trailing bytes 215 * error or failure. |private_key| must be a new uninitialized key. |in_len|
271 * in |in|. This format is verbose and should be avoided. Private keys should be 216 * must be the correct length for the encoded format of |private_key. On success
272 * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|. 217 * |private_key| is initialized to the value parsed from |in|.
218 *
219 * This format is wastefully verbose and should be avoided. Private keys should
220 * be stored as seeds from |MLKEM_generate_key|, and then parsed using
221 * |MLKEM_private_key_from_seed|.
273 */ 222 */
274int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 223int MLKEM_parse_private_key(MLKEM_private_key *private_key, const uint8_t *in,
275 const uint8_t *input, size_t input_len); 224 size_t in_len);
276 225
277#if defined(__cplusplus) 226#if defined(__cplusplus)
278} 227}