summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/mlkem/mlkem.h
diff options
context:
space:
mode:
authorbeck <>2024-12-13 00:03:57 +0000
committerbeck <>2024-12-13 00:03:57 +0000
commitc3bf83f7cf1ff567aae1e260425898b2af6bf4cc (patch)
treea9ff1c725db56dbeb46224505b3dd6fd05a21777 /src/lib/libcrypto/mlkem/mlkem.h
parentf0b174e51673db27d4324ea95b112eb95ad05291 (diff)
downloadopenbsd-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.h168
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 */
26struct cbs_st;
27struct cbb_st;
28#endif
29
30#if defined(__cplusplus)
31extern "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 */
45struct 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 */
56struct 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 */
86void 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 */
96int 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 */
105void 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 */
116void 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 */
131int 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 */
142int 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 */
151int 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 */
161int 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 */