Coverage Report

Created: 2026-10-19 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/crypto/hpke/hpke.cc
Line
Count
Source
1
// Copyright 2020 The BoringSSL Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#include <openssl/hpke.h>
16
17
#include <assert.h>
18
#include <string.h>
19
20
#include <array>
21
#include <string_view>
22
23
#include <openssl/aead.h>
24
#include <openssl/bytestring.h>
25
#include <openssl/curve25519.h>
26
#include <openssl/digest.h>
27
#include <openssl/ec.h>
28
#include <openssl/err.h>
29
#include <openssl/evp.h>
30
#include <openssl/evp_errors.h>
31
#include <openssl/hkdf.h>
32
#include <openssl/mem.h>
33
#include <openssl/mlkem.h>
34
#include <openssl/rand.h>
35
#include <openssl/sha2.h>
36
#include <openssl/span.h>
37
#include <openssl/xwing.h>
38
39
#include "../fipsmodule/ec/internal.h"
40
#include "../fipsmodule/keccak/internal.h"
41
#include "../internal.h"
42
#include "../mem_internal.h"
43
44
45
using namespace bssl;
46
47
// This file implements RFC 9180.
48
49
#define MAX_SEED_LEN XWING_SEED_LEN
50
#define MAX_SHARED_SECRET_LEN SHA256_DIGEST_LENGTH
51
52
namespace {
53
54
// HpkeKeyMethod implements the key-type-specific operations that HPKE performs
55
// on keys of a particular `EVP_PKEY_ALG` type.
56
struct HpkeKeyMethod {
57
  // hpke_kem_id is the ID of the KEM in RFC 9180.
58
  uint16_t hpke_kem_id;
59
60
  // public_key_len corresponds to Npk in RFC 9180.
61
  size_t public_key_len;
62
  // private_key_len corresponds to Nsk in RFC 9180.
63
  size_t private_key_len;
64
65
  const EVP_PKEY_ALG *(*alg_func)();
66
67
  // deserialize_private_key and serialize_private_key implement the
68
  // DeserializePrivateKey and SerializePrivateKey operations for the key type
69
  // from section 4 of RFC 9180, using the same format accepted by
70
  // `EVP_HPKE_KEY_init`.
71
  EVP_PKEY *(*deserialize_private_key)(const EVP_PKEY_ALG *alg,
72
                                       const uint8_t *in, size_t len);
73
  int (*serialize_private_key)(const EVP_PKEY *pkey, uint8_t *out,
74
                               size_t *out_len);
75
76
  // deserialize_public_key and serialize_public_key implement the
77
  // DeserializePublicKey and SerializePublicKey operations from section 4 of
78
  // RFC 9180.
79
  EVP_PKEY *(*deserialize_public_key)(const EVP_PKEY_ALG *alg,
80
                                      const uint8_t *in, size_t len);
81
  int (*serialize_public_key)(const EVP_PKEY *pkey, uint8_t *out,
82
                              size_t *out_len);
83
84
  // derive_key_pair implements the DeriveKeyPair operation from section 4 of
85
  // RFC 9180.
86
  EVP_PKEY *(*derive_key_pair)(const EVP_PKEY_ALG *alg, uint16_t kem_suite_id,
87
                               Span<const uint8_t> ikm);
88
};
89
90
}  // namespace
91
92
struct evp_hpke_kem_st {
93
  uint16_t id;
94
95
  // evp_kem_func and key_method, if non-null, provide the EVP_PKEY_CTX and
96
  // EVP_KEM functionality backing this EVP_HPKE_KEM. If these are non-null,
97
  // then (until fully migrated):
98
  //  * `init_key`, `generate_key`, and `derive_key` are null (these operations
99
  //    are supplied by `key_method`),
100
  //  * `encap_with_seed`, and `decap` are null (these operations are supplied
101
  //    by the `EVP_KEM`),
102
  //  * `public_key_len` and `private_key_len` are zero (they are supplied by
103
  //    `key_method`), and
104
  //  * `seed_len` and `enc_len` are zero (they are supplied by the `EVP_KEM`).
105
  // TODO(crbug.com/535883377): Unify EVP_HPKE_KEM and EVP_KEM for all supported
106
  // HPKE KEMs.
107
  const EVP_KEM *(*evp_kem_func)();
108
  const HpkeKeyMethod *key_method;
109
110
  size_t public_key_len;
111
  size_t private_key_len;
112
  size_t seed_len;
113
  size_t enc_len;
114
  int (*init_key)(EVP_HPKE_KEY *key, const uint8_t *priv_key,
115
                  size_t priv_key_len);
116
  int (*generate_key)(EVP_HPKE_KEY *key);
117
  int (*derive_key)(EVP_HPKE_KEY *key, Span<const uint8_t> ikm);
118
  int (*encap_with_seed)(const EVP_HPKE_KEM *kem, uint8_t *out_shared_secret,
119
                         size_t *out_shared_secret_len, uint8_t *out_enc,
120
                         size_t *out_enc_len, size_t max_enc,
121
                         const uint8_t *peer_public_key,
122
                         size_t peer_public_key_len, const uint8_t *seed,
123
                         size_t seed_len);
124
  int (*decap)(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
125
               size_t *out_shared_secret_len, const uint8_t *enc,
126
               size_t enc_len);
127
  int (*auth_encap_with_seed)(const EVP_HPKE_KEY *key,
128
                              uint8_t *out_shared_secret,
129
                              size_t *out_shared_secret_len, uint8_t *out_enc,
130
                              size_t *out_enc_len, size_t max_enc,
131
                              const uint8_t *peer_public_key,
132
                              size_t peer_public_key_len, const uint8_t *seed,
133
                              size_t seed_len);
134
  int (*auth_decap)(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
135
                    size_t *out_shared_secret_len, const uint8_t *enc,
136
                    size_t enc_len, const uint8_t *peer_public_key,
137
                    size_t peer_public_key_len);
138
};
139
140
struct evp_hpke_kdf_st {
141
  uint16_t id;
142
  // We only support HKDF-based KDFs.
143
  const EVP_MD *(*hkdf_md_func)();
144
};
145
146
struct evp_hpke_aead_st {
147
  uint16_t id;
148
  const EVP_AEAD *(*aead_func)();
149
};
150
151
152
// Low-level labeled KDF functions.
153
154
static const char kHpkeVersionId[] = "HPKE-v1";
155
156
4.65k
static int add_label_string(CBB *cbb, const char *label) {
157
4.65k
  return CBB_add_bytes(cbb, (const uint8_t *)label, strlen(label));
158
4.65k
}
159
160
static int hpke_labeled_extract(const EVP_MD *hkdf_md, uint8_t *out_key,
161
                                size_t *out_len, const uint8_t *salt,
162
                                size_t salt_len, const uint8_t *suite_id,
163
                                size_t suite_id_len, const char *label,
164
1.16k
                                const uint8_t *ikm, size_t ikm_len) {
165
  // labeledIKM = concat("HPKE-v1", suite_id, label, IKM)
166
1.16k
  CBB labeled_ikm;
167
1.16k
  int ok = CBB_init(&labeled_ikm, 0) &&
168
1.16k
           add_label_string(&labeled_ikm, kHpkeVersionId) &&
169
1.16k
           CBB_add_bytes(&labeled_ikm, suite_id, suite_id_len) &&
170
1.16k
           add_label_string(&labeled_ikm, label) &&
171
1.16k
           CBB_add_bytes(&labeled_ikm, ikm, ikm_len) &&
172
1.16k
           HKDF_extract(out_key, out_len, hkdf_md, CBB_data(&labeled_ikm),
173
1.16k
                        CBB_len(&labeled_ikm), salt, salt_len);
174
1.16k
  CBB_cleanup(&labeled_ikm);
175
1.16k
  return ok;
176
1.16k
}
177
178
static int hpke_labeled_expand(const EVP_MD *hkdf_md, uint8_t *out_key,
179
                               size_t out_len, const uint8_t *prk,
180
                               size_t prk_len, const uint8_t *suite_id,
181
                               size_t suite_id_len, const char *label,
182
1.16k
                               const uint8_t *info, size_t info_len) {
183
  // labeledInfo = concat(I2OSP(L, 2), "HPKE-v1", suite_id, label, info)
184
1.16k
  CBB labeled_info;
185
1.16k
  int ok = CBB_init(&labeled_info, 0) &&  //
186
1.16k
           CBB_add_u16(&labeled_info, out_len) &&
187
1.16k
           add_label_string(&labeled_info, kHpkeVersionId) &&
188
1.16k
           CBB_add_bytes(&labeled_info, suite_id, suite_id_len) &&
189
1.16k
           add_label_string(&labeled_info, label) &&
190
1.16k
           CBB_add_bytes(&labeled_info, info, info_len) &&
191
1.16k
           HKDF_expand(out_key, out_len, hkdf_md, prk, prk_len,
192
1.16k
                       CBB_data(&labeled_info), CBB_len(&labeled_info));
193
1.16k
  CBB_cleanup(&labeled_info);
194
1.16k
  return ok;
195
1.16k
}
196
197
0
static void absorb_u16(BORINGSSL_keccak_st *ctx, uint16_t n) {
198
0
  uint8_t bytes[2];
199
0
  CRYPTO_store_u16_be(bytes, n);
200
0
  BORINGSSL_keccak_absorb(ctx, bytes, sizeof(bytes));
201
0
}
202
203
static void hpke_shake256_labeled_derive(Span<uint8_t> out,
204
                                         Span<const uint8_t> ikm,
205
                                         Span<const uint8_t> suite_id,
206
                                         std::string_view label,
207
0
                                         Span<const uint8_t> context) {
208
  // https://www.ietf.org/archive/id/draft-ietf-hpke-hpke-03.html#name-labeled-derivation-function
209
  // https://www.ietf.org/archive/id/draft-ietf-hpke-pq-04.html#name-single-stage-kdfs
210
0
  BORINGSSL_keccak_st ctx;
211
0
  BORINGSSL_keccak_init(&ctx, boringssl_shake256);
212
0
  BORINGSSL_keccak_absorb(&ctx, ikm.data(), ikm.size());
213
0
  auto hpke_version_id = StringAsBytes(kHpkeVersionId);
214
0
  BORINGSSL_keccak_absorb(&ctx, hpke_version_id.data(), hpke_version_id.size());
215
0
  BORINGSSL_keccak_absorb(&ctx, suite_id.data(), suite_id.size());
216
0
  auto label_bytes = StringAsBytes(label);
217
0
  assert(label_bytes.size() < 0xffff);
218
0
  absorb_u16(&ctx, static_cast<uint16_t>(label_bytes.size()));
219
0
  BORINGSSL_keccak_absorb(&ctx, label_bytes.data(), label_bytes.size());
220
0
  assert(out.size() <= 0xffff);
221
0
  absorb_u16(&ctx, static_cast<uint16_t>(out.size()));
222
0
  BORINGSSL_keccak_absorb(&ctx, context.data(), context.size());
223
0
  BORINGSSL_keccak_squeeze(&ctx, out.data(), out.size());
224
0
}
225
226
227
// KEM implementations.
228
229
291
static std::array<uint8_t, 5> hpke_kem_suite_id(uint16_t kem_id) {
230
  // concat("KEM", I2OSP(kem_id, 2))
231
291
  return {'K', 'E', 'M', static_cast<uint8_t>(kem_id >> 8),
232
291
          static_cast<uint8_t>(kem_id)};
233
291
}
234
235
// dhkem_extract_and_expand implements the ExtractAndExpand operation in the
236
// DHKEM construction. See section 4.1 of RFC 9180.
237
static int dhkem_extract_and_expand(uint16_t kem_id, const EVP_MD *hkdf_md,
238
                                    uint8_t *out_key, size_t out_len,
239
                                    const uint8_t *dh, size_t dh_len,
240
                                    const uint8_t *kem_context,
241
291
                                    size_t kem_context_len) {
242
291
  auto suite_id = hpke_kem_suite_id(kem_id);
243
291
  uint8_t prk[EVP_MAX_MD_SIZE];
244
291
  size_t prk_len;
245
291
  return hpke_labeled_extract(hkdf_md, prk, &prk_len, nullptr, 0,
246
291
                              suite_id.data(), suite_id.size(), "eae_prk", dh,
247
291
                              dh_len) &&
248
291
         hpke_labeled_expand(hkdf_md, out_key, out_len, prk, prk_len,
249
291
                             suite_id.data(), suite_id.size(), "shared_secret",
250
291
                             kem_context, kem_context_len);
251
291
}
252
253
static int x25519_init_key(EVP_HPKE_KEY *key, const uint8_t *priv_key,
254
13.6k
                           size_t priv_key_len) {
255
13.6k
  if (priv_key_len != X25519_PRIVATE_KEY_LEN) {
256
802
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
257
802
    return 0;
258
802
  }
259
260
12.8k
  OPENSSL_memcpy(key->private_key, priv_key, priv_key_len);
261
12.8k
  X25519_public_from_private(key->public_key, priv_key);
262
12.8k
  return 1;
263
13.6k
}
264
265
0
static int x25519_generate_key(EVP_HPKE_KEY *key) {
266
0
  X25519_keypair(key->public_key, key->private_key);
267
0
  return 1;
268
0
}
269
270
0
static int x25519_derive_key(EVP_HPKE_KEY *key, Span<const uint8_t> ikm) {
271
  // https://www.rfc-editor.org/rfc/rfc9180.html#name-derivekeypair
272
0
  auto suite_id = hpke_kem_suite_id(EVP_HPKE_DHKEM_X25519_HKDF_SHA256);
273
0
  uint8_t dkp_prk[SHA256_DIGEST_LENGTH];
274
0
  size_t dkp_prk_len;
275
0
  uint8_t sk[32];
276
0
  if (!hpke_labeled_extract(EVP_sha256(), dkp_prk, &dkp_prk_len, nullptr, 0,
277
0
                            suite_id.data(), suite_id.size(), "dkp_prk",
278
0
                            ikm.data(), ikm.size()) ||
279
0
      !hpke_labeled_expand(EVP_sha256(), sk, sizeof(sk), dkp_prk, dkp_prk_len,
280
0
                           suite_id.data(), suite_id.size(), "sk",
281
0
                           /*info=*/nullptr, /*info_len=*/0)) {
282
0
    return 0;
283
0
  }
284
0
  return x25519_init_key(key, sk, sizeof(sk));
285
0
}
286
287
static int x25519_encap_with_seed(
288
    const EVP_HPKE_KEM *kem, uint8_t *out_shared_secret,
289
    size_t *out_shared_secret_len, uint8_t *out_enc, size_t *out_enc_len,
290
    size_t max_enc, const uint8_t *peer_public_key, size_t peer_public_key_len,
291
0
    const uint8_t *seed, size_t seed_len) {
292
0
  if (max_enc < X25519_PUBLIC_VALUE_LEN) {
293
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
294
0
    return 0;
295
0
  }
296
0
  if (seed_len != X25519_PRIVATE_KEY_LEN) {
297
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
298
0
    return 0;
299
0
  }
300
0
  X25519_public_from_private(out_enc, seed);
301
302
0
  uint8_t dh[X25519_SHARED_KEY_LEN];
303
0
  if (peer_public_key_len != X25519_PUBLIC_VALUE_LEN ||
304
0
      !X25519(dh, seed, peer_public_key)) {
305
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
306
0
    return 0;
307
0
  }
308
309
0
  uint8_t kem_context[2 * X25519_PUBLIC_VALUE_LEN];
310
0
  OPENSSL_memcpy(kem_context, out_enc, X25519_PUBLIC_VALUE_LEN);
311
0
  OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, peer_public_key,
312
0
                 X25519_PUBLIC_VALUE_LEN);
313
0
  if (!dhkem_extract_and_expand(kem->id, EVP_sha256(), out_shared_secret,
314
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
315
0
                                kem_context, sizeof(kem_context))) {
316
0
    return 0;
317
0
  }
318
319
0
  *out_enc_len = X25519_PUBLIC_VALUE_LEN;
320
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
321
0
  return 1;
322
0
}
323
324
static int x25519_decap(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
325
                        size_t *out_shared_secret_len, const uint8_t *enc,
326
303
                        size_t enc_len) {
327
303
  uint8_t dh[X25519_SHARED_KEY_LEN];
328
303
  if (enc_len != X25519_PUBLIC_VALUE_LEN ||
329
294
      !X25519(dh, key->private_key, enc)) {
330
12
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
331
12
    return 0;
332
12
  }
333
334
291
  uint8_t kem_context[2 * X25519_PUBLIC_VALUE_LEN];
335
291
  OPENSSL_memcpy(kem_context, enc, X25519_PUBLIC_VALUE_LEN);
336
291
  OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, key->public_key,
337
291
                 X25519_PUBLIC_VALUE_LEN);
338
291
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
339
291
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
340
291
                                kem_context, sizeof(kem_context))) {
341
0
    return 0;
342
0
  }
343
344
291
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
345
291
  return 1;
346
291
}
347
348
static int x25519_auth_encap_with_seed(
349
    const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
350
    size_t *out_shared_secret_len, uint8_t *out_enc, size_t *out_enc_len,
351
    size_t max_enc, const uint8_t *peer_public_key, size_t peer_public_key_len,
352
0
    const uint8_t *seed, size_t seed_len) {
353
0
  if (max_enc < X25519_PUBLIC_VALUE_LEN) {
354
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
355
0
    return 0;
356
0
  }
357
0
  if (seed_len != X25519_PRIVATE_KEY_LEN) {
358
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
359
0
    return 0;
360
0
  }
361
0
  X25519_public_from_private(out_enc, seed);
362
363
0
  uint8_t dh[2 * X25519_SHARED_KEY_LEN];
364
0
  if (peer_public_key_len != X25519_PUBLIC_VALUE_LEN ||
365
0
      !X25519(dh, seed, peer_public_key) ||
366
0
      !X25519(dh + X25519_SHARED_KEY_LEN, key->private_key, peer_public_key)) {
367
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
368
0
    return 0;
369
0
  }
370
371
0
  uint8_t kem_context[3 * X25519_PUBLIC_VALUE_LEN];
372
0
  OPENSSL_memcpy(kem_context, out_enc, X25519_PUBLIC_VALUE_LEN);
373
0
  OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, peer_public_key,
374
0
                 X25519_PUBLIC_VALUE_LEN);
375
0
  OPENSSL_memcpy(kem_context + 2 * X25519_PUBLIC_VALUE_LEN, key->public_key,
376
0
                 X25519_PUBLIC_VALUE_LEN);
377
0
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
378
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
379
0
                                kem_context, sizeof(kem_context))) {
380
0
    return 0;
381
0
  }
382
383
0
  *out_enc_len = X25519_PUBLIC_VALUE_LEN;
384
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
385
0
  return 1;
386
0
}
387
388
static int x25519_auth_decap(const EVP_HPKE_KEY *key,
389
                             uint8_t *out_shared_secret,
390
                             size_t *out_shared_secret_len, const uint8_t *enc,
391
                             size_t enc_len, const uint8_t *peer_public_key,
392
0
                             size_t peer_public_key_len) {
393
0
  uint8_t dh[2 * X25519_SHARED_KEY_LEN];
394
0
  if (enc_len != X25519_PUBLIC_VALUE_LEN ||
395
0
      peer_public_key_len != X25519_PUBLIC_VALUE_LEN ||
396
0
      !X25519(dh, key->private_key, enc) ||
397
0
      !X25519(dh + X25519_SHARED_KEY_LEN, key->private_key, peer_public_key)) {
398
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
399
0
    return 0;
400
0
  }
401
402
0
  uint8_t kem_context[3 * X25519_PUBLIC_VALUE_LEN];
403
0
  OPENSSL_memcpy(kem_context, enc, X25519_PUBLIC_VALUE_LEN);
404
0
  OPENSSL_memcpy(kem_context + X25519_PUBLIC_VALUE_LEN, key->public_key,
405
0
                 X25519_PUBLIC_VALUE_LEN);
406
0
  OPENSSL_memcpy(kem_context + 2 * X25519_PUBLIC_VALUE_LEN, peer_public_key,
407
0
                 X25519_PUBLIC_VALUE_LEN);
408
0
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
409
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
410
0
                                kem_context, sizeof(kem_context))) {
411
0
    return 0;
412
0
  }
413
414
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
415
0
  return 1;
416
0
}
417
418
13.6k
const EVP_HPKE_KEM *EVP_hpke_x25519_hkdf_sha256() {
419
13.6k
  static const EVP_HPKE_KEM kKEM = {
420
13.6k
      /*id=*/EVP_HPKE_DHKEM_X25519_HKDF_SHA256,
421
      // TODO(crbug.com/503758094): Expose this as an EVP_KEM.
422
13.6k
      /*evp_kem_func=*/nullptr,
423
13.6k
      /*key_method=*/nullptr,
424
13.6k
      /*public_key_len=*/X25519_PUBLIC_VALUE_LEN,
425
13.6k
      /*private_key_len=*/X25519_PRIVATE_KEY_LEN,
426
13.6k
      /*seed_len=*/X25519_PRIVATE_KEY_LEN,
427
13.6k
      /*enc_len=*/X25519_PUBLIC_VALUE_LEN,
428
13.6k
      x25519_init_key,
429
13.6k
      x25519_generate_key,
430
13.6k
      x25519_derive_key,
431
13.6k
      x25519_encap_with_seed,
432
13.6k
      x25519_decap,
433
13.6k
      x25519_auth_encap_with_seed,
434
13.6k
      x25519_auth_decap,
435
13.6k
  };
436
13.6k
  return &kKEM;
437
13.6k
}
438
439
0
#define P256_PRIVATE_KEY_LEN 32
440
0
#define P256_PUBLIC_KEY_LEN 65
441
0
#define P256_PUBLIC_VALUE_LEN 65
442
0
#define P256_SEED_LEN 32
443
0
#define P256_SHARED_KEY_LEN 32
444
445
static int p256_public_from_private(uint8_t out_pub[P256_PUBLIC_VALUE_LEN],
446
0
                                    const uint8_t priv[P256_PRIVATE_KEY_LEN]) {
447
0
  const EC_GROUP *const group = EC_group_p256();
448
0
  const uint8_t kAllZeros[P256_PRIVATE_KEY_LEN] = {0};
449
0
  EC_SCALAR private_scalar;
450
0
  EC_JACOBIAN public_point;
451
0
  EC_AFFINE public_point_affine;
452
453
0
  if (CRYPTO_memcmp(kAllZeros, priv, sizeof(kAllZeros)) == 0) {
454
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
455
0
    return 0;
456
0
  }
457
458
0
  if (!ec_scalar_from_bytes(group, &private_scalar, priv,
459
0
                            P256_PRIVATE_KEY_LEN) ||
460
0
      !ec_point_mul_scalar_base(group, &public_point, &private_scalar) ||
461
0
      !ec_jacobian_to_affine(group, &public_point_affine, &public_point)) {
462
0
    return 0;
463
0
  }
464
465
0
  size_t out_len_x, out_len_y;
466
0
  out_pub[0] = POINT_CONVERSION_UNCOMPRESSED;
467
0
  ec_felem_to_bytes(group, &out_pub[1], &out_len_x, &public_point_affine.X);
468
0
  ec_felem_to_bytes(group, &out_pub[33], &out_len_y, &public_point_affine.Y);
469
0
  return 1;
470
0
}
471
472
static int p256_init_key(EVP_HPKE_KEY *key, const uint8_t *priv_key,
473
0
                         size_t priv_key_len) {
474
0
  if (priv_key_len != P256_PRIVATE_KEY_LEN) {
475
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
476
0
    return 0;
477
0
  }
478
479
0
  if (!p256_public_from_private(key->public_key, priv_key)) {
480
0
    return 0;
481
0
  }
482
483
0
  OPENSSL_memcpy(key->private_key, priv_key, priv_key_len);
484
0
  return 1;
485
0
}
486
487
static int p256_private_key_from_seed(uint8_t out_priv[P256_PRIVATE_KEY_LEN],
488
0
                                      const uint8_t *seed, size_t seed_len) {
489
  // https://www.rfc-editor.org/rfc/rfc9180.html#name-derivekeypair
490
0
  auto suite_id = hpke_kem_suite_id(EVP_HPKE_DHKEM_P256_HKDF_SHA256);
491
0
  uint8_t dkp_prk[32];
492
0
  size_t dkp_prk_len;
493
0
  if (!hpke_labeled_extract(EVP_sha256(), dkp_prk, &dkp_prk_len, nullptr, 0,
494
0
                            suite_id.data(), suite_id.size(), "dkp_prk", seed,
495
0
                            seed_len)) {
496
0
    return 0;
497
0
  }
498
0
  assert(dkp_prk_len == sizeof(dkp_prk));
499
500
0
  const EC_GROUP *const group = EC_group_p256();
501
0
  EC_SCALAR private_scalar;
502
503
0
  for (unsigned counter = 0; counter < 256; counter++) {
504
0
    const uint8_t counter_byte = counter & 0xff;
505
0
    if (!hpke_labeled_expand(EVP_sha256(), out_priv, P256_PRIVATE_KEY_LEN,
506
0
                             dkp_prk, sizeof(dkp_prk), suite_id.data(),
507
0
                             suite_id.size(), "candidate", &counter_byte,
508
0
                             sizeof(counter_byte))) {
509
0
      return 0;
510
0
    }
511
512
    // `ec_scalar_from_bytes` checks that the scalar is less than the order.
513
0
    if (ec_scalar_from_bytes(group, &private_scalar, out_priv,
514
0
                             P256_PRIVATE_KEY_LEN) &&
515
0
        !ec_scalar_is_zero(group, &private_scalar)) {
516
0
      return 1;
517
0
    }
518
0
  }
519
520
  // This happens with probability of 2^-(32*256).
521
0
  OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
522
0
  return 0;
523
0
}
524
525
0
static int p256_derive_key(EVP_HPKE_KEY *key, Span<const uint8_t> ikm) {
526
0
  if (!p256_private_key_from_seed(key->private_key, ikm.data(), ikm.size()) ||
527
0
      !p256_public_from_private(key->public_key, key->private_key)) {
528
0
    return 0;
529
0
  }
530
0
  return 1;
531
0
}
532
533
0
static int p256_generate_key(EVP_HPKE_KEY *key) {
534
0
  uint8_t seed[P256_SEED_LEN];
535
0
  RAND_bytes(seed, sizeof(seed));
536
0
  return p256_derive_key(key, seed);
537
0
}
538
539
static int p256(uint8_t out_dh[P256_SHARED_KEY_LEN],
540
                const uint8_t my_private[P256_PRIVATE_KEY_LEN],
541
0
                const uint8_t their_public[P256_PUBLIC_VALUE_LEN]) {
542
0
  const EC_GROUP *const group = EC_group_p256();
543
0
  EC_SCALAR private_scalar;
544
0
  EC_FELEM x, y;
545
0
  EC_JACOBIAN shared_point, their_point;
546
0
  EC_AFFINE their_point_affine, shared_point_affine;
547
548
0
  if (their_public[0] != POINT_CONVERSION_UNCOMPRESSED ||
549
0
      !ec_felem_from_bytes(group, &x, &their_public[1], 32) ||
550
0
      !ec_felem_from_bytes(group, &y, &their_public[33], 32) ||
551
0
      !ec_point_set_affine_coordinates(group, &their_point_affine, &x, &y) ||
552
0
      !ec_scalar_from_bytes(group, &private_scalar, my_private,
553
0
                            P256_PRIVATE_KEY_LEN)) {
554
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
555
0
    return 0;
556
0
  }
557
558
0
  ec_affine_to_jacobian(group, &their_point, &their_point_affine);
559
0
  if (!ec_point_mul_scalar(group, &shared_point, &their_point,
560
0
                           &private_scalar) ||
561
0
      !ec_jacobian_to_affine(group, &shared_point_affine, &shared_point)) {
562
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_INTERNAL_ERROR);
563
0
    return 0;
564
0
  }
565
566
0
  size_t out_len;
567
0
  ec_felem_to_bytes(group, out_dh, &out_len, &shared_point_affine.X);
568
0
  assert(out_len == P256_SHARED_KEY_LEN);
569
0
  return 1;
570
0
}
571
572
static int p256_encap_with_seed(const EVP_HPKE_KEM *kem,
573
                                uint8_t *out_shared_secret,
574
                                size_t *out_shared_secret_len, uint8_t *out_enc,
575
                                size_t *out_enc_len, size_t max_enc,
576
                                const uint8_t *peer_public_key,
577
                                size_t peer_public_key_len, const uint8_t *seed,
578
0
                                size_t seed_len) {
579
0
  if (max_enc < P256_PUBLIC_VALUE_LEN) {
580
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
581
0
    return 0;
582
0
  }
583
0
  if (seed_len != P256_SEED_LEN) {
584
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
585
0
    return 0;
586
0
  }
587
0
  uint8_t private_key[P256_PRIVATE_KEY_LEN];
588
0
  if (!p256_private_key_from_seed(private_key, seed, seed_len) ||
589
0
      !p256_public_from_private(out_enc, private_key)) {
590
0
    return 0;
591
0
  }
592
593
0
  uint8_t dh[P256_SHARED_KEY_LEN];
594
0
  if (peer_public_key_len != P256_PUBLIC_VALUE_LEN ||
595
0
      !p256(dh, private_key, peer_public_key)) {
596
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
597
0
    return 0;
598
0
  }
599
600
0
  uint8_t kem_context[2 * P256_PUBLIC_VALUE_LEN];
601
0
  OPENSSL_memcpy(kem_context, out_enc, P256_PUBLIC_VALUE_LEN);
602
0
  OPENSSL_memcpy(kem_context + P256_PUBLIC_VALUE_LEN, peer_public_key,
603
0
                 P256_PUBLIC_VALUE_LEN);
604
0
  if (!dhkem_extract_and_expand(kem->id, EVP_sha256(), out_shared_secret,
605
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
606
0
                                kem_context, sizeof(kem_context))) {
607
0
    return 0;
608
0
  }
609
610
0
  *out_enc_len = P256_PUBLIC_VALUE_LEN;
611
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
612
0
  return 1;
613
0
}
614
615
static int p256_decap(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
616
                      size_t *out_shared_secret_len, const uint8_t *enc,
617
0
                      size_t enc_len) {
618
0
  uint8_t dh[P256_SHARED_KEY_LEN];
619
0
  if (enc_len != P256_PUBLIC_VALUE_LEN ||  //
620
0
      !p256(dh, key->private_key, enc)) {
621
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
622
0
    return 0;
623
0
  }
624
625
0
  uint8_t kem_context[2 * P256_PUBLIC_VALUE_LEN];
626
0
  OPENSSL_memcpy(kem_context, enc, P256_PUBLIC_VALUE_LEN);
627
0
  OPENSSL_memcpy(kem_context + P256_PUBLIC_VALUE_LEN, key->public_key,
628
0
                 P256_PUBLIC_VALUE_LEN);
629
0
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
630
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
631
0
                                kem_context, sizeof(kem_context))) {
632
0
    return 0;
633
0
  }
634
635
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
636
0
  return 1;
637
0
}
638
639
static int p256_auth_encap_with_seed(
640
    const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
641
    size_t *out_shared_secret_len, uint8_t *out_enc, size_t *out_enc_len,
642
    size_t max_enc, const uint8_t *peer_public_key, size_t peer_public_key_len,
643
0
    const uint8_t *seed, size_t seed_len) {
644
0
  if (max_enc < P256_PUBLIC_VALUE_LEN) {
645
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
646
0
    return 0;
647
0
  }
648
0
  if (seed_len != P256_SEED_LEN) {
649
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
650
0
    return 0;
651
0
  }
652
0
  uint8_t private_key[P256_PRIVATE_KEY_LEN];
653
0
  if (!p256_private_key_from_seed(private_key, seed, seed_len) ||
654
0
      !p256_public_from_private(out_enc, private_key)) {
655
0
    return 0;
656
0
  }
657
658
0
  uint8_t dh[2 * P256_SHARED_KEY_LEN];
659
0
  if (peer_public_key_len != P256_PUBLIC_VALUE_LEN ||
660
0
      !p256(dh, private_key, peer_public_key) ||
661
0
      !p256(dh + P256_SHARED_KEY_LEN, key->private_key, peer_public_key)) {
662
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
663
0
    return 0;
664
0
  }
665
666
0
  uint8_t kem_context[3 * P256_PUBLIC_VALUE_LEN];
667
0
  OPENSSL_memcpy(kem_context, out_enc, P256_PUBLIC_VALUE_LEN);
668
0
  OPENSSL_memcpy(kem_context + P256_PUBLIC_VALUE_LEN, peer_public_key,
669
0
                 P256_PUBLIC_VALUE_LEN);
670
0
  OPENSSL_memcpy(kem_context + 2 * P256_PUBLIC_VALUE_LEN, key->public_key,
671
0
                 P256_PUBLIC_VALUE_LEN);
672
0
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
673
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
674
0
                                kem_context, sizeof(kem_context))) {
675
0
    return 0;
676
0
  }
677
678
0
  *out_enc_len = P256_PUBLIC_VALUE_LEN;
679
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
680
0
  return 1;
681
0
}
682
683
static int p256_auth_decap(const EVP_HPKE_KEY *key, uint8_t *out_shared_secret,
684
                           size_t *out_shared_secret_len, const uint8_t *enc,
685
                           size_t enc_len, const uint8_t *peer_public_key,
686
0
                           size_t peer_public_key_len) {
687
0
  uint8_t dh[2 * P256_SHARED_KEY_LEN];
688
0
  if (enc_len != P256_PUBLIC_VALUE_LEN ||
689
0
      peer_public_key_len != P256_PUBLIC_VALUE_LEN ||
690
0
      !p256(dh, key->private_key, enc) ||
691
0
      !p256(dh + P256_SHARED_KEY_LEN, key->private_key, peer_public_key)) {
692
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PEER_KEY);
693
0
    return 0;
694
0
  }
695
696
0
  uint8_t kem_context[3 * P256_PUBLIC_VALUE_LEN];
697
0
  OPENSSL_memcpy(kem_context, enc, P256_PUBLIC_VALUE_LEN);
698
0
  OPENSSL_memcpy(kem_context + P256_PUBLIC_VALUE_LEN, key->public_key,
699
0
                 P256_PUBLIC_VALUE_LEN);
700
0
  OPENSSL_memcpy(kem_context + 2 * P256_PUBLIC_VALUE_LEN, peer_public_key,
701
0
                 P256_PUBLIC_VALUE_LEN);
702
0
  if (!dhkem_extract_and_expand(key->kem->id, EVP_sha256(), out_shared_secret,
703
0
                                SHA256_DIGEST_LENGTH, dh, sizeof(dh),
704
0
                                kem_context, sizeof(kem_context))) {
705
0
    return 0;
706
0
  }
707
708
0
  *out_shared_secret_len = SHA256_DIGEST_LENGTH;
709
0
  return 1;
710
0
}
711
712
0
const EVP_HPKE_KEM *EVP_hpke_p256_hkdf_sha256() {
713
0
  static const EVP_HPKE_KEM kKEM = {
714
0
      /*id=*/EVP_HPKE_DHKEM_P256_HKDF_SHA256,
715
      // TODO(crbug.com/503758094): Expose this as an EVP_KEM.
716
0
      /*evp_kem_func=*/nullptr,
717
0
      /*key_method=*/nullptr,
718
0
      /*public_key_len=*/P256_PUBLIC_KEY_LEN,
719
0
      /*private_key_len=*/P256_PRIVATE_KEY_LEN,
720
0
      /*seed_len=*/P256_SEED_LEN,
721
0
      /*enc_len=*/P256_PUBLIC_VALUE_LEN,
722
0
      p256_init_key,
723
0
      p256_generate_key,
724
0
      p256_derive_key,
725
0
      p256_encap_with_seed,
726
0
      p256_decap,
727
0
      p256_auth_encap_with_seed,
728
0
      p256_auth_decap,
729
0
  };
730
0
  return &kKEM;
731
0
}
732
733
#define XWING_PRIVATE_KEY_LEN XWING_PRIVATE_KEY_BYTES
734
#define XWING_PUBLIC_KEY_LEN XWING_PUBLIC_KEY_BYTES
735
#define XWING_PUBLIC_VALUE_LEN XWING_CIPHERTEXT_BYTES
736
#define XWING_SEED_LEN 64
737
#define XWING_SHARED_KEY_LEN XWING_SHARED_SECRET_BYTES
738
739
template <size_t SEED_BYTES>
740
static EVP_PKEY *shake256_derive_key_pair_from_private_seed(
741
0
    const EVP_PKEY_ALG *alg, uint16_t kem_suite_id, Span<const uint8_t> ikm) {
742
0
  uint8_t seed[SEED_BYTES];
743
0
  hpke_shake256_labeled_derive(seed, ikm, hpke_kem_suite_id(kem_suite_id),
744
0
                               "DeriveKeyPair", /*context=*/{});
745
0
  return EVP_PKEY_from_private_seed(alg, seed, sizeof(seed));
746
0
}
Unexecuted instantiation: hpke.cc:evp_pkey_st* shake256_derive_key_pair_from_private_seed<32ul>(evp_pkey_alg_st const*, unsigned short, bssl::Span<unsigned char const, 18446744073709551615ul>)
Unexecuted instantiation: hpke.cc:evp_pkey_st* shake256_derive_key_pair_from_private_seed<64ul>(evp_pkey_alg_st const*, unsigned short, bssl::Span<unsigned char const, 18446744073709551615ul>)
747
748
static constexpr HpkeKeyMethod kXwingKeyMethod = {
749
    /*hpke_kem_id=*/EVP_HPKE_XWING,
750
    /*public_key_len=*/XWING_PUBLIC_KEY_LEN,
751
    /*private_key_len=*/XWING_PRIVATE_KEY_LEN,
752
    /*alg_func=*/&EVP_pkey_xwing,
753
    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
754
    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
755
    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
756
    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
757
    /*derive_key_pair=*/
758
    shake256_derive_key_pair_from_private_seed<XWING_PRIVATE_KEY_LEN>,
759
};
760
761
0
const EVP_HPKE_KEM *EVP_hpke_xwing() {
762
0
  static const EVP_HPKE_KEM kKEM = {
763
0
      /*id=*/EVP_HPKE_XWING,
764
0
      /*evp_kem_func=*/&EVP_kem_xwing,
765
0
      /*key_method=*/&kXwingKeyMethod,
766
0
      /*public_key_len=*/0,
767
0
      /*private_key_len=*/0,
768
0
      /*seed_len=*/0,
769
0
      /*enc_len=*/0,
770
0
      /*init_key=*/nullptr,
771
0
      /*generate_key=*/nullptr,
772
0
      /*derive_key=*/nullptr,
773
0
      /*encap_with_seed=*/nullptr,
774
0
      /*decap=*/nullptr,
775
      // X-Wing doesn't support authenticated encapsulation/decapsulation:
776
      // https://datatracker.ietf.org/doc/html/draft-connolly-cfrg-xwing-kem-08#name-use-in-hpke
777
0
      /*auth_encap_with_seed=*/nullptr,
778
0
      /*auth_decap=*/nullptr,
779
0
  };
780
0
  return &kKEM;
781
0
}
782
783
static constexpr HpkeKeyMethod kMlkem768KeyMethod = {
784
    /*hpke_kem_id=*/EVP_HPKE_MLKEM768,
785
    /*public_key_len=*/MLKEM768_PUBLIC_KEY_BYTES,
786
    /*private_key_len=*/MLKEM_SEED_BYTES,
787
    /*alg_func=*/&EVP_pkey_ml_kem_768,
788
    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
789
    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
790
    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
791
    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
792
    /*derive_key_pair=*/
793
    shake256_derive_key_pair_from_private_seed<MLKEM_SEED_BYTES>,
794
};
795
796
0
const EVP_HPKE_KEM *EVP_hpke_mlkem768() {
797
0
  static const EVP_HPKE_KEM kKEM = {
798
0
      /*id=*/EVP_HPKE_MLKEM768,
799
0
      /*evp_kem_func=*/&EVP_kem_ml_kem_768,
800
0
      /*key_method=*/&kMlkem768KeyMethod,
801
0
      /*public_key_len=*/0,
802
0
      /*private_key_len=*/0,
803
0
      /*seed_len=*/0,
804
0
      /*enc_len=*/0,
805
0
      /*init_key=*/nullptr,
806
0
      /*generate_key=*/nullptr,
807
0
      /*derive_key=*/nullptr,
808
0
      /*encap_with_seed=*/nullptr,
809
0
      /*decap=*/nullptr,
810
      // ML-KEM doesn't support authenticated encapsulation/decapsulation:
811
      // https://datatracker.ietf.org/doc/draft-ietf-hpke-pq/01/
812
0
      /*auth_encap_with_seed=*/nullptr,
813
0
      /*auth_decap=*/nullptr,
814
0
  };
815
0
  return &kKEM;
816
0
}
817
818
static constexpr HpkeKeyMethod kMlkem1024KeyMethod = {
819
    /*hpke_kem_id=*/EVP_HPKE_MLKEM1024,
820
    /*public_key_len=*/MLKEM1024_PUBLIC_KEY_BYTES,
821
    /*private_key_len=*/MLKEM_SEED_BYTES,
822
    /*alg_func=*/&EVP_pkey_ml_kem_1024,
823
    /*deserialize_private_key=*/&EVP_PKEY_from_private_seed,
824
    /*serialize_private_key=*/&EVP_PKEY_get_private_seed,
825
    /*deserialize_public_key=*/&EVP_PKEY_from_raw_public_key,
826
    /*serialize_public_key=*/&EVP_PKEY_get_raw_public_key,
827
    /*derive_key_pair=*/
828
    shake256_derive_key_pair_from_private_seed<MLKEM_SEED_BYTES>,
829
};
830
831
0
const EVP_HPKE_KEM *EVP_hpke_mlkem1024() {
832
0
  static const EVP_HPKE_KEM kKEM = {
833
0
      /*id=*/EVP_HPKE_MLKEM1024,
834
0
      /*evp_kem_func=*/&EVP_kem_ml_kem_1024,
835
0
      /*key_method=*/&kMlkem1024KeyMethod,
836
0
      /*public_key_len=*/0,
837
0
      /*private_key_len=*/0,
838
0
      /*seed_len=*/0,
839
0
      /*enc_len=*/0,
840
0
      /*init_key=*/nullptr,
841
0
      /*generate_key=*/nullptr,
842
0
      /*derive_key=*/nullptr,
843
0
      /*encap_with_seed=*/nullptr,
844
0
      /*decap=*/nullptr,
845
      // ML-KEM doesn't support authenticated encapsulation/decapsulation:
846
      // https://datatracker.ietf.org/doc/draft-ietf-hpke-pq/01/
847
0
      /*auth_encap_with_seed=*/nullptr,
848
0
      /*auth_decap=*/nullptr,
849
0
  };
850
0
  return &kKEM;
851
0
}
852
853
namespace {
854
855
// Temporary helper to switch between EVP_KEM-based implementation and legacy
856
// EVP_HPKE_KEM implementation.
857
// TODO(crbug.com/535883377): Unify EVP_HPKE_KEM and EVP_KEM for all supported
858
// HPKE KEMs.
859
860
15.1k
bool uses_evp(const EVP_HPKE_KEM *kem) {
861
15.1k
  return kem->evp_kem_func != nullptr && kem->key_method != nullptr;
862
15.1k
}
863
864
}  // namespace
865
866
451
uint16_t EVP_HPKE_KEM_id(const EVP_HPKE_KEM *kem) { return kem->id; }
867
868
451
size_t EVP_HPKE_KEM_public_key_len(const EVP_HPKE_KEM *kem) {
869
451
  if (uses_evp(kem)) {
870
0
    return kem->key_method->public_key_len;
871
0
  }
872
451
  return kem->public_key_len;
873
451
}
874
875
0
size_t EVP_HPKE_KEM_private_key_len(const EVP_HPKE_KEM *kem) {
876
0
  if (uses_evp(kem)) {
877
0
    return kem->key_method->private_key_len;
878
0
  }
879
0
  return kem->private_key_len;
880
0
}
881
882
// TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
883
// HPKE KEMs.
884
0
size_t EVP_HPKE_KEM_enc_len(const EVP_HPKE_KEM *kem) {
885
0
  if (uses_evp(kem)) {
886
0
    return EVP_KEM_ciphertext_len(kem->evp_kem_func());
887
0
  }
888
0
  return kem->enc_len;
889
0
}
890
891
// TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
892
// HPKE KEMs.
893
291
size_t EVP_HPKE_KEM_shared_secret_len(const EVP_HPKE_KEM *kem) {
894
291
  if (uses_evp(kem)) {
895
0
    return EVP_KEM_secret_len(kem->evp_kem_func());
896
0
  }
897
  // All other KEMs have the same shared secret length. We assume we'll finish
898
  // https://crbug.com/503758094 and move all KEMs to EVP before adding one that
899
  // breaks this.
900
291
  return SHA256_DIGEST_LENGTH;
901
291
}
902
903
// TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
904
// HPKE KEMs.
905
40.0k
void EVP_HPKE_KEY_zero(EVP_HPKE_KEY *key) {
906
40.0k
  OPENSSL_memset(key, 0, sizeof(EVP_HPKE_KEY));
907
40.0k
}
908
909
// TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
910
// HPKE KEMs.
911
26.4k
void EVP_HPKE_KEY_cleanup(EVP_HPKE_KEY *key) {
912
26.4k
  EVP_PKEY_free(key->pkey);
913
26.4k
  key->pkey = nullptr;
914
26.4k
}
915
916
0
EVP_HPKE_KEY *EVP_HPKE_KEY_new() {
917
0
  EVP_HPKE_KEY *key = New<EVP_HPKE_KEY>();
918
0
  if (key == nullptr) {
919
0
    return nullptr;
920
0
  }
921
0
  EVP_HPKE_KEY_zero(key);
922
0
  return key;
923
0
}
924
925
0
void EVP_HPKE_KEY_free(EVP_HPKE_KEY *key) {
926
0
  if (key != nullptr) {
927
0
    EVP_HPKE_KEY_cleanup(key);
928
0
    Delete(key);
929
0
  }
930
0
}
931
932
// TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
933
// HPKE KEMs.
934
6
int EVP_HPKE_KEY_copy(EVP_HPKE_KEY *dst, const EVP_HPKE_KEY *src) {
935
6
  dst->kem = src->kem;
936
6
  OPENSSL_memcpy(dst->private_key, src->private_key, sizeof(src->private_key));
937
6
  OPENSSL_memcpy(dst->public_key, src->public_key, sizeof(src->public_key));
938
6
  dst->pkey = EVP_PKEY_dup_ref(src->pkey);
939
6
  return 1;
940
6
}
941
942
0
void EVP_HPKE_KEY_move(EVP_HPKE_KEY *out, EVP_HPKE_KEY *in) {
943
0
  EVP_HPKE_KEY_cleanup(out);
944
  // For now, `EVP_HPKE_KEY` is trivially movable.
945
  // Note that Rust may move this structure. See
946
  // bssl-crypto/src/scoped.rs:EvpHpkeKey.
947
0
  *out = *in;
948
0
  EVP_HPKE_KEY_zero(in);
949
0
}
950
951
int EVP_HPKE_KEY_init(EVP_HPKE_KEY *key, const EVP_HPKE_KEM *kem,
952
13.6k
                      const uint8_t *priv_key, size_t priv_key_len) {
953
13.6k
  EVP_HPKE_KEY_zero(key);
954
13.6k
  key->kem = kem;
955
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
956
  // HPKE KEMs.
957
13.6k
  if (uses_evp(kem)) {
958
0
    UniquePtr<EVP_PKEY> pkey(kem->key_method->deserialize_private_key(
959
0
        kem->key_method->alg_func(), priv_key, priv_key_len));
960
0
    if (pkey == nullptr) {
961
0
      key->kem = nullptr;
962
0
      return 0;
963
0
    }
964
0
    key->pkey = pkey.release();
965
0
    return 1;
966
0
  }
967
13.6k
  if (!kem->init_key(key, priv_key, priv_key_len)) {
968
802
    key->kem = nullptr;
969
802
    return 0;
970
802
  }
971
12.8k
  return 1;
972
13.6k
}
973
974
0
int EVP_HPKE_KEY_generate(EVP_HPKE_KEY *key, const EVP_HPKE_KEM *kem) {
975
0
  EVP_HPKE_KEY_zero(key);
976
0
  key->kem = kem;
977
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
978
  // HPKE KEMs.
979
0
  if (uses_evp(kem)) {
980
0
    UniquePtr<EVP_PKEY> pkey(
981
0
        EVP_PKEY_generate_from_alg(kem->key_method->alg_func()));
982
0
    if (pkey == nullptr) {
983
0
      key->kem = nullptr;
984
0
      return 0;
985
0
    }
986
0
    key->pkey = pkey.release();
987
0
    return 1;
988
0
  }
989
0
  if (!kem->generate_key(key)) {
990
0
    key->kem = nullptr;
991
0
    return 0;
992
0
  }
993
0
  return 1;
994
0
}
995
996
int EVP_HPKE_KEY_derive(EVP_HPKE_KEY *key, const EVP_HPKE_KEM *kem,
997
0
                        const uint8_t *ikm, size_t ikm_len) {
998
0
  EVP_HPKE_KEY_zero(key);
999
0
  key->kem = kem;
1000
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1001
  // HPKE KEMs.
1002
0
  if (uses_evp(kem)) {
1003
0
    UniquePtr<EVP_PKEY> pkey(kem->key_method->derive_key_pair(
1004
0
        kem->key_method->alg_func(), kem->id, Span(ikm, ikm_len)));
1005
0
    if (pkey == nullptr) {
1006
0
      key->kem = nullptr;
1007
0
      return 0;
1008
0
    }
1009
0
    key->pkey = pkey.release();
1010
0
    return 1;
1011
0
  }
1012
0
  if (!kem->derive_key(key, Span(ikm, ikm_len))) {
1013
0
    key->kem = nullptr;
1014
0
    return 0;
1015
0
  }
1016
0
  return 1;
1017
0
}
1018
1019
451
const EVP_HPKE_KEM *EVP_HPKE_KEY_kem(const EVP_HPKE_KEY *key) {
1020
451
  return key->kem;
1021
451
}
1022
1023
int EVP_HPKE_KEY_public_key(const EVP_HPKE_KEY *key, uint8_t *out,
1024
451
                            size_t *out_len, size_t max_out) {
1025
451
  if (max_out < EVP_HPKE_KEM_public_key_len(key->kem)) {
1026
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
1027
0
    return 0;
1028
0
  }
1029
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1030
  // HPKE KEMs.
1031
451
  if (uses_evp(key->kem)) {
1032
0
    *out_len = max_out;
1033
0
    return key->kem->key_method->serialize_public_key(key->pkey, out, out_len);
1034
0
  }
1035
451
  OPENSSL_memcpy(out, key->public_key, key->kem->public_key_len);
1036
451
  *out_len = key->kem->public_key_len;
1037
451
  return 1;
1038
451
}
1039
1040
int EVP_HPKE_KEY_private_key(const EVP_HPKE_KEY *key, uint8_t *out,
1041
0
                             size_t *out_len, size_t max_out) {
1042
0
  if (max_out < EVP_HPKE_KEM_private_key_len(key->kem)) {
1043
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
1044
0
    return 0;
1045
0
  }
1046
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1047
  // HPKE KEMs.
1048
0
  if (uses_evp(key->kem)) {
1049
0
    *out_len = max_out;
1050
0
    return key->kem->key_method->serialize_private_key(key->pkey, out, out_len);
1051
0
  }
1052
0
  OPENSSL_memcpy(out, key->private_key, key->kem->private_key_len);
1053
0
  *out_len = key->kem->private_key_len;
1054
0
  return 1;
1055
0
}
1056
1057
1058
// Supported KDFs and AEADs.
1059
1060
303
const EVP_HPKE_KDF *EVP_hpke_hkdf_sha256() {
1061
303
  static const EVP_HPKE_KDF kKDF = {EVP_HPKE_HKDF_SHA256, &EVP_sha256};
1062
303
  return &kKDF;
1063
303
}
1064
1065
0
const EVP_HPKE_KDF *EVP_hpke_hkdf_sha384() {
1066
0
  static const EVP_HPKE_KDF kKDF = {EVP_HPKE_HKDF_SHA384, &EVP_sha384};
1067
0
  return &kKDF;
1068
0
}
1069
1070
60
uint16_t EVP_HPKE_KDF_id(const EVP_HPKE_KDF *kdf) { return kdf->id; }
1071
1072
0
const EVP_MD *EVP_HPKE_KDF_hkdf_md(const EVP_HPKE_KDF *kdf) {
1073
0
  return kdf->hkdf_md_func();
1074
0
}
1075
1076
3.18k
const EVP_HPKE_AEAD *EVP_hpke_aes_128_gcm() {
1077
3.18k
  static const EVP_HPKE_AEAD kAEAD = {EVP_HPKE_AES_128_GCM,
1078
3.18k
                                      &EVP_aead_aes_128_gcm};
1079
3.18k
  return &kAEAD;
1080
3.18k
}
1081
1082
2.43k
const EVP_HPKE_AEAD *EVP_hpke_aes_256_gcm() {
1083
2.43k
  static const EVP_HPKE_AEAD kAEAD = {EVP_HPKE_AES_256_GCM,
1084
2.43k
                                      &EVP_aead_aes_256_gcm};
1085
2.43k
  return &kAEAD;
1086
2.43k
}
1087
1088
2.42k
const EVP_HPKE_AEAD *EVP_hpke_chacha20_poly1305() {
1089
2.42k
  static const EVP_HPKE_AEAD kAEAD = {EVP_HPKE_CHACHA20_POLY1305,
1090
2.42k
                                      &EVP_aead_chacha20_poly1305};
1091
2.42k
  return &kAEAD;
1092
2.42k
}
1093
1094
8.08k
uint16_t EVP_HPKE_AEAD_id(const EVP_HPKE_AEAD *aead) { return aead->id; }
1095
1096
291
const EVP_AEAD *EVP_HPKE_AEAD_aead(const EVP_HPKE_AEAD *aead) {
1097
291
  return aead->aead_func();
1098
291
}
1099
1100
1101
// HPKE implementation.
1102
1103
291
static std::array<uint8_t, 10> hpke_full_suite_id(const EVP_HPKE_CTX *ctx) {
1104
291
  return {
1105
291
      'H',
1106
291
      'P',
1107
291
      'K',
1108
291
      'E',
1109
291
      static_cast<uint8_t>(ctx->kem->id >> 8),
1110
291
      static_cast<uint8_t>(ctx->kem->id),
1111
291
      static_cast<uint8_t>(ctx->kdf->id >> 8),
1112
291
      static_cast<uint8_t>(ctx->kdf->id),
1113
291
      static_cast<uint8_t>(ctx->aead->id >> 8),
1114
291
      static_cast<uint8_t>(ctx->aead->id),
1115
291
  };
1116
291
}
1117
1118
291
#define HPKE_MODE_BASE 0
1119
0
#define HPKE_MODE_AUTH 2
1120
1121
static int hpke_key_schedule(EVP_HPKE_CTX *ctx, uint8_t mode,
1122
                             const uint8_t *shared_secret,
1123
                             size_t shared_secret_len, const uint8_t *info,
1124
291
                             size_t info_len) {
1125
291
  auto suite_id = hpke_full_suite_id(ctx);
1126
1127
  // psk_id_hash = LabeledExtract("", "psk_id_hash", psk_id)
1128
  // TODO(davidben): Precompute this value and store it with the EVP_HPKE_KDF.
1129
291
  const EVP_MD *hkdf_md = ctx->kdf->hkdf_md_func();
1130
291
  uint8_t psk_id_hash[EVP_MAX_MD_SIZE];
1131
291
  size_t psk_id_hash_len;
1132
291
  if (!hpke_labeled_extract(hkdf_md, psk_id_hash, &psk_id_hash_len, nullptr, 0,
1133
291
                            suite_id.data(), suite_id.size(), "psk_id_hash",
1134
291
                            nullptr, 0)) {
1135
0
    return 0;
1136
0
  }
1137
1138
  // info_hash = LabeledExtract("", "info_hash", info)
1139
291
  uint8_t info_hash[EVP_MAX_MD_SIZE];
1140
291
  size_t info_hash_len;
1141
291
  if (!hpke_labeled_extract(hkdf_md, info_hash, &info_hash_len, nullptr, 0,
1142
291
                            suite_id.data(), suite_id.size(), "info_hash", info,
1143
291
                            info_len)) {
1144
0
    return 0;
1145
0
  }
1146
1147
  // key_schedule_context = concat(mode, psk_id_hash, info_hash)
1148
291
  uint8_t context[sizeof(uint8_t) + 2 * EVP_MAX_MD_SIZE];
1149
291
  size_t context_len;
1150
291
  CBB context_cbb;
1151
291
  CBB_init_fixed(&context_cbb, context, sizeof(context));
1152
291
  if (!CBB_add_u8(&context_cbb, mode) ||
1153
291
      !CBB_add_bytes(&context_cbb, psk_id_hash, psk_id_hash_len) ||
1154
291
      !CBB_add_bytes(&context_cbb, info_hash, info_hash_len) ||
1155
291
      !CBB_finish(&context_cbb, nullptr, &context_len)) {
1156
0
    return 0;
1157
0
  }
1158
1159
  // secret = LabeledExtract(shared_secret, "secret", psk)
1160
291
  uint8_t secret[EVP_MAX_MD_SIZE];
1161
291
  size_t secret_len;
1162
291
  if (!hpke_labeled_extract(hkdf_md, secret, &secret_len, shared_secret,
1163
291
                            shared_secret_len, suite_id.data(), suite_id.size(),
1164
291
                            "secret", nullptr, 0)) {
1165
0
    return 0;
1166
0
  }
1167
1168
  // key = LabeledExpand(secret, "key", key_schedule_context, Nk)
1169
291
  const EVP_AEAD *aead = EVP_HPKE_AEAD_aead(ctx->aead);
1170
291
  uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
1171
291
  const size_t kKeyLen = EVP_AEAD_key_length(aead);
1172
291
  if (!hpke_labeled_expand(hkdf_md, key, kKeyLen, secret, secret_len,
1173
291
                           suite_id.data(), suite_id.size(), "key", context,
1174
291
                           context_len) ||
1175
291
      !EVP_AEAD_CTX_init(&ctx->aead_ctx, aead, key, kKeyLen,
1176
291
                         EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
1177
0
    return 0;
1178
0
  }
1179
1180
  // base_nonce = LabeledExpand(secret, "base_nonce", key_schedule_context, Nn)
1181
291
  if (!hpke_labeled_expand(hkdf_md, ctx->base_nonce,
1182
291
                           EVP_AEAD_nonce_length(aead), secret, secret_len,
1183
291
                           suite_id.data(), suite_id.size(), "base_nonce",
1184
291
                           context, context_len)) {
1185
0
    return 0;
1186
0
  }
1187
1188
  // exporter_secret = LabeledExpand(secret, "exp", key_schedule_context, Nh)
1189
291
  if (!hpke_labeled_expand(hkdf_md, ctx->exporter_secret, EVP_MD_size(hkdf_md),
1190
291
                           secret, secret_len, suite_id.data(), suite_id.size(),
1191
291
                           "exp", context, context_len)) {
1192
0
    return 0;
1193
0
  }
1194
1195
291
  return 1;
1196
291
}
1197
1198
98.2k
void EVP_HPKE_CTX_zero(EVP_HPKE_CTX *ctx) {
1199
98.2k
  OPENSSL_memset(ctx, 0, sizeof(EVP_HPKE_CTX));
1200
98.2k
  EVP_AEAD_CTX_zero(&ctx->aead_ctx);
1201
98.2k
}
1202
1203
97.6k
void EVP_HPKE_CTX_cleanup(EVP_HPKE_CTX *ctx) {
1204
97.6k
  EVP_AEAD_CTX_cleanup(&ctx->aead_ctx);
1205
97.6k
}
1206
1207
0
EVP_HPKE_CTX *EVP_HPKE_CTX_new() {
1208
0
  EVP_HPKE_CTX *ctx = New<EVP_HPKE_CTX>();
1209
0
  if (ctx == nullptr) {
1210
0
    return nullptr;
1211
0
  }
1212
0
  EVP_HPKE_CTX_zero(ctx);
1213
0
  return ctx;
1214
0
}
1215
1216
0
void EVP_HPKE_CTX_free(EVP_HPKE_CTX *ctx) {
1217
0
  if (ctx != nullptr) {
1218
0
    EVP_HPKE_CTX_cleanup(ctx);
1219
0
    Delete(ctx);
1220
0
  }
1221
0
}
1222
1223
int EVP_HPKE_CTX_setup_sender(EVP_HPKE_CTX *ctx, uint8_t *out_enc,
1224
                              size_t *out_enc_len, size_t max_enc,
1225
                              const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf,
1226
                              const EVP_HPKE_AEAD *aead,
1227
                              const uint8_t *peer_public_key,
1228
                              size_t peer_public_key_len, const uint8_t *info,
1229
0
                              size_t info_len) {
1230
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1231
  // HPKE KEMs.
1232
0
  if (uses_evp(kem)) {
1233
0
    EVP_HPKE_CTX_zero(ctx);
1234
0
    ctx->is_sender = 1;
1235
0
    ctx->kem = kem;
1236
0
    ctx->kdf = kdf;
1237
0
    ctx->aead = aead;
1238
0
    uint8_t shared_secret[MAX_SHARED_SECRET_LEN];
1239
0
    size_t shared_secret_len;
1240
1241
0
    const EVP_KEM *evp_kem = kem->evp_kem_func();
1242
0
    if (max_enc < EVP_KEM_ciphertext_len(evp_kem)) {
1243
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
1244
0
      return 0;
1245
0
    }
1246
0
    *out_enc_len = EVP_KEM_ciphertext_len(evp_kem);
1247
0
    shared_secret_len = EVP_KEM_secret_len(evp_kem);
1248
0
    assert(size_t{MAX_SHARED_SECRET_LEN} >= shared_secret_len);
1249
1250
0
    UniquePtr<EVP_PKEY> peer_pubkey(kem->key_method->deserialize_public_key(
1251
0
        kem->key_method->alg_func(), peer_public_key, peer_public_key_len));
1252
0
    if (peer_pubkey == nullptr ||
1253
0
        !EVP_KEM_encap(evp_kem, out_enc, *out_enc_len, shared_secret,
1254
0
                       shared_secret_len, peer_pubkey.get()) ||
1255
0
        !hpke_key_schedule(ctx, HPKE_MODE_BASE, shared_secret,
1256
0
                           shared_secret_len, info, info_len)) {
1257
0
      EVP_HPKE_CTX_cleanup(ctx);
1258
0
      return 0;
1259
0
    }
1260
0
    return 1;
1261
0
  }
1262
1263
0
  uint8_t seed[MAX_SEED_LEN];
1264
0
  RAND_bytes(seed, kem->seed_len);
1265
0
  return EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
1266
0
      ctx, out_enc, out_enc_len, max_enc, kem, kdf, aead, peer_public_key,
1267
0
      peer_public_key_len, info, info_len, seed, kem->seed_len);
1268
0
}
1269
1270
int EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
1271
    EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc,
1272
    const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead,
1273
    const uint8_t *peer_public_key, size_t peer_public_key_len,
1274
    const uint8_t *info, size_t info_len, const uint8_t *seed,
1275
0
    size_t seed_len) {
1276
0
  EVP_HPKE_CTX_zero(ctx);
1277
0
  ctx->is_sender = 1;
1278
0
  ctx->kem = kem;
1279
0
  ctx->kdf = kdf;
1280
0
  ctx->aead = aead;
1281
0
  uint8_t shared_secret[MAX_SHARED_SECRET_LEN];
1282
0
  size_t shared_secret_len;
1283
1284
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1285
  // HPKE KEMs.
1286
0
  if (uses_evp(kem)) {
1287
0
    const EVP_KEM *evp_kem = kem->evp_kem_func();
1288
0
    if (max_enc < EVP_KEM_ciphertext_len(evp_kem)) {
1289
0
      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
1290
0
      return 0;
1291
0
    }
1292
0
    *out_enc_len = EVP_KEM_ciphertext_len(evp_kem);
1293
0
    shared_secret_len = EVP_KEM_secret_len(evp_kem);
1294
0
    assert(size_t{MAX_SHARED_SECRET_LEN} >= shared_secret_len);
1295
1296
0
    UniquePtr<EVP_PKEY> peer_pubkey(kem->key_method->deserialize_public_key(
1297
0
        kem->key_method->alg_func(), peer_public_key, peer_public_key_len));
1298
0
    if (peer_pubkey == nullptr ||
1299
0
        !EVP_KEM_encap_external_entropy_for_testing(
1300
0
            evp_kem, out_enc, *out_enc_len, shared_secret, shared_secret_len,
1301
0
            peer_pubkey.get(), seed, seed_len) ||
1302
0
        !hpke_key_schedule(ctx, HPKE_MODE_BASE, shared_secret,
1303
0
                           shared_secret_len, info, info_len)) {
1304
0
      EVP_HPKE_CTX_cleanup(ctx);
1305
0
      return 0;
1306
0
    }
1307
0
    return 1;
1308
0
  }
1309
1310
0
  if (!kem->encap_with_seed(kem, shared_secret, &shared_secret_len, out_enc,
1311
0
                            out_enc_len, max_enc, peer_public_key,
1312
0
                            peer_public_key_len, seed, seed_len) ||
1313
0
      !hpke_key_schedule(ctx, HPKE_MODE_BASE, shared_secret, shared_secret_len,
1314
0
                         info, info_len)) {
1315
0
    EVP_HPKE_CTX_cleanup(ctx);
1316
0
    return 0;
1317
0
  }
1318
0
  return 1;
1319
0
}
1320
1321
int EVP_HPKE_CTX_setup_recipient_with_shared_secret(
1322
    EVP_HPKE_CTX *ctx, const EVP_HPKE_KEM *kem, const EVP_HPKE_KDF *kdf,
1323
    const EVP_HPKE_AEAD *aead, const uint8_t *shared_secret,
1324
291
    size_t shared_secret_len, const uint8_t *info, size_t info_len) {
1325
291
  EVP_HPKE_CTX_zero(ctx);
1326
1327
291
  if (shared_secret_len != EVP_HPKE_KEM_shared_secret_len(kem)) {
1328
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_BUFFER_SIZE);
1329
0
    return 0;
1330
0
  }
1331
1332
291
  ctx->is_sender = 0;
1333
291
  ctx->kem = kem;
1334
291
  ctx->kdf = kdf;
1335
291
  ctx->aead = aead;
1336
291
  if (!hpke_key_schedule(ctx, HPKE_MODE_BASE, shared_secret, shared_secret_len,
1337
291
                         info, info_len)) {
1338
0
    EVP_HPKE_CTX_cleanup(ctx);
1339
0
    return 0;
1340
0
  }
1341
291
  return 1;
1342
291
}
1343
1344
int EVP_HPKE_CTX_setup_recipient(EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key,
1345
                                 const EVP_HPKE_KDF *kdf,
1346
                                 const EVP_HPKE_AEAD *aead, const uint8_t *enc,
1347
                                 size_t enc_len, const uint8_t *info,
1348
303
                                 size_t info_len) {
1349
303
  EVP_HPKE_CTX_zero(ctx);
1350
1351
303
  uint8_t shared_secret[MAX_SHARED_SECRET_LEN];
1352
303
  size_t shared_secret_len;
1353
1354
  // TODO(crbug.com/535883377): Implement in terms of EVP_KEM for all supported
1355
  // HPKE KEMs.
1356
303
  int decap_ok;
1357
303
  if (uses_evp(key->kem)) {
1358
0
    const EVP_KEM *evp_kem = key->kem->evp_kem_func();
1359
0
    const EVP_PKEY *decap_key = key->pkey;
1360
0
    shared_secret_len = EVP_KEM_secret_len(evp_kem);
1361
0
    assert(size_t{MAX_SHARED_SECRET_LEN} >= shared_secret_len);
1362
1363
0
    decap_ok = EVP_KEM_decap(evp_kem, shared_secret, shared_secret_len, enc,
1364
0
                             enc_len, decap_key);
1365
303
  } else {
1366
303
    decap_ok =
1367
303
        key->kem->decap(key, shared_secret, &shared_secret_len, enc, enc_len);
1368
303
  }
1369
1370
303
  return decap_ok && EVP_HPKE_CTX_setup_recipient_with_shared_secret(
1371
291
                         ctx, key->kem, kdf, aead, shared_secret,
1372
291
                         shared_secret_len, info, info_len);
1373
303
}
1374
1375
1376
int EVP_HPKE_CTX_setup_auth_sender(
1377
    EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc,
1378
    const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead,
1379
    const uint8_t *peer_public_key, size_t peer_public_key_len,
1380
0
    const uint8_t *info, size_t info_len) {
1381
0
  if (key->kem->auth_encap_with_seed == nullptr) {
1382
    // Not all HPKE KEMs support AuthEncap.
1383
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
1384
0
    return 0;
1385
0
  }
1386
0
  assert(!uses_evp(key->kem));
1387
0
  uint8_t seed[MAX_SEED_LEN];
1388
0
  RAND_bytes(seed, key->kem->seed_len);
1389
0
  return EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing(
1390
0
      ctx, out_enc, out_enc_len, max_enc, key, kdf, aead, peer_public_key,
1391
0
      peer_public_key_len, info, info_len, seed, key->kem->seed_len);
1392
0
}
1393
1394
int EVP_HPKE_CTX_setup_auth_sender_with_seed_for_testing(
1395
    EVP_HPKE_CTX *ctx, uint8_t *out_enc, size_t *out_enc_len, size_t max_enc,
1396
    const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf, const EVP_HPKE_AEAD *aead,
1397
    const uint8_t *peer_public_key, size_t peer_public_key_len,
1398
    const uint8_t *info, size_t info_len, const uint8_t *seed,
1399
0
    size_t seed_len) {
1400
0
  if (key->kem->auth_encap_with_seed == nullptr) {
1401
    // Not all HPKE KEMs support AuthEncap.
1402
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
1403
0
    return 0;
1404
0
  }
1405
1406
0
  EVP_HPKE_CTX_zero(ctx);
1407
0
  ctx->is_sender = 1;
1408
0
  ctx->kem = key->kem;
1409
0
  ctx->kdf = kdf;
1410
0
  ctx->aead = aead;
1411
0
  uint8_t shared_secret[MAX_SHARED_SECRET_LEN];
1412
0
  size_t shared_secret_len;
1413
0
  if (!key->kem->auth_encap_with_seed(
1414
0
          key, shared_secret, &shared_secret_len, out_enc, out_enc_len, max_enc,
1415
0
          peer_public_key, peer_public_key_len, seed, seed_len) ||
1416
0
      !hpke_key_schedule(ctx, HPKE_MODE_AUTH, shared_secret, shared_secret_len,
1417
0
                         info, info_len)) {
1418
0
    EVP_HPKE_CTX_cleanup(ctx);
1419
0
    return 0;
1420
0
  }
1421
0
  return 1;
1422
0
}
1423
1424
int EVP_HPKE_CTX_setup_auth_recipient(
1425
    EVP_HPKE_CTX *ctx, const EVP_HPKE_KEY *key, const EVP_HPKE_KDF *kdf,
1426
    const EVP_HPKE_AEAD *aead, const uint8_t *enc, size_t enc_len,
1427
    const uint8_t *info, size_t info_len, const uint8_t *peer_public_key,
1428
0
    size_t peer_public_key_len) {
1429
0
  if (key->kem->auth_decap == nullptr) {
1430
    // Not all HPKE KEMs support AuthDecap.
1431
0
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
1432
0
    return 0;
1433
0
  }
1434
1435
0
  EVP_HPKE_CTX_zero(ctx);
1436
0
  ctx->is_sender = 0;
1437
0
  ctx->kem = key->kem;
1438
0
  ctx->kdf = kdf;
1439
0
  ctx->aead = aead;
1440
0
  uint8_t shared_secret[MAX_SHARED_SECRET_LEN];
1441
0
  size_t shared_secret_len;
1442
0
  if (!key->kem->auth_decap(key, shared_secret, &shared_secret_len, enc,
1443
0
                            enc_len, peer_public_key, peer_public_key_len) ||
1444
0
      !hpke_key_schedule(ctx, HPKE_MODE_AUTH, shared_secret, shared_secret_len,
1445
0
                         info, info_len)) {
1446
0
    EVP_HPKE_CTX_cleanup(ctx);
1447
0
    return 0;
1448
0
  }
1449
0
  return 1;
1450
0
}
1451
1452
static void hpke_nonce(const EVP_HPKE_CTX *ctx, uint8_t *out_nonce,
1453
30
                       size_t nonce_len) {
1454
30
  assert(nonce_len >= 8);
1455
1456
  // Write padded big-endian bytes of `ctx->seq` to `out_nonce`.
1457
30
  OPENSSL_memset(out_nonce, 0, nonce_len);
1458
30
  uint64_t seq_copy = ctx->seq;
1459
270
  for (size_t i = 0; i < 8; i++) {
1460
240
    out_nonce[nonce_len - i - 1] = seq_copy & 0xff;
1461
240
    seq_copy >>= 8;
1462
240
  }
1463
1464
  // XOR the encoded sequence with the `ctx->base_nonce`.
1465
390
  for (size_t i = 0; i < nonce_len; i++) {
1466
360
    out_nonce[i] ^= ctx->base_nonce[i];
1467
360
  }
1468
30
}
1469
1470
int EVP_HPKE_CTX_open(EVP_HPKE_CTX *ctx, uint8_t *out, size_t *out_len,
1471
                      size_t max_out_len, const uint8_t *in, size_t in_len,
1472
30
                      const uint8_t *ad, size_t ad_len) {
1473
30
  if (ctx->is_sender) {
1474
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1475
0
    return 0;
1476
0
  }
1477
30
  if (ctx->seq == UINT64_MAX) {
1478
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW);
1479
0
    return 0;
1480
0
  }
1481
1482
30
  uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
1483
30
  const size_t nonce_len = EVP_AEAD_nonce_length(ctx->aead_ctx.aead);
1484
30
  hpke_nonce(ctx, nonce, nonce_len);
1485
1486
30
  if (!EVP_AEAD_CTX_open(&ctx->aead_ctx, out, out_len, max_out_len, nonce,
1487
30
                         nonce_len, in, in_len, ad, ad_len)) {
1488
30
    return 0;
1489
30
  }
1490
0
  ctx->seq++;
1491
0
  return 1;
1492
30
}
1493
1494
int EVP_HPKE_CTX_seal(EVP_HPKE_CTX *ctx, uint8_t *out, size_t *out_len,
1495
                      size_t max_out_len, const uint8_t *in, size_t in_len,
1496
0
                      const uint8_t *ad, size_t ad_len) {
1497
0
  if (!ctx->is_sender) {
1498
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1499
0
    return 0;
1500
0
  }
1501
0
  if (ctx->seq == UINT64_MAX) {
1502
0
    OPENSSL_PUT_ERROR(EVP, ERR_R_OVERFLOW);
1503
0
    return 0;
1504
0
  }
1505
1506
0
  uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
1507
0
  const size_t nonce_len = EVP_AEAD_nonce_length(ctx->aead_ctx.aead);
1508
0
  hpke_nonce(ctx, nonce, nonce_len);
1509
1510
0
  if (!EVP_AEAD_CTX_seal(&ctx->aead_ctx, out, out_len, max_out_len, nonce,
1511
0
                         nonce_len, in, in_len, ad, ad_len)) {
1512
0
    return 0;
1513
0
  }
1514
0
  ctx->seq++;
1515
0
  return 1;
1516
0
}
1517
1518
int EVP_HPKE_CTX_export(const EVP_HPKE_CTX *ctx, uint8_t *out,
1519
                        size_t secret_len, const uint8_t *context,
1520
0
                        size_t context_len) {
1521
0
  auto suite_id = hpke_full_suite_id(ctx);
1522
0
  const EVP_MD *hkdf_md = ctx->kdf->hkdf_md_func();
1523
0
  if (!hpke_labeled_expand(hkdf_md, out, secret_len, ctx->exporter_secret,
1524
0
                           EVP_MD_size(hkdf_md), suite_id.data(),
1525
0
                           suite_id.size(), "sec", context, context_len)) {
1526
0
    return 0;
1527
0
  }
1528
0
  return 1;
1529
0
}
1530
1531
0
size_t EVP_HPKE_CTX_max_overhead(const EVP_HPKE_CTX *ctx) {
1532
0
  assert(ctx->is_sender);
1533
0
  return EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(&ctx->aead_ctx));
1534
0
}
1535
1536
0
const EVP_HPKE_KEM *EVP_HPKE_CTX_kem(const EVP_HPKE_CTX *ctx) {
1537
0
  return ctx->kem;
1538
0
}
1539
1540
45
const EVP_HPKE_AEAD *EVP_HPKE_CTX_aead(const EVP_HPKE_CTX *ctx) {
1541
45
  return ctx->aead;
1542
45
}
1543
1544
60
const EVP_HPKE_KDF *EVP_HPKE_CTX_kdf(const EVP_HPKE_CTX *ctx) {
1545
60
  return ctx->kdf;
1546
60
}