@@ -132,24 +132,44 @@ impl<Ids: KeyIds> KeyStoreContext<'_, Ids> {
132132 ///
133133 /// # Arguments
134134 ///
135- /// * `encryption_key ` - The key id used to decrypt the `encrypted_key `. It must already exist
135+ /// * `wrapping_key ` - The key id used to decrypt the `wrapped_key `. It must already exist
136136 /// in the context
137137 /// * `new_key_id` - The key id where the decrypted key will be stored. If it already exists, it
138138 /// will be overwritten
139- /// * `encrypted_key ` - The key to decrypt
139+ /// * `wrapped_key ` - The key to decrypt
140140 pub fn unwrap_symmetric_key (
141141 & mut self ,
142- encryption_key : Ids :: Symmetric ,
142+ wrapping_key : Ids :: Symmetric ,
143143 new_key_id : Ids :: Symmetric ,
144- encrypted_key : & EncString ,
144+ wrapped_key : & EncString ,
145145 ) -> Result < Ids :: Symmetric > {
146- let mut new_key_material =
147- self . decrypt_data_with_symmetric_key ( encryption_key, encrypted_key) ?;
146+ let wrapping_key = self . get_symmetric_key ( wrapping_key) ?;
147+
148+ let key = match ( wrapped_key, wrapping_key) {
149+ ( EncString :: Aes256Cbc_B64 { iv, data } , SymmetricCryptoKey :: Aes256CbcKey ( key) ) => {
150+ SymmetricCryptoKey :: try_from ( crate :: aes:: decrypt_aes256 ( iv, data. clone ( ) , & key. enc_key ) ?) ?
151+ }
152+ (
153+ EncString :: Aes256Cbc_HmacSha256_B64 { iv, mac, data } ,
154+ SymmetricCryptoKey :: Aes256CbcHmacKey ( key) ,
155+ ) => {
156+ SymmetricCryptoKey :: try_from ( crate :: aes:: decrypt_aes256_hmac ( iv, mac, data. clone ( ) , & key. mac_key , & key. enc_key ) ?) ?
157+ }
158+ ( EncString :: Cose_Encrypt0_B64 { data } , SymmetricCryptoKey :: XChaCha20Poly1305Key ( key) ) => {
159+ let ( content_bytes, content_format) = crate :: cose:: decrypt_xchacha20_poly1305 ( data, key) ?;
160+ match content_format {
161+ ContentFormat :: OctetStream => SymmetricCryptoKey :: try_from ( content_bytes) ?,
162+ ContentFormat :: CoseKey => SymmetricCryptoKey :: try_from_cose ( & content_bytes) ?,
163+ _ => return Err ( CryptoError :: InvalidKey )
164+ }
165+ }
166+ _ => return Err ( CryptoError :: InvalidKey ) ,
167+ } ;
148168
149169 #[ allow( deprecated) ]
150170 self . set_symmetric_key (
151171 new_key_id,
152- SymmetricCryptoKey :: try_from ( new_key_material . as_mut_slice ( ) ) ? ,
172+ key ,
153173 ) ?;
154174
155175 // Returning the new key identifier for convenience
@@ -179,7 +199,7 @@ impl<Ids: KeyIds> KeyStoreContext<'_, Ids> {
179199 // or `Aes256CbcKey`, or by specifying the content format to be CoseKey, in case the
180200 // wrapped key is a `XChaCha20Poly1305Key`.
181201 match ( wrapping_key_instance, key_to_wrap_instance) {
182- ( Aes256CbcHmacKey ( _) , Aes256CbcHmacKey ( _) | Aes256CbcKey ( _) ) => self
202+ ( Aes256CbcHmacKey ( _) , Aes256CbcHmacKey ( _) | Aes256CbcKey ( _) | XChaCha20Poly1305Key ( _ ) ) => self
183203 . encrypt_data_with_symmetric_key (
184204 wrapping_key,
185205 key_to_wrap_instance. to_encoded ( ) . as_slice ( ) ,
@@ -368,6 +388,10 @@ impl<Ids: KeyIds> KeyStoreContext<'_, Ids> {
368388 EncString :: Aes256Cbc_HmacSha256_B64 { iv, mac, data } ,
369389 SymmetricCryptoKey :: Aes256CbcHmacKey ( key) ,
370390 ) => crate :: aes:: decrypt_aes256_hmac ( iv, mac, data. clone ( ) , & key. mac_key , & key. enc_key ) ,
391+ ( EncString :: Cose_Encrypt0_B64 { data } , SymmetricCryptoKey :: XChaCha20Poly1305Key ( key) ) => {
392+ let ( data, _) = crate :: cose:: decrypt_xchacha20_poly1305 ( data, key) ?;
393+ Ok ( data)
394+ }
371395 _ => Err ( CryptoError :: InvalidKey ) ,
372396 }
373397 }
@@ -468,4 +492,44 @@ mod tests {
468492 // Assert that the decrypted data is the same
469493 assert_eq ! ( decrypted1. 0 , decrypted2. 0 ) ;
470494 }
495+
496+ #[ test]
497+ fn test_wrap_unwrap_aes256_cbc_hmac ( ) {
498+ let store: KeyStore < TestIds > = KeyStore :: default ( ) ;
499+ let mut ctx = store. context_mut ( ) ;
500+
501+ // Aes256 CBC HMAC keys
502+ let key_aes_1_id = TestSymmKey :: A ( 1 ) ;
503+ let key_aes_1 = SymmetricCryptoKey :: make_aes256_cbc_hmac_key ( ) ;
504+ ctx. set_symmetric_key ( key_aes_1_id, key_aes_1. clone ( ) ) . unwrap ( ) ;
505+ let key_aes_2_id = TestSymmKey :: A ( 2 ) ;
506+ let key_aes_2 = SymmetricCryptoKey :: make_aes256_cbc_hmac_key ( ) ;
507+ ctx. set_symmetric_key ( key_aes_2_id, key_aes_2. clone ( ) ) . unwrap ( ) ;
508+
509+ // XChaCha20 Poly1305 keys
510+ let key_xchacha_3_id = TestSymmKey :: A ( 3 ) ;
511+ let key_xchacha_3 = SymmetricCryptoKey :: make_xchacha20_poly1305_key ( ) ;
512+ ctx. set_symmetric_key ( key_xchacha_3_id, key_xchacha_3. clone ( ) ) . unwrap ( ) ;
513+ let key_xchacha_4_id = TestSymmKey :: A ( 4 ) ;
514+ let key_xchacha_4 = SymmetricCryptoKey :: make_xchacha20_poly1305_key ( ) ;
515+ ctx. set_symmetric_key ( key_xchacha_4_id, key_xchacha_4. clone ( ) ) . unwrap ( ) ;
516+
517+ // Wrap and unwrap the keys
518+ let wrapped_key_1_2 = ctx. wrap_symmetric_key ( key_aes_1_id, key_aes_2_id) . unwrap ( ) ;
519+ let wrapped_key_1_3 = ctx. wrap_symmetric_key ( key_aes_1_id, key_xchacha_3_id) . unwrap ( ) ;
520+ let wrapped_key_3_1 = ctx. wrap_symmetric_key ( key_xchacha_3_id, key_aes_1_id) . unwrap ( ) ;
521+ let wrapped_key_3_4 = ctx. wrap_symmetric_key ( key_xchacha_3_id, key_xchacha_4_id) . unwrap ( ) ;
522+
523+ // Unwrap the keys
524+ let unwrapped_key_2 = ctx. unwrap_symmetric_key ( key_aes_1_id, key_aes_2_id, & wrapped_key_1_2) . unwrap ( ) ;
525+ let unwrapped_key_3 = ctx. unwrap_symmetric_key ( key_aes_1_id, key_xchacha_3_id, & wrapped_key_1_3) . unwrap ( ) ;
526+ let unwrapped_key_1 = ctx. unwrap_symmetric_key ( key_xchacha_3_id, key_aes_1_id, & wrapped_key_3_1) . unwrap ( ) ;
527+ let unwrapped_key_4 = ctx. unwrap_symmetric_key ( key_xchacha_3_id, key_xchacha_4_id, & wrapped_key_3_4) . unwrap ( ) ;
528+
529+ // Assert that the unwrapped keys are the same as the original keys
530+ assert_eq ! ( unwrapped_key_2, key_aes_2_id) ;
531+ assert_eq ! ( unwrapped_key_3, key_xchacha_3_id) ;
532+ assert_eq ! ( unwrapped_key_1, key_aes_1_id) ;
533+ assert_eq ! ( unwrapped_key_4, key_xchacha_4_id) ;
534+ }
471535}
0 commit comments