diff options
| author | beck <> | 2024-12-13 00:03:57 +0000 |
|---|---|---|
| committer | beck <> | 2024-12-13 00:03:57 +0000 |
| commit | c3bf83f7cf1ff567aae1e260425898b2af6bf4cc (patch) | |
| tree | a9ff1c725db56dbeb46224505b3dd6fd05a21777 /src/lib/libcrypto/mlkem/mlkem.h | |
| parent | f0b174e51673db27d4324ea95b112eb95ad05291 (diff) | |
| download | openbsd-c3bf83f7cf1ff567aae1e260425898b2af6bf4cc.tar.gz openbsd-c3bf83f7cf1ff567aae1e260425898b2af6bf4cc.tar.bz2 openbsd-c3bf83f7cf1ff567aae1e260425898b2af6bf4cc.zip | |
Add ML-KEM 768 from BoringSSL
Changes include conversion from C++, basic KNF, then adaptation to
use our sha3 functions for sha3 and shake instead of the BorinSSL
version. This Adds units tests to run against BoringSSL and NIST test
vectors.
The future public API is the same as Boring's - but is not yet exposed
pending making bytesring.h public (which will happen separately) and
a minor bump
Currently this will just ensure we build and run regress.
ok tb@ to get it into the tree and massage from there.
Diffstat (limited to 'src/lib/libcrypto/mlkem/mlkem.h')
| -rw-r--r-- | src/lib/libcrypto/mlkem/mlkem.h | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/src/lib/libcrypto/mlkem/mlkem.h b/src/lib/libcrypto/mlkem/mlkem.h new file mode 100644 index 0000000000..8040f4844b --- /dev/null +++ b/src/lib/libcrypto/mlkem/mlkem.h | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | /* Copyright (c) 2024, Google Inc. | ||
| 2 | * | ||
| 3 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 4 | * purpose with or without fee is hereby granted, provided that the above | ||
| 5 | * copyright notice and this permission notice appear in all copies. | ||
| 6 | * | ||
| 7 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 8 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 9 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 10 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 11 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 12 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 13 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ | ||
| 14 | |||
| 15 | #ifndef OPENSSL_HEADER_MLKEM_H | ||
| 16 | #define OPENSSL_HEADER_MLKEM_H | ||
| 17 | |||
| 18 | #include <sys/types.h> | ||
| 19 | #include <stdint.h> | ||
| 20 | |||
| 21 | #ifdef LIBRESSL_HAS_MLKEM | ||
| 22 | /* This needs to become public */ | ||
| 23 | #include <openssl/bytestring.h> | ||
| 24 | #else | ||
| 25 | /* Hack for now */ | ||
| 26 | struct cbs_st; | ||
| 27 | struct cbb_st; | ||
| 28 | #endif | ||
| 29 | |||
| 30 | #if defined(__cplusplus) | ||
| 31 | extern "C" { | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* | ||
| 35 | * ML-KEM-768 | ||
| 36 | * | ||
| 37 | * This implements the Module-Lattice-Based Key-Encapsulation Mechanism from | ||
| 38 | * https://csrc.nist.gov/pubs/fips/204/final | ||
| 39 | */ | ||
| 40 | |||
| 41 | /* | ||
| 42 | * MLKEM768_public_key contains a ML-KEM-768 public key. The contents of this | ||
| 43 | * object should never leave the address space since the format is unstable. | ||
| 44 | */ | ||
| 45 | struct MLKEM768_public_key { | ||
| 46 | union { | ||
| 47 | uint8_t bytes[512 * (3 + 9) + 32 + 32]; | ||
| 48 | uint16_t alignment; | ||
| 49 | } opaque; | ||
| 50 | }; | ||
| 51 | |||
| 52 | /* | ||
| 53 | * MLKEM768_private_key contains a ML-KEM-768 private key. The contents of this | ||
| 54 | * object should never leave the address space since the format is unstable. | ||
| 55 | */ | ||
| 56 | struct MLKEM768_private_key { | ||
| 57 | union { | ||
| 58 | uint8_t bytes[512 * (3 + 3 + 9) + 32 + 32 + 32]; | ||
| 59 | uint16_t alignment; | ||
| 60 | } opaque; | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* | ||
| 64 | * MLKEM768_PUBLIC_KEY_BYTES is the number of bytes in an encoded ML-KEM768 public | ||
| 65 | * key. | ||
| 66 | */ | ||
| 67 | #define MLKEM768_PUBLIC_KEY_BYTES 1184 | ||
| 68 | |||
| 69 | /* MLKEM_SEED_BYTES is the number of bytes in an ML-KEM seed. */ | ||
| 70 | #define MLKEM_SEED_BYTES 64 | ||
| 71 | |||
| 72 | /* | ||
| 73 | * MLKEM_SHARED_SECRET_BYTES is the number of bytes in the ML-KEM768 shared | ||
| 74 | * secret. Although the round-3 specification has a variable-length output, the | ||
| 75 | * final ML-KEM construction is expected to use a fixed 32-byte output. To | ||
| 76 | * simplify the future transition, we apply the same restriction. | ||
| 77 | */ | ||
| 78 | #define MLKEM_SHARED_SECRET_BYTES 32 | ||
| 79 | |||
| 80 | /* | ||
| 81 | * MLKEM_generate_key generates a random public/private key pair, writes the | ||
| 82 | * encoded public key to |out_encoded_public_key| and sets |out_private_key| to | ||
| 83 | * the private key. If |optional_out_seed| us not NULL then te seed used to | ||
| 84 | * generate te private key is written to it. | ||
| 85 | */ | ||
| 86 | void MLKEM768_generate_key( | ||
| 87 | uint8_t out_encoded_public_key[MLKEM768_PUBLIC_KEY_BYTES], | ||
| 88 | uint8_t optional_out_seed[MLKEM_SEED_BYTES], | ||
| 89 | struct MLKEM768_private_key *out_private_key); | ||
| 90 | |||
| 91 | /* | ||
| 92 | * MLKEM768_private_key_from_seed derives a private key from a seed that was | ||
| 93 | * generated by |MLKEM768_generate_key|. It fails and returns 0 if |seed_len| is | ||
| 94 | * incorrect, otherwise it writes |*out_private_key| and returns 1. | ||
| 95 | */ | ||
| 96 | int MLKEM768_private_key_from_seed(struct MLKEM768_private_key *out_private_key, | ||
| 97 | const uint8_t *seed, size_t seed_len); | ||
| 98 | |||
| 99 | /* | ||
| 100 | * MLKEM_public_from_private sets |*out_public_key| to the public key that | ||
| 101 | * corresponds to |private_key|. (This is faster than parsing the output of | ||
| 102 | * |MLKEM_generate_key| if, for some reason, you need to encapsulate to a key | ||
| 103 | * that was just generated.) | ||
| 104 | */ | ||
| 105 | void MLKEM768_public_from_private(struct MLKEM768_public_key *out_public_key, | ||
| 106 | const struct MLKEM768_private_key *private_key); | ||
| 107 | |||
| 108 | /* MLKEM768_CIPHERTEXT_BYTES is number of bytes in the ML-KEM768 ciphertext. */ | ||
| 109 | #define MLKEM768_CIPHERTEXT_BYTES 1088 | ||
| 110 | |||
| 111 | /* | ||
| 112 | * MLKEM768_encap encrypts a random shared secret for |public_key|, writes the | ||
| 113 | * ciphertext to |out_ciphertext|, and writes the random shared secret to | ||
| 114 | * |out_shared_secret|. | ||
| 115 | */ | ||
| 116 | void MLKEM768_encap(uint8_t out_ciphertext[MLKEM768_CIPHERTEXT_BYTES], | ||
| 117 | uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
| 118 | const struct MLKEM768_public_key *public_key); | ||
| 119 | |||
| 120 | /* | ||
| 121 | * MLKEM768_decap decrypts a shared secret from |ciphertext| using |private_key| | ||
| 122 | * and writes it to |out_shared_secret|. If |ciphertext_len| is incorrect it | ||
| 123 | * returns 0, otherwise it rreturns 1. If |ciphertext| is invalid, | ||
| 124 | * |out_shared_secret| is filled with a key that will always be the same for the | ||
| 125 | * same |ciphertext| and |private_key|, but which appears to be random unless | ||
| 126 | * one has access to |private_key|. These alternatives occur in constant time. | ||
| 127 | * Any subsequent symmetric encryption using |out_shared_secret| must use an | ||
| 128 | * authenticated encryption scheme in order to discover the decapsulation | ||
| 129 | * failure. | ||
| 130 | */ | ||
| 131 | int MLKEM768_decap(uint8_t out_shared_secret[MLKEM_SHARED_SECRET_BYTES], | ||
| 132 | const uint8_t *ciphertext, size_t ciphertext_len, | ||
| 133 | const struct MLKEM768_private_key *private_key); | ||
| 134 | |||
| 135 | /* Serialisation of keys. */ | ||
| 136 | |||
| 137 | /* | ||
| 138 | * MLKEM768_marshal_public_key serializes |public_key| to |out| in the standard | ||
| 139 | * format for ML-KEM public keys. It returns one on success or zero on allocation | ||
| 140 | * error. | ||
| 141 | */ | ||
| 142 | int MLKEM768_marshal_public_key(struct cbb_st *out, | ||
| 143 | const struct MLKEM768_public_key *public_key); | ||
| 144 | |||
| 145 | /* | ||
| 146 | * MLKEM768_parse_public_key parses a public key, in the format generated by | ||
| 147 | * |MLKEM_marshal_public_key|, from |in| and writes the result to | ||
| 148 | * |out_public_key|. It returns one on success or zero on parse error or if | ||
| 149 | * there are trailing bytes in |in|. | ||
| 150 | */ | ||
| 151 | int MLKEM768_parse_public_key(struct MLKEM768_public_key *out_public_key, | ||
| 152 | struct cbs_st *in); | ||
| 153 | |||
| 154 | /* | ||
| 155 | * MLKEM_parse_private_key parses a private key, in the format generated by | ||
| 156 | * |MLKEM_marshal_private_key|, from |in| and writes the result to | ||
| 157 | * |out_private_key|. It returns one on success or zero on parse error or if | ||
| 158 | * there are trailing bytes in |in|. This formate is verbose and should be avoided. | ||
| 159 | * Private keys should be stored as seeds and parsed using |MLKEM768_private_key_from_seed|. | ||
| 160 | */ | ||
| 161 | int MLKEM768_parse_private_key(struct MLKEM768_private_key *out_private_key, | ||
| 162 | struct cbs_st *in); | ||
| 163 | |||
| 164 | #if defined(__cplusplus) | ||
| 165 | } | ||
| 166 | #endif | ||
| 167 | |||
| 168 | #endif /* OPENSSL_HEADER_MLKEM_H */ | ||
