@@ -379,49 +379,6 @@ impl CipherCtxRef {
379379        unsafe  {  ffi:: EVP_CIPHER_CTX_num ( self . as_ptr ( ) )  as  usize  } 
380380    } 
381381
382-     /// Returns number of bytes cached in partial block update. 
383-      #[ cfg( ossl110) ]  
384-     fn  used_block_size ( & self )  -> usize  { 
385-         self . num ( ) 
386-     } 
387- 
388-     /// Returns maximum number of bytes that could be cached. 
389-      #[ cfg( not( ossl110) ) ]  
390-     fn  used_block_size ( & self )  -> usize  { 
391-         self . block_size ( ) 
392-     } 
393- 
394-     /// Calculate the minimal size of the output buffer given the 
395-      /// input buffer size. 
396-      /// 
397-      /// For streaming ciphers the minimal output size is the same as 
398-      /// the input size. For block ciphers the minimal output size 
399-      /// additionally depends on the partial blocks that might have 
400-      /// been written in previous calls to [`Self::cipher_update`]. 
401-      /// 
402-      /// This function takes into account the number of partially 
403-      /// written blocks for block ciphers for supported targets 
404-      /// (OpenSSL >= 1.1). For unsupported targets the number of 
405-      /// partially written bytes is assumed to contain one full block 
406-      /// (pessimistic case). 
407-      /// 
408-      /// # Panics 
409-      /// 
410-      /// Panics if the context has not been initialized with a cipher. 
411-      pub  fn  minimal_output_size ( & self ,  inlen :  usize )  -> usize  { 
412-         let  block_size = self . block_size ( ) ; 
413-         if  block_size > 1  { 
414-             // block cipher 
415-             let  num = self . used_block_size ( ) ; 
416-             let  total_size = inlen + num; 
417-             let  num_blocks = total_size / block_size; 
418-             num_blocks *  block_size
419-         }  else  { 
420-             // streaming cipher 
421-             inlen
422-         } 
423-     } 
424- 
425382    /// Sets the length of the IV expected by this context. 
426383     /// 
427384     /// Only some ciphers support configurable IV lengths. 
@@ -569,7 +526,11 @@ impl CipherCtxRef {
569526        output :  Option < & mut  [ u8 ] > , 
570527    )  -> Result < usize ,  ErrorStack >  { 
571528        if  let  Some ( output)  = & output { 
572-             let  min_output_size = self . minimal_output_size ( input. len ( ) ) ; 
529+             let  mut  block_size = self . block_size ( ) ; 
530+             if  block_size == 1  { 
531+                 block_size = 0 ; 
532+             } 
533+             let  min_output_size = input. len ( )  + block_size; 
573534            assert ! ( 
574535                output. len( )  >= min_output_size, 
575536                "Output buffer size should be at least {} bytes." , 
@@ -588,16 +549,13 @@ impl CipherCtxRef {
588549     /// 
589550     /// This function is the same as [`Self::cipher_update`] but with the 
590551     /// output size check removed. It can be used when the exact 
591-      /// buffer size control is maintained by the caller and the 
592-      /// underlying cryptographic library doesn't expose exact block 
593-      /// cache data (e.g. OpenSSL < 1.1, BoringSSL, LibreSSL). 
552+      /// buffer size control is maintained by the caller. 
594553     /// 
595554     /// SAFETY: The caller is expected to provide `output` buffer 
596555     /// large enough to contain correct number of bytes. For streaming 
597556     /// ciphers the output buffer size should be at least as big as 
598557     /// the input buffer. For block ciphers the size of the output 
599-      /// buffer depends on the state of partially updated blocks (see 
600-      /// [`Self::minimal_output_size`]). 
558+      /// buffer depends on the state of partially updated blocks. 
601559     #[ corresponds( EVP_CipherUpdate ) ]  
602560    pub  unsafe  fn  cipher_update_unchecked ( 
603561        & mut  self , 
@@ -649,14 +607,34 @@ impl CipherCtxRef {
649607            assert ! ( output. len( )  >= block_size) ; 
650608        } 
651609
610+         unsafe  {  self . cipher_final_unchecked ( output)  } 
611+     } 
612+ 
613+     /// Finalizes the encryption or decryption process. 
614+      /// 
615+      /// Any remaining data will be written to the output buffer. 
616+      /// 
617+      /// Returns the number of bytes written to `output`. 
618+      /// 
619+      /// This function is the same as [`Self::cipher_final`] but with 
620+      /// the output buffer size check removed. 
621+      /// 
622+      /// SAFETY: The caller is expected to provide `output` buffer 
623+      /// large enough to contain correct number of bytes. For streaming 
624+      /// ciphers the output buffer can be empty, for block ciphers the 
625+      /// output buffer should be at least as big as the block. 
626+      #[ corresponds( EVP_CipherFinal ) ]  
627+     pub  unsafe  fn  cipher_final_unchecked ( 
628+         & mut  self , 
629+         output :  & mut  [ u8 ] , 
630+     )  -> Result < usize ,  ErrorStack >  { 
652631        let  mut  outl = 0 ; 
653-         unsafe  { 
654-             cvt ( ffi:: EVP_CipherFinal ( 
655-                 self . as_ptr ( ) , 
656-                 output. as_mut_ptr ( ) , 
657-                 & mut  outl, 
658-             ) ) ?; 
659-         } 
632+ 
633+         cvt ( ffi:: EVP_CipherFinal ( 
634+             self . as_ptr ( ) , 
635+             output. as_mut_ptr ( ) , 
636+             & mut  outl, 
637+         ) ) ?; 
660638
661639        Ok ( outl as  usize ) 
662640    } 
@@ -757,75 +735,6 @@ mod test {
757735        aes_128_cbc ( cipher) ; 
758736    } 
759737
760-     #[ test]  
761-     #[ cfg( ossl110) ]  
762-     fn  partial_block_updates ( )  { 
763-         test_block_cipher_for_partial_block_updates ( Cipher :: aes_128_cbc ( ) ) ; 
764-         test_block_cipher_for_partial_block_updates ( Cipher :: aes_256_cbc ( ) ) ; 
765-         test_block_cipher_for_partial_block_updates ( Cipher :: des_ede3_cbc ( ) ) ; 
766-     } 
767- 
768-     #[ cfg( ossl110) ]  
769-     fn  test_block_cipher_for_partial_block_updates ( cipher :  & ' static  CipherRef )  { 
770-         let  mut  key = vec ! [ 0 ;  cipher. key_length( ) ] ; 
771-         rand_bytes ( & mut  key) . unwrap ( ) ; 
772-         let  mut  iv = vec ! [ 0 ;  cipher. iv_length( ) ] ; 
773-         rand_bytes ( & mut  iv) . unwrap ( ) ; 
774- 
775-         let  mut  ctx = CipherCtx :: new ( ) . unwrap ( ) ; 
776- 
777-         ctx. encrypt_init ( Some ( cipher) ,  Some ( & key) ,  Some ( & iv) ) 
778-             . unwrap ( ) ; 
779-         ctx. set_padding ( false ) ; 
780- 
781-         let  block_size = cipher. block_size ( ) ; 
782-         assert ! ( block_size > 1 ,  "Need a block cipher, not a stream cipher" ) ; 
783- 
784-         // update cipher with non-full block 
785-         // expect no output until a block is complete 
786-         let  outlen = ctx
787-             . cipher_update ( & vec ! [ 0 ;  block_size - 1 ] ,  Some ( & mut  [ 0 ;  0 ] ) ) 
788-             . unwrap ( ) ; 
789-         assert_eq ! ( 0 ,  outlen) ; 
790- 
791-         // update cipher with missing bytes from the previous block 
792-         // and one additional block, output should contain two blocks 
793-         let  mut  two_blocks = vec ! [ 0 ;  block_size *  2 ] ; 
794-         let  outlen = ctx
795-             . cipher_update ( & vec ! [ 0 ;  block_size + 1 ] ,  Some ( & mut  two_blocks) ) 
796-             . unwrap ( ) ; 
797-         assert_eq ! ( block_size *  2 ,  outlen) ; 
798- 
799-         ctx. cipher_final_vec ( & mut  vec ! [ 0 ;  0 ] ) . unwrap ( ) ; 
800- 
801-         // try to decrypt 
802-         ctx. decrypt_init ( Some ( cipher) ,  Some ( & key) ,  Some ( & iv) ) 
803-             . unwrap ( ) ; 
804-         ctx. set_padding ( false ) ; 
805- 
806-         // update cipher with non-full block 
807-         // expect no output until a block is complete 
808-         let  outlen = ctx
809-             . cipher_update ( & two_blocks[ 0 ..block_size - 1 ] ,  Some ( & mut  [ 0 ;  0 ] ) ) 
810-             . unwrap ( ) ; 
811-         assert_eq ! ( 0 ,  outlen) ; 
812- 
813-         // update cipher with missing bytes from the previous block 
814-         // and one additional block, output should contain two blocks 
815-         let  mut  two_blocks_decrypted = vec ! [ 0 ;  block_size *  2 ] ; 
816-         let  outlen = ctx
817-             . cipher_update ( 
818-                 & two_blocks[ block_size - 1 ..] , 
819-                 Some ( & mut  two_blocks_decrypted) , 
820-             ) 
821-             . unwrap ( ) ; 
822-         assert_eq ! ( block_size *  2 ,  outlen) ; 
823- 
824-         ctx. cipher_final_vec ( & mut  vec ! [ 0 ;  0 ] ) . unwrap ( ) ; 
825-         // check if the decrypted blocks are the same as input (all zeros) 
826-         assert_eq ! ( two_blocks_decrypted,  vec![ 0 ;  block_size *  2 ] ) ; 
827-     } 
828- 
829738    #[ test]  
830739    fn  test_stream_ciphers ( )  { 
831740        test_stream_cipher ( Cipher :: aes_192_ctr ( ) ) ; 
@@ -894,43 +803,19 @@ mod test {
894803    } 
895804
896805    #[ test]  
897-     #[ should_panic( expected = "Output buffer size should be at least 16 bytes." ) ]  
898-     #[ cfg( ossl110) ]  
899-     fn  full_block_updates_aes_128 ( )  { 
900-         output_buffer_too_small ( Cipher :: aes_128_cbc ( ) ) ; 
901-     } 
902- 
903-     #[ test]  
904-     #[ should_panic( expected = "Output buffer size should be at least 16 bytes." ) ]  
905-     #[ cfg( ossl110) ]  
906-     fn  full_block_updates_aes_256 ( )  { 
907-         output_buffer_too_small ( Cipher :: aes_256_cbc ( ) ) ; 
908-     } 
909- 
910-     #[ test]  
911-     #[ should_panic( expected = "Output buffer size should be at least 8 bytes." ) ]  
912-     #[ cfg( ossl110) ]  
913-     fn  full_block_updates_3des ( )  { 
914-         output_buffer_too_small ( Cipher :: des_ede3_cbc ( ) ) ; 
915-     } 
916- 
917-     #[ test]  
918-     #[ should_panic( expected = "Output buffer size should be at least 32 bytes." ) ]  
919-     #[ cfg( not( ossl110) ) ]  
806+     #[ should_panic( expected = "Output buffer size should be at least 33 bytes." ) ]  
920807    fn  full_block_updates_aes_128 ( )  { 
921808        output_buffer_too_small ( Cipher :: aes_128_cbc ( ) ) ; 
922809    } 
923810
924811    #[ test]  
925-     #[ should_panic( expected = "Output buffer size should be at least 32 bytes." ) ]  
926-     #[ cfg( not( ossl110) ) ]  
812+     #[ should_panic( expected = "Output buffer size should be at least 33 bytes." ) ]  
927813    fn  full_block_updates_aes_256 ( )  { 
928814        output_buffer_too_small ( Cipher :: aes_256_cbc ( ) ) ; 
929815    } 
930816
931817    #[ test]  
932-     #[ should_panic( expected = "Output buffer size should be at least 16 bytes." ) ]  
933-     #[ cfg( not( ossl110) ) ]  
818+     #[ should_panic( expected = "Output buffer size should be at least 17 bytes." ) ]  
934819    fn  full_block_updates_3des ( )  { 
935820        output_buffer_too_small ( Cipher :: des_ede3_cbc ( ) ) ; 
936821    } 
0 commit comments