24
24
// The goal for this implementation is to drive the overhead as close to zero
25
25
// as possible.
26
26
27
- use crate :: { c, cpu, debug, endian:: BigEndian , polyfill} ;
27
+ use crate :: {
28
+ c, cpu, debug,
29
+ endian:: { ArrayEncoding , BigEndian } ,
30
+ polyfill,
31
+ } ;
28
32
use core:: num:: Wrapping ;
29
- use zerocopy:: { AsBytes , FromBytes } ;
30
33
31
34
mod sha1;
32
35
mod sha2;
@@ -111,9 +114,7 @@ impl BlockContext {
111
114
112
115
Digest {
113
116
algorithm : self . algorithm ,
114
- // SAFETY: Invariant on this field promises that this is the correct
115
- // format function for this algorithm's block size.
116
- value : unsafe { ( self . algorithm . format_output ) ( self . state ) } ,
117
+ value : ( self . algorithm . format_output ) ( self . state ) ,
117
118
}
118
119
}
119
120
}
@@ -247,11 +248,8 @@ impl Digest {
247
248
impl AsRef < [ u8 ] > for Digest {
248
249
#[ inline( always) ]
249
250
fn as_ref ( & self ) -> & [ u8 ] {
250
- let data = ( & self . value as * const Output ) . cast :: < u8 > ( ) ;
251
- // SAFETY: So long as `self.algorithm` is the correct algorithm, all
252
- // code initializes all bytes of `self.value` in the range `[0,
253
- // self.algorithm.output_len)`.
254
- unsafe { core:: slice:: from_raw_parts ( data, self . algorithm . output_len ) }
251
+ let as64 = unsafe { & self . value . as64 } ;
252
+ & as64. as_byte_array ( ) [ ..self . algorithm . output_len ]
255
253
}
256
254
}
257
255
@@ -272,9 +270,7 @@ pub struct Algorithm {
272
270
len_len : usize ,
273
271
274
272
block_data_order : unsafe extern "C" fn ( state : & mut State , data : * const u8 , num : c:: size_t ) ,
275
- // INVARIANT: This is always set to the correct output for the algorithm's
276
- // block size.
277
- format_output : unsafe fn ( input : State ) -> Output ,
273
+ format_output : fn ( input : State ) -> Output ,
278
274
279
275
initial_state : State ,
280
276
@@ -478,38 +474,14 @@ pub const MAX_OUTPUT_LEN: usize = 512 / 8;
478
474
/// algorithms in this module.
479
475
pub const MAX_CHAINING_LEN : usize = MAX_OUTPUT_LEN ;
480
476
481
- fn sha256_format_output ( input : State ) -> Output
482
- where
483
- [ BigEndian < u32 > ; 256 / 8 / core:: mem:: size_of :: < BigEndian < u32 > > ( ) ] : FromBytes ,
484
- [ BigEndian < u64 > ; 512 / 8 / core:: mem:: size_of :: < BigEndian < u64 > > ( ) ] : AsBytes ,
485
- {
486
- // SAFETY: There are two cases:
487
- // - The union is initialized as `as32`, in which case this is trivially
488
- // sound.
489
- // - The union is initialized as `as64`. In this case, the `as64` variant is
490
- // longer than the `as32` variant, so all bytes of `as32` are initialized
491
- // as they are in the prefix of `as64`. Since `as64`'s type is `AsBytes`
492
- // (see the where bound on this function), all of its bytes are
493
- // initialized (ie, none are padding). Since `as32`'s type is `FromBytes`,
494
- // any initialized sequence of bytes constitutes a valid instance of the
495
- // type, so this is sound.
477
+ fn sha256_format_output ( input : State ) -> Output {
496
478
let input = unsafe { & input. as32 } ;
497
479
Output {
498
480
as32 : input. map ( BigEndian :: from) ,
499
481
}
500
482
}
501
483
502
- /// # Safety
503
- ///
504
- /// The caller must ensure that all bytes of `State` have been initialized.
505
- unsafe fn sha512_format_output ( input : State ) -> Output
506
- where
507
- [ BigEndian < u64 > ; 512 / 8 / core:: mem:: size_of :: < BigEndian < u64 > > ( ) ] : FromBytes ,
508
- {
509
- // SAFETY: Caller has promised that all bytes are initialized. Since
510
- // `input.as64` is `FromBytes`, we know that this is sufficient to guarantee
511
- // that the input has been initialized to a valid instance of the type of
512
- // `input.as64`.
484
+ fn sha512_format_output ( input : State ) -> Output {
513
485
let input = unsafe { & input. as64 } ;
514
486
Output {
515
487
as64 : input. map ( BigEndian :: from) ,
0 commit comments