1 | use alloc::boxed::Box; |
2 | use alloc::vec::Vec; |
3 | use core::fmt::Debug; |
4 | |
5 | use zeroize::Zeroize; |
6 | |
7 | use crate::Error; |
8 | use crate::msgs::enums::HpkeKem; |
9 | use crate::msgs::handshake::HpkeSymmetricCipherSuite; |
10 | |
11 | /// An HPKE suite, specifying a key encapsulation mechanism and a symmetric cipher suite. |
12 | #[derive (Clone, Copy, Debug, Eq, PartialEq)] |
13 | pub 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. |
25 | pub 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. |
94 | pub 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. |
104 | pub 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)] |
111 | pub struct HpkePublicKey(pub Vec<u8>); |
112 | |
113 | /// An HPKE private key. |
114 | pub struct HpkePrivateKey(Vec<u8>); |
115 | |
116 | impl HpkePrivateKey { |
117 | /// Return the private key bytes. |
118 | pub fn secret_bytes(&self) -> &[u8] { |
119 | self.0.as_slice() |
120 | } |
121 | } |
122 | |
123 | impl From<Vec<u8>> for HpkePrivateKey { |
124 | fn from(bytes: Vec<u8>) -> Self { |
125 | Self(bytes) |
126 | } |
127 | } |
128 | |
129 | impl 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. |
136 | pub 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)] |
145 | pub struct EncapsulatedSecret(pub Vec<u8>); |
146 | |