openmls/ciphersuite/
hpke.rs1use openmls_traits::{
38 crypto::OpenMlsCrypto,
39 types::{Ciphersuite, CryptoError, HpkeCiphertext},
40};
41use thiserror::Error;
42use tls_codec::{Serialize, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize, VLBytes};
43
44use super::LABEL_PREFIX;
45
46#[derive(Error, Debug, PartialEq, Clone)]
48pub(crate) enum Error {
49 #[error(
51 "Error while serializing content. This should only happen if a bounds check was missing."
52 )]
53 MissingBoundCheck,
54 #[error("Decryption failed.")]
56 DecryptionFailed,
57}
58
59impl From<tls_codec::Error> for Error {
60 fn from(_: tls_codec::Error) -> Self {
61 Self::MissingBoundCheck
62 }
63}
64
65impl From<CryptoError> for Error {
66 fn from(_: CryptoError) -> Self {
67 Self::DecryptionFailed
68 }
69}
70
71#[derive(Debug, Clone, TlsSerialize, TlsDeserialize, TlsDeserializeBytes, TlsSize)]
73pub struct EncryptContext {
74 label: VLBytes,
75 context: VLBytes,
76}
77
78impl EncryptContext {
79 pub fn new(label: &str, context: VLBytes) -> Self {
81 let label_string = LABEL_PREFIX.to_owned() + label;
82 let label = label_string.as_bytes().into();
83 Self { label, context }
84 }
85}
86
87impl From<(&str, &[u8])> for EncryptContext {
88 fn from((label, context): (&str, &[u8])) -> Self {
89 Self::new(label, context.into())
90 }
91}
92
93pub(crate) fn encrypt_with_label(
95 public_key: &[u8],
96 label: &str,
97 context: &[u8],
98 plaintext: &[u8],
99 ciphersuite: Ciphersuite,
100 crypto: &impl OpenMlsCrypto,
101) -> Result<HpkeCiphertext, Error> {
102 let context: EncryptContext = (label, context).into();
103 let context = context.tls_serialize_detached()?;
104
105 log_crypto!(
106 debug,
107 "HPKE Encrypt with label `{label}` and ciphersuite `{ciphersuite:?}`:"
108 );
109 log_crypto!(debug, "* context: {context:x?}");
110 log_crypto!(debug, "* public key: {public_key:x?}");
111 log_crypto!(debug, "* plaintext: {plaintext:x?}");
112
113 let cipher = crypto.hpke_seal(
114 ciphersuite.hpke_config(),
115 public_key,
116 &context,
117 &[],
118 plaintext,
119 )?;
120
121 log_crypto!(debug, "* ciphertext: {:x?}", cipher);
122
123 Ok(cipher)
124}
125
126pub(crate) fn decrypt_with_label(
128 private_key: &[u8],
129 label: &str,
130 context: &[u8],
131 ciphertext: &HpkeCiphertext,
132 ciphersuite: Ciphersuite,
133 crypto: &impl OpenMlsCrypto,
134) -> Result<Vec<u8>, Error> {
135 let context: EncryptContext = (label, context).into();
136 let context = context.tls_serialize_detached()?;
137
138 log_crypto!(
139 debug,
140 "HPKE Decrypt with label `{label}` and `ciphersuite` {ciphersuite:?}:"
141 );
142 log_crypto!(debug, "* context: {context:x?}");
143 log_crypto!(debug, "* private key: {private_key:x?}");
144 log_crypto!(debug, "* ciphertext: {ciphertext:x?}");
145
146 let plaintext = crypto
147 .hpke_open(
148 ciphersuite.hpke_config(),
149 ciphertext,
150 private_key,
151 &context,
152 &[],
153 )
154 .map_err(|e| e.into());
155
156 log_crypto!(debug, "* plaintext: {plaintext:x?}");
157
158 plaintext
159}