@@ -243,7 +243,7 @@ pub fn unwrap_key(
243243 in_ : & [ u8 ] ,
244244) -> Result < usize , KeyError > {
245245 unsafe {
246- assert ! ( out. len( ) + 8 < = in_. len( ) ) ;
246+ assert ! ( out. len( ) + 8 > = in_. len( ) ) ;
247247
248248 let written = ffi:: AES_unwrap_key (
249249 & key. 0 as * const _ as * mut _ , // this is safe, the implementation only uses the key as a const pointer.
@@ -296,6 +296,74 @@ mod test {
296296 assert_eq ! ( pt_actual, pt) ;
297297 }
298298
299+ // out is larger than in_.len() - 8 but still valid; should succeed.
300+ #[ test]
301+ fn test_unwrap_key_out_oversized ( ) {
302+ let raw_key = Vec :: from_hex ( "000102030405060708090A0B0C0D0E0F" ) . unwrap ( ) ;
303+ let key_data = Vec :: from_hex ( "00112233445566778899AABBCCDDEEFF" ) . unwrap ( ) ;
304+ let wrapped = Vec :: from_hex ( "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5" ) . unwrap ( ) ;
305+ let dec_key = AesKey :: new_decrypt ( & raw_key) . unwrap ( ) ;
306+
307+ let mut out = vec ! [ 0u8 ; 32 ] ; // larger than the 16 bytes that will be written
308+ let n = unwrap_key ( & dec_key, None , & mut out, & wrapped) . unwrap ( ) ;
309+ assert_eq ! ( n, 16 ) ;
310+ assert_eq ! ( & out[ ..16 ] , & key_data[ ..] ) ;
311+ }
312+
313+ // out is smaller than in_.len() - 8; must panic.
314+ #[ test]
315+ #[ should_panic]
316+ fn test_unwrap_key_out_too_small_panics ( ) {
317+ let raw_key = Vec :: from_hex ( "000102030405060708090A0B0C0D0E0F" ) . unwrap ( ) ;
318+ let wrapped = Vec :: from_hex ( "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5" ) . unwrap ( ) ;
319+ let dec_key = AesKey :: new_decrypt ( & raw_key) . unwrap ( ) ;
320+
321+ let mut out = vec ! [ 0u8 ; 8 ] ; // too small: needs 16 bytes
322+ let _ = unwrap_key ( & dec_key, None , & mut out, & wrapped) ;
323+ }
324+
325+ // Verify that unwrap_key returns Err when the ciphertext has been tampered with.
326+ #[ test]
327+ fn test_unwrap_key_tampered_ciphertext ( ) {
328+ let raw_key = Vec :: from_hex ( "000102030405060708090A0B0C0D0E0F" ) . unwrap ( ) ;
329+ let mut wrapped =
330+ Vec :: from_hex ( "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5" ) . unwrap ( ) ;
331+ // Flip a byte so the integrity check fails
332+ wrapped[ 0 ] ^= 0xFF ;
333+
334+ let dec_key = AesKey :: new_decrypt ( & raw_key) . unwrap ( ) ;
335+ let mut out = [ 0u8 ; 16 ] ;
336+ assert ! (
337+ unwrap_key( & dec_key, None , & mut out, & wrapped) . is_err( ) ,
338+ "expected Err for tampered ciphertext"
339+ ) ;
340+ }
341+
342+ // Verify that wrap/unwrap round-trips correctly with an explicit IV.
343+ #[ test]
344+ fn test_wrap_unwrap_with_iv ( ) {
345+ let raw_key = Vec :: from_hex ( "000102030405060708090A0B0C0D0E0F" ) . unwrap ( ) ;
346+ let key_data = Vec :: from_hex ( "00112233445566778899AABBCCDDEEFF" ) . unwrap ( ) ;
347+ let iv: [ u8 ; 8 ] = [ 0xA6 , 0xA6 , 0xA6 , 0xA6 , 0xA6 , 0xA6 , 0xA6 , 0xA6 ] ;
348+
349+ let enc_key = AesKey :: new_encrypt ( & raw_key) . unwrap ( ) ;
350+ let mut wrapped = [ 0u8 ; 24 ] ;
351+ wrap_key ( & enc_key, Some ( iv) , & mut wrapped, & key_data) . unwrap ( ) ;
352+
353+ let dec_key = AesKey :: new_decrypt ( & raw_key) . unwrap ( ) ;
354+ let mut unwrapped = [ 0u8 ; 16 ] ;
355+ unwrap_key ( & dec_key, Some ( iv) , & mut unwrapped, & wrapped) . unwrap ( ) ;
356+ assert_eq ! ( & unwrapped[ ..] , & key_data[ ..] ) ;
357+
358+ // Using a different IV must fail
359+ let wrong_iv: [ u8 ; 8 ] = [ 0x00 ; 8 ] ;
360+ let mut unwrapped2 = [ 0u8 ; 16 ] ;
361+ assert ! (
362+ unwrap_key( & dec_key, Some ( wrong_iv) , & mut unwrapped2, & wrapped) . is_err( ) ,
363+ "expected Err when IV does not match"
364+ ) ;
365+ }
366+
299367 // from the RFC https://tools.ietf.org/html/rfc3394#section-2.2.3
300368 #[ test]
301369 fn test_wrap_unwrap ( ) {
0 commit comments