Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Sha224 digest, HMAC-SHA224, and SHA224 KAT #204

Merged
merged 9 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
bencivjan marked this conversation as resolved.
Show resolved Hide resolved
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