diff --git a/kem/src/lib.rs b/kem/src/lib.rs index 41e4a873..ec923df6 100644 --- a/kem/src/lib.rs +++ b/kem/src/lib.rs @@ -28,7 +28,13 @@ pub trait Encapsulate { &self, rng: &mut impl CryptoRngCore, encapsulated_key: &mut EK, - ) -> Result; + ) -> Result { + // Provide a default encapsulate_in_place implementation. If an implementer is + // performance-conscious, they can override this. + let (ek, ss) = self.encapsulate(rng)?; + *encapsulated_key = ek; + Ok(ss) + } } /// A value that can be used to decapsulate an encapsulated key. Often, this will just be a secret diff --git a/kem/tests/hpke.rs b/kem/tests/hpke.rs index 26349962..9eb892f6 100644 --- a/kem/tests/hpke.rs +++ b/kem/tests/hpke.rs @@ -23,16 +23,6 @@ impl Encapsulate for PublicKey { ) -> Result<(EncappedKey, SharedSecret), HpkeError> { ::encap(&self.0, None, &mut csprng).map(|(ss, ek)| (ek, ss)) } - - fn encapsulate_in_place( - &self, - csprng: &mut impl CryptoRngCore, - encapsulated_key: &mut EncappedKey, - ) -> Result { - let (ek, ss) = self.encapsulate(csprng)?; - *encapsulated_key = ek; - Ok(ss) - } } impl Decapsulate for PrivateKey { @@ -60,4 +50,6 @@ fn test_hpke() { let (ek, ss1) = pk_recip.encapsulate(&mut rng).unwrap(); let ss2 = sk_recip.decapsulate(&ek).unwrap(); assert_eq!(ss1.0, ss2.0); + + // Can't use encapsulate_in_place for this crate, because EncappedKey has no constructor } diff --git a/kem/tests/saber.rs b/kem/tests/saber.rs index 8c2b3357..e45a0794 100644 --- a/kem/tests/saber.rs +++ b/kem/tests/saber.rs @@ -23,16 +23,6 @@ impl Encapsulate for SaberPublicKey { let (ss, ek) = encapsulate(&self.0); Ok((ek, ss)) } - - fn encapsulate_in_place( - &self, - csprng: &mut impl CryptoRngCore, - encapsulated_key: &mut SaberEncappedKey, - ) -> Result { - let (ek, ss) = self.encapsulate(csprng)?; - *encapsulated_key = ek; - Ok(ss) - } } impl Decapsulate for SaberPrivateKey { @@ -60,4 +50,6 @@ fn test_saber() { let (ek, ss1) = pk_recip.encapsulate(&mut rng).unwrap(); let ss2 = sk_recip.decapsulate(&ek).unwrap(); assert_eq!(ss1.as_bytes(), ss2.as_bytes()); + + // Can't use encapsulate_in_place for this crate, because Ciphertext has no constructor } diff --git a/kem/tests/x3dh.rs b/kem/tests/x3dh.rs index e343bafa..56092ca8 100644 --- a/kem/tests/x3dh.rs +++ b/kem/tests/x3dh.rs @@ -68,16 +68,6 @@ impl Encapsulate for EncapContext { Ok((ek, shared_secret)) } - - fn encapsulate_in_place( - &self, - rng: &mut impl CryptoRngCore, - encapsulated_key: &mut EphemeralKey, - ) -> Result { - let (ek, ss) = self.encapsulate(rng)?; - *encapsulated_key = ek; - Ok(ss) - } } // Define an decapsulator. Since authenticated and unauthenticated encapped keys are represented by @@ -120,4 +110,12 @@ fn test_x3dh() { let (encapped_key, ss1) = encap_context.encapsulate(&mut rng).unwrap(); let ss2 = decap_context.decapsulate(&encapped_key).unwrap(); assert_eq!(ss1, ss2); + + // Now do the same but with encapsulate_in_place + let mut encapped_key = EphemeralKey::default(); + let ss1 = encap_context + .encapsulate_in_place(&mut rng, &mut encapped_key) + .unwrap(); + let ss2 = decap_context.decapsulate(&encapped_key).unwrap(); + assert_eq!(ss1, ss2); }