@@ -12,7 +12,7 @@ use thiserror::Error;
1212use typenum:: U32 ;
1313
1414use crate :: {
15- ContentFormat , CryptoError , SymmetricCryptoKey , XChaCha20Poly1305Key ,
15+ ContentFormat , CoseEncrypt0Bytes , CryptoError , SymmetricCryptoKey , XChaCha20Poly1305Key ,
1616 content_format:: { Bytes , ConstContentFormat , CoseContentFormat } ,
1717 error:: { EncStringParseError , EncodingError } ,
1818 xchacha20,
@@ -40,13 +40,15 @@ const CONTENT_TYPE_SPKI_PUBLIC_KEY: &str = "application/x.bitwarden.spki-public-
4040//
4141/// The label used for the namespace ensuring strong domain separation when using signatures.
4242pub ( crate ) const SIGNING_NAMESPACE : i64 = -80000 ;
43+ /// The label used for the namespace ensuring strong domain separation when using data envelopes.
44+ pub ( crate ) const DATA_ENVELOPE_NAMESPACE : i64 = -80001 ;
4345
4446/// Encrypts a plaintext message using XChaCha20Poly1305 and returns a COSE Encrypt0 message
4547pub ( crate ) fn encrypt_xchacha20_poly1305 (
4648 plaintext : & [ u8 ] ,
4749 key : & crate :: XChaCha20Poly1305Key ,
4850 content_format : ContentFormat ,
49- ) -> Result < Vec < u8 > , CryptoError > {
51+ ) -> Result < CoseEncrypt0Bytes , CryptoError > {
5052 let mut plaintext = plaintext. to_vec ( ) ;
5153
5254 let header_builder: coset:: HeaderBuilder = content_format. into ( ) ;
@@ -78,14 +80,15 @@ pub(crate) fn encrypt_xchacha20_poly1305(
7880 cose_encrypt0
7981 . to_vec ( )
8082 . map_err ( |err| CryptoError :: EncString ( EncStringParseError :: InvalidCoseEncoding ( err) ) )
83+ . map ( CoseEncrypt0Bytes :: from)
8184}
8285
8386/// Decrypts a COSE Encrypt0 message, using a XChaCha20Poly1305 key
8487pub ( crate ) fn decrypt_xchacha20_poly1305 (
85- cose_encrypt0_message : & [ u8 ] ,
88+ cose_encrypt0_message : & CoseEncrypt0Bytes ,
8689 key : & crate :: XChaCha20Poly1305Key ,
8790) -> Result < ( Vec < u8 > , ContentFormat ) , CryptoError > {
88- let msg = coset:: CoseEncrypt0 :: from_slice ( cose_encrypt0_message)
91+ let msg = coset:: CoseEncrypt0 :: from_slice ( cose_encrypt0_message. as_ref ( ) )
8992 . map_err ( |err| CryptoError :: EncString ( EncStringParseError :: InvalidCoseEncoding ( err) ) ) ?;
9093
9194 let Some ( ref alg) = msg. protected . header . alg else {
@@ -180,12 +183,16 @@ impl From<ContentFormat> for coset::HeaderBuilder {
180183 }
181184 ContentFormat :: CoseSign1 => header_builder. content_format ( CoapContentFormat :: CoseSign1 ) ,
182185 ContentFormat :: CoseKey => header_builder. content_format ( CoapContentFormat :: CoseKey ) ,
186+ ContentFormat :: CoseEncrypt0 => {
187+ header_builder. content_format ( CoapContentFormat :: CoseEncrypt0 )
188+ }
183189 ContentFormat :: BitwardenLegacyKey => {
184190 header_builder. content_type ( CONTENT_TYPE_BITWARDEN_LEGACY_KEY . to_string ( ) )
185191 }
186192 ContentFormat :: OctetStream => {
187193 header_builder. content_format ( CoapContentFormat :: OctetStream )
188194 }
195+ ContentFormat :: Cbor => header_builder. content_format ( CoapContentFormat :: Cbor ) ,
189196 }
190197 }
191198}
@@ -211,6 +218,7 @@ impl TryFrom<&coset::Header> for ContentFormat {
211218 Some ( ContentType :: Assigned ( CoapContentFormat :: OctetStream ) ) => {
212219 Ok ( ContentFormat :: OctetStream )
213220 }
221+ Some ( ContentType :: Assigned ( CoapContentFormat :: Cbor ) ) => Ok ( ContentFormat :: Cbor ) ,
214222 _ => Err ( CryptoError :: EncString (
215223 EncStringParseError :: CoseMissingContentType ,
216224 ) ) ,
@@ -363,7 +371,9 @@ mod test {
363371 key_id : KEY_ID ,
364372 enc_key : Box :: pin ( * GenericArray :: from_slice ( & KEY_DATA ) ) ,
365373 } ;
366- let decrypted = decrypt_xchacha20_poly1305 ( TEST_VECTOR_COSE_ENCRYPT0 , & key) . unwrap ( ) ;
374+ let decrypted =
375+ decrypt_xchacha20_poly1305 ( & CoseEncrypt0Bytes :: from ( TEST_VECTOR_COSE_ENCRYPT0 ) , & key)
376+ . unwrap ( ) ;
367377 assert_eq ! (
368378 decrypted,
369379 ( TEST_VECTOR_PLAINTEXT . to_vec( ) , ContentFormat :: OctetStream )
@@ -377,7 +387,7 @@ mod test {
377387 enc_key : Box :: pin ( * GenericArray :: from_slice ( & KEY_DATA ) ) ,
378388 } ;
379389 assert ! ( matches!(
380- decrypt_xchacha20_poly1305( TEST_VECTOR_COSE_ENCRYPT0 , & key) ,
390+ decrypt_xchacha20_poly1305( & CoseEncrypt0Bytes :: from ( TEST_VECTOR_COSE_ENCRYPT0 ) , & key) ,
381391 Err ( CryptoError :: WrongCoseKeyId )
382392 ) ) ;
383393 }
@@ -394,7 +404,7 @@ mod test {
394404 . create_ciphertext ( & [ ] , & [ ] , |_, _| Vec :: new ( ) )
395405 . unprotected ( coset:: HeaderBuilder :: new ( ) . iv ( nonce. to_vec ( ) ) . build ( ) )
396406 . build ( ) ;
397- let serialized_message = cose_encrypt0. to_vec ( ) . unwrap ( ) ;
407+ let serialized_message = CoseEncrypt0Bytes :: from ( cose_encrypt0. to_vec ( ) . unwrap ( ) ) ;
398408
399409 let key = XChaCha20Poly1305Key {
400410 key_id : KEY_ID ,
0 commit comments