@@ -199,35 +199,68 @@ impl EvpCipherAead {
199199 aad : Option < Aad < ' _ > > ,
200200 nonce : Option < & [ u8 ] > ,
201201 ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
202+ // Temporary while we remove this function
203+ if ciphertext. len ( ) < self . tag_len {
204+ return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
205+ }
206+
202207 let mut ctx = openssl:: cipher_ctx:: CipherCtx :: new ( ) ?;
203208 ctx. copy ( & self . base_decryption_ctx ) ?;
204- Self :: decrypt_with_context (
209+ Ok ( pyo3 :: types :: PyBytes :: new_with (
205210 py,
211+ ciphertext. len ( ) - self . tag_len ,
212+ |b| {
213+ EvpCipherAead :: decrypt_with_context (
214+ ctx,
215+ ciphertext,
216+ aad,
217+ nonce,
218+ self . tag_len ,
219+ self . tag_first ,
220+ false ,
221+ b,
222+ ) ?;
223+ Ok ( ( ) )
224+ } ,
225+ ) ?)
226+ }
227+
228+ fn decrypt_into (
229+ & self ,
230+ // We have this arg so we have consistent arguments with decrypt_into in
231+ // LazyEvpCipherAead. We can remove it when we remove LazyEvpCipherAead.
232+ _py : pyo3:: Python < ' _ > ,
233+ ciphertext : & [ u8 ] ,
234+ aad : Option < Aad < ' _ > > ,
235+ nonce : Option < & [ u8 ] > ,
236+ buf : & mut [ u8 ] ,
237+ ) -> CryptographyResult < ( ) > {
238+ let mut ctx = openssl:: cipher_ctx:: CipherCtx :: new ( ) ?;
239+ ctx. copy ( & self . base_decryption_ctx ) ?;
240+
241+ Self :: decrypt_with_context (
206242 ctx,
207243 ciphertext,
208244 aad,
209245 nonce,
210246 self . tag_len ,
211247 self . tag_first ,
212248 false ,
249+ buf,
213250 )
214251 }
215252
216253 #[ allow( clippy:: too_many_arguments) ]
217- fn decrypt_with_context < ' p > (
218- py : pyo3:: Python < ' p > ,
254+ fn decrypt_with_context (
219255 mut ctx : openssl:: cipher_ctx:: CipherCtx ,
220256 ciphertext : & [ u8 ] ,
221257 aad : Option < Aad < ' _ > > ,
222258 nonce : Option < & [ u8 ] > ,
223259 tag_len : usize ,
224260 tag_first : bool ,
225261 is_ccm : bool ,
226- ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
227- if ciphertext. len ( ) < tag_len {
228- return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
229- }
230-
262+ buf : & mut [ u8 ] ,
263+ ) -> CryptographyResult < ( ) > {
231264 let tag;
232265 let ciphertext_data;
233266 if tag_first {
@@ -253,16 +286,10 @@ impl EvpCipherAead {
253286
254287 Self :: process_aad ( & mut ctx, aad) ?;
255288
256- Ok ( pyo3:: types:: PyBytes :: new_with (
257- py,
258- ciphertext_data. len ( ) ,
259- |b| {
260- Self :: process_data ( & mut ctx, ciphertext_data, b, is_ccm)
261- . map_err ( |_| exceptions:: InvalidTag :: new_err ( ( ) ) ) ?;
289+ Self :: process_data ( & mut ctx, ciphertext_data, buf, is_ccm)
290+ . map_err ( |_| exceptions:: InvalidTag :: new_err ( ( ) ) ) ?;
262291
263- Ok ( ( ) )
264- } ,
265- ) ?)
292+ Ok ( ( ) )
266293 }
267294}
268295
@@ -350,16 +377,27 @@ impl LazyEvpCipherAead {
350377 decryption_ctx. decrypt_init ( Some ( self . cipher ) , Some ( key_buf. as_bytes ( ) ) , None ) ?;
351378 }
352379
353- EvpCipherAead :: decrypt_with_context (
380+ if ciphertext. len ( ) < self . tag_len {
381+ return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
382+ }
383+
384+ Ok ( pyo3:: types:: PyBytes :: new_with (
354385 py,
355- decryption_ctx,
356- ciphertext,
357- aad,
358- nonce,
359- self . tag_len ,
360- self . tag_first ,
361- self . is_ccm ,
362- )
386+ ciphertext. len ( ) - self . tag_len ,
387+ |b| {
388+ EvpCipherAead :: decrypt_with_context (
389+ decryption_ctx,
390+ ciphertext,
391+ aad,
392+ nonce,
393+ self . tag_len ,
394+ self . tag_first ,
395+ self . is_ccm ,
396+ b,
397+ ) ?;
398+ Ok ( ( ) )
399+ } ,
400+ ) ?)
363401 }
364402}
365403
@@ -1060,8 +1098,50 @@ impl AesSiv {
10601098 data : CffiBuf < ' _ > ,
10611099 associated_data : Option < pyo3:: Bound < ' _ , pyo3:: types:: PyList > > ,
10621100 ) -> CryptographyResult < pyo3:: Bound < ' p , pyo3:: types:: PyBytes > > {
1101+ if data. as_bytes ( ) . len ( ) < self . ctx . tag_len {
1102+ return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
1103+ }
1104+ Ok ( pyo3:: types:: PyBytes :: new_with (
1105+ py,
1106+ data. as_bytes ( ) . len ( ) - self . ctx . tag_len ,
1107+ |b| {
1108+ let buf = CffiMutBuf :: from_bytes ( py, b) ;
1109+ self . decrypt_into ( py, data, associated_data, buf) ?;
1110+ Ok ( ( ) )
1111+ } ,
1112+ ) ?)
1113+ }
1114+
1115+ #[ pyo3( signature = ( data, associated_data, buf) ) ]
1116+ fn decrypt_into (
1117+ & self ,
1118+ py : pyo3:: Python < ' _ > ,
1119+ data : CffiBuf < ' _ > ,
1120+ associated_data : Option < pyo3:: Bound < ' _ , pyo3:: types:: PyList > > ,
1121+ mut buf : CffiMutBuf < ' _ > ,
1122+ ) -> CryptographyResult < usize > {
1123+ let data_bytes = data. as_bytes ( ) ;
10631124 let aad = associated_data. map ( Aad :: List ) ;
1064- self . ctx . decrypt ( py, data. as_bytes ( ) , aad, None )
1125+
1126+ // We need to do this check early to prevent underflow when computing expected_len
1127+ if data_bytes. len ( ) < self . ctx . tag_len {
1128+ return Err ( CryptographyError :: from ( exceptions:: InvalidTag :: new_err ( ( ) ) ) ) ;
1129+ }
1130+
1131+ let expected_len = data_bytes. len ( ) - self . ctx . tag_len ;
1132+ if buf. as_mut_bytes ( ) . len ( ) != expected_len {
1133+ return Err ( CryptographyError :: from (
1134+ pyo3:: exceptions:: PyValueError :: new_err ( format ! (
1135+ "buffer must be {} bytes" ,
1136+ expected_len
1137+ ) ) ,
1138+ ) ) ;
1139+ }
1140+
1141+ self . ctx
1142+ . decrypt_into ( py, data_bytes, aad, None , buf. as_mut_bytes ( ) ) ?;
1143+
1144+ Ok ( expected_len)
10651145 }
10661146}
10671147
0 commit comments