2323 */
2424
2525
26+ use cryptoutil:: { write_u32_be, read_u32v_be, shift_add_check_overflow, FixedBuffer , FixedBuffer64 ,
27+ StandardPadding } ;
2628use digest:: Digest ;
2729
2830/*
@@ -33,7 +35,6 @@ use digest::Digest;
3335
3436// Some unexported constants
3537static DIGEST_BUF_LEN : uint = 5 u;
36- static MSG_BLOCK_LEN : uint = 64 u;
3738static WORK_BUF_LEN : uint = 80 u;
3839static K0 : u32 = 0x5A827999u32 ;
3940static K1 : u32 = 0x6ED9EBA1u32 ;
@@ -43,58 +44,38 @@ static K3: u32 = 0xCA62C1D6u32;
4344/// Structure representing the state of a Sha1 computation
4445pub struct Sha1 {
4546 priv h: [ u32 , ..DIGEST_BUF_LEN ] ,
46- priv len_low : u32 ,
47- priv len_high : u32 ,
48- priv msg_block : [ u8 , ..MSG_BLOCK_LEN ] ,
49- priv msg_block_idx : uint ,
47+ priv length_bits : u64 ,
48+ priv buffer : FixedBuffer64 ,
5049 priv computed : bool ,
51- priv work_buf : [ u32 , ..WORK_BUF_LEN ]
5250}
5351
5452fn add_input ( st : & mut Sha1 , msg : & [ u8 ] ) {
5553 assert ! ( ( !st. computed) ) ;
56- foreach element in msg. iter ( ) {
57- st. msg_block [ st. msg_block_idx ] = * element;
58- st. msg_block_idx += 1 ;
59- st. len_low += 8 ;
60- if st. len_low == 0 {
61- st. len_high += 1 ;
62- if st. len_high == 0 {
63- // FIXME: Need better failure mode (#2346)
64- fail ! ( ) ;
65- }
66- }
67- if st. msg_block_idx == MSG_BLOCK_LEN { process_msg_block ( st) ; }
68- }
54+ // Assumes that msg.len() can be converted to u64 without overflow
55+ st. length_bits = shift_add_check_overflow ( st. length_bits , msg. len ( ) as u64 , 3 ) ;
56+ st. buffer . input ( msg, |d : & [ u8 ] | { process_msg_block ( d, & mut st. h ) ; } ) ;
6957}
7058
71- fn process_msg_block ( st : & mut Sha1 ) {
59+ fn process_msg_block ( data : & [ u8 ] , h : & mut [ u32 , .. DIGEST_BUF_LEN ] ) {
7260 let mut t : int ; // Loop counter
73- let mut w = st. work_buf ;
61+
62+ let mut w = [ 0u32 , ..WORK_BUF_LEN ] ;
7463
7564 // Initialize the first 16 words of the vector w
76- t = 0 ;
77- while t < 16 {
78- let mut tmp;
79- tmp = ( st. msg_block [ t * 4 ] as u32 ) << 24u32 ;
80- tmp = tmp | ( st. msg_block [ t * 4 + 1 ] as u32 ) << 16u32 ;
81- tmp = tmp | ( st. msg_block [ t * 4 + 2 ] as u32 ) << 8u32 ;
82- tmp = tmp | ( st. msg_block [ t * 4 + 3 ] as u32 ) ;
83- w[ t] = tmp;
84- t += 1 ;
85- }
65+ read_u32v_be ( w. mut_slice ( 0 , 16 ) , data) ;
8666
8767 // Initialize the rest of vector w
68+ t = 16 ;
8869 while t < 80 {
8970 let val = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ] ;
9071 w[ t] = circular_shift ( 1 , val) ;
9172 t += 1 ;
9273 }
93- let mut a = st . h [ 0 ] ;
94- let mut b = st . h [ 1 ] ;
95- let mut c = st . h [ 2 ] ;
96- let mut d = st . h [ 3 ] ;
97- let mut e = st . h [ 4 ] ;
74+ let mut a = h[ 0 ] ;
75+ let mut b = h[ 1 ] ;
76+ let mut c = h[ 2 ] ;
77+ let mut d = h[ 3 ] ;
78+ let mut e = h[ 4 ] ;
9879 let mut temp: u32 ;
9980 t = 0 ;
10081 while t < 20 {
@@ -135,86 +116,42 @@ fn process_msg_block(st: &mut Sha1) {
135116 a = temp;
136117 t += 1 ;
137118 }
138- st. h [ 0 ] = st. h [ 0 ] + a;
139- st. h [ 1 ] = st. h [ 1 ] + b;
140- st. h [ 2 ] = st. h [ 2 ] + c;
141- st. h [ 3 ] = st. h [ 3 ] + d;
142- st. h [ 4 ] = st. h [ 4 ] + e;
143- st. msg_block_idx = 0 ;
119+ h[ 0 ] += a;
120+ h[ 1 ] += b;
121+ h[ 2 ] += c;
122+ h[ 3 ] += d;
123+ h[ 4 ] += e;
144124}
145125
146126fn circular_shift ( bits : u32 , word : u32 ) -> u32 {
147127 return word << bits | word >> 32u32 - bits;
148128}
149129
150130fn mk_result ( st : & mut Sha1 , rs : & mut [ u8 ] ) {
151- if !st. computed { pad_msg ( st) ; st. computed = true ; }
152- let mut i = 0 ;
153- foreach ptr_hpart in st. h . mut_iter ( ) {
154- let hpart = * ptr_hpart;
155- rs[ i] = ( hpart >> 24u32 & 0xFFu32 ) as u8 ;
156- rs[ i+1 ] = ( hpart >> 16u32 & 0xFFu32 ) as u8 ;
157- rs[ i+2 ] = ( hpart >> 8u32 & 0xFFu32 ) as u8 ;
158- rs[ i+3 ] = ( hpart & 0xFFu32 ) as u8 ;
159- i += 4 ;
160- }
161- }
131+ if !st. computed {
132+ st. buffer . standard_padding ( 8 , |d : & [ u8 ] | { process_msg_block ( d, & mut st. h ) } ) ;
133+ write_u32_be ( st. buffer . next ( 4 ) , ( st. length_bits >> 32 ) as u32 ) ;
134+ write_u32_be ( st. buffer . next ( 4 ) , st. length_bits as u32 ) ;
135+ process_msg_block ( st. buffer . full_buffer ( ) , & mut st. h ) ;
162136
163- /*
164- * According to the standard, the message must be padded to an even
165- * 512 bits. The first padding bit must be a '1'. The last 64 bits
166- * represent the length of the original message. All bits in between
167- * should be 0. This function will pad the message according to those
168- * rules by filling the msg_block vector accordingly. It will also
169- * call process_msg_block() appropriately. When it returns, it
170- * can be assumed that the message digest has been computed.
171- */
172- fn pad_msg ( st : & mut Sha1 ) {
173- /*
174- * Check to see if the current message block is too small to hold
175- * the initial padding bits and length. If so, we will pad the
176- * block, process it, and then continue padding into a second block.
177- */
178- if st. msg_block_idx > 55 {
179- st. msg_block [ st. msg_block_idx ] = 0x80 ;
180- st. msg_block_idx += 1 ;
181- while st. msg_block_idx < MSG_BLOCK_LEN {
182- st. msg_block [ st. msg_block_idx ] = 0 ;
183- st. msg_block_idx += 1 ;
184- }
185- process_msg_block ( st) ;
186- } else {
187- st. msg_block [ st. msg_block_idx ] = 0x80 ;
188- st. msg_block_idx += 1 ;
189- }
190- while st. msg_block_idx < 56 {
191- st. msg_block [ st. msg_block_idx ] = 0u8 ;
192- st. msg_block_idx += 1 ;
137+ st. computed = true ;
193138 }
194139
195- // Store the message length as the last 8 octets
196- st. msg_block [ 56 ] = ( st. len_high >> 24u32 & 0xFFu32 ) as u8 ;
197- st. msg_block [ 57 ] = ( st. len_high >> 16u32 & 0xFFu32 ) as u8 ;
198- st. msg_block [ 58 ] = ( st. len_high >> 8u32 & 0xFFu32 ) as u8 ;
199- st. msg_block [ 59 ] = ( st. len_high & 0xFFu32 ) as u8 ;
200- st. msg_block [ 60 ] = ( st. len_low >> 24u32 & 0xFFu32 ) as u8 ;
201- st. msg_block [ 61 ] = ( st. len_low >> 16u32 & 0xFFu32 ) as u8 ;
202- st. msg_block [ 62 ] = ( st. len_low >> 8u32 & 0xFFu32 ) as u8 ;
203- st. msg_block [ 63 ] = ( st. len_low & 0xFFu32 ) as u8 ;
204- process_msg_block ( st) ;
140+ write_u32_be ( rs. mut_slice ( 0 , 4 ) , st. h [ 0 ] ) ;
141+ write_u32_be ( rs. mut_slice ( 4 , 8 ) , st. h [ 1 ] ) ;
142+ write_u32_be ( rs. mut_slice ( 8 , 12 ) , st. h [ 2 ] ) ;
143+ write_u32_be ( rs. mut_slice ( 12 , 16 ) , st. h [ 3 ] ) ;
144+ write_u32_be ( rs. mut_slice ( 16 , 20 ) , st. h [ 4 ] ) ;
205145}
206146
207147impl Sha1 {
208148 /// Construct a `sha` object
209149 pub fn new ( ) -> Sha1 {
210150 let mut st = Sha1 {
211151 h : [ 0u32 , ..DIGEST_BUF_LEN ] ,
212- len_low : 0u32 ,
213- len_high : 0u32 ,
214- msg_block : [ 0u8 , ..MSG_BLOCK_LEN ] ,
215- msg_block_idx : 0 ,
152+ length_bits : 0u64 ,
153+ buffer : FixedBuffer64 :: new ( ) ,
216154 computed : false ,
217- work_buf : [ 0u32 , ..WORK_BUF_LEN ]
218155 } ;
219156 st. reset ( ) ;
220157 return st;
@@ -223,14 +160,13 @@ impl Sha1 {
223160
224161impl Digest for Sha1 {
225162 pub fn reset ( & mut self ) {
226- self . len_low = 0 ;
227- self . len_high = 0 ;
228- self . msg_block_idx = 0 ;
163+ self . length_bits = 0 ;
229164 self . h [ 0 ] = 0x67452301u32 ;
230165 self . h [ 1 ] = 0xEFCDAB89u32 ;
231166 self . h [ 2 ] = 0x98BADCFEu32 ;
232167 self . h [ 3 ] = 0x10325476u32 ;
233168 self . h [ 4 ] = 0xC3D2E1F0u32 ;
169+ self . buffer . reset ( ) ;
234170 self . computed = false ;
235171 }
236172 pub fn input ( & mut self , msg : & [ u8 ] ) { add_input ( self , msg) ; }
0 commit comments