1use crate::{
5 ciphersuite::{signable::*, *},
6 credentials::*,
7 extensions::{AnyObject, Extensions},
8 treesync::node::leaf_node::{LeafNodeIn, VerifiableLeafNode},
9 versions::ProtocolVersion,
10};
11use openmls_traits::{crypto::OpenMlsCrypto, types::Ciphersuite};
12use serde::{Deserialize, Serialize};
13use tls_codec::{
14 Serialize as TlsSerializeTrait, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
15};
16
17use super::{
18 errors::KeyPackageVerifyError, InitKey, KeyPackage, KeyPackageTbs, SIGNATURE_KEY_PACKAGE_LABEL,
19};
20
21#[cfg(any(feature = "test-utils", test))]
22use super::KeyPackageBundle;
23
24struct VerifiableKeyPackage {
26 payload: KeyPackageTbs,
27 signature: Signature,
28}
29
30impl VerifiableKeyPackage {
31 fn new(payload: KeyPackageTbs, signature: Signature) -> Self {
32 Self { payload, signature }
33 }
34}
35
36impl Verifiable for VerifiableKeyPackage {
37 type VerifiedStruct = KeyPackage;
38
39 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
40 self.payload.tls_serialize_detached()
41 }
42
43 fn signature(&self) -> &Signature {
44 &self.signature
45 }
46
47 fn label(&self) -> &str {
48 SIGNATURE_KEY_PACKAGE_LABEL
49 }
50
51 fn verify(
52 self,
53 crypto: &impl OpenMlsCrypto,
54 pk: &OpenMlsSignaturePublicKey,
55 ) -> Result<Self::VerifiedStruct, SignatureError> {
56 self.verify_no_out(crypto, pk)?;
57
58 Ok(KeyPackage {
59 payload: self.payload,
60 signature: self.signature,
61 serialized_payload: None,
62 })
63 }
64}
65
66impl VerifiedStruct for KeyPackage {}
67
68#[derive(
80 Debug,
81 Clone,
82 PartialEq,
83 TlsSize,
84 TlsSerialize,
85 TlsDeserialize,
86 TlsDeserializeBytes,
87 Serialize,
88 Deserialize,
89)]
90struct KeyPackageTbsIn {
91 protocol_version: ProtocolVersion,
92 ciphersuite: Ciphersuite,
93 init_key: InitKey,
94 leaf_node: LeafNodeIn,
95 extensions: Extensions<AnyObject>,
96}
97
98#[derive(
100 Debug,
101 PartialEq,
102 Clone,
103 Serialize,
104 Deserialize,
105 TlsSerialize,
106 TlsDeserialize,
107 TlsDeserializeBytes,
108 TlsSize,
109)]
110pub struct KeyPackageIn {
111 payload: KeyPackageTbsIn,
112 signature: Signature,
113}
114
115impl KeyPackageIn {
116 pub fn unverified_credential(&self) -> CredentialWithKey {
118 let credential = self.payload.leaf_node.credential().clone();
119 let signature_key = self.payload.leaf_node.signature_key().clone();
120 CredentialWithKey {
121 credential,
122 signature_key,
123 }
124 }
125
126 pub(crate) fn unverified_ciphersuite(&self) -> Ciphersuite {
128 self.payload.ciphersuite
129 }
130
131 pub fn validate(
143 self,
144 crypto: &impl OpenMlsCrypto,
145 protocol_version: ProtocolVersion,
146 ) -> Result<KeyPackage, KeyPackageVerifyError> {
147 let ciphersuite = self.payload.ciphersuite;
148 crypto
149 .supports(ciphersuite)
150 .map_err(|_| KeyPackageVerifyError::UnsupportedCiphersuite(ciphersuite))?;
151
152 let leaf_node = self.payload.leaf_node.clone().into_verifiable_leaf_node();
154
155 let signature_key = &OpenMlsSignaturePublicKey::from_signature_key(
156 self.payload.leaf_node.signature_key().clone(),
157 self.payload.ciphersuite.signature_algorithm(),
158 );
159
160 let leaf_node = match leaf_node {
162 VerifiableLeafNode::KeyPackage(leaf_node) => leaf_node
163 .verify(crypto, signature_key)
164 .map_err(|_| KeyPackageVerifyError::InvalidLeafNodeSignature)?,
165 _ => return Err(KeyPackageVerifyError::InvalidLeafNodeSourceType),
166 };
167
168 if !self.version_is_supported(protocol_version) {
171 return Err(KeyPackageVerifyError::InvalidProtocolVersion);
172 }
173
174 if leaf_node.encryption_key().key() == self.payload.init_key.key() {
177 return Err(KeyPackageVerifyError::InitKeyEqualsEncryptionKey);
178 }
179
180 let key_package_tbs = KeyPackageTbs {
181 protocol_version: self.payload.protocol_version,
182 ciphersuite: self.payload.ciphersuite,
183 init_key: self.payload.init_key,
184 leaf_node,
185 extensions: self.payload.extensions.try_into()?,
186 };
187
188 let key_package = VerifiableKeyPackage::new(key_package_tbs, self.signature)
191 .verify(crypto, signature_key)
192 .map_err(|_| KeyPackageVerifyError::InvalidSignature)?;
193
194 if !key_package
197 .payload
198 .leaf_node
199 .capabilities()
200 .contains_extensions(&key_package.payload.extensions)
201 {
202 return Err(KeyPackageVerifyError::UnsupportedExtension);
203 }
204
205 if let Some(life_time) = key_package.payload.leaf_node.life_time() {
207 life_time.validate()?;
208 } else {
209 return Err(KeyPackageVerifyError::MissingLifetime);
212 }
213
214 Ok(key_package)
215 }
216
217 pub(crate) fn version_is_supported(&self, protocol_version: ProtocolVersion) -> bool {
220 self.payload.protocol_version == protocol_version
221 }
222
223 #[cfg(feature = "unchecked-conversions")]
229 pub fn into_unchecked(self) -> KeyPackage {
230 let payload = KeyPackageTbs {
231 protocol_version: self.payload.protocol_version,
232 ciphersuite: self.payload.ciphersuite,
233 init_key: self.payload.init_key,
234 leaf_node: self.payload.leaf_node.into_unchecked(),
235 extensions: self.payload.extensions.into_unchecked(),
236 };
237 KeyPackage {
238 payload,
239 signature: self.signature,
240 serialized_payload: None,
241 }
242 }
243}
244
245#[cfg(any(feature = "test-utils", test))]
246impl From<KeyPackageTbsIn> for KeyPackageTbs {
247 fn from(value: KeyPackageTbsIn) -> Self {
248 KeyPackageTbs {
249 protocol_version: value.protocol_version,
250 ciphersuite: value.ciphersuite,
251 init_key: value.init_key,
252 leaf_node: value.leaf_node.into(),
253 extensions: value.extensions.coerce(),
254 }
255 }
256}
257
258impl From<KeyPackageTbs> for KeyPackageTbsIn {
259 fn from(value: KeyPackageTbs) -> Self {
260 Self {
261 protocol_version: value.protocol_version,
262 ciphersuite: value.ciphersuite,
263 init_key: value.init_key,
264 leaf_node: value.leaf_node.into(),
265 extensions: value.extensions.into(),
266 }
267 }
268}
269
270impl From<KeyPackage> for KeyPackageIn {
271 fn from(value: KeyPackage) -> Self {
272 Self {
273 payload: value.payload.into(),
274 signature: value.signature,
275 }
276 }
277}
278
279#[cfg(any(feature = "test-utils", test))]
280impl From<KeyPackageBundle> for KeyPackageIn {
281 fn from(value: KeyPackageBundle) -> Self {
282 Self {
283 payload: value.key_package.payload.into(),
284 signature: value.key_package.signature,
285 }
286 }
287}
288
289#[cfg(any(feature = "test-utils", test))]
290impl From<KeyPackageIn> for KeyPackage {
291 fn from(value: KeyPackageIn) -> Self {
292 Self {
293 payload: value.payload.into(),
294 signature: value.signature,
295 serialized_payload: None,
296 }
297 }
298}