| 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 | |