-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathcrypto.h
More file actions
290 lines (232 loc) · 7.4 KB
/
Copy pathcrypto.h
File metadata and controls
290 lines (232 loc) · 7.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#pragma once
#include <functional>
#include <hpke/digest.h>
#include <hpke/hpke.h>
#include <hpke/random.h>
#include <hpke/signature.h>
#include <mls/common.h>
#include <namespace.h>
#include <tls/tls_syntax.h>
#include <vector>
namespace MLS_NAMESPACE {
/// Signature Code points, borrowed from RFC 8446
enum struct SignatureScheme : uint16_t
{
ecdsa_secp256r1_sha256 = 0x0403,
ecdsa_secp384r1_sha384 = 0x0805,
ecdsa_secp521r1_sha512 = 0x0603,
ed25519 = 0x0807,
ed448 = 0x0808,
rsa_pkcs1_sha256 = 0x0401,
};
SignatureScheme
tls_signature_scheme(hpke::Signature::ID id);
/// Cipher suites
struct KeyAndNonce
{
bytes key;
bytes nonce;
};
// opaque HashReference<V>;
// HashReference KeyPackageRef;
// HashReference ProposalRef;
using HashReference = bytes;
using KeyPackageRef = HashReference;
using ProposalRef = HashReference;
struct CipherSuite
{
enum struct ID : uint16_t
{
unknown = 0x0000,
X25519_AES128GCM_SHA256_Ed25519 = 0x0001,
P256_AES128GCM_SHA256_P256 = 0x0002,
X25519_CHACHA20POLY1305_SHA256_Ed25519 = 0x0003,
X448_AES256GCM_SHA512_Ed448 = 0x0004,
P521_AES256GCM_SHA512_P521 = 0x0005,
X448_CHACHA20POLY1305_SHA512_Ed448 = 0x0006,
P384_AES256GCM_SHA384_P384 = 0x0007,
MLKEM768X25519_AES256GCM_SHA384_Ed25519 = 0x0008,
MLKEM768P256_AES256GCM_SHA384_P256 = 0x0009,
MLKEM1024P384_AES256GCM_SHA384_P384 = 0x000a,
// GREASE values, included here mainly so that debugger output looks nice
GREASE_0 = 0x0A0A,
GREASE_1 = 0x1A1A,
GREASE_2 = 0x2A2A,
GREASE_3 = 0x3A3A,
GREASE_4 = 0x4A4A,
GREASE_5 = 0x5A5A,
GREASE_6 = 0x6A6A,
GREASE_7 = 0x7A7A,
GREASE_8 = 0x8A8A,
GREASE_9 = 0x9A9A,
GREASE_A = 0xAAAA,
GREASE_B = 0xBABA,
GREASE_C = 0xCACA,
GREASE_D = 0xDADA,
GREASE_E = 0xEAEA,
};
CipherSuite();
CipherSuite(ID id_in);
ID cipher_suite() const { return id; }
SignatureScheme signature_scheme() const;
size_t secret_size() const { return get().digest.hash_size; }
size_t key_size() const { return get().hpke.aead.key_size; }
size_t nonce_size() const { return get().hpke.aead.nonce_size; }
bytes zero() const { return bytes(secret_size(), 0); }
const hpke::HPKE& hpke() const { return get().hpke; }
const hpke::Digest& digest() const { return get().digest; }
const hpke::Signature& sig() const { return get().sig; }
bytes expand_with_label(const bytes& secret,
const std::string& label,
const bytes& context,
size_t length) const;
bytes derive_secret(const bytes& secret, const std::string& label) const;
bytes derive_tree_secret(const bytes& secret,
const std::string& label,
uint32_t generation,
size_t length) const;
template<typename T>
bytes ref(const T& value) const
{
return raw_ref(reference_label<T>(), tls::marshal(value));
}
bytes raw_ref(const bytes& label, const bytes& value) const
{
// RefHash(label, value) = Hash(RefHashInput)
//
// struct {
// opaque label<V>;
// opaque value<V>;
// } RefHashInput;
auto w = tls::ostream();
w << label << value;
return digest().hash(w.bytes());
}
TLS_SERIALIZABLE(id)
private:
ID id;
struct Ciphers
{
hpke::HPKE hpke;
const hpke::Digest& digest;
const hpke::Signature& sig;
};
const Ciphers& get() const;
template<typename T>
static const bytes& reference_label();
};
#if defined(WITH_BORINGSSL)
static constexpr size_t n_supported_x448_suites = 0;
#else
static constexpr size_t n_supported_x448_suites = 2;
#endif
#if defined(WITH_PQ)
static constexpr size_t n_supported_pq_suites = 3;
#else
static constexpr size_t n_supported_pq_suites = 0;
#endif
static constexpr size_t n_supported_suites =
5 + n_supported_x448_suites + n_supported_pq_suites;
extern const std::array<CipherSuite::ID, n_supported_suites>
all_supported_cipher_suites;
// Utilities
using MLS_NAMESPACE::hpke::random_bytes;
// HPKE Keys
namespace encrypt_label {
extern const std::string update_path_node;
extern const std::string welcome;
} // namespace encrypt_label
struct HPKECiphertext
{
bytes kem_output;
bytes ciphertext;
TLS_SERIALIZABLE(kem_output, ciphertext)
};
struct HPKEPublicKey
{
bytes data;
HPKECiphertext encrypt(CipherSuite suite,
const std::string& label,
const bytes& context,
const bytes& pt) const;
std::tuple<bytes, bytes> do_export(CipherSuite suite,
const bytes& info,
const std::string& label,
size_t size) const;
TLS_SERIALIZABLE(data)
};
struct HPKEPrivateKey
{
static HPKEPrivateKey generate(CipherSuite suite);
static HPKEPrivateKey parse(CipherSuite suite, const bytes& data);
static HPKEPrivateKey derive(CipherSuite suite, const bytes& secret);
HPKEPrivateKey() = default;
bytes data;
HPKEPublicKey public_key;
bytes decrypt(CipherSuite suite,
const std::string& label,
const bytes& context,
const HPKECiphertext& ct) const;
bytes do_export(CipherSuite suite,
const bytes& info,
const bytes& kem_output,
const std::string& label,
size_t size) const;
void set_public_key(CipherSuite suite);
TLS_SERIALIZABLE(data)
private:
HPKEPrivateKey(bytes priv_data, bytes pub_data);
};
// Signature Keys
namespace sign_label {
extern const std::string mls_content;
extern const std::string leaf_node;
extern const std::string key_package;
extern const std::string group_info;
extern const std::string multi_credential;
} // namespace sign_label
struct SignaturePublicKey
{
static SignaturePublicKey from_jwk(CipherSuite suite,
const std::string& json_str);
bytes data;
bool verify(const CipherSuite& suite,
const std::string& label,
const bytes& message,
const bytes& signature) const;
std::string to_jwk(CipherSuite suite) const;
TLS_SERIALIZABLE(data)
};
struct PublicJWK
{
SignatureScheme signature_scheme;
std::optional<std::string> key_id;
SignaturePublicKey public_key;
static PublicJWK parse(const std::string& jwk_json);
};
struct SignaturePrivateKey
{
using SignerFunc = std::function<bytes(const std::vector<uint8_t>&)>;
static SignaturePrivateKey generate(CipherSuite suite);
static SignaturePrivateKey parse(CipherSuite suite, const bytes& data);
static SignaturePrivateKey parse_der(CipherSuite suite, const bytes& data);
static SignaturePrivateKey derive(CipherSuite suite, const bytes& secret);
static SignaturePrivateKey from_jwk(CipherSuite suite,
const std::string& json_str);
static SignaturePrivateKey from_func(SignerFunc func, bytes pub_data);
SignaturePrivateKey() = default;
bytes data;
SignaturePublicKey public_key;
bytes sign(const CipherSuite& suite,
const std::string& label,
const bytes& message) const;
void set_public_key(CipherSuite suite);
std::string to_jwk(CipherSuite suite) const;
TLS_SERIALIZABLE(data)
private:
SignerFunc _sign_func;
SignaturePrivateKey(bytes priv_data,
bytes pub_data,
SignerFunc func = SignerFunc());
};
} // namespace MLS_NAMESPACE