1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use crate::msgs::enums::HpkeKem;
6use crate::msgs::handshake::HpkeSymmetricCipherSuite;
7use crate::Error;
8
9/// A provider for [RFC 9180] Hybrid Public Key Encryption (HPKE) in base mode.
10///
11/// At a minimum each provider must support the [HPKE ciphersuite profile] required for
12/// encrypted client hello (ECH):
13/// * KEM: DHKEM(X25519, HKDF-SHA256)
14/// * symmetric ciphersuite: AES-128-GCM w/ HKDF-SHA256
15///
16/// [RFC 9180]: <https://www.rfc-editor.org/rfc/rfc9180.html>
17/// [HPKE ciphersuite profile]: <https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-17#section-9>
18pub trait HpkeProvider: Debug + Send + Sync + 'static {
19 /// Start setting up to use HPKE in base mode with the chosen suite.
20 ///
21 /// May return an error if the suite is unsupported by the provider.
22 fn start(&self, suite: &HpkeSuite) -> Result<Box<dyn Hpke>, Error>;
23
24 /// Does the provider support the given [HpkeSuite]?
25 fn supports_suite(&self, suite: &HpkeSuite) -> bool;
26}
27
28/// An HPKE suite, specifying a key encapsulation mechanism and a symmetric cipher suite.
29pub struct HpkeSuite {
30 /// The choice of HPKE key encapsulation mechanism.
31 pub kem: HpkeKem,
32
33 /// The choice of HPKE symmetric cipher suite.
34 ///
35 /// This combines a choice of authenticated encryption with additional data (AEAD) algorithm
36 /// and a key derivation function (KDF).
37 pub sym: HpkeSymmetricCipherSuite,
38}
39
40/// An HPKE instance that can be used for base-mode single-shot encryption and decryption.
41pub trait Hpke: Debug + Send + Sync {
42 /// Seal the provided `plaintext` to the recipient public key `pk_r` with application supplied
43 /// `info`, and additional data `aad`.
44 ///
45 /// Returns ciphertext that can be used with [Self::open] by the recipient to recover plaintext
46 /// using the same `info` and `aad` and the private key corresponding to `pk_r`.
47 fn seal(
48 &mut self,
49 pk_r: &HpkePublicKey,
50 info: &[u8],
51 aad: &[u8],
52 plaintext: &[u8],
53 ) -> Result<(EncapsulatedSecret, Vec<u8>), Error>;
54
55 /// Open the provided `ciphertext` using the encapsulated secret `enc`, with application
56 /// supplied `info`, and additional data `aad`.
57 ///
58 /// Returns plaintext if the `info` and `aad` match those used with [Self::seal], and
59 /// decryption with `sk_r` succeeds.
60 fn open(
61 &mut self,
62 enc: &EncapsulatedSecret,
63 sk_r: &HpkePrivateKey,
64 info: &[u8],
65 aad: &[u8],
66 ciphertext: &[u8],
67 ) -> Result<Vec<u8>, Error>;
68}
69
70/// An HPKE public key.
71pub struct HpkePublicKey(pub Vec<u8>);
72
73/// An HPKE private key.
74pub struct HpkePrivateKey(Vec<u8>);
75
76impl HpkePrivateKey {
77 /// Return the private key bytes.
78 pub fn secret_bytes(&self) -> &[u8] {
79 self.0.as_slice()
80 }
81}
82
83impl From<Vec<u8>> for HpkePrivateKey {
84 fn from(bytes: Vec<u8>) -> Self {
85 Self(bytes)
86 }
87}
88
89/// An HPKE key pair, made of a matching public and private key.
90pub struct HpkeKeyPair {
91 /// A HPKE public key.
92 pub public_key: HpkePublicKey,
93 /// A HPKE private key.
94 pub private_key: HpkePrivateKey,
95}
96
97/// An encapsulated secret returned from setting up a sender or receiver context.
98pub struct EncapsulatedSecret(pub Vec<u8>);
99