55 html_logo_url = "https://github.com/RustCrypto/meta/master/logo.svg" ,
66 html_favicon_url = "https://github.com/RustCrypto/meta/master/logo.svg"
77) ]
8- #![ deny( unsafe_code) ]
8+ // #![deny(unsafe_code)]
99#![ warn( missing_docs, rust_2018_idioms) ]
1010
1111/// Constants used, reexported for convenience.
@@ -21,11 +21,12 @@ pub use aead::{
2121use aead:: { PostfixTagged , array:: ArraySize } ;
2222use cipher:: {
2323 BlockCipherDecrypt , BlockCipherEncrypt , BlockSizeUser ,
24- consts:: { U12 , U16 } ,
24+ consts:: { U2 , U12 , U16 } ,
2525 typenum:: Unsigned ,
2626} ;
27- use core:: marker:: PhantomData ;
27+ use core:: { marker:: PhantomData , ops :: Mul } ;
2828use dbl:: Dbl ;
29+ use inout:: { InOut , InOutBuf } ;
2930use subtle:: ConstantTimeEq ;
3031
3132/// Number of L values to be precomputed. Precomputing m values, allows
@@ -55,7 +56,9 @@ pub type Nonce<NonceSize> = Array<u8, NonceSize>;
5556/// OCB3 tag
5657pub type Tag < TagSize > = Array < u8 , TagSize > ;
5758
58- pub ( crate ) type Block = Array < u8 , U16 > ;
59+ type BlockSize = U16 ;
60+ pub ( crate ) type Block = Array < u8 , BlockSize > ;
61+ type DoubleBlock = Array < u8 , <BlockSize as Mul < U2 > >:: Output > ;
5962
6063mod sealed {
6164 use aead:: array:: {
@@ -210,34 +213,36 @@ where
210213 associated_data : & [ u8 ] ,
211214 buffer : & mut [ u8 ] ,
212215 ) -> aead:: Result < aead:: Tag < Self > > {
216+ let buffer = InOutBuf :: from ( buffer) ;
213217 if ( buffer. len ( ) > P_MAX ) || ( associated_data. len ( ) > A_MAX ) {
214218 unimplemented ! ( )
215219 }
216220
217221 // First, try to process many blocks at once.
218- let ( processed_bytes , mut offset_i, mut checksum_i) = self . wide_encrypt ( nonce, buffer) ;
222+ let ( tail , index , mut offset_i, mut checksum_i) = self . wide_encrypt ( nonce, buffer) ;
219223
220- let mut i = ( processed_bytes / 16 ) + 1 ;
224+ let mut i = index ;
221225
222226 // Then, process the remaining blocks.
223- for p_i in Block :: slice_as_chunks_mut ( & mut buffer[ processed_bytes..] ) . 0 {
227+ let ( blocks, mut tail) : ( InOutBuf < ' _ , ' _ , Block > , _ ) = tail. into_chunks ( ) ;
228+
229+ for p_i in blocks {
224230 // offset_i = offset_{i-1} xor L_{ntz(i)}
225231 inplace_xor ( & mut offset_i, & self . ll [ ntz ( i) ] ) ;
226232 // checksum_i = checksum_{i-1} xor p_i
227- inplace_xor ( & mut checksum_i, p_i) ;
233+ inplace_xor ( & mut checksum_i, p_i. get_in ( ) ) ;
228234 // c_i = offset_i xor ENCIPHER(K, p_i xor offset_i)
229- let c_i = p_i;
230- inplace_xor ( c_i, & offset_i) ;
231- self . cipher . encrypt_block ( c_i) ;
232- inplace_xor ( c_i, & offset_i) ;
235+ let mut c_i = p_i;
236+ c_i. xor_in2out ( & offset_i) ;
237+ self . cipher . encrypt_block ( c_i. get_out ( ) ) ;
238+ inplace_xor ( c_i. get_out ( ) , & offset_i) ;
233239
234240 i += 1 ;
235241 }
236242
237243 // Process any partial blocks.
238- if ( buffer. len ( ) % 16 ) != 0 {
239- let processed_bytes = ( i - 1 ) * 16 ;
240- let remaining_bytes = buffer. len ( ) - processed_bytes;
244+ if !tail. is_empty ( ) {
245+ let remaining_bytes = tail. len ( ) ;
241246
242247 // offset_* = offset_m xor L_*
243248 inplace_xor ( & mut offset_i, & self . ll_star ) ;
@@ -247,11 +252,11 @@ where
247252 self . cipher . encrypt_block ( & mut pad) ;
248253 // checksum_* = checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*)))
249254 let checksum_rhs = & mut [ 0u8 ; 16 ] ;
250- checksum_rhs[ ..remaining_bytes] . copy_from_slice ( & buffer [ processed_bytes.. ] ) ;
255+ checksum_rhs[ ..remaining_bytes] . copy_from_slice ( tail . get_in ( ) ) ;
251256 checksum_rhs[ remaining_bytes] = 0b1000_0000 ;
252257 inplace_xor ( & mut checksum_i, checksum_rhs. as_ref ( ) ) ;
253258 // C_* = P_* xor Pad[1..bitlen(P_*)]
254- let p_star = & mut buffer [ processed_bytes.. ] ;
259+ let p_star = tail . get_out ( ) ;
255260 let pad = & mut pad[ ..p_star. len ( ) ] ;
256261 for ( aa, bb) in p_star. iter_mut ( ) . zip ( pad) {
257262 * aa ^= * bb;
@@ -295,32 +300,32 @@ where
295300 if ( buffer. len ( ) > C_MAX ) || ( associated_data. len ( ) > A_MAX ) {
296301 unimplemented ! ( )
297302 }
303+ let buffer = InOutBuf :: from ( buffer) ;
298304
299305 // First, try to process many blocks at once.
300- let ( processed_bytes , mut offset_i, mut checksum_i) = self . wide_decrypt ( nonce, buffer) ;
306+ let ( tail , index , mut offset_i, mut checksum_i) = self . wide_decrypt ( nonce, buffer) ;
301307
302- let mut i = ( processed_bytes / 16 ) + 1 ;
308+ let mut i = index ;
303309
304310 // Then, process the remaining blocks.
305- let ( blocks, _remaining ) = Block :: slice_as_chunks_mut ( & mut buffer [ processed_bytes.. ] ) ;
311+ let ( blocks, mut tail ) : ( InOutBuf < ' _ , ' _ , Block > , _ ) = tail . into_chunks ( ) ;
306312 for c_i in blocks {
307313 // offset_i = offset_{i-1} xor L_{ntz(i)}
308314 inplace_xor ( & mut offset_i, & self . ll [ ntz ( i) ] ) ;
309315 // p_i = offset_i xor DECIPHER(K, c_i xor offset_i)
310- let p_i = c_i;
311- inplace_xor ( p_i, & offset_i) ;
312- self . cipher . decrypt_block ( p_i) ;
313- inplace_xor ( p_i, & offset_i) ;
316+ let mut p_i = c_i;
317+ p_i. xor_in2out ( & offset_i) ;
318+ self . cipher . decrypt_block ( p_i. get_out ( ) ) ;
319+ inplace_xor ( p_i. get_out ( ) , & offset_i) ;
314320 // checksum_i = checksum_{i-1} xor p_i
315- inplace_xor ( & mut checksum_i, p_i) ;
321+ inplace_xor ( & mut checksum_i, p_i. get_out ( ) ) ;
316322
317323 i += 1 ;
318324 }
319325
320326 // Process any partial blocks.
321- if ( buffer. len ( ) % 16 ) != 0 {
322- let processed_bytes = ( i - 1 ) * 16 ;
323- let remaining_bytes = buffer. len ( ) - processed_bytes;
327+ if !tail. is_empty ( ) {
328+ let remaining_bytes = tail. len ( ) ;
324329
325330 // offset_* = offset_m xor L_*
326331 inplace_xor ( & mut offset_i, & self . ll_star ) ;
@@ -329,14 +334,12 @@ where
329334 inplace_xor ( & mut pad, & offset_i) ;
330335 self . cipher . encrypt_block ( & mut pad) ;
331336 // P_* = C_* xor Pad[1..bitlen(C_*)]
332- let c_star = & mut buffer [ processed_bytes.. ] ;
337+ let c_star = tail . get_in ( ) ;
333338 let pad = & mut pad[ ..c_star. len ( ) ] ;
334- for ( aa, bb) in c_star. iter_mut ( ) . zip ( pad) {
335- * aa ^= * bb;
336- }
339+ tail. xor_in2out ( pad) ;
337340 // checksum_* = checksum_m xor (P_* || 1 || zeros(127-bitlen(P_*)))
338341 let checksum_rhs = & mut [ 0u8 ; 16 ] ;
339- checksum_rhs[ ..remaining_bytes] . copy_from_slice ( & buffer [ processed_bytes.. ] ) ;
342+ checksum_rhs[ ..remaining_bytes] . copy_from_slice ( tail . get_out ( ) ) ;
340343 checksum_rhs[ remaining_bytes] = 0b1000_0000 ;
341344 inplace_xor ( & mut checksum_i, checksum_rhs. as_ref ( ) ) ;
342345 }
@@ -347,20 +350,24 @@ where
347350 /// Encrypts plaintext in groups of two.
348351 ///
349352 /// Adapted from https://www.cs.ucdavis.edu/~rogaway/ocb/news/code/ocb.c
350- fn wide_encrypt ( & self , nonce : & Nonce < NonceSize > , buffer : & mut [ u8 ] ) -> ( usize , Block , Block ) {
353+ fn wide_encrypt < ' i , ' o > (
354+ & self ,
355+ nonce : & Nonce < NonceSize > ,
356+ buffer : InOutBuf < ' i , ' o , u8 > ,
357+ ) -> ( InOutBuf < ' i , ' o , u8 > , usize , Block , Block ) {
351358 const WIDTH : usize = 2 ;
352359
353360 let mut i = 1 ;
354361
355362 let mut offset_i = [ Block :: default ( ) ; WIDTH ] ;
356363 offset_i[ offset_i. len ( ) - 1 ] = initial_offset ( & self . cipher , nonce, TagSize :: to_u32 ( ) ) ;
357364 let mut checksum_i = Block :: default ( ) ;
358- for wide_blocks in buffer. chunks_exact_mut ( <Block as AssocArraySize >:: Size :: USIZE * WIDTH ) {
359- let p_i = split_into_two_blocks ( wide_blocks) ;
360365
361- // checksum_i = checksum_{i-1} xor p_i
366+ let ( wide_blocks, tail) : ( InOutBuf < ' _ , ' _ , DoubleBlock > , _ ) = buffer. into_chunks ( ) ;
367+ for wide_block in wide_blocks. into_iter ( ) {
368+ let mut p_i = split_into_two_blocks ( wide_block) ;
362369 for p_ij in & p_i {
363- inplace_xor ( & mut checksum_i, p_ij) ;
370+ inplace_xor ( & mut checksum_i, p_ij. get_in ( ) ) ;
364371 }
365372
366373 // offset_i = offset_{i-1} xor L_{ntz(i)}
@@ -373,32 +380,36 @@ where
373380
374381 // c_i = offset_i xor ENCIPHER(K, p_i xor offset_i)
375382 for j in 0 ..p_i. len ( ) {
376- inplace_xor ( p_i[ j] , & offset_i[ j] ) ;
377- self . cipher . encrypt_block ( p_i[ j] ) ;
378- inplace_xor ( p_i[ j] , & offset_i[ j] )
383+ p_i[ j] . xor_in2out ( & offset_i[ j] ) ;
384+ self . cipher . encrypt_block ( p_i[ j] . get_out ( ) ) ;
385+ inplace_xor ( p_i[ j] . get_out ( ) , & offset_i[ j] ) ;
379386 }
380387
381388 i += WIDTH ;
382389 }
383390
384- let processed_bytes = ( buffer. len ( ) / ( WIDTH * 16 ) ) * ( WIDTH * 16 ) ;
385-
386- ( processed_bytes, offset_i[ offset_i. len ( ) - 1 ] , checksum_i)
391+ ( tail, i, offset_i[ offset_i. len ( ) - 1 ] , checksum_i)
387392 }
388393
389394 /// Decrypts plaintext in groups of two.
390395 ///
391396 /// Adapted from https://www.cs.ucdavis.edu/~rogaway/ocb/news/code/ocb.c
392- fn wide_decrypt ( & self , nonce : & Nonce < NonceSize > , buffer : & mut [ u8 ] ) -> ( usize , Block , Block ) {
397+ fn wide_decrypt < ' i , ' o > (
398+ & self ,
399+ nonce : & Nonce < NonceSize > ,
400+ buffer : InOutBuf < ' i , ' o , u8 > ,
401+ ) -> ( InOutBuf < ' i , ' o , u8 > , usize , Block , Block ) {
393402 const WIDTH : usize = 2 ;
394403
395404 let mut i = 1 ;
396405
397406 let mut offset_i = [ Block :: default ( ) ; WIDTH ] ;
398407 offset_i[ offset_i. len ( ) - 1 ] = initial_offset ( & self . cipher , nonce, TagSize :: to_u32 ( ) ) ;
399408 let mut checksum_i = Block :: default ( ) ;
400- for wide_blocks in buffer. chunks_exact_mut ( 16 * WIDTH ) {
401- let c_i = split_into_two_blocks ( wide_blocks) ;
409+
410+ let ( wide_blocks, tail) : ( InOutBuf < ' _ , ' _ , DoubleBlock > , _ ) = buffer. into_chunks ( ) ;
411+ for wide_block in wide_blocks. into_iter ( ) {
412+ let mut c_i = split_into_two_blocks ( wide_block) ;
402413
403414 // offset_i = offset_{i-1} xor L_{ntz(i)}
404415 offset_i[ 0 ] = offset_i[ offset_i. len ( ) - 1 ] ;
@@ -411,17 +422,16 @@ where
411422 // p_i = offset_i xor DECIPHER(K, c_i xor offset_i)
412423 // checksum_i = checksum_{i-1} xor p_i
413424 for j in 0 ..c_i. len ( ) {
414- inplace_xor ( c_i[ j] , & offset_i[ j] ) ;
415- self . cipher . decrypt_block ( c_i[ j] ) ;
416- inplace_xor ( c_i[ j] , & offset_i[ j] ) ;
417- inplace_xor ( & mut checksum_i, c_i[ j] ) ;
425+ c_i[ j] . xor_in2out ( & offset_i[ j] ) ;
426+ self . cipher . decrypt_block ( c_i[ j] . get_out ( ) ) ;
427+ inplace_xor ( c_i[ j] . get_out ( ) , & offset_i[ j] ) ;
428+ inplace_xor ( & mut checksum_i, c_i[ j] . get_out ( ) ) ;
418429 }
419430
420431 i += WIDTH ;
421432 }
422433
423- let processed_bytes = ( buffer. len ( ) / ( WIDTH * 16 ) ) * ( WIDTH * 16 ) ;
424- ( processed_bytes, offset_i[ offset_i. len ( ) - 1 ] , checksum_i)
434+ ( tail, i, offset_i[ offset_i. len ( ) - 1 ] , checksum_i)
425435 }
426436
427437 /// Computes HASH function defined in https://www.rfc-editor.org/rfc/rfc7253.html#section-4.1
@@ -580,11 +590,20 @@ pub(crate) fn ntz(n: usize) -> usize {
580590}
581591
582592#[ inline]
583- pub ( crate ) fn split_into_two_blocks ( two_blocks : & mut [ u8 ] ) -> [ & mut Block ; 2 ] {
584- const BLOCK_SIZE : usize = 16 ;
585- debug_assert_eq ! ( two_blocks. len( ) , BLOCK_SIZE * 2 ) ;
586- let ( b0, b1) = two_blocks. split_at_mut ( BLOCK_SIZE ) ;
587- [ b0. try_into ( ) . unwrap ( ) , b1. try_into ( ) . unwrap ( ) ]
593+ pub ( crate ) fn split_into_two_blocks < ' i , ' o > (
594+ two_blocks : InOut < ' i , ' o , DoubleBlock > ,
595+ ) -> [ InOut < ' i , ' o , Block > ; 2 ] {
596+ let ( input, output) = two_blocks. into_raw ( ) ;
597+
598+ let ( bi0, bi1) = unsafe { input. as_ref ( ) }
599+ . unwrap ( )
600+ . split_at ( BlockSize :: USIZE ) ;
601+ let ( bi0, bi1) : ( & Block , & Block ) = ( bi0. try_into ( ) . unwrap ( ) , bi1. try_into ( ) . unwrap ( ) ) ;
602+ let ( bo0, bo1) = unsafe { output. as_mut ( ) }
603+ . unwrap ( )
604+ . split_at_mut ( BlockSize :: USIZE ) ;
605+ let ( bo0, bo1) : ( & mut Block , & mut Block ) = ( bo0. try_into ( ) . unwrap ( ) , bo1. try_into ( ) . unwrap ( ) ) ;
606+ [ InOut :: from ( ( bi0, bo0) ) , InOut :: from ( ( bi1, bo1) ) ]
588607}
589608
590609#[ cfg( test) ]
0 commit comments