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