1 /* $OpenBSD: mlkem_internal.h,v 1.10 2025年09月05日 23:30:12 beck Exp $ */ 2 /* 3 * Copyright (c) 2023, Google Inc. 4 * Copyright (c) 2025, Bob Beck <beck@obtuse.com> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#ifndef OPENSSL_HEADER_CRYPTO_MLKEM_INTERNAL_H 20#define OPENSSL_HEADER_CRYPTO_MLKEM_INTERNAL_H 21 22#include "bytestring.h" 23#include "mlkem.h" 24 25#if defined(__cplusplus) 26 extern "C" { 27#endif 28 29 __BEGIN_HIDDEN_DECLS 30 31 /* Public opaque ML-KEM key structures. */ 32 33#define MLKEM_PUBLIC_KEY_UNINITIALIZED 1 34#define MLKEM_PUBLIC_KEY_INITIALIZED 2 35#define MLKEM_PRIVATE_KEY_UNINITIALIZED 3 36#define MLKEM_PRIVATE_KEY_INITIALIZED 4 37 38 struct MLKEM_public_key_st { 39 uint16_t rank; 40 int state; 41 struct MLKEM768_public_key *key_768; 42 struct MLKEM1024_public_key *key_1024; 43}; 44 45 struct MLKEM_private_key_st { 46 uint16_t rank; 47 int state; 48 struct MLKEM768_private_key *key_768; 49 struct MLKEM1024_private_key *key_1024; 50}; 51 52 /* 53 * ML-KEM-768 and ML-KEM-1024 54 * 55 * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from 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. 75 */ 76 77 /* 78 * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this 79 * object should never leave the address space since the format is unstable. 80 */ 81 struct MLKEM1024_public_key { 82 uint8_t bytes[512 * (4 + 16) + 32 + 32]; 83 uint16_t alignment; 84}; 85 86 /* 87 * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of 88 * this object should never leave the address space since the format is 89 * unstable. 90 */ 91 struct MLKEM1024_private_key { 92 uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32]; 93 uint16_t alignment; 94}; 95 96 /* 97 * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this 98 * object should never leave the address space since the format is unstable. 99 */ 100 struct MLKEM768_public_key { 101 uint8_t bytes[512 * (3 + 9) + 32 + 32]; 102 uint16_t alignment; 103}; 104 105 /* 106 * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this 107 * object should never leave the address space since the format is unstable. 108 */ 109 struct MLKEM768_private_key { 110 uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; 111 uint16_t alignment; 112}; 113 114 /* 115 * MLKEM_SEED_LENGTH is the number of bytes in an ML-KEM seed. An ML-KEM 116 * seed is normally used to represent a private key. 117 */ 118#define MLKEM_SEED_LENGTH 64 119 120 /* 121 * MLKEM_SHARED_SECRET_LENGTH is the number of bytes in an ML-KEM shared 122 * secret. 123 */ 124#define MLKEM_SHARED_SECRET_LENGTH 32 125 126 /* 127 * MLKEM_ENCAP_ENTROPY is the number of bytes of uniformly random entropy 128 * necessary to encapsulate a secret. The entropy will be leaked to the 129 * decapsulating party. 130 */ 131#define MLKEM_ENCAP_ENTROPY 32 132 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 138 139 /* 140 * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 141 * key. 142 */ 143#define MLKEM768_PUBLIC_KEY_BYTES 1184 144 145 /* 146 * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024 147 * public key. 148 */ 149#define MLKEM1024_PUBLIC_KEY_BYTES 1568 150 151 /* 152 * MLKEM768_PRIVATE_KEY_BYTES is the length of the data produced by 153 * |marshal_private_key| for a RANK768 MLKEM_private_key. 154 */ 155#define MLKEM768_PRIVATE_KEY_BYTES 2400 156 157 /* 158 * MLKEM1024_PRIVATE_KEY_BYTES is the length of the data produced by 159 * |marshal_private_key| for a RANK1024 MLKEM_private_key. 160 */ 161#define MLKEM1024_PRIVATE_KEY_BYTES 3168 162 163 /* 164 * Internal MLKEM 768 and MLKEM 1024 functions come largely from BoringSSL, but 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. 173 */ 174 175 /* Key generation. */ 176 177 /* 178 * mlkem_generate_key generates a random public/private key pair, writes the 179 * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 180 * the private key. If |optional_out_seed| is not NULL then the seed used to 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|. 184 */ 185 int mlkem_generate_key(uint8_t *out_encoded_public_key, 186 uint8_t *optional_out_seed, MLKEM_private_key *out_private_key); 187 188 /* 189 * mlkem_private_key_from_seed modifies |out_private_key| to generate a key of 190 * the rank of |*out_private_key| from a seed that was generated by 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. 194 */ 195 int mlkem_private_key_from_seed(const uint8_t *seed, size_t seed_len, 196 MLKEM_private_key *out_private_key); 197 198 /* 199 * mlkem_public_from_private sets |*out_public_key| to the public key that 200 * corresponds to |*private_key|. (This is faster than parsing the output of 201 * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key 202 * that was just generated.) 203 */ 204 void mlkem_public_from_private(const MLKEM_private_key *private_key, 205 MLKEM_public_key *out_public_key); 206 207 208 /* Encapsulation and decapsulation of secrets. */ 209 210 /* 211 * mlkem_encap encrypts a random shared secret for |public_key|, writes the 212 * ciphertext to |out_ciphertext|, and writes the random shared secret to 213 * |out_shared_secret|. 214 */ 215 void mlkem_encap(const MLKEM_public_key *public_key, 216 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 217 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH]); 218 219 /* 220 * mlkem_decap decrypts a shared secret from |ciphertext| using |private_key| 221 * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it 222 * returns 0, otherwise it returns 1. If |ciphertext| is invalid, 223 * |out_shared_secret| is filled with a key that will always be the same for the 224 * same |ciphertext| and |private_key|, but which appears to be random unless 225 * one has access to |private_key|. These alternatives occur in constant time. 226 * Any subsequent symmetric encryption using |out_shared_secret| must use an 227 * authenticated encryption scheme in order to discover the decapsulation 228 * failure. 229 */ 230 int mlkem_decap(const MLKEM_private_key *private_key, 231 const uint8_t *ciphertext, size_t ciphertext_len, 232 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH]); 233 234 235 /* Serialisation of keys. */ 236 237 /* 238 * mlkem_marshal_public_key serializes |public_key| to |output| in the standard 239 * format for ML-KEM public keys. It returns one on success or zero on allocation 240 * error. 241 */ 242 int mlkem_marshal_public_key(const MLKEM_public_key *public_key, 243 uint8_t **output, size_t *output_len); 244 245 /* 246 * mlkem_parse_public_key parses a public key, in the format generated by 247 * |MLKEM_marshal_public_key|, from |input| and writes the result to 248 * |out_public_key|. It returns one on success or zero on parse error or if 249 * there are trailing bytes in |input|. 250 */ 251 int mlkem_parse_public_key(const uint8_t *input, size_t input_len, 252 MLKEM_public_key *out_public_key); 253 254 /* 255 * mlkem_parse_private_key parses a private key, in the format generated by 256 * |MLKEM_marshal_private_key|, from |input| and writes the result to 257 * |out_private_key|. It returns one on success or zero on parse error or if 258 * there are trailing bytes in |input|. This formate is verbose and should be avoided. 259 * Private keys should be stored as seeds and parsed using |mlkem_private_key_from_seed|. 260 */ 261 int mlkem_parse_private_key(const uint8_t *input, size_t input_len, 262 MLKEM_private_key *out_private_key); 263 264 265 /* Functions that are only used for test purposes. */ 266 267 /* 268 * mlkem_generate_key_external_entropy is a deterministic function to create a 269 * pair of ML-KEM 768 keys, using the supplied entropy. The entropy needs to be 270 * uniformly random generated. This function is should only be used for tests, 271 * regular callers should use the non-deterministic |MLKEM_generate_key| 272 * directly. 273 */ 274 int mlkem_generate_key_external_entropy( 275 uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 276 MLKEM_private_key *out_private_key, 277 const uint8_t entropy[MLKEM_SEED_LENGTH]); 278 279 /* 280 * mlkem_marshal_private_key serializes |private_key| to |out_private_key| in the standard 281 * format for ML-KEM private keys. It returns one on success or zero on 282 * allocation error. 283 */ 284 int mlkem_marshal_private_key(const MLKEM_private_key *private_key, 285 uint8_t **out_private_key, size_t *out_private_key_len); 286 287 /* 288 * mlkem_encap_external_entropy behaves like |mlkem_encap|, but uses 289 * |MLKEM_ENCAP_ENTROPY| bytes of |entropy| for randomization. The decapsulating 290 * side will be able to recover |entropy| in full. This function should only be 291 * used for tests, regular callers should use the non-deterministic 292 * |MLKEM_encap| directly. 293 */ 294 void mlkem_encap_external_entropy( 295 uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 296 uint8_t out_shared_secret[MLKEM_SHARED_SECRET_LENGTH], 297 const MLKEM_public_key *public_key, 298 const uint8_t entropy[MLKEM_ENCAP_ENTROPY]); 299 300 /* 301 * |MLKEM_encap_external_entropy| behaves exactly like the public |MLKEM_encap| 302 * with the entropy provided by the caller. It is directly called internally 303 * and by tests. 304 */ 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); 309 310 /* 311 * |MLKEM_generate_key_external_entropy| behaves exactly like the public 312 * |MLKEM_generate_key| with the entropy provided by the caller. 313 * It is directly called internally and by tests. 314 */ 315 int MLKEM_generate_key_external_entropy(MLKEM_private_key *private_key, 316 uint8_t **out_encoded_public_key, size_t *out_encoded_public_key_len, 317 const uint8_t *entropy); 318 319 320 __END_HIDDEN_DECLS 321 322#if defined(__cplusplus) 323} 324#endif 325 326#endif /* OPENSSL_HEADER_CRYPTO_MLKEM_INTERNAL_H */ 327