23
23
*/
24
24
25
25
26
+ use cryptoutil:: { write_u32_be, read_u32v_be, shift_add_check_overflow, FixedBuffer , FixedBuffer64 ,
27
+ StandardPadding } ;
26
28
use digest:: Digest ;
27
29
28
30
/*
@@ -33,7 +35,6 @@ use digest::Digest;
33
35
34
36
// Some unexported constants
35
37
static DIGEST_BUF_LEN : uint = 5 u;
36
- static MSG_BLOCK_LEN : uint = 64 u;
37
38
static WORK_BUF_LEN : uint = 80 u;
38
39
static K0 : u32 = 0x5A827999u32 ;
39
40
static K1 : u32 = 0x6ED9EBA1u32 ;
@@ -43,58 +44,38 @@ static K3: u32 = 0xCA62C1D6u32;
43
44
/// Structure representing the state of a Sha1 computation
44
45
pub struct Sha1 {
45
46
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 ,
50
49
priv computed : bool ,
51
- priv work_buf : [ u32 , ..WORK_BUF_LEN ]
52
50
}
53
51
54
52
fn add_input ( st : & mut Sha1 , msg : & [ u8 ] ) {
55
53
assert ! ( ( !st. computed) ) ;
56
- for msg. iter( ) . advance |element| {
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 in.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 ) ; } ) ;
69
57
}
70
58
71
- fn process_msg_block( st : & mut Sha1 ) {
59
+ fn process_msg_block ( data : & [ u8 ] , h : & mut [ u32 , .. DIGEST_BUF_LEN ] ) {
72
60
let mut t : int ; // Loop counter
73
- let mut w = st. work_buf;
61
+
62
+ let mut w = [ 0u32 , ..WORK_BUF_LEN ] ;
74
63
75
64
// 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) ;
86
66
87
67
// Initialize the rest of vector w
68
+ t = 16 ;
88
69
while t < 80 {
89
70
let val = w[ t - 3 ] ^ w[ t - 8 ] ^ w[ t - 14 ] ^ w[ t - 16 ] ;
90
71
w[ t] = circular_shift ( 1 , val) ;
91
72
t += 1 ;
92
73
}
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 ] ;
98
79
let mut temp: u32 ;
99
80
t = 0 ;
100
81
while t < 20 {
@@ -135,86 +116,42 @@ fn process_msg_block(st: &mut Sha1) {
135
116
a = temp;
136
117
t += 1 ;
137
118
}
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;
144
124
}
145
125
146
126
fn circular_shift ( bits : u32 , word : u32 ) -> u32 {
147
127
return word << bits | word >> 32u32 - bits;
148
128
}
149
129
150
130
fn mk_result ( st : & mut Sha1 , rs : & mut [ u8 ] ) {
151
- if !st. computed { pad_msg ( st) ; st. computed = true ; }
152
- let mut i = 0 ;
153
- for st. h. mut_iter( ) . advance |ptr_hpart| {
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 ) ;
162
136
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 ;
193
138
}
194
139
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 ] ) ;
205
145
}
206
146
207
147
impl Sha1 {
208
148
/// Construct a `sha` object
209
149
pub fn new ( ) -> Sha1 {
210
150
let mut st = Sha1 {
211
151
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 ( ) ,
216
154
computed : false ,
217
- work_buf : [ 0u32 , ..WORK_BUF_LEN ]
218
155
} ;
219
156
st. reset ( ) ;
220
157
return st;
@@ -223,14 +160,13 @@ impl Sha1 {
223
160
224
161
impl Digest for Sha1 {
225
162
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 ;
229
164
self . h [ 0 ] = 0x67452301u32 ;
230
165
self . h [ 1 ] = 0xEFCDAB89u32 ;
231
166
self . h [ 2 ] = 0x98BADCFEu32 ;
232
167
self . h [ 3 ] = 0x10325476u32 ;
233
168
self . h [ 4 ] = 0xC3D2E1F0u32 ;
169
+ self . buffer . reset ( ) ;
234
170
self . computed = false ;
235
171
}
236
172
pub fn input ( & mut self , msg : & [ u8 ] ) { add_input ( self , msg) ; }
0 commit comments