@@ -94,40 +94,42 @@ mod real_chachapoly {
94
94
}
95
95
96
96
pub fn decrypt ( & mut self , input : & [ u8 ] , output : & mut [ u8 ] , tag : & [ u8 ] ) -> bool {
97
- if self . decrypt_inner ( input, Some ( output) , Some ( tag) ) {
98
- self . cipher . process ( input, output) ;
99
- return true
100
- }
101
- false
102
- }
103
-
104
- // Decrypt in place, and check the tag if it's provided. If the tag is not provided, then
105
- // `finish_and_check_tag` may be called to check it later.
106
- pub fn decrypt_in_place ( & mut self , input : & mut [ u8 ] , tag : Option < & [ u8 ] > ) -> bool {
107
- if self . decrypt_inner ( input, None , tag) {
108
- self . cipher . process_in_place ( input) ;
109
- return true
110
- }
111
- false
112
- }
113
-
114
- fn decrypt_inner ( & mut self , input : & [ u8 ] , output : Option < & mut [ u8 ] > , tag : Option < & [ u8 ] > ) -> bool {
115
- if let Some ( output) = output {
116
- assert ! ( input. len( ) == output. len( ) ) ;
117
- }
97
+ assert ! ( input. len( ) == output. len( ) ) ;
118
98
assert ! ( self . finished == false ) ;
119
99
100
+ self . finished = true ;
101
+
120
102
self . mac . input ( input) ;
121
103
122
104
self . data_len += input. len ( ) ;
105
+ ChaCha20Poly1305RFC :: pad_mac_16 ( & mut self . mac , self . data_len ) ;
106
+ self . mac . input ( & self . aad_len . to_le_bytes ( ) ) ;
107
+ self . mac . input ( & ( self . data_len as u64 ) . to_le_bytes ( ) ) ;
123
108
124
- if let Some ( tag) = tag {
125
- return self . finish_and_check_tag ( tag)
109
+ let mut calc_tag = [ 0u8 ; 16 ] ;
110
+ self . mac . raw_result ( & mut calc_tag) ;
111
+ if fixed_time_eq ( & calc_tag, tag) {
112
+ self . cipher . process ( input, output) ;
113
+ true
114
+ } else {
115
+ false
126
116
}
127
- true
128
117
}
129
118
130
- pub fn finish_and_check_tag ( & mut self , tag : & [ u8 ] ) -> bool {
119
+ // Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it
120
+ // later when decryption finishes.
121
+ //
122
+ // pub(super) because the public API should always enforce tag checking.
123
+ pub ( super ) fn decrypt_in_place ( & mut self , input_output : & mut [ u8 ] ) {
124
+ assert ! ( self . finished == false ) ;
125
+ self . mac . input ( input_output) ;
126
+ self . data_len += input_output. len ( ) ;
127
+ self . cipher . process_in_place ( input_output) ;
128
+ }
129
+
130
+ // If we were previously decrypting with `decrypt_in_place`, this method must be used to finish
131
+ // decrypting and check the tag. Returns whether or not the tag is valid.
132
+ pub ( super ) fn finish_and_check_tag ( & mut self , tag : & [ u8 ] ) -> bool {
131
133
self . finished = true ;
132
134
ChaCha20Poly1305RFC :: pad_mac_16 ( & mut self . mac , self . data_len ) ;
133
135
self . mac . input ( & self . aad_len . to_le_bytes ( ) ) ;
@@ -159,7 +161,7 @@ impl<'a, R: Read> Read for ChaChaPolyReader<'a, R> {
159
161
fn read ( & mut self , dest : & mut [ u8 ] ) -> Result < usize , io:: Error > {
160
162
let res = self . read . read ( dest) ?;
161
163
if res > 0 {
162
- self . chacha . decrypt_in_place ( & mut dest[ 0 ..res] , None ) ;
164
+ self . chacha . decrypt_in_place ( & mut dest[ 0 ..res] ) ;
163
165
}
164
166
Ok ( res)
165
167
}
@@ -305,13 +307,8 @@ mod fuzzy_chachapoly {
305
307
true
306
308
}
307
309
308
- pub fn decrypt_in_place ( & mut self , _input : & mut [ u8 ] , tag : Option < & [ u8 ] > ) -> bool {
310
+ pub fn decrypt_in_place ( & mut self , _input : & mut [ u8 ] ) {
309
311
assert ! ( self . finished == false ) ;
310
- if let Some ( tag) = tag {
311
- if tag[ ..] != self . tag [ ..] { return false ; }
312
- }
313
- self . finished = true ;
314
- true
315
312
}
316
313
317
314
pub fn finish_and_check_tag ( & mut self , tag : & [ u8 ] ) -> bool {
0 commit comments