@@ -4,8 +4,8 @@ use crate::{RealmId, Result};
44
55use super :: auth:: { constant_time_eq, footer_aad, mac_hk} ;
66use super :: fields:: {
7- FOOTER_CLEARTEXT_END_V1 , FOOTER_CLEARTEXT_END_V2 , FOOTER_FIELDS_END_V1 , FOOTER_FIELDS_END_V2 ,
8- MAGIC , MANIFEST_TAG_LEN , SegmentFooterFields , max_manifest_len, max_manifest_len_v2 ,
7+ FOOTER_CLEARTEXT_END , FOOTER_FIELDS_END , FORMAT_VERSION , MAGIC , MANIFEST_TAG_LEN ,
8+ SegmentFooterFields , max_manifest_len,
99} ;
1010
1111pub fn decode_segment_footer (
@@ -17,47 +17,27 @@ pub fn decode_segment_footer(
1717 let parsed = parse_cleartext ( bytes, page_size) ?;
1818 authenticate_cleartext ( bytes, hk, & parsed) ?;
1919 let ( fields, ciphertext_end, tag_end) = assemble_fields ( bytes, & parsed, cipher) ?;
20- let manifest = authenticate_manifest (
21- bytes,
22- cipher,
23- & fields,
24- parsed. cleartext_end ,
25- ciphertext_end,
26- tag_end,
27- ) ?;
20+ let manifest = authenticate_manifest ( bytes, cipher, & fields, ciphertext_end, tag_end) ?;
2821 Ok ( ( fields, manifest) )
2922}
3023
3124struct ParsedFooter {
32- fields_end : usize ,
33- cleartext_end : usize ,
34- max_manifest : usize ,
3525 manifest_offset : u32 ,
3626 manifest_len : usize ,
3727 fields : SegmentFooterFields ,
3828}
3929
4030fn parse_cleartext ( bytes : & [ u8 ] , page_size : usize ) -> Result < ParsedFooter > {
41- if bytes. len ( ) != page_size || page_size < FOOTER_CLEARTEXT_END_V1 + MANIFEST_TAG_LEN {
31+ if bytes. len ( ) != page_size || page_size < FOOTER_CLEARTEXT_END + MANIFEST_TAG_LEN {
4232 return Err ( PagedbError :: Unsupported ) ;
4333 }
4434 if bytes[ ..8 ] != MAGIC {
4535 return Err ( PagedbError :: footer_framing_invalid ( "magic" ) ) ;
4636 }
4737 let format_version = u16_le ( & bytes[ 8 ..10 ] ) ;
48- let ( fields_end, cleartext_end, max_manifest) = match format_version {
49- 1 => (
50- FOOTER_FIELDS_END_V1 ,
51- FOOTER_CLEARTEXT_END_V1 ,
52- max_manifest_len ( page_size) ,
53- ) ,
54- 2 if page_size >= FOOTER_CLEARTEXT_END_V2 + MANIFEST_TAG_LEN => (
55- FOOTER_FIELDS_END_V2 ,
56- FOOTER_CLEARTEXT_END_V2 ,
57- max_manifest_len_v2 ( page_size) ,
58- ) ,
59- _ => return Err ( PagedbError :: Unsupported ) ,
60- } ;
38+ if format_version != FORMAT_VERSION {
39+ return Err ( PagedbError :: footer_framing_invalid ( "format_version" ) ) ;
40+ }
6141 let mut offset = 10 ;
6242 let cipher_id = bytes[ offset] ;
6343 offset += 1 ;
@@ -80,26 +60,10 @@ fn parse_cleartext(bytes: &[u8], page_size: usize) -> Result<ParsedFooter> {
8060 let manifest_len = usize:: try_from ( u32_le ( & bytes[ offset..offset + 4 ] ) )
8161 . map_err ( |_| PagedbError :: Unsupported ) ?;
8262 offset += 4 ;
83- let ( index_start_page, index_page_count) = if format_version == 2 {
84- (
85- u64_le ( & bytes[ offset..offset + 8 ] ) ,
86- u32_le ( & bytes[ offset + 8 ..offset + 12 ] ) ,
87- )
88- } else {
89- ( 0 , 0 )
90- } ;
91- debug_assert_eq ! (
92- if format_version == 2 {
93- offset + 12
94- } else {
95- offset
96- } ,
97- fields_end
98- ) ;
63+ let index_start_page = u64_le ( & bytes[ offset..offset + 8 ] ) ;
64+ let index_page_count = u32_le ( & bytes[ offset + 8 ..offset + 12 ] ) ;
65+ debug_assert_eq ! ( offset + 12 , FOOTER_FIELDS_END ) ;
9966 Ok ( ParsedFooter {
100- fields_end,
101- cleartext_end,
102- max_manifest,
10367 manifest_offset,
10468 manifest_len,
10569 fields : SegmentFooterFields {
@@ -123,13 +87,13 @@ fn authenticate_cleartext(
12387 hk : & crate :: crypto:: keys:: DerivedKey ,
12488 parsed : & ParsedFooter ,
12589) -> Result < ( ) > {
126- let mac = mac_hk ( hk, & bytes[ ..parsed . fields_end ] ) ?;
127- let valid_mac = constant_time_eq ( & mac, & bytes[ parsed . fields_end ..parsed . cleartext_end ] ) ;
90+ let mac = mac_hk ( hk, & bytes[ ..FOOTER_FIELDS_END ] ) ?;
91+ let valid_mac = constant_time_eq ( & mac, & bytes[ FOOTER_FIELDS_END .. FOOTER_CLEARTEXT_END ] ) ;
12892 let expected_offset =
129- u32:: try_from ( parsed . cleartext_end ) . map_err ( |_| PagedbError :: Unsupported ) ?;
93+ u32:: try_from ( FOOTER_CLEARTEXT_END ) . map_err ( |_| PagedbError :: Unsupported ) ?;
13094 if !valid_mac
13195 || parsed. manifest_offset != expected_offset
132- || parsed. manifest_len > parsed . max_manifest
96+ || parsed. manifest_len > max_manifest_len ( bytes . len ( ) )
13397 {
13498 return Err ( PagedbError :: footer_framing_invalid (
13599 "manifest_offset_or_length" ,
@@ -152,8 +116,7 @@ fn assemble_fields(
152116 } ,
153117 ) ) ;
154118 }
155- let ciphertext_end = parsed
156- . cleartext_end
119+ let ciphertext_end = FOOTER_CLEARTEXT_END
157120 . checked_add ( parsed. manifest_len )
158121 . ok_or_else ( || PagedbError :: arithmetic_overflow ( "footer manifest end" ) ) ?;
159122 let tag_end = ciphertext_end
@@ -169,7 +132,6 @@ fn authenticate_manifest(
169132 bytes : & [ u8 ] ,
170133 cipher : & Cipher ,
171134 fields : & SegmentFooterFields ,
172- cleartext_end : usize ,
173135 ciphertext_end : usize ,
174136 tag_end : usize ,
175137) -> Result < Vec < u8 > > {
@@ -181,7 +143,7 @@ fn authenticate_manifest(
181143 let mut file_id = [ 0u8 ; 6 ] ;
182144 file_id. copy_from_slice ( & fields. segment_id [ ..6 ] ) ;
183145 let nonce = Nonce :: from_parts ( file_id, nonce_counter) ;
184- let mut manifest = bytes[ cleartext_end ..ciphertext_end] . to_vec ( ) ;
146+ let mut manifest = bytes[ FOOTER_CLEARTEXT_END ..ciphertext_end] . to_vec ( ) ;
185147 let mut tag = [ 0u8 ; MANIFEST_TAG_LEN ] ;
186148 tag. copy_from_slice ( & bytes[ ciphertext_end..tag_end] ) ;
187149 cipher
0 commit comments