Skip to content

Commit 9ff79f6

Browse files
author
Palmer Cox
committed
Sha1: Update Sha1 to use new functionality in cryptoutil.rs
1 parent 0b95463 commit 9ff79f6

File tree

1 file changed

+37
-101
lines changed

1 file changed

+37
-101
lines changed

src/libextra/crypto/sha1.rs

+37-101
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
*/
2424

2525

26+
use cryptoutil::{write_u32_be, read_u32v_be, shift_add_check_overflow, FixedBuffer, FixedBuffer64,
27+
StandardPadding};
2628
use digest::Digest;
2729

2830
/*
@@ -33,7 +35,6 @@ use digest::Digest;
3335

3436
// Some unexported constants
3537
static DIGEST_BUF_LEN: uint = 5u;
36-
static MSG_BLOCK_LEN: uint = 64u;
3738
static WORK_BUF_LEN: uint = 80u;
3839
static K0: u32 = 0x5A827999u32;
3940
static K1: u32 = 0x6ED9EBA1u32;
@@ -43,58 +44,38 @@ static K3: u32 = 0xCA62C1D6u32;
4344
/// Structure representing the state of a Sha1 computation
4445
pub 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

5452
fn add_input(st: &mut Sha1, msg: &[u8]) {
5553
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); });
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

146126
fn circular_shift(bits: u32, word: u32) -> u32 {
147127
return word << bits | word >> 32u32 - bits;
148128
}
149129

150130
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);
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

207147
impl 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

224161
impl 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

Comments
 (0)