1*ef1019e6Stb /* $OpenBSD: mlkem.h,v 1.4 2024/12/19 23:52:26 tb Exp $ */ 2bee138d5Stb /* 3bee138d5Stb * Copyright (c) 2024, Google Inc. 475c083a0Sbeck * 575c083a0Sbeck * Permission to use, copy, modify, and/or distribute this software for any 675c083a0Sbeck * purpose with or without fee is hereby granted, provided that the above 775c083a0Sbeck * copyright notice and this permission notice appear in all copies. 875c083a0Sbeck * 975c083a0Sbeck * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1075c083a0Sbeck * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1175c083a0Sbeck * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 1275c083a0Sbeck * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1375c083a0Sbeck * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1475c083a0Sbeck * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15bee138d5Stb * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16bee138d5Stb */ 1775c083a0Sbeck 1875c083a0Sbeck #ifndef OPENSSL_HEADER_MLKEM_H 1975c083a0Sbeck #define OPENSSL_HEADER_MLKEM_H 2075c083a0Sbeck 2175c083a0Sbeck #include <sys/types.h> 2275c083a0Sbeck #include <stdint.h> 2375c083a0Sbeck 2475c083a0Sbeck #if defined(__cplusplus) 2575c083a0Sbeck extern "C" { 2675c083a0Sbeck #endif 2775c083a0Sbeck 28bee138d5Stb /* Hack for now */ 29bee138d5Stb struct cbs_st; 30bee138d5Stb struct cbb_st; 31bee138d5Stb 3275c083a0Sbeck /* 3375c083a0Sbeck * ML-KEM-768 3475c083a0Sbeck * 3575c083a0Sbeck * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from 3675c083a0Sbeck * https://csrc.nist.gov/pubs/fips/204/final 3775c083a0Sbeck */ 3875c083a0Sbeck 3975c083a0Sbeck /* 4075c083a0Sbeck * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this 4175c083a0Sbeck * object should never leave the address space since the format is unstable. 4275c083a0Sbeck */ 4375c083a0Sbeck struct MLKEM768_public_key { 4475c083a0Sbeck union { 4575c083a0Sbeck uint8_t bytes[512 * (3 + 9) + 32 + 32]; 4675c083a0Sbeck uint16_t alignment; 4775c083a0Sbeck } opaque; 4875c083a0Sbeck }; 4975c083a0Sbeck 5075c083a0Sbeck /* 5175c083a0Sbeck * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this 5275c083a0Sbeck * object should never leave the address space since the format is unstable. 5375c083a0Sbeck */ 5475c083a0Sbeck struct MLKEM768_private_key { 5575c083a0Sbeck union { 5675c083a0Sbeck uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; 5775c083a0Sbeck uint16_t alignment; 5875c083a0Sbeck } opaque; 5975c083a0Sbeck }; 6075c083a0Sbeck 6175c083a0Sbeck /* 6275c083a0Sbeck * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public 6375c083a0Sbeck * key. 6475c083a0Sbeck */ 6575c083a0Sbeck #define MLKEM768_PUBLIC_KEY_BYTES 1184 6675c083a0Sbeck 6775c083a0Sbeck /* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ 6875c083a0Sbeck #define MLKEM_SEED_BYTES 64 6975c083a0Sbeck 7075c083a0Sbeck /* 7175c083a0Sbeck * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared 7275c083a0Sbeck * secret. Although the round-3 specification has a variable-length output, the 7375c083a0Sbeck * final ML-KEM construction is expected to use a fixed 32-byte output. To 7475c083a0Sbeck * simplify the future transition, we apply the same restriction. 7575c083a0Sbeck */ 7675c083a0Sbeck #define MLKEM_SHARED_SECRET_BYTES 32 7775c083a0Sbeck 7875c083a0Sbeck /* 7975c083a0Sbeck * MLKEM_generate_key generates a random public/private key pair, writes the 8075c083a0Sbeck * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 8175c083a0Sbeck * the private key. If |optional_out_seed| us not NULL then te seed used to 8275c083a0Sbeck * generate te private key is written to it. 8375c083a0Sbeck */ 8475c083a0Sbeck void MLKEM768_generate_key( 8575c083a0Sbeck uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], 8675c083a0Sbeck uint8_t optional_out_seed[MLKEM_SEED_BYTES], 8775c083a0Sbeck struct MLKEM768_private_key *out_private_key); 8875c083a0Sbeck 8975c083a0Sbeck /* 9075c083a0Sbeck * MLKEM768_private_key_from_seed derives a private key from a seed that was 9175c083a0Sbeck * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is 9275c083a0Sbeck * incorrect, otherwise it writes |*out_private_key| and returns 1. 9375c083a0Sbeck */ 9475c083a0Sbeck int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, 9575c083a0Sbeck const uint8_t *seed, size_t seed_len); 9675c083a0Sbeck 9775c083a0Sbeck /* 9875c083a0Sbeck * MLKEM_public_from_private sets |*out_public_key| to the public key that 9975c083a0Sbeck * corresponds to |private_key|. (This is faster than parsing the output of 10075c083a0Sbeck * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key 10175c083a0Sbeck * that was just generated.) 10275c083a0Sbeck */ 10375c083a0Sbeck void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, 10475c083a0Sbeck const struct MLKEM768_private_key *private_key); 10575c083a0Sbeck 10675c083a0Sbeck /* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */ 10775c083a0Sbeck #define MLKEM768_CIPHERTEXT_BYTES 1088 10875c083a0Sbeck 10975c083a0Sbeck /* 11075c083a0Sbeck * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the 11175c083a0Sbeck * ciphertext to |out_ciphertext|, and writes the random shared secret to 11275c083a0Sbeck * |out_shared_secret|. 11375c083a0Sbeck */ 11475c083a0Sbeck void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], 11575c083a0Sbeck uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 11675c083a0Sbeck const struct MLKEM768_public_key *public_key); 11775c083a0Sbeck 11875c083a0Sbeck /* 11975c083a0Sbeck * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key| 12075c083a0Sbeck * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it 12175c083a0Sbeck * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid, 12275c083a0Sbeck * |out_shared_secret| is filled with a key that will always be the same for the 12375c083a0Sbeck * same |ciphertext| and |private_key|, but which appears to be random unless 12475c083a0Sbeck * one has access to |private_key|. These alternatives occur in constant time. 12575c083a0Sbeck * Any subsequent symmetric encryption using |out_shared_secret| must use an 12675c083a0Sbeck * authenticated encryption scheme in order to discover the decapsulation 12775c083a0Sbeck * failure. 12875c083a0Sbeck */ 12975c083a0Sbeck int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 13075c083a0Sbeck const uint8_t *ciphertext, size_t ciphertext_len, 13175c083a0Sbeck const struct MLKEM768_private_key *private_key); 13275c083a0Sbeck 13375c083a0Sbeck /* Serialisation of keys. */ 13475c083a0Sbeck 13575c083a0Sbeck /* 13675c083a0Sbeck * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard 13775c083a0Sbeck * format for ML-KEM public keys. It returns one on success or zero on allocation 13875c083a0Sbeck * error. 13975c083a0Sbeck */ 14075c083a0Sbeck int MLKEM768_marshal_public_key(struct cbb_st *out, 14175c083a0Sbeck const struct MLKEM768_public_key *public_key); 14275c083a0Sbeck 14375c083a0Sbeck /* 14475c083a0Sbeck * MLKEM768_parse_public_key parses a public key, in the format generated by 14575c083a0Sbeck * |MLKEM_marshal_public_key|, from |in| and writes the result to 14675c083a0Sbeck * |out_public_key|. It returns one on success or zero on parse error or if 14775c083a0Sbeck * there are trailing bytes in |in|. 14875c083a0Sbeck */ 14975c083a0Sbeck int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, 15075c083a0Sbeck struct cbs_st *in); 15175c083a0Sbeck 15275c083a0Sbeck /* 15375c083a0Sbeck * MLKEM_parse_private_key parses a private key, in the format generated by 15475c083a0Sbeck * |MLKEM_marshal_private_key|, from |in| and writes the result to 15575c083a0Sbeck * |out_private_key|. It returns one on success or zero on parse error or if 15675c083a0Sbeck * there are trailing bytes in |in|. This formate is verbose and should be avoided. 15775c083a0Sbeck * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|. 15875c083a0Sbeck */ 15975c083a0Sbeck int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key, 16075c083a0Sbeck struct cbs_st *in); 16175c083a0Sbeck 16208c63c71Sbeck /* 16308c63c71Sbeck * ML-KEM-1024 16408c63c71Sbeck * 16508c63c71Sbeck * ML-KEM-1024 also exists. You should prefer ML-KEM-768 where possible. 16608c63c71Sbeck */ 16708c63c71Sbeck 16808c63c71Sbeck /* 16908c63c71Sbeck * MLKEM1024_public_key contains an ML-KEM-1024 public key. The contents of this 17008c63c71Sbeck * object should never leave the address space since the format is unstable. 17108c63c71Sbeck */ 17208c63c71Sbeck struct MLKEM1024_public_key { 17308c63c71Sbeck union { 17408c63c71Sbeck uint8_t bytes[512 * (4 + 16) + 32 + 32]; 17508c63c71Sbeck uint16_t alignment; 17608c63c71Sbeck } opaque; 17708c63c71Sbeck }; 17808c63c71Sbeck 17908c63c71Sbeck /* 18008c63c71Sbeck * MLKEM1024_private_key contains a ML-KEM-1024 private key. The contents of 18108c63c71Sbeck * this object should never leave the address space since the format is 18208c63c71Sbeck * unstable. 18308c63c71Sbeck */ 18408c63c71Sbeck struct MLKEM1024_private_key { 18508c63c71Sbeck union { 18608c63c71Sbeck uint8_t bytes[512 * (4 + 4 + 16) + 32 + 32 + 32]; 18708c63c71Sbeck uint16_t alignment; 18808c63c71Sbeck } opaque; 18908c63c71Sbeck }; 19008c63c71Sbeck 19108c63c71Sbeck /* 19208c63c71Sbeck * MLKEM1024_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM-1024 19308c63c71Sbeck * public key. 19408c63c71Sbeck */ 19508c63c71Sbeck #define MLKEM1024_PUBLIC_KEY_BYTES 1568 19608c63c71Sbeck 19708c63c71Sbeck /* 19808c63c71Sbeck * MLKEM1024_generate_key generates a random public/private key pair, writes the 19908c63c71Sbeck * encoded public key to |out_encoded_public_key| and sets |out_private_key| to 20008c63c71Sbeck * the private key. If |optional_out_seed| is not NULL then the seed used to 20108c63c71Sbeck * generate the private key is written to it. 20208c63c71Sbeck */ 20308c63c71Sbeck void MLKEM1024_generate_key( 20408c63c71Sbeck uint8_t out_encoded_public_key[MLKEM1024_PUBLIC_KEY_BYTES], 20508c63c71Sbeck uint8_t optional_out_seed[MLKEM_SEED_BYTES], 20608c63c71Sbeck struct MLKEM1024_private_key *out_private_key); 20708c63c71Sbeck 20808c63c71Sbeck /* 20908c63c71Sbeck * MLKEM1024_private_key_from_seed derives a private key from a seed that was 21008c63c71Sbeck * generated by |MLKEM1024_generate_key|. It fails and returns 0 if |seed_len| 21108c63c71Sbeck * is incorrect, otherwise it writes |*out_private_key| and returns 1. 21208c63c71Sbeck */ 21308c63c71Sbeck int MLKEM1024_private_key_from_seed( 21408c63c71Sbeck struct MLKEM1024_private_key *out_private_key, const uint8_t *seed, 21508c63c71Sbeck size_t seed_len); 21608c63c71Sbeck 21708c63c71Sbeck /* 21808c63c71Sbeck * MLKEM1024_public_from_private sets |*out_public_key| to the public key that 21908c63c71Sbeck * corresponds to |private_key|. (This is faster than parsing the output of 22008c63c71Sbeck * |MLKEM1024_generate_key| if, for some reason, you need to encapsulate to a 22108c63c71Sbeck * key that was just generated.) 22208c63c71Sbeck */ 22308c63c71Sbeck void MLKEM1024_public_from_private(struct MLKEM1024_public_key *out_public_key, 22408c63c71Sbeck const struct MLKEM1024_private_key *private_key); 22508c63c71Sbeck 22608c63c71Sbeck /* MLKEM1024_CIPHERTEXT_BYTES is number of bytes in the ML-KEM-1024 ciphertext. */ 22708c63c71Sbeck #define MLKEM1024_CIPHERTEXT_BYTES 1568 22808c63c71Sbeck 22908c63c71Sbeck /* 23008c63c71Sbeck * MLKEM1024_encap encrypts a random shared secret for |public_key|, writes the 23108c63c71Sbeck * ciphertext to |out_ciphertext|, and writes the random shared secret to 23208c63c71Sbeck * |out_shared_secret|. 23308c63c71Sbeck */ 23408c63c71Sbeck void MLKEM1024_encap(uint8_t out_ciphertext[MLKEM1024_CIPHERTEXT_BYTES], 23508c63c71Sbeck uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 23608c63c71Sbeck const struct MLKEM1024_public_key *public_key); 23708c63c71Sbeck 23808c63c71Sbeck /* 23908c63c71Sbeck * MLKEM1024_decap decrypts a shared secret from |ciphertext| using 24008c63c71Sbeck * |private_key| and writes it to |out_shared_secret|. If |ciphertext_len| is 24108c63c71Sbeck * incorrect it returns 0, otherwise it returns 1. If |ciphertext| is invalid 24208c63c71Sbeck * (but of the correct length), |out_shared_secret| is filled with a key that 24308c63c71Sbeck * will always be the same for the same |ciphertext| and |private_key|, but 24408c63c71Sbeck * which appears to be random unless one has access to |private_key|. These 24508c63c71Sbeck * alternatives occur in constant time. Any subsequent symmetric encryption 24608c63c71Sbeck * using |out_shared_secret| must use an authenticated encryption scheme in 24708c63c71Sbeck * order to discover the decapsulation failure. 24808c63c71Sbeck */ 24908c63c71Sbeck int MLKEM1024_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], 25008c63c71Sbeck const uint8_t *ciphertext, size_t ciphertext_len, 25108c63c71Sbeck const struct MLKEM1024_private_key *private_key); 25208c63c71Sbeck 25308c63c71Sbeck /* 25408c63c71Sbeck * Serialisation of ML-KEM-1024 keys. 25508c63c71Sbeck * MLKEM1024_marshal_public_key serializes |public_key| to |out| in the standard 25608c63c71Sbeck * format for ML-KEM-1024 public keys. It returns one on success or zero on 25708c63c71Sbeck * allocation error. 25808c63c71Sbeck */ 25908c63c71Sbeck int MLKEM1024_marshal_public_key(struct cbb_st *out, 26008c63c71Sbeck const struct MLKEM1024_public_key *public_key); 26108c63c71Sbeck 26208c63c71Sbeck /* 26308c63c71Sbeck * MLKEM1024_parse_public_key parses a public key, in the format generated by 26408c63c71Sbeck * |MLKEM1024_marshal_public_key|, from |in| and writes the result to 26508c63c71Sbeck * |out_public_key|. It returns one on success or zero on parse error or if 26608c63c71Sbeck * there are trailing bytes in |in|. 26708c63c71Sbeck */ 26808c63c71Sbeck int MLKEM1024_parse_public_key(struct MLKEM1024_public_key *out_public_key, 26908c63c71Sbeck struct cbs_st *in); 27008c63c71Sbeck 27108c63c71Sbeck /* 27208c63c71Sbeck * MLKEM1024_parse_private_key parses a private key, in NIST's format for 27308c63c71Sbeck * private keys, from |in| and writes the result to |out_private_key|. It 27408c63c71Sbeck * returns one on success or zero on parse error or if there are trailing bytes 27508c63c71Sbeck * in |in|. This format is verbose and should be avoided. Private keys should be 27608c63c71Sbeck * stored as seeds and parsed using |MLKEM1024_private_key_from_seed|. 27708c63c71Sbeck */ 27808c63c71Sbeck int MLKEM1024_parse_private_key(struct MLKEM1024_private_key *out_private_key, 27908c63c71Sbeck struct cbs_st *in); 28008c63c71Sbeck 28175c083a0Sbeck #if defined(__cplusplus) 28275c083a0Sbeck } 28375c083a0Sbeck #endif 28475c083a0Sbeck 28575c083a0Sbeck #endif /* OPENSSL_HEADER_MLKEM_H */ 286