summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/mlkem/mlkem.h333
1 files changed, 139 insertions, 194 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem.h b/src/lib/libcrypto/mlkem/mlkem.h
index a5645facc6..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.4 2024/12/19 23:52:26 tb 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
@@ -25,258 +25,203 @@
25extern "C" { 25extern "C" {
26#endif 26#endif
27 27
28/* Hack for now */
29struct cbs_st;
30struct 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/* 28/*
40 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this 29 * ML-KEM constants
41 * object should never leave the address space since the format is unstable.
42 */ 30 */
43struct MLKEM768_public_key {
44 union {
45 uint8_t bytes[512 * (3 + 9) + 32 + 32];
46 uint16_t alignment;
47 } opaque;
48};
49 31
50/* 32#define RANK768 3
51 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this 33#define RANK1024 4
52 * object should never leave the address space since the format is unstable.
53 */
54struct MLKEM768_private_key {
55 union {
56 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32];
57 uint16_t alignment;
58 } opaque;
59};
60 34
61/* 35/*
62 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 36 * ML-KEM keys
63 * key.
64 */ 37 */
65#define MLKEM768_PUBLIC_KEY_BYTES 1184
66 38
67/* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ 39typedef struct MLKEM_private_key_st MLKEM_private_key;
68#define MLKEM_SEED_BYTES 64 40typedef struct MLKEM_public_key_st MLKEM_public_key;
69 41
70/* 42/*
71 * 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
72 * 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
73 * 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
74 * 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|.
75 */ 48 */
76#define MLKEM_SHARED_SECRET_BYTES 32 49MLKEM_private_key *MLKEM_private_key_new(int rank);
77 50
78/* 51/*
79 * 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
80 * 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.
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 */ 54 */
84void MLKEM768_generate_key( 55void MLKEM_private_key_free(MLKEM_private_key *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 56
89/* 57/*
90 * 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
91 * 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
92 * 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.
93 */ 62 */
94int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, 63size_t MLKEM_private_key_encoded_length(const MLKEM_private_key *key);
95 const uint8_t *seed, size_t seed_len);
96 64
97/* 65/*
98 * 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
99 * 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
100 * |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.
101 * that was just generated.)
102 */ 69 */
103void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, 70size_t MLKEM_private_key_ciphertext_length(const MLKEM_private_key *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 71
109/* 72/*
110 * 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
111 * 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
112 * |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|.
113 */ 78 */
114void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 79MLKEM_public_key *MLKEM_public_key_new(int rank);
115 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES],
116 const struct MLKEM768_public_key *public_key);
117 80
118/* 81/*
119 * 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
120 * 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.
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 */ 84 */
129int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 85void MLKEM_public_key_free(MLKEM_public_key *key);
130 const uint8_t *ciphertext, size_t ciphertext_len,
131 const struct MLKEM768_private_key *private_key);
132
133/* Serialisation of keys. */
134 86
135/* 87/*
136 * 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
137 * 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
138 * 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.
139 */ 92 */
140int MLKEM768_marshal_public_key(struct cbb_st *out, 93size_t MLKEM_public_key_encoded_length(const MLKEM_public_key *key);
141 const struct MLKEM768_public_key *public_key);
142 94
143/* 95/*
144 * 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
145 * |MLKEM_marshal_public_key|, from |in| and writes the result to 97 * ciphertext when encrypting a shared secret with |key| using |MLKEM_encap|. Zero
146 * |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.
147 * there are trailing bytes in |in|.
148 */ 99 */
149int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, 100size_t MLKEM_public_key_ciphertext_length(const MLKEM_public_key *key);
150 struct cbs_st *in);
151 101
152/* 102/*
153 * MLKEM_parse_private_key parses a private key, in the format generated by 103 * ML-KEM operations
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 */ 104 */
159int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key,
160 struct cbs_st *in);
161 105
162/* 106/*
163 * 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|.
164 * 119 *
165 * 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
121 * save |out_optional_seed| as the private key, along with the ML-KEM rank value.
122 * An MLKEM_private_key of the correct rank can then be constructed using
123 * |MLKEM_private_key_from_seed|.
166 */ 124 */
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);
167 128
168/* 129/*
169 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this 130 * MLKEM_private_key_from_seed derives a private key from a seed that was
170 * object should never leave the address space since the format is unstable. 131 * generated by |MLKEM_generate_key| initializing |private_key|. It returns one
171 */ 132 * on success, and zero on failure or error. |private_key| must be a new
172struct MLKEM1024_public_key { 133 * uninitialized key. |seed_len| must be MLKEM_SEED_LENGTH.
173 union { 134 *
174 uint8_t bytes[512 * (4 + 16) + 32 + 32]; 135 * For |private_key| to match the key generated by |MLKEM_generate_key|,
175 uint16_t alignment; 136 * |private_key| must have been created with the same rank as used when generating
176 } opaque; 137 * the key.
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 */
184struct 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 */ 138 */
203void MLKEM1024_generate_key( 139int MLKEM_private_key_from_seed(MLKEM_private_key *private_key,
204 uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 140 const uint8_t *seed, size_t seed_len);
205 uint8_t optional_out_seed[MLKEM_SEED_BYTES],
206 struct MLKEM1024_private_key *out_private_key);
207 141
208/* 142/*
209 * 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
210 * 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
211 * 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|.
212 */ 149 */
213int MLKEM1024_private_key_from_seed( 150int MLKEM_public_from_private(const MLKEM_private_key *private_key,
214 struct MLKEM1024_private_key *out_private_key, const uint8_t *seed, 151 MLKEM_public_key *public_key);
215 size_t seed_len);
216 152
217/* 153/*
218 * MLKEM1024_public_from_private sets |*out_public_key| to the public key that 154 * MLKEM_encap encrypts a random shared secret for an initialized
219 * 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
220 * |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
221 * 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|
222 */ 163 */
223void MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key, 164int MLKEM_encap(const MLKEM_public_key *public_key,
224 const struct MLKEM1024_private_key *private_key); 165 uint8_t **out_ciphertext, size_t *out_ciphertext_len,
225 166 uint8_t **out_shared_secret, size_t *out_shared_secret_len);
226/* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */
227#define MLKEM1024_CIPHERTEXT_BYTES 1568
228 167
229/* 168/*
230 * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the 169 * MLKEM_decap decrypts a shared secret from |ciphertext| using an initialized
231 * 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|
232 * |out_shared_secret|. 171 * and the length in bytes of |*out_shared_secret| in |*out_shared_secret_len|.
233 */ 172 *
234void MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 173 * If |ciphertext_len| is incorrect for |private_key|, |*out_shared_secret| is
235 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 174 * not NULL, or memory can not be allocated, it returns zero, otherwise it
236 const struct MLKEM1024_public_key *public_key); 175 * returns one. If |ciphertext| is invalid, a pointer is returned in
237 176 * |out_shared_secret| pointing to a key that will always be the same for the
238/* 177 * same |ciphertext| and |private_key|, but which appears to be random unless
239 * MLKEM1024_decap decrypts a shared secret from |ciphertext| using 178 * one has access to |private_key|. These alternatives occur in constant time.
240 * |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
241 * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid 180 * authenticated encryption scheme in order to discover the decapsulation
242 * (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
243 * will always be the same for the same |ciphertext| and |private_key|, but 182 * in |out_shared_secret|.
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 */ 183 */
249int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 184int MLKEM_decap(const MLKEM_private_key *private_key,
250 const uint8_t *ciphertext, size_t ciphertext_len, 185 const uint8_t *ciphertext, size_t ciphertext_len,
251 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. */
252 189
253/* 190/*
254 * Serialisation of ML-KEM-1024 keys. 191 * MLKEM_marshal_public_key serializes an initialized |public_key| in the
255 * 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
256 * 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
257 * 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|.
258 */ 198 */
259int MLKEM1024_marshal_public_key(struct cbb_st *out, 199int MLKEM_marshal_public_key(const MLKEM_public_key *public_key, uint8_t **out,
260 const struct MLKEM1024_public_key *public_key); 200 size_t *out_len);
261 201
262/* 202/*
263 * 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
264 * |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
265 * |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
266 * 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|.
267 */ 208 */
268int 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,
269 struct cbs_st *in); 210 size_t in_len);
270 211
271/* 212/*
272 * 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
273 * 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
274 * 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|
275 * 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
276 * 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|.
277 */ 222 */
278int 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,
279 struct cbs_st *in); 224 size_t in_len);
280 225
281#if defined(__cplusplus) 226#if defined(__cplusplus)
282} 227}