// Copyright 2015-2016 Brian Smith. // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. use ring::{digest, hmac, test, test_file}; #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] use wasm_bindgen_test::{wasm_bindgen_test as test, wasm_bindgen_test_configure}; #[cfg(all(target_arch = "wasm32", target_os = "unknown"))] wasm_bindgen_test_configure!(run_in_browser); #[test] fn hmac_tests() { test::run(test_file!("hmac_tests.txt"), |section, test_case| { assert_eq!(section, ""); let digest_alg = test_case.consume_digest_alg("HMAC"); let key_value = test_case.consume_bytes("Key"); let mut input = test_case.consume_bytes("Input"); let output = test_case.consume_bytes("Output"); let algorithm = { let digest_alg = match digest_alg { Some(digest_alg) => digest_alg, None => { return Ok(()); } // Unsupported digest algorithm }; if digest_alg == &digest::SHA1_FOR_LEGACY_USE_ONLY { hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY } else if digest_alg == &digest::SHA256 { hmac::HMAC_SHA256 } else if digest_alg == &digest::SHA384 { hmac::HMAC_SHA384 } else if digest_alg == &digest::SHA512 { hmac::HMAC_SHA512 } else { unreachable!() } }; hmac_test_case_inner(algorithm, &key_value[..], &input[..], &output[..], true); // Tamper with the input and check that verification fails. if input.is_empty() { input.push(0); } else { input[0] ^= 1; } hmac_test_case_inner(algorithm, &key_value[..], &input[..], &output[..], false); Ok(()) }); } fn hmac_test_case_inner( algorithm: hmac::Algorithm, key_value: &[u8], input: &[u8], output: &[u8], is_ok: bool, ) { let key = hmac::Key::new(algorithm, key_value); // One-shot API. { let signature = hmac::sign(&key, input); assert_eq!(is_ok, signature.as_ref() == output); assert_eq!(is_ok, hmac::verify(&key, input, output).is_ok()); } // Multi-part API, one single part. { let mut s_ctx = hmac::Context::with_key(&key); s_ctx.update(input); let signature = s_ctx.sign(); assert_eq!(is_ok, signature.as_ref() == output); } // Multi-part API, byte by byte. { let mut ctx = hmac::Context::with_key(&key); for b in input { ctx.update(&[*b]); } let signature = ctx.sign(); assert_eq!(is_ok, signature.as_ref() == output); } } #[test] fn hmac_debug() { let key = hmac::Key::new(hmac::HMAC_SHA256, &[0; 32]); assert_eq!("Key { algorithm: SHA256 }", format!("{:?}", &key)); let ctx = hmac::Context::with_key(&key); assert_eq!("Context { algorithm: SHA256 }", format!("{:?}", &ctx)); }