rustls/crypto/
hpke.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use zeroize::Zeroize;
6
7use crate::msgs::enums::HpkeKem;
8use crate::msgs::handshake::HpkeSymmetricCipherSuite;
9use crate::Error;
10
11/// An HPKE suite, specifying a key encapsulation mechanism and a symmetric cipher suite.
12#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13pub struct HpkeSuite {
14    /// The choice of HPKE key encapsulation mechanism.
15    pub kem: HpkeKem,
16
17    /// The choice of HPKE symmetric cipher suite.
18    ///
19    /// This combines a choice of authenticated encryption with additional data (AEAD) algorithm
20    /// and a key derivation function (KDF).
21    pub sym: HpkeSymmetricCipherSuite,
22}
23
24/// An HPKE instance that can be used for base-mode single-shot encryption and decryption.
25pub trait Hpke: Debug + Send + Sync {
26    /// Seal the provided `plaintext` to the recipient public key `pub_key` with application supplied
27    /// `info`, and additional data `aad`.
28    ///
29    /// Returns ciphertext that can be used with [Self::open] by the recipient to recover plaintext
30    /// using the same `info` and `aad` and the private key corresponding to `pub_key`. RFC 9180
31    /// refers to `pub_key` as `pkR`.
32    fn seal(
33        &self,
34        info: &[u8],
35        aad: &[u8],
36        plaintext: &[u8],
37        pub_key: &HpkePublicKey,
38    ) -> Result<(EncapsulatedSecret, Vec<u8>), Error>;
39
40    /// Set up a sealer context for the receiver public key `pub_key` with application supplied `info`.
41    ///
42    /// Returns both an encapsulated ciphertext and a sealer context that can be used to seal
43    /// messages to the recipient. RFC 9180 refers to `pub_key` as `pkR`.
44    fn setup_sealer(
45        &self,
46        info: &[u8],
47        pub_key: &HpkePublicKey,
48    ) -> Result<(EncapsulatedSecret, Box<dyn HpkeSealer + 'static>), Error>;
49
50    /// Open the provided `ciphertext` using the encapsulated secret `enc`, with application
51    /// supplied `info`, and additional data `aad`.
52    ///
53    /// Returns plaintext if  the `info` and `aad` match those used with [Self::seal], and
54    /// decryption with `secret_key` succeeds. RFC 9180 refers to `secret_key` as `skR`.
55    fn open(
56        &self,
57        enc: &EncapsulatedSecret,
58        info: &[u8],
59        aad: &[u8],
60        ciphertext: &[u8],
61        secret_key: &HpkePrivateKey,
62    ) -> Result<Vec<u8>, Error>;
63
64    /// Set up an opener context for the secret key `secret_key` with application supplied `info`.
65    ///
66    /// Returns an opener context that can be used to open sealed messages encrypted to the
67    /// public key corresponding to `secret_key`. RFC 9180 refers to `secret_key` as `skR`.
68    fn setup_opener(
69        &self,
70        enc: &EncapsulatedSecret,
71        info: &[u8],
72        secret_key: &HpkePrivateKey,
73    ) -> Result<Box<dyn HpkeOpener + 'static>, Error>;
74
75    /// Generate a new public key and private key pair compatible with this HPKE instance.
76    ///
77    /// Key pairs should be encoded as raw big endian fixed length integers sized based
78    /// on the suite's DH KEM algorithm.
79    fn generate_key_pair(&self) -> Result<(HpkePublicKey, HpkePrivateKey), Error>;
80
81    /// Return whether the HPKE instance is FIPS compatible.
82    fn fips(&self) -> bool {
83        false
84    }
85
86    /// Return the [HpkeSuite] that this HPKE instance supports.
87    fn suite(&self) -> HpkeSuite;
88}
89
90/// An HPKE sealer context.
91///
92/// This is a stateful object that can be used to seal messages for receipt by
93/// a receiver.
94pub trait HpkeSealer: Debug + Send + Sync + 'static {
95    /// Seal the provided `plaintext` with additional data `aad`, returning
96    /// ciphertext.
97    fn seal(&mut self, aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, Error>;
98}
99
100/// An HPKE opener context.
101///
102/// This is a stateful object that can be used to open sealed messages sealed
103/// by a sender.
104pub trait HpkeOpener: Debug + Send + Sync + 'static {
105    /// Open the provided `ciphertext` with additional data `aad`, returning plaintext.
106    fn open(&mut self, aad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, Error>;
107}
108
109/// An HPKE public key.
110#[derive(Clone, Debug)]
111pub struct HpkePublicKey(pub Vec<u8>);
112
113/// An HPKE private key.
114pub struct HpkePrivateKey(Vec<u8>);
115
116impl HpkePrivateKey {
117    /// Return the private key bytes.
118    pub fn secret_bytes(&self) -> &[u8] {
119        self.0.as_slice()
120    }
121}
122
123impl From<Vec<u8>> for HpkePrivateKey {
124    fn from(bytes: Vec<u8>) -> Self {
125        Self(bytes)
126    }
127}
128
129impl Drop for HpkePrivateKey {
130    fn drop(&mut self) {
131        self.0.zeroize();
132    }
133}
134
135/// An HPKE key pair, made of a matching public and private key.
136pub struct HpkeKeyPair {
137    /// A HPKE public key.
138    pub public_key: HpkePublicKey,
139    /// A HPKE private key.
140    pub private_key: HpkePrivateKey,
141}
142
143/// An encapsulated secret returned from setting up a sender or receiver context.
144#[derive(Debug)]
145pub struct EncapsulatedSecret(pub Vec<u8>);