1 // Copyright 2015-2017 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 use ring::{digest, test, test_file};
16
17 #[cfg(target_arch = "wasm32")]
18 use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure};
19
20 #[cfg(target_arch = "wasm32")]
21 wasm_bindgen_test_configure!(run_in_browser);
22
23 /// Test vectors from BoringSSL, Go, and other sources.
24 #[test]
digest_misc()25 fn digest_misc() {
26 test::run(test_file!("digest_tests.txt"), |section, test_case| {
27 assert_eq!(section, "");
28 let digest_alg = test_case.consume_digest_alg("Hash").unwrap();
29 let input = test_case.consume_bytes("Input");
30 let repeat = test_case.consume_usize("Repeat");
31 let expected = test_case.consume_bytes("Output");
32
33 let mut ctx = digest::Context::new(digest_alg);
34 let mut data = Vec::new();
35 for _ in 0..repeat {
36 ctx.update(&input);
37 data.extend(&input);
38 }
39 let actual_from_chunks = ctx.finish();
40 assert_eq!(&expected, &actual_from_chunks.as_ref());
41
42 let actual_from_one_shot = digest::digest(digest_alg, &data);
43 assert_eq!(&expected, &actual_from_one_shot.as_ref());
44
45 Ok(())
46 });
47 }
48
49 // wasm_bindgen doesn't build this correctly.
50 #[cfg(not(target_arch = "wsam32"))]
51 mod digest_shavs {
52 use ring::{digest, test};
53
run_known_answer_test(digest_alg: &'static digest::Algorithm, test_file: test::File)54 fn run_known_answer_test(digest_alg: &'static digest::Algorithm, test_file: test::File) {
55 let section_name = &format!("L = {}", digest_alg.output_len);
56 test::run(test_file, |section, test_case| {
57 assert_eq!(section_name, section);
58 let len_bits = test_case.consume_usize("Len");
59
60 let mut msg = test_case.consume_bytes("Msg");
61 // The "msg" field contains the dummy value "00" when the
62 // length is zero.
63 if len_bits == 0 {
64 assert_eq!(msg, &[0u8]);
65 msg.truncate(0);
66 }
67
68 assert_eq!(msg.len() * 8, len_bits);
69 let expected = test_case.consume_bytes("MD");
70 let actual = digest::digest(digest_alg, &msg);
71 assert_eq!(&expected, &actual.as_ref());
72
73 Ok(())
74 });
75 }
76
77 macro_rules! shavs_tests {
78 ( $file_name:ident, $algorithm_name:ident ) => {
79 #[allow(non_snake_case)]
80 mod $algorithm_name {
81 use super::{run_known_answer_test, run_monte_carlo_test};
82 use ring::{digest, test_file};
83
84 #[cfg(target_arch = "wasm32")]
85 use wasm_bindgen_test::wasm_bindgen_test as test;
86
87 #[test]
88 fn short_msg_known_answer_test() {
89 run_known_answer_test(
90 &digest::$algorithm_name,
91 test_file!(concat!(
92 "../third_party/NIST/SHAVS/",
93 stringify!($file_name),
94 "ShortMsg.rsp"
95 )),
96 );
97 }
98
99 #[test]
100 fn long_msg_known_answer_test() {
101 run_known_answer_test(
102 &digest::$algorithm_name,
103 test_file!(concat!(
104 "../third_party/NIST/SHAVS/",
105 stringify!($file_name),
106 "LongMsg.rsp"
107 )),
108 );
109 }
110
111 #[test]
112 fn monte_carlo_test() {
113 run_monte_carlo_test(
114 &digest::$algorithm_name,
115 test_file!(concat!(
116 "../third_party/NIST/SHAVS/",
117 stringify!($file_name),
118 "Monte.rsp"
119 )),
120 );
121 }
122 }
123 };
124 }
125
run_monte_carlo_test(digest_alg: &'static digest::Algorithm, test_file: test::File)126 fn run_monte_carlo_test(digest_alg: &'static digest::Algorithm, test_file: test::File) {
127 let section_name = &format!("L = {}", digest_alg.output_len);
128
129 let mut expected_count: isize = -1;
130 let mut seed = Vec::with_capacity(digest_alg.output_len);
131
132 test::run(test_file, |section, test_case| {
133 assert_eq!(section_name, section);
134
135 if expected_count == -1 {
136 seed.extend(test_case.consume_bytes("Seed"));
137 expected_count = 0;
138 return Ok(());
139 }
140
141 assert!(expected_count >= 0);
142 let actual_count = test_case.consume_usize("COUNT");
143 assert_eq!(expected_count as usize, actual_count);
144 expected_count += 1;
145
146 let expected_md = test_case.consume_bytes("MD");
147
148 let mut mds = Vec::with_capacity(4);
149 mds.push(seed.clone());
150 mds.push(seed.clone());
151 mds.push(seed.clone());
152 for _ in 0..1000 {
153 let mut ctx = digest::Context::new(digest_alg);
154 ctx.update(&mds[0]);
155 ctx.update(&mds[1]);
156 ctx.update(&mds[2]);
157 let md_i = ctx.finish();
158 let _ = mds.remove(0);
159 mds.push(Vec::from(md_i.as_ref()));
160 }
161 let md_j = mds.last().unwrap();
162 assert_eq!(&expected_md, md_j);
163 seed = md_j.clone();
164
165 Ok(())
166 });
167
168 assert_eq!(expected_count, 100);
169 }
170
171 shavs_tests!(SHA1, SHA1_FOR_LEGACY_USE_ONLY);
172 shavs_tests!(SHA256, SHA256);
173 shavs_tests!(SHA384, SHA384);
174 shavs_tests!(SHA512, SHA512);
175 }
176
177 /// Test some ways in which `Context::update` and/or `Context::finish`
178 /// could go wrong by testing every combination of updating three inputs
179 /// that vary from zero bytes to one byte larger than the block length.
180 ///
181 /// These are not run in dev (debug) builds because they are too slow.
182 macro_rules! test_i_u_f {
183 ( $test_name:ident, $alg:expr) => {
184 #[cfg(not(debug_assertions))]
185 // TODO: Get this working on WebAssembly
186 #[cfg(not(target_arch = "wasm32"))]
187 #[test]
188 fn $test_name() {
189 let mut input = [0; (digest::MAX_BLOCK_LEN + 1) * 3];
190 let max = $alg.block_len + 1;
191 for i in 0..(max * 3) {
192 input[i] = (i & 0xff) as u8;
193 }
194
195 for i in 0..max {
196 for j in 0..max {
197 for k in 0..max {
198 let part1 = &input[..i];
199 let part2 = &input[i..(i + j)];
200 let part3 = &input[(i + j)..(i + j + k)];
201
202 let mut ctx = digest::Context::new(&$alg);
203 ctx.update(part1);
204 ctx.update(part2);
205 ctx.update(part3);
206 let i_u_f = ctx.finish();
207
208 let one_shot = digest::digest(&$alg, &input[..(i + j + k)]);
209
210 assert_eq!(i_u_f.as_ref(), one_shot.as_ref());
211 }
212 }
213 }
214 }
215 };
216 }
217 test_i_u_f!(digest_test_i_u_f_sha1, digest::SHA1_FOR_LEGACY_USE_ONLY);
218 test_i_u_f!(digest_test_i_u_f_sha256, digest::SHA256);
219 test_i_u_f!(digest_test_i_u_f_sha384, digest::SHA384);
220 test_i_u_f!(digest_test_i_u_f_sha512, digest::SHA512);
221
222 /// See https://bugzilla.mozilla.org/show_bug.cgi?id=610162. This tests the
223 /// calculation of 8GB of the byte 123.
224 ///
225 /// You can verify the expected values in many ways. One way is
226 /// `python ~/p/write_big.py`, where write_big.py is:
227 ///
228 /// ```python
229 /// chunk = bytearray([123] * (16 * 1024))
230 /// with open('tempfile', 'w') as f:
231 /// for i in xrange(0, 8 * 1024 * 1024 * 1024, len(chunk)):
232 /// f.write(chunk)
233 /// ```
234 /// Then:
235 ///
236 /// ```sh
237 /// sha1sum -b tempfile
238 /// sha256sum -b tempfile
239 /// sha384sum -b tempfile
240 /// sha512sum -b tempfile
241 /// ```
242 ///
243 /// This is not run in dev (debug) builds because it is too slow.
244 macro_rules! test_large_digest {
245 ( $test_name:ident, $alg:expr, $len:expr, $expected:expr) => {
246 // TODO: get this working on WebAssembly.
247 #[cfg(not(debug_assertions))]
248 #[cfg(not(target_arch = "wasm32"))]
249 #[test]
250 fn $test_name() {
251 let chunk = vec![123u8; 16 * 1024];
252 let chunk_len = chunk.len() as u64;
253 let mut ctx = digest::Context::new(&$alg);
254 let mut hashed = 0u64;
255 loop {
256 ctx.update(&chunk);
257 hashed += chunk_len;
258 if hashed >= 8u64 * 1024 * 1024 * 1024 {
259 break;
260 }
261 }
262 let calculated = ctx.finish();
263 let expected: [u8; $len] = $expected;
264 assert_eq!(&expected[..], calculated.as_ref());
265 }
266 };
267 }
268
269 // XXX: This test is too slow on Android ARM.
270 #[cfg(any(not(target_os = "android"), not(target_arch = "arm")))]
271 test_large_digest!(
272 digest_test_large_digest_sha1,
273 digest::SHA1_FOR_LEGACY_USE_ONLY,
274 160 / 8,
275 [
276 0xCA, 0xC3, 0x4C, 0x31, 0x90, 0x5B, 0xDE, 0x3B, 0xE4, 0x0D, 0x46, 0x6D, 0x70, 0x76, 0xAD,
277 0x65, 0x3C, 0x20, 0xE4, 0xBD
278 ]
279 );
280
281 test_large_digest!(
282 digest_test_large_digest_sha256,
283 digest::SHA256,
284 256 / 8,
285 [
286 0x8D, 0xD1, 0x6D, 0xD8, 0xB2, 0x5A, 0x29, 0xCB, 0x7F, 0xB9, 0xAE, 0x86, 0x72, 0xE9, 0xCE,
287 0xD6, 0x65, 0x4C, 0xB6, 0xC3, 0x5C, 0x58, 0x21, 0xA7, 0x07, 0x97, 0xC5, 0xDD, 0xAE, 0x5C,
288 0x68, 0xBD
289 ]
290 );
291 test_large_digest!(
292 digest_test_large_digest_sha384,
293 digest::SHA384,
294 384 / 8,
295 [
296 0x3D, 0xFE, 0xC1, 0xA9, 0xD0, 0x9F, 0x08, 0xD5, 0xBB, 0xE8, 0x7C, 0x9E, 0xE0, 0x0A, 0x87,
297 0x0E, 0xB0, 0xEA, 0x8E, 0xEA, 0xDB, 0x82, 0x36, 0xAE, 0x74, 0xCF, 0x9F, 0xDC, 0x86, 0x1C,
298 0xE3, 0xE9, 0xB0, 0x68, 0xCD, 0x19, 0x3E, 0x39, 0x90, 0x02, 0xE1, 0x58, 0x5D, 0x66, 0xC4,
299 0x55, 0x11, 0x9B
300 ]
301 );
302 test_large_digest!(
303 digest_test_large_digest_sha512,
304 digest::SHA512,
305 512 / 8,
306 [
307 0xFC, 0x8A, 0x98, 0x20, 0xFC, 0x82, 0xD8, 0x55, 0xF8, 0xFF, 0x2F, 0x6E, 0xAE, 0x41, 0x60,
308 0x04, 0x08, 0xE9, 0x49, 0xD7, 0xCD, 0x1A, 0xED, 0x22, 0xEB, 0x55, 0xE1, 0xFD, 0x80, 0x50,
309 0x3B, 0x01, 0x2F, 0xC6, 0xF4, 0x33, 0x86, 0xFB, 0x60, 0x75, 0x2D, 0xA5, 0xA9, 0x93, 0xE7,
310 0x00, 0x45, 0xA8, 0x49, 0x1A, 0x6B, 0xEC, 0x9C, 0x98, 0xC8, 0x19, 0xA6, 0xA9, 0x88, 0x3E,
311 0x2F, 0x09, 0xB9, 0x9A
312 ]
313 );
314
315 // TODO: test_large_digest!(digest_test_large_digest_sha512_256,
316 // digest::SHA512_256, 256 / 8, [ ... ]);
317
318 #[test]
test_fmt_algorithm()319 fn test_fmt_algorithm() {
320 assert_eq!("SHA1", &format!("{:?}", digest::SHA1_FOR_LEGACY_USE_ONLY));
321 assert_eq!("SHA256", &format!("{:?}", digest::SHA256));
322 assert_eq!("SHA384", &format!("{:?}", digest::SHA384));
323 assert_eq!("SHA512", &format!("{:?}", digest::SHA512));
324 assert_eq!("SHA512_256", &format!("{:?}", digest::SHA512_256));
325 }
326
327 #[test]
digest_test_fmt()328 fn digest_test_fmt() {
329 assert_eq!(
330 "SHA1:b7e23ec29af22b0b4e41da31e868d57226121c84",
331 &format!(
332 "{:?}",
333 digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, b"hello, world")
334 )
335 );
336 assert_eq!(
337 "SHA256:09ca7e4eaa6e8ae9c7d261167129184883644d\
338 07dfba7cbfbc4c8a2e08360d5b",
339 &format!("{:?}", digest::digest(&digest::SHA256, b"hello, world"))
340 );
341 assert_eq!(
342 "SHA384:1fcdb6059ce05172a26bbe2a3ccc88ed5a8cd5\
343 fc53edfd9053304d429296a6da23b1cd9e5c9ed3bb34f0\
344 0418a70cdb7e",
345 &format!("{:?}", digest::digest(&digest::SHA384, b"hello, world"))
346 );
347 assert_eq!(
348 "SHA512:8710339dcb6814d0d9d2290ef422285c9322b7\
349 163951f9a0ca8f883d3305286f44139aa374848e4174f5\
350 aada663027e4548637b6d19894aec4fb6c46a139fbf9",
351 &format!("{:?}", digest::digest(&digest::SHA512, b"hello, world"))
352 );
353
354 assert_eq!(
355 "SHA512_256:11f2c88c04f0a9c3d0970894ad2472505e\
356 0bc6e8c7ec46b5211cd1fa3e253e62",
357 &format!("{:?}", digest::digest(&digest::SHA512_256, b"hello, world"))
358 );
359 }
360