xref: /openbsd/lib/libcrypto/mlkem/mlkem.h (revision ef1019e6)
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