1 | use alloc::boxed::Box; |
2 | use alloc::vec::Vec; |
3 | use core::fmt::Debug; |
4 | |
5 | use crate::msgs::enums::HpkeKem; |
6 | use crate::msgs::handshake::HpkeSymmetricCipherSuite; |
7 | use 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> |
18 | pub 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. |
29 | pub 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. |
41 | pub 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. |
71 | pub struct HpkePublicKey(pub Vec<u8>); |
72 | |
73 | /// An HPKE private key. |
74 | pub struct HpkePrivateKey(Vec<u8>); |
75 | |
76 | impl HpkePrivateKey { |
77 | /// Return the private key bytes. |
78 | pub fn secret_bytes(&self) -> &[u8] { |
79 | self.0.as_slice() |
80 | } |
81 | } |
82 | |
83 | impl 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. |
90 | pub 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. |
98 | pub struct EncapsulatedSecret(pub Vec<u8>); |
99 | |