1use crate::{
92 ciphersuite::{
93 hash_ref::{make_key_package_ref, KeyPackageRef},
94 signable::*,
95 *,
96 },
97 credentials::*,
98 error::LibraryError,
99 extensions::{
100 errors::InvalidExtensionError, Extension, ExtensionType, Extensions, LastResortExtension,
101 },
102 storage::OpenMlsProvider,
103 treesync::{
104 node::{
105 encryption_keys::{EncryptionKeyPair, EncryptionPrivateKey},
106 leaf_node::{Capabilities, LeafNodeSource, NewLeafNodeParams, TreeInfoTbs},
107 },
108 LeafNode,
109 },
110 versions::ProtocolVersion,
111};
112use openmls_traits::{
113 crypto::OpenMlsCrypto, signatures::Signer, storage::StorageProvider, types::Ciphersuite,
114};
115use serde::{Deserialize, Serialize};
116use tls_codec::{
117 Serialize as TlsSerializeTrait, TlsDeserialize, TlsDeserializeBytes, TlsSerialize, TlsSize,
118};
119
120use errors::*;
122
123pub mod errors;
125pub mod key_package_in;
126
127mod lifetime;
128
129#[cfg(test)]
131pub(crate) mod tests;
132
133pub use key_package_in::KeyPackageIn;
135pub use lifetime::Lifetime;
136
137#[derive(Debug, Clone, PartialEq, TlsSize, TlsSerialize, Serialize, Deserialize)]
151struct KeyPackageTbs {
152 protocol_version: ProtocolVersion,
153 ciphersuite: Ciphersuite,
154 init_key: InitKey,
155 leaf_node: LeafNode,
156 extensions: Extensions,
157}
158
159impl Signable for KeyPackageTbs {
160 type SignedOutput = KeyPackage;
161
162 fn unsigned_payload(&self) -> Result<Vec<u8>, tls_codec::Error> {
163 self.tls_serialize_detached()
164 }
165
166 fn label(&self) -> &str {
167 SIGNATURE_KEY_PACKAGE_LABEL
168 }
169}
170
171impl From<KeyPackage> for KeyPackageTbs {
172 fn from(kp: KeyPackage) -> Self {
173 kp.payload
174 }
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize, TlsSize)]
179pub struct KeyPackage {
180 payload: KeyPackageTbs,
181 signature: Signature,
182 #[serde(skip)]
183 #[tls_codec(skip)]
184 serialized_payload: Option<Vec<u8>>,
185}
186
187impl TlsSerializeTrait for KeyPackage {
188 fn tls_serialize<W: std::io::Write>(&self, writer: &mut W) -> Result<usize, tls_codec::Error> {
189 let mut written = 0;
190 if let Some(ref bytes) = self.serialized_payload {
191 written += writer.write(bytes)?;
192 } else {
193 written += self.payload.tls_serialize(writer)?;
194 }
195 written += self.signature.tls_serialize(writer)?;
196 Ok(written)
197 }
198}
199
200impl PartialEq for KeyPackage {
201 fn eq(&self, other: &Self) -> bool {
202 self.payload == other.payload
205 }
206}
207
208impl SignedStruct<KeyPackageTbs> for KeyPackage {
209 fn from_payload(
210 payload: KeyPackageTbs,
211 signature: Signature,
212 serialized_payload: Vec<u8>,
213 ) -> Self {
214 Self {
215 payload,
216 signature,
217 serialized_payload: Some(serialized_payload),
218 }
219 }
220}
221
222const SIGNATURE_KEY_PACKAGE_LABEL: &str = "KeyPackageTBS";
223
224pub(crate) struct KeyPackageCreationResult {
226 pub key_package: KeyPackage,
227 pub encryption_keypair: EncryptionKeyPair,
228 pub init_private_key: HpkePrivateKey,
229}
230
231#[derive(
233 Debug,
234 Clone,
235 PartialEq,
236 TlsSize,
237 TlsSerialize,
238 Serialize,
239 Deserialize,
240 TlsDeserialize,
241 TlsDeserializeBytes,
242)]
243pub struct InitKey {
244 key: HpkePublicKey,
245}
246
247impl InitKey {
248 pub fn key(&self) -> &HpkePublicKey {
250 &self.key
251 }
252
253 pub fn as_slice(&self) -> &[u8] {
255 self.key.as_slice()
256 }
257}
258
259impl From<Vec<u8>> for InitKey {
260 fn from(key: Vec<u8>) -> Self {
261 Self {
262 key: HpkePublicKey::from(key),
263 }
264 }
265}
266
267impl From<HpkePublicKey> for InitKey {
268 fn from(key: HpkePublicKey) -> Self {
269 Self { key }
270 }
271}
272
273impl KeyPackage {
275 pub fn builder() -> KeyPackageBuilder {
279 KeyPackageBuilder::new()
280 }
281
282 #[allow(clippy::too_many_arguments)]
283 pub(crate) fn create(
285 ciphersuite: Ciphersuite,
286 provider: &impl OpenMlsProvider,
287 signer: &impl Signer,
288 credential_with_key: CredentialWithKey,
289 lifetime: Lifetime,
290 extensions: Extensions,
291 leaf_node_capabilities: Capabilities,
292 leaf_node_extensions: Extensions,
293 ) -> Result<KeyPackageCreationResult, KeyPackageNewError> {
294 if ciphersuite.signature_algorithm() != signer.signature_scheme() {
295 return Err(KeyPackageNewError::CiphersuiteSignatureSchemeMismatch);
296 }
297
298 let ikm = Secret::random(ciphersuite, provider.rand())
300 .map_err(LibraryError::unexpected_crypto_error)?;
301 let init_key = provider
302 .crypto()
303 .derive_hpke_keypair(ciphersuite.hpke_config(), ikm.as_slice())
304 .map_err(|e| {
305 KeyPackageNewError::LibraryError(LibraryError::unexpected_crypto_error(e))
306 })?;
307 let (key_package, encryption_keypair) = Self::new_from_keys(
308 ciphersuite,
309 provider,
310 signer,
311 credential_with_key,
312 lifetime,
313 extensions,
314 leaf_node_capabilities,
315 leaf_node_extensions,
316 init_key.public.into(),
317 )?;
318
319 Ok(KeyPackageCreationResult {
320 key_package,
321 encryption_keypair,
322 init_private_key: init_key.private,
323 })
324 }
325
326 #[allow(clippy::too_many_arguments)]
336 fn new_from_keys(
337 ciphersuite: Ciphersuite,
338 provider: &impl OpenMlsProvider,
339 signer: &impl Signer,
340 credential_with_key: CredentialWithKey,
341 lifetime: Lifetime,
342 extensions: Extensions,
343 capabilities: Capabilities,
344 leaf_node_extensions: Extensions,
345 init_key: InitKey,
346 ) -> Result<(Self, EncryptionKeyPair), KeyPackageNewError> {
347 let new_leaf_node_params = NewLeafNodeParams {
351 ciphersuite,
352 leaf_node_source: LeafNodeSource::KeyPackage(lifetime),
353 credential_with_key,
354 capabilities,
355 extensions: leaf_node_extensions,
356 tree_info_tbs: TreeInfoTbs::KeyPackage,
357 };
358
359 let (leaf_node, encryption_key_pair) =
360 LeafNode::new(provider, signer, new_leaf_node_params)?;
361
362 let key_package_tbs = KeyPackageTbs {
363 protocol_version: ProtocolVersion::default(),
364 ciphersuite,
365 init_key,
366 leaf_node,
367 extensions,
368 };
369
370 let key_package = key_package_tbs.sign(signer)?;
371
372 Ok((key_package, encryption_key_pair))
373 }
374
375 pub fn extensions(&self) -> &Extensions {
377 &self.payload.extensions
378 }
379
380 pub fn check_extension_support(
383 &self,
384 required_extensions: &[ExtensionType],
385 ) -> Result<(), KeyPackageExtensionSupportError> {
386 for required_extension in required_extensions.iter() {
387 if !self.extensions().contains(*required_extension) {
388 return Err(KeyPackageExtensionSupportError::UnsupportedExtension);
389 }
390 }
391
392 Ok(())
393 }
394
395 pub fn hash_ref(&self, crypto: &impl OpenMlsCrypto) -> Result<KeyPackageRef, LibraryError> {
399 make_key_package_ref(
400 &self
401 .tls_serialize_detached()
402 .map_err(LibraryError::missing_bound_check)?,
403 self.payload.ciphersuite,
404 crypto,
405 )
406 .map_err(LibraryError::unexpected_crypto_error)
407 }
408
409 pub fn ciphersuite(&self) -> Ciphersuite {
411 self.payload.ciphersuite
412 }
413
414 pub fn leaf_node(&self) -> &LeafNode {
416 &self.payload.leaf_node
417 }
418
419 pub fn hpke_init_key(&self) -> &InitKey {
421 &self.payload.init_key
422 }
423
424 pub fn last_resort(&self) -> bool {
426 self.payload.extensions.contains(ExtensionType::LastResort)
427 }
428
429 pub fn life_time(&self) -> &Lifetime {
431 self.payload.leaf_node.life_time().unwrap()
435 }
436}
437
438impl KeyPackage {
440 pub(crate) fn protocol_version(&self) -> ProtocolVersion {
442 self.payload.protocol_version
443 }
444}
445
446#[derive(Default, Debug, Clone, Serialize, Deserialize)]
448pub struct KeyPackageBuilder {
449 key_package_lifetime: Option<Lifetime>,
450 key_package_extensions: Option<Extensions>,
451 leaf_node_capabilities: Option<Capabilities>,
452 leaf_node_extensions: Option<Extensions>,
453 last_resort: bool,
454}
455
456impl KeyPackageBuilder {
457 pub fn new() -> Self {
459 Self {
460 key_package_lifetime: None,
461 key_package_extensions: None,
462 leaf_node_capabilities: None,
463 leaf_node_extensions: None,
464 last_resort: false,
465 }
466 }
467
468 pub fn key_package_lifetime(mut self, lifetime: Lifetime) -> Self {
470 self.key_package_lifetime.replace(lifetime);
471 self
472 }
473
474 pub fn key_package_extensions(mut self, extensions: Extensions) -> Self {
476 self.key_package_extensions.replace(extensions);
477 self
478 }
479
480 pub fn mark_as_last_resort(mut self) -> Self {
482 self.last_resort = true;
483 self
484 }
485
486 pub fn leaf_node_capabilities(mut self, capabilities: Capabilities) -> Self {
488 self.leaf_node_capabilities.replace(capabilities);
489 self
490 }
491
492 pub fn leaf_node_extensions(
496 mut self,
497 extensions: Extensions,
498 ) -> Result<Self, InvalidExtensionError> {
499 extensions.validate_extension_types_for_leaf_node()?;
501 self.leaf_node_extensions.replace(extensions);
502
503 Ok(self)
504 }
505
506 fn ensure_last_resort(&mut self) {
509 if self.last_resort {
510 let last_resort_extension = Extension::LastResort(LastResortExtension::default());
511 if let Some(extensions) = self.key_package_extensions.as_mut() {
512 extensions.add_or_replace(last_resort_extension);
513 } else {
514 self.key_package_extensions = Some(Extensions::single(last_resort_extension));
515 }
516 }
517 }
518
519 #[cfg(test)]
520 pub(crate) fn build_without_storage(
521 mut self,
522 ciphersuite: Ciphersuite,
523 provider: &impl OpenMlsProvider,
524 signer: &impl Signer,
525 credential_with_key: CredentialWithKey,
526 ) -> Result<KeyPackageCreationResult, KeyPackageNewError> {
527 self.ensure_last_resort();
528 KeyPackage::create(
529 ciphersuite,
530 provider,
531 signer,
532 credential_with_key,
533 self.key_package_lifetime.unwrap_or_default(),
534 self.key_package_extensions.unwrap_or_default(),
535 self.leaf_node_capabilities.unwrap_or_default(),
536 self.leaf_node_extensions.unwrap_or_default(),
537 )
538 }
539
540 pub fn build(
542 mut self,
543 ciphersuite: Ciphersuite,
544 provider: &impl OpenMlsProvider,
545 signer: &impl Signer,
546 credential_with_key: CredentialWithKey,
547 ) -> Result<KeyPackageBundle, KeyPackageNewError> {
548 self.ensure_last_resort();
549 let KeyPackageCreationResult {
550 key_package,
551 encryption_keypair,
552 init_private_key,
553 } = KeyPackage::create(
554 ciphersuite,
555 provider,
556 signer,
557 credential_with_key,
558 self.key_package_lifetime.unwrap_or_default(),
559 self.key_package_extensions.unwrap_or_default(),
560 self.leaf_node_capabilities.unwrap_or_default(),
561 self.leaf_node_extensions.unwrap_or_default(),
562 )?;
563
564 let full_kp = KeyPackageBundle {
567 key_package,
568 private_init_key: init_private_key,
569 private_encryption_key: encryption_keypair.private_key().clone(),
570 };
571 provider
572 .storage()
573 .write_key_package(&full_kp.key_package.hash_ref(provider.crypto())?, &full_kp)
574 .map_err(|_| KeyPackageNewError::StorageError)?;
575
576 Ok(full_kp)
577 }
578}
579
580#[derive(Debug, Clone, Serialize, Deserialize)]
586pub struct KeyPackageBundle {
587 pub(crate) key_package: KeyPackage,
588 pub(crate) private_init_key: HpkePrivateKey,
589 pub(crate) private_encryption_key: EncryptionPrivateKey,
590}
591
592impl KeyPackageBundle {
594 pub fn key_package(&self) -> &KeyPackage {
596 &self.key_package
597 }
598
599 pub fn init_private_key(&self) -> &HpkePrivateKey {
601 &self.private_init_key
602 }
603
604 pub(crate) fn encryption_key_pair(&self) -> EncryptionKeyPair {
606 EncryptionKeyPair::from((
607 self.key_package.leaf_node().encryption_key().clone(),
608 self.private_encryption_key.clone(),
609 ))
610 }
611}
612
613#[cfg(any(test, feature = "test-utils"))]
614impl KeyPackageBundle {
615 pub fn new(
617 key_package: KeyPackage,
618 private_init_key: HpkePrivateKey,
619 private_encryption_key: EncryptionPrivateKey,
620 ) -> Self {
621 Self {
622 key_package,
623 private_init_key,
624 private_encryption_key,
625 }
626 }
627
628 pub fn encryption_private_key(&self) -> &HpkePrivateKey {
630 self.private_encryption_key.key()
631 }
632}
633
634#[cfg(test)]
635impl KeyPackageBundle {
636 pub(crate) fn generate(
637 provider: &impl OpenMlsProvider,
638 signer: &impl Signer,
639 ciphersuite: Ciphersuite,
640 credential_with_key: CredentialWithKey,
641 ) -> Self {
642 KeyPackage::builder()
643 .build(ciphersuite, provider, signer, credential_with_key)
644 .unwrap()
645 }
646}