Skip to content

Commit

Permalink
Add Sha224 digest, HMAC-SHA224, and SHA224 KAT (#204)
Browse files Browse the repository at this point in the history
  • Loading branch information
bencivjan authored Aug 1, 2023
1 parent bac4b9f commit 15daf8e
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 39 deletions.
14 changes: 9 additions & 5 deletions aws-lc-rs/src/digest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ mod sha;
use crate::error::Unspecified;
use crate::ptr::ConstPointer;
use aws_lc::{
EVP_DigestFinal, EVP_DigestUpdate, EVP_sha1, EVP_sha256, EVP_sha384, EVP_sha3_256,
EVP_DigestFinal, EVP_DigestUpdate, EVP_sha1, EVP_sha224, EVP_sha256, EVP_sha384, EVP_sha3_256,
EVP_sha3_384, EVP_sha3_512, EVP_sha512, EVP_sha512_256, EVP_MD,
};
use digest_ctx::DigestContext;
pub use sha::{
SHA1_FOR_LEGACY_USE_ONLY, SHA1_OUTPUT_LEN, SHA256, SHA256_OUTPUT_LEN, SHA384,
SHA384_OUTPUT_LEN, SHA3_256, SHA3_384, SHA3_512, SHA512, SHA512_256, SHA512_256_OUTPUT_LEN,
SHA512_OUTPUT_LEN,
SHA1_FOR_LEGACY_USE_ONLY, SHA1_OUTPUT_LEN, SHA224, SHA224_OUTPUT_LEN, SHA256,
SHA256_OUTPUT_LEN, SHA384, SHA384_OUTPUT_LEN, SHA3_256, SHA3_384, SHA3_512, SHA512, SHA512_256,
SHA512_256_OUTPUT_LEN, SHA512_OUTPUT_LEN,
};
use std::mem::MaybeUninit;
use std::os::raw::c_uint;
Expand Down Expand Up @@ -226,7 +226,7 @@ pub struct Algorithm {

/// The size of the chaining value of the digest function, in bytes. For
/// non-truncated algorithms (SHA-1, SHA-256, SHA-512), this is equal to
/// `output_len`. For truncated algorithms (e.g. SHA-384, SHA-512/256),
/// `output_len`. For truncated algorithms (e.g. SHA-224, SHA-384, SHA-512/256),
/// this is equal to the length before truncation. This is mostly helpful
/// for determining the size of an HMAC key that is appropriate for the
/// digest algorithm.
Expand Down Expand Up @@ -254,6 +254,7 @@ unsafe impl Send for Algorithm {}
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum AlgorithmID {
SHA1,
SHA224,
SHA256,
SHA384,
SHA512,
Expand Down Expand Up @@ -290,6 +291,7 @@ pub(crate) fn match_digest_type(algorithm_id: &AlgorithmID) -> ConstPointer<EVP_
unsafe {
ConstPointer::new(match algorithm_id {
AlgorithmID::SHA1 => EVP_sha1(),
AlgorithmID::SHA224 => EVP_sha224(),
AlgorithmID::SHA256 => EVP_sha256(),
AlgorithmID::SHA384 => EVP_sha384(),
AlgorithmID::SHA512 => EVP_sha512(),
Expand Down Expand Up @@ -371,6 +373,7 @@ mod tests {
}

max_input_tests!(SHA1_FOR_LEGACY_USE_ONLY);
max_input_tests!(SHA224);
max_input_tests!(SHA256);
max_input_tests!(SHA384);
max_input_tests!(SHA512);
Expand All @@ -384,6 +387,7 @@ mod tests {

for alg in [
&digest::SHA1_FOR_LEGACY_USE_ONLY,
&digest::SHA224,
&digest::SHA256,
&digest::SHA384,
&digest::SHA512,
Expand Down
88 changes: 55 additions & 33 deletions aws-lc-rs/src/digest/sha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@

use crate::digest::{Algorithm, AlgorithmID, Context};
use aws_lc::{
NID_sha1, NID_sha256, NID_sha384, NID_sha3_256, NID_sha3_384, NID_sha3_512, NID_sha512,
NID_sha512_256,
NID_sha1, NID_sha224, NID_sha256, NID_sha384, NID_sha3_256, NID_sha3_384, NID_sha3_512,
NID_sha512, NID_sha512_256,
};

pub const BLOCK_LEN: usize = 512 / 8;
pub const CHAINING_LEN: usize = 160 / 8;
pub const OUTPUT_LEN: usize = 160 / 8;
/// The length of a block for SHA-1, in bytes.
const SHA1_BLOCK_LEN: usize = 512 / 8;

/// The length of the output of SHA-1, in bytes.
pub const SHA1_OUTPUT_LEN: usize = OUTPUT_LEN;
pub const SHA1_OUTPUT_LEN: usize = 160 / 8;

/// The length of the output of SHA-224, in bytes.
pub const SHA224_OUTPUT_LEN: usize = 224 / 8;

/// The length of the output of SHA-256, in bytes.
pub const SHA256_OUTPUT_LEN: usize = 256 / 8;

/// The length of a block for SHA-256-based algorithms, in bytes.
const SHA256_BLOCK_LEN: usize = 512 / 8;

/// The length of the output of SHA-384, in bytes.
pub const SHA384_OUTPUT_LEN: usize = 384 / 8;

Expand All @@ -31,15 +36,6 @@ pub const SHA512_256_OUTPUT_LEN: usize = 256 / 8;
/// The length of a block for SHA-512-based algorithms, in bytes.
const SHA512_BLOCK_LEN: usize = 1024 / 8;

/// SHA-1 and SHA-256 are limited to an input size of 2^64-1 bits.
#[allow(clippy::cast_possible_truncation)]
const SHA256_MAX_INPUT_LEN: u64 = u64::MAX;

/// SHA-384, SHA-512, and SHA-512/256 are limited to an input size of 2^128-1 bits according to the spec.
/// u64 is more than sufficient enough for practical usecases, so we limit the input length to 2^64-1 bits.
#[allow(clippy::cast_possible_truncation)]
const SHA512_MAX_INPUT_LEN: u64 = u64::MAX;

/// The length of a block for SHA3-256-based algorithms, in bytes.
const SHA3_256_BLOCK_LEN: usize = 136;

Expand All @@ -58,24 +54,21 @@ pub const SHA3_384_OUTPUT_LEN: usize = 384 / 8;
/// The length of the output of SHA3-512, in bytes.
pub const SHA3_512_OUTPUT_LEN: usize = 512 / 8;

/// SHA-1, SHA-224, and SHA-256 are limited to an input size of 2^64-1 bits.
/// SHA-384, SHA-512, and SHA-512/256 are limited to an input size of 2^128-1 bits according to the spec.
/// u64 is more than sufficient enough for practical usecases, so we limit the input length to 2^64-1 bits.
#[allow(clippy::cast_possible_truncation)]
const SHA3_256_MAX_INPUT_LEN: u64 = u64::MAX;

#[allow(clippy::cast_possible_truncation)]
const SHA3_384_MAX_INPUT_LEN: u64 = u64::MAX;

#[allow(clippy::cast_possible_truncation)]
const SHA3_512_MAX_INPUT_LEN: u64 = u64::MAX;
const DIGEST_MAX_INPUT_LEN: u64 = u64::MAX;

/// SHA-1 as specified in [FIPS 180-4]. Deprecated.
///
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
#[allow(deprecated)]
pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
output_len: SHA1_OUTPUT_LEN,
chaining_len: CHAINING_LEN,
block_len: BLOCK_LEN,
max_input_len: SHA256_MAX_INPUT_LEN,
chaining_len: SHA1_OUTPUT_LEN,
block_len: SHA1_BLOCK_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha1_digest,

Expand All @@ -84,15 +77,35 @@ pub static SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm {
hash_nid: NID_sha1,
};

/// SHA-224 as specified in [FIPS 180-4].
///
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
#[allow(deprecated)]
pub static SHA224: Algorithm = Algorithm {
output_len: SHA224_OUTPUT_LEN,

// The chaining length is equivalent to the length before truncation.
// SHA-224 is truncated from 256 bits so the chaining length is 256 bits, or 32 bytes.
chaining_len: SHA256_OUTPUT_LEN,
block_len: SHA256_BLOCK_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha224_digest,

id: AlgorithmID::SHA224,

hash_nid: NID_sha224,
};

/// SHA-256 as specified in [FIPS 180-4].
///
/// [FIPS 180-4]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
#[allow(deprecated)]
pub static SHA256: Algorithm = Algorithm {
output_len: SHA256_OUTPUT_LEN,
chaining_len: SHA256_OUTPUT_LEN,
block_len: 512 / 8,
max_input_len: SHA256_MAX_INPUT_LEN,
block_len: SHA256_BLOCK_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha256_digest,

Expand All @@ -107,9 +120,12 @@ pub static SHA256: Algorithm = Algorithm {
#[allow(deprecated)]
pub static SHA384: Algorithm = Algorithm {
output_len: SHA384_OUTPUT_LEN,

// The chaining length is equivalent to the length before truncation.
// SHA-384 is truncated from 512 bits so the chaining length is 512 bits, or 64 bytes.
chaining_len: SHA512_OUTPUT_LEN,
block_len: SHA512_BLOCK_LEN,
max_input_len: SHA512_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha384_digest,

Expand All @@ -125,7 +141,7 @@ pub static SHA512: Algorithm = Algorithm {
output_len: SHA512_OUTPUT_LEN,
chaining_len: SHA512_OUTPUT_LEN,
block_len: SHA512_BLOCK_LEN,
max_input_len: SHA512_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha512_digest,

Expand All @@ -141,7 +157,7 @@ pub static SHA512_256: Algorithm = Algorithm {
output_len: SHA512_256_OUTPUT_LEN,
chaining_len: SHA512_OUTPUT_LEN,
block_len: SHA512_BLOCK_LEN,
max_input_len: SHA512_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha512_256_digest,

Expand All @@ -157,7 +173,7 @@ pub static SHA3_256: Algorithm = Algorithm {
output_len: SHA3_256_OUTPUT_LEN,
chaining_len: SHA3_256_OUTPUT_LEN,
block_len: SHA3_256_BLOCK_LEN,
max_input_len: SHA3_256_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha3_256_digest,

Expand All @@ -173,7 +189,7 @@ pub static SHA3_384: Algorithm = Algorithm {
output_len: SHA3_384_OUTPUT_LEN,
chaining_len: SHA3_384_OUTPUT_LEN,
block_len: SHA3_384_BLOCK_LEN,
max_input_len: SHA3_384_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha3_384_digest,

Expand All @@ -189,7 +205,7 @@ pub static SHA3_512: Algorithm = Algorithm {
output_len: SHA3_512_OUTPUT_LEN,
chaining_len: SHA3_512_OUTPUT_LEN,
block_len: SHA3_512_BLOCK_LEN,
max_input_len: SHA3_512_MAX_INPUT_LEN,
max_input_len: DIGEST_MAX_INPUT_LEN,

one_shot_hash: sha3_512_digest,

Expand All @@ -203,6 +219,12 @@ fn sha1_digest(msg: &[u8], output: &mut [u8]) {
}
}

fn sha224_digest(msg: &[u8], output: &mut [u8]) {
unsafe {
aws_lc::SHA224(msg.as_ptr(), msg.len(), output.as_mut_ptr());
}
}

fn sha256_digest(msg: &[u8], output: &mut [u8]) {
unsafe {
aws_lc::SHA256(msg.as_ptr(), msg.len(), output.as_mut_ptr());
Expand Down
5 changes: 5 additions & 0 deletions aws-lc-rs/src/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ impl Algorithm {
/// HMAC using SHA-1. Obsolete.
pub static HMAC_SHA1_FOR_LEGACY_USE_ONLY: Algorithm = Algorithm(&digest::SHA1_FOR_LEGACY_USE_ONLY);

/// HMAC using SHA-224.
pub static HMAC_SHA224: Algorithm = Algorithm(&digest::SHA224);

/// HMAC using SHA-256.
pub static HMAC_SHA256: Algorithm = Algorithm(&digest::SHA256);

Expand Down Expand Up @@ -458,6 +461,7 @@ mod tests {

for algorithm in &[
hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
hmac::HMAC_SHA224,
hmac::HMAC_SHA256,
hmac::HMAC_SHA384,
hmac::HMAC_SHA512,
Expand All @@ -478,6 +482,7 @@ mod tests {

for &alg in &[
hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY,
hmac::HMAC_SHA224,
hmac::HMAC_SHA256,
hmac::HMAC_SHA384,
hmac::HMAC_SHA512,
Expand Down
2 changes: 1 addition & 1 deletion aws-lc-rs/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl TestCase {
let name = self.consume_string(key);
match name.as_ref() {
"SHA1" => Some(&digest::SHA1_FOR_LEGACY_USE_ONLY),
"SHA224" => None, // We actively skip SHA-224 support.
"SHA224" => Some(&digest::SHA224),
"SHA256" => Some(&digest::SHA256),
"SHA384" => Some(&digest::SHA384),
"SHA512" => Some(&digest::SHA512),
Expand Down
42 changes: 42 additions & 0 deletions aws-lc-rs/tests/data/digest_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,48 @@ Input = "0123456701234567012345670123456701234567012345670123456701234567"
Repeat = 10
Output = dea356a2cddd90c7a7ecedc5ebb563934f460452

# SHA-224 tests from NIST.

Hash = SHA224
Input = ff
Repeat = 1
Output = e33f9d75e6ae1369dbabf81b96b4591ae46bba30b591a6b6c62542b5

Hash = SHA224
Repeat = 1
Input = 84
Output = 3cd36921df5d6963e73739cf4d20211e2d8877c19cff087ade9d0e3a

Hash = SHA224
Repeat = 1
Input = 5c7b
Output = daff9bce685eb831f97fc1225b03c275a6c112e2d6e76f5faf7a36e6

Hash = SHA224
Repeat = 1
Input = 51ca3d
Output = 2c8959023515476e38388abb43599a29876b4b33d56adc06032de3a2

Hash = SHA224
Repeat = 1
Input = 6084347e
Output = ae57c0a6d49739ba338adfa53bdae063e5c09122b77604780a8eeaa3

Hash = SHA224
Repeat = 1
Input = 493e14623c
Output = 7f631f295e024e74552083245ca8f988a3fb65680ae97c3040d2e65c

Hash = SHA224
Repeat = 1
Input = d729d8cd1631
Output = 342e8e6b23c1c6a54910631f098e08e836259c57e49c1b1d023d166d

Hash = SHA224
Repeat = 1
Input = cbf2061e10faa5
Output = 3aa702b1b66dc57d7aec3ccdbdfbd88592d7520f843ba5d0fa481168

# SHA-256 tests from NIST.

Hash = SHA256
Expand Down
17 changes: 17 additions & 0 deletions aws-lc-rs/tests/digest_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ mod digest_shavs {
}

shavs_tests!(SHA1, SHA1_FOR_LEGACY_USE_ONLY, TestType::Fips180_4);
shavs_tests!(SHA224, SHA224, TestType::Fips180_4);
shavs_tests!(SHA256, SHA256, TestType::Fips180_4);
shavs_tests!(SHA384, SHA384, TestType::Fips180_4);
shavs_tests!(SHA512, SHA512, TestType::Fips180_4);
Expand Down Expand Up @@ -275,6 +276,7 @@ macro_rules! test_i_u_f {
};
}
test_i_u_f!(digest_test_i_u_f_sha1, digest::SHA1_FOR_LEGACY_USE_ONLY);
test_i_u_f!(digest_test_i_u_f_sha224, digest::SHA224);
test_i_u_f!(digest_test_i_u_f_sha256, digest::SHA256);
test_i_u_f!(digest_test_i_u_f_sha384, digest::SHA384);
test_i_u_f!(digest_test_i_u_f_sha512, digest::SHA512);
Expand All @@ -295,6 +297,7 @@ test_i_u_f!(digest_test_i_u_f_sha512, digest::SHA512);
///
/// ```sh
/// sha1sum -b tempfile
/// sha224sum -b tempfile
/// sha256sum -b tempfile
/// sha384sum -b tempfile
/// sha512sum -b tempfile
Expand Down Expand Up @@ -337,6 +340,15 @@ test_large_digest!(
0x65, 0x3C, 0x20, 0xE4, 0xBD
]
);
test_large_digest!(
digest_test_large_digest_sha224,
digest::SHA224,
224 / 8,
[
0xC2, 0x58, 0x05, 0x9f, 0xa8, 0x03, 0x85, 0xeb, 0xf9, 0xf7, 0x3d, 0x01, 0xfe, 0x94, 0x36,
0xd9, 0x62, 0xc4, 0x9a, 0xeb, 0x2c, 0xd0, 0x7e, 0x21, 0x1e, 0xe1, 0x05, 0x55
]
);
test_large_digest!(
digest_test_large_digest_sha256,
digest::SHA256,
Expand Down Expand Up @@ -377,6 +389,7 @@ test_large_digest!(
#[test]
fn test_fmt_algorithm() {
assert_eq!("SHA1", &format!("{:?}", digest::SHA1_FOR_LEGACY_USE_ONLY));
assert_eq!("SHA224", &format!("{:?}", digest::SHA224));
assert_eq!("SHA256", &format!("{:?}", digest::SHA256));
assert_eq!("SHA384", &format!("{:?}", digest::SHA384));
assert_eq!("SHA512", &format!("{:?}", digest::SHA512));
Expand All @@ -392,6 +405,10 @@ fn digest_test_fmt() {
digest::digest(&digest::SHA1_FOR_LEGACY_USE_ONLY, b"hello, world")
)
);
assert_eq!(
"SHA224:6e1a93e32fb44081a401f3db3ef2e6e108b7bbeeb5705afdaf01fb27",
&format!("{:?}", digest::digest(&digest::SHA224, b"hello, world"))
);
assert_eq!(
"SHA256:09ca7e4eaa6e8ae9c7d261167129184883644d\
07dfba7cbfbc4c8a2e08360d5b",
Expand Down
Loading

0 comments on commit 15daf8e

Please sign in to comment.