@@ -36,26 +36,16 @@ impl<'a> V1FixedFields<'a> {
3636}
3737
3838#[ tokio:: test( flavor = "multi_thread" ) ]
39- async fn test_v1_header_serialized ( ) {
40- let pt = b"test v1 header" ;
39+ async fn test_v1_header_version ( ) {
40+ let pt = b"test v1 header version " ;
4141 let ct = encrypt_v1_with_ec ( pt, EncryptionContext :: new ( ) ) . await ;
4242 let hdr = V1FixedFields :: parse ( & ct) ;
4343 //= spec/client-apis/encrypt.md#v1-header
4444 //= type=test
4545 //# If the message format version associated with the [algorithm suite](../framework/algorithm-suites.md#supported-algorithm-suites) is 1.0,
4646 //# the remaining header fields MUST be serialized according to the
4747 //# [Header Body Version 1.0](../data-format/message-header.md#header-body-version-10) specification:
48- // V1 header starts with version byte 0x01
49- assert_eq ! ( hdr. version, 0x01 , "first byte must be V1 version 0x01" ) ;
50- // Round-trip proves the V1 message is valid end-to-end.
51- let result = round_trip_v1 ( pt, EncryptionContext :: new ( ) ) . await ;
52- assert_eq ! ( result, pt) ;
53- }
54-
55- #[ tokio:: test( flavor = "multi_thread" ) ]
56- async fn test_v1_header_version ( ) {
57- let ct = encrypt_v1_with_ec ( b"version test" , EncryptionContext :: new ( ) ) . await ;
58- let hdr = V1FixedFields :: parse ( & ct) ;
48+ //
5949 //= spec/client-apis/encrypt.md#v1-header
6050 //= type=test
6151 //# - MUST serialize the [Version](../data-format/message-header.md#version).
@@ -65,9 +55,9 @@ async fn test_v1_header_version() {
6555 //= type=test
6656 //# The value of the `Version` field MUST be `01` in the Version 1.0 header body.
6757 assert_eq ! ( hdr. version, 0x01 , "Version field must be 0x01 for V1" ) ;
68- // Round-trip proves the version field is correctly processed .
69- let result = round_trip_v1 ( b"version test" , EncryptionContext :: new ( ) ) . await ;
70- assert_eq ! ( result, b"version test" ) ;
58+ // Round-trip proves the V1 message is valid end-to-end .
59+ let result = round_trip_v1 ( pt , EncryptionContext :: new ( ) ) . await ;
60+ assert_eq ! ( result, pt ) ;
7161}
7262
7363#[ tokio:: test( flavor = "multi_thread" ) ]
@@ -132,11 +122,6 @@ async fn test_v1_header_message_id() {
132122 //# The length of the serialized message ID MUST be 16 bytes for [version 1.0](#header-body-version-10) headers.
133123 assert_eq ! ( hdr1. message_id. len( ) , 16 , "V1 message ID must be 16 bytes" ) ;
134124
135- //= spec/data-format/message-header.md#message-id
136- //= type=test
137- //# The message ID MUST be interpreted as bytes.
138- assert_eq ! ( hdr1. message_id, & ct1[ 4 ..20 ] , "V1 message ID must be preserved as raw bytes" ) ;
139-
140125 //= spec/data-format/message-header.md#message-id
141126 //= type=test
142127 //# While implementations cannot guarantee complete uniqueness,
@@ -222,15 +207,15 @@ async fn test_v1_header_aad() {
222207
223208#[ tokio:: test( flavor = "multi_thread" ) ]
224209async fn test_v1_header_encrypted_data_keys ( ) {
210+ let pt = b"edk test" ;
211+ let ct = encrypt_v1_with_ec ( pt, EncryptionContext :: new ( ) ) . await ;
212+ // Parse past AAD to find EDK count
213+ let edk_section = parse_edk_section ( & ct, Version :: V1 ) ;
225214 //= spec/client-apis/encrypt.md#v1-header
226215 //= type=test
227216 //# - MUST serialize the [Encrypted Data Keys](../data-format/message-header.md#encrypted-data-keys).
228217 //# The value MUST be the serialization of the
229218 //# [encrypted data keys](../framework/structures.md#encrypted-data-keys) in the [encryption materials](../framework/structures.md#encryption-materials).
230- let pt = b"edk test" ;
231- let ct = encrypt_v1_with_ec ( pt, EncryptionContext :: new ( ) ) . await ;
232- // Parse past AAD to find EDK count
233- let edk_section = parse_edk_section ( & ct, Version :: V1 ) ;
234219 assert ! ( edk_section. edk_count >= 1 , "must have at least one EDK" ) ;
235220 assert ! ( !edk_section. edks[ 0 ] . edk. is_empty( ) , "EDK ciphertext must be non-empty" ) ;
236221 // Round-trip proves EDKs are correctly serialized (decrypt uses them to recover the data key)
@@ -280,16 +265,33 @@ async fn test_v1_header_reserved() {
280265#[ tokio:: test( flavor = "multi_thread" ) ]
281266async fn test_v1_header_iv_length ( ) {
282267 let ct = encrypt_v1_with_ec ( b"iv length test" , EncryptionContext :: new ( ) ) . await ;
283- let ( _, _, iv_length_offset, _ ) = parse_v1_trailing_offsets ( & ct) ;
268+ let ( _, _, iv_length_offset, frame_length_offset ) = parse_v1_trailing_offsets ( & ct) ;
284269 //= spec/client-apis/encrypt.md#v1-header
285270 //= type=test
286271 //# - MUST serialize the [IV Length](../data-format/message-header.md#iv-length).
287272 //# The value MUST match the [IV length](../framework/algorithm-suites.md#iv-length)
288273 //# specified by the [algorithm suite](../framework/algorithm-suites.md).
274+ //
275+ //= spec/data-format/message-header.md#iv-length
276+ //= type=test
277+ //# The IV length MUST be interpreted as a UInt8.
278+ //
279+ //= spec/data-format/message-header.md#iv-length
280+ //= type=test
281+ //# This value MUST be equal to the [IV length](../framework/algorithm-suites.md#iv-length) value of the
282+ //# [algorithm suite](../framework/algorithm-suites.md) specified by the [Algorithm Suite ID](#algorithm-suite-id) field.
289283 // AlgAes256GcmIv12Tag16HkdfSha256 has IV length 12
290284 assert_eq ! (
291285 ct[ iv_length_offset] , 12 ,
292- "IV Length must be 12, matching the algorithm suite"
286+ "IV Length must be 12, matching the algorithm suite (serialized as UInt8)"
287+ ) ;
288+ //= spec/data-format/message-header.md#iv-length
289+ //= type=test
290+ //# The length of the serialized IV length field MUST be 1 byte.
291+ assert_eq ! (
292+ frame_length_offset - iv_length_offset,
293+ 1 ,
294+ "IV length field must be exactly 1 byte"
293295 ) ;
294296 // Round-trip proves the IV length is correctly processed.
295297 let result = round_trip_v1 ( b"iv length test" , EncryptionContext :: new ( ) ) . await ;
@@ -299,18 +301,27 @@ async fn test_v1_header_iv_length() {
299301#[ tokio:: test( flavor = "multi_thread" ) ]
300302async fn test_v1_header_frame_length ( ) {
301303 let ct = encrypt_v1_with_ec ( b"frame length test" , EncryptionContext :: new ( ) ) . await ;
302- let ( _, _, _ , frame_length_offset) = parse_v1_trailing_offsets ( & ct) ;
303- //= spec/client-apis/encrypt .md#v1-header
304+ let ( _, _, iv_length_offset , frame_length_offset) = parse_v1_trailing_offsets ( & ct) ;
305+ //= spec/data-format/message-header .md#frame-length
304306 //= type=test
305- //# - MUST serialize the [Frame Length](../data-format/message-header.md#frame-length).
306- //# The value MUST be the value of the frame size determined above.
307+ //# The frame length MUST be interpreted as a UInt32.
308+ // Frame length field is 4 bytes (UInt32), immediately after IV length
309+ assert_eq ! (
310+ frame_length_offset - iv_length_offset,
311+ 1 ,
312+ "frame length immediately follows IV length (confirming IV length is 1 byte)"
313+ ) ;
307314 let frame_length = u32:: from_be_bytes ( [
308315 ct[ frame_length_offset] ,
309316 ct[ frame_length_offset + 1 ] ,
310317 ct[ frame_length_offset + 2 ] ,
311318 ct[ frame_length_offset + 3 ] ,
312319 ] ) ;
313- assert_eq ! ( frame_length, 4096 , "Frame Length must be the default 4096" ) ;
320+ //= spec/client-apis/encrypt.md#v1-header
321+ //= type=test
322+ //# - MUST serialize the [Frame Length](../data-format/message-header.md#frame-length).
323+ //# The value MUST be the value of the frame size determined above.
324+ assert_eq ! ( frame_length, 4096 , "Frame Length must be the default 4096 (serialized as UInt32)" ) ;
314325 // Round-trip proves the frame length is correctly processed.
315326 let result = round_trip_v1 ( b"frame length test" , EncryptionContext :: new ( ) ) . await ;
316327 assert_eq ! ( result, b"frame length test" ) ;
@@ -420,89 +431,6 @@ async fn test_v1_reserved_field_is_4_bytes() {
420431 ) ;
421432}
422433
423- #[ tokio:: test( flavor = "multi_thread" ) ]
424- async fn test_v1_iv_length_field_is_1_byte ( ) {
425- let ct = encrypt_v1_with_ec ( b"iv length 1 byte test" , EncryptionContext :: new ( ) ) . await ;
426- let ( _, _, iv_length_offset, frame_length_offset) = parse_v1_trailing_offsets ( & ct) ;
427- //= spec/data-format/message-header.md#iv-length
428- //= type=test
429- //# The length of the serialized IV length field MUST be 1 byte.
430- assert_eq ! (
431- frame_length_offset - iv_length_offset,
432- 1 ,
433- "IV length field must be exactly 1 byte"
434- ) ;
435- }
436-
437- #[ tokio:: test( flavor = "multi_thread" ) ]
438- async fn test_v1_iv_length_serialized_as_uint8 ( ) {
439- let ct = encrypt_v1_with_ec ( b"iv length uint8 test" , EncryptionContext :: new ( ) ) . await ;
440- let ( _, _, iv_length_offset, _) = parse_v1_trailing_offsets ( & ct) ;
441- //= spec/data-format/message-header.md#iv-length
442- //= type=test
443- //# The IV length MUST be interpreted as a UInt8.
444- // AlgAes256GcmIv12Tag16HkdfSha256 has IV length 12
445- let iv_length = ct[ iv_length_offset] ;
446- assert_eq ! (
447- iv_length, 12 ,
448- "IV length must be 12 for this algorithm suite, serialized as single UInt8 byte"
449- ) ;
450- }
451-
452- #[ tokio:: test( flavor = "multi_thread" ) ]
453- async fn test_v1_iv_length_equals_suite_iv_length ( ) {
454- let ct = encrypt_v1_with_ec ( b"iv length suite test" , EncryptionContext :: new ( ) ) . await ;
455- let ( _, _, iv_length_offset, _) = parse_v1_trailing_offsets ( & ct) ;
456- //= spec/data-format/message-header.md#iv-length
457- //= type=test
458- //# This value MUST be equal to the [IV length](../framework/algorithm-suites.md#iv-length) value of the
459- //# [algorithm suite](../framework/algorithm-suites.md) specified by the [Algorithm Suite ID](#algorithm-suite-id) field.
460- // AlgAes256GcmIv12Tag16HkdfSha256 has IV length 12
461- assert_eq ! (
462- ct[ iv_length_offset] , 12 ,
463- "IV length must match algorithm suite IV length (12)"
464- ) ;
465- // Round-trip proves the IV length is validated during decrypt.
466- let result = round_trip_v1 ( b"iv length suite test" , EncryptionContext :: new ( ) ) . await ;
467- assert_eq ! ( result, b"iv length suite test" ) ;
468- }
469-
470- #[ tokio:: test( flavor = "multi_thread" ) ]
471- async fn test_v1_frame_length_field_is_4_bytes ( ) {
472- let ct = encrypt_v1_with_ec ( b"frame length 4 bytes v1 test" , EncryptionContext :: new ( ) ) . await ;
473- let ( _, _, _, frame_length_offset) = parse_v1_trailing_offsets ( & ct) ;
474- let frame_length = u32:: from_be_bytes ( [
475- ct[ frame_length_offset] ,
476- ct[ frame_length_offset + 1 ] ,
477- ct[ frame_length_offset + 2 ] ,
478- ct[ frame_length_offset + 3 ] ,
479- ] ) ;
480- assert_eq ! ( frame_length, 4096 , "default frame length should be 4096" ) ;
481- }
482-
483- #[ tokio:: test( flavor = "multi_thread" ) ]
484- async fn test_v1_frame_length_serialized_as_uint32 ( ) {
485- let ct = encrypt_v1_with_ec ( b"frame length uint32 v1 test" , EncryptionContext :: new ( ) ) . await ;
486- let ( _, _, _, frame_length_offset) = parse_v1_trailing_offsets ( & ct) ;
487- //= spec/data-format/message-header.md#frame-length
488- //= type=test
489- //# The frame length MUST be interpreted as a UInt32.
490- // Parse as big-endian UInt32
491- let frame_length = u32:: from_be_bytes ( [
492- ct[ frame_length_offset] ,
493- ct[ frame_length_offset + 1 ] ,
494- ct[ frame_length_offset + 2 ] ,
495- ct[ frame_length_offset + 3 ] ,
496- ] ) ;
497- assert_eq ! (
498- frame_length, 4096 ,
499- "default frame length should be 4096 when serialized as UInt32"
500- ) ;
501- // Confirm round-trip succeeds
502- let result = round_trip_v1 ( b"frame length uint32 v1 test" , EncryptionContext :: new ( ) ) . await ;
503- assert_eq ! ( result, b"frame length uint32 v1 test" ) ;
504- }
505-
506434#[ tokio:: test( flavor = "multi_thread" ) ]
507435async fn test_v1_reserved_bytes_tampered_rejected ( ) {
508436 let keyring = test_keyring ( ) . await ;
0 commit comments