@@ -591,6 +591,50 @@ impl CipherCtxRef {
591
591
Ok ( len)
592
592
}
593
593
594
+ /// Like [`Self::cipher_update`] except that it writes output into the
595
+ /// `data` buffer. The `inlen` parameter specifies the number of bytes in
596
+ /// `data` that are considered the input. For streaming ciphers, the size of
597
+ /// `data` must be at least the input size. Otherwise, it must be at least
598
+ /// an additional block size larger.
599
+ ///
600
+ /// Note: Use [`Self::cipher_update`] with no output argument to write AAD.
601
+ ///
602
+ /// # Panics
603
+ ///
604
+ /// This function panics if the input size cannot be represented as `int` or
605
+ /// exceeds the buffer size, or if the output buffer does not contain enough
606
+ /// additional space.
607
+ #[ corresponds( EVP_CipherUpdate ) ]
608
+ pub fn cipher_update_inplace (
609
+ & mut self ,
610
+ data : & mut [ u8 ] ,
611
+ inlen : usize ,
612
+ ) -> Result < usize , ErrorStack > {
613
+ assert ! ( inlen <= data. len( ) , "Input size may not exceed buffer size" ) ;
614
+ let block_size = self . block_size ( ) ;
615
+ if block_size != 1 {
616
+ assert ! (
617
+ data. len( ) >= inlen + block_size,
618
+ "Output buffer size must be at least {} bytes." ,
619
+ inlen + block_size
620
+ ) ;
621
+ }
622
+
623
+ let inlen = c_int:: try_from ( inlen) . unwrap ( ) ;
624
+ let mut outlen = 0 ;
625
+ unsafe {
626
+ cvt ( ffi:: EVP_CipherUpdate (
627
+ self . as_ptr ( ) ,
628
+ data. as_mut_ptr ( ) ,
629
+ & mut outlen,
630
+ data. as_ptr ( ) ,
631
+ inlen,
632
+ ) )
633
+ } ?;
634
+
635
+ Ok ( outlen as usize )
636
+ }
637
+
594
638
/// Finalizes the encryption or decryption process.
595
639
///
596
640
/// Any remaining data will be written to the output buffer.
@@ -778,6 +822,26 @@ mod test {
778
822
779
823
ctx. cipher_final_vec ( & mut vec ! [ 0 ; 0 ] ) . unwrap ( ) ;
780
824
825
+ // encrypt again, but use in-place encryption this time
826
+ // First reset the IV
827
+ ctx. encrypt_init ( None , None , Some ( & iv) ) . unwrap ( ) ;
828
+ ctx. set_padding ( false ) ;
829
+ let mut data_inplace: [ u8 ; 32 ] = [ 1 ; 32 ] ;
830
+ let outlen = ctx
831
+ . cipher_update_inplace ( & mut data_inplace[ 0 ..15 ] , 15 )
832
+ . unwrap ( ) ;
833
+ assert_eq ! ( 15 , outlen) ;
834
+
835
+ let outlen = ctx
836
+ . cipher_update_inplace ( & mut data_inplace[ 15 ..32 ] , 17 )
837
+ . unwrap ( ) ;
838
+ assert_eq ! ( 17 , outlen) ;
839
+
840
+ ctx. cipher_final ( & mut [ 0u8 ; 0 ] ) . unwrap ( ) ;
841
+
842
+ // Check that the resulting data is encrypted in the same manner
843
+ assert_eq ! ( data_inplace. as_slice( ) , output. as_slice( ) ) ;
844
+
781
845
// try to decrypt
782
846
ctx. decrypt_init ( Some ( cipher) , Some ( & key) , Some ( & iv) )
783
847
. unwrap ( ) ;
@@ -800,6 +864,19 @@ mod test {
800
864
ctx. cipher_final_vec ( & mut vec ! [ 0 ; 0 ] ) . unwrap ( ) ;
801
865
// check if the decrypted blocks are the same as input (all ones)
802
866
assert_eq ! ( output_decrypted, vec![ 1 ; 32 ] ) ;
867
+
868
+ // decrypt again, but now the output in-place
869
+ ctx. decrypt_init ( None , None , Some ( & iv) ) . unwrap ( ) ;
870
+ ctx. set_padding ( false ) ;
871
+
872
+ let outlen = ctx. cipher_update_inplace ( & mut output[ 0 ..15 ] , 15 ) . unwrap ( ) ;
873
+ assert_eq ! ( 15 , outlen) ;
874
+
875
+ let outlen = ctx. cipher_update_inplace ( & mut output[ 15 ..] , 17 ) . unwrap ( ) ;
876
+ assert_eq ! ( 17 , outlen) ;
877
+
878
+ ctx. cipher_final_vec ( & mut vec ! [ 0 ; 0 ] ) . unwrap ( ) ;
879
+ assert_eq ! ( output_decrypted, output) ;
803
880
}
804
881
805
882
#[ test]
0 commit comments