Skip to content

Commit

Permalink
[smithy-rs] Support PowerPC architecture for sigv4 signature (#1847)
Browse files Browse the repository at this point in the history
* Use hmac and sha2 instead of ring on powerpc

* Enable aws-sig-auth in CI

* Update CHANGELOG

* Run tests against exotic platforms

* Run tests only against aws rust runtime

* PowerPC 32 and 64 bit should be fully testable now

* Maybe this time build and test will work

* Add licence header to hmac.rs

* Properly use finalized_fixed

* Revert leftover

* Temporary disable crc32c test on powerpc

* Temporary disable system_time_conversion_test on 32bit CPUs

* Disable other 3 tests on 32bit

* Temporarily disable last test

* Update CHANGELOG and document TODOs with issues

* Run aws-smithy-client tests in CI with crosscompiled local openssl

* Simplify CI script

* Use correct curl options

* Use the right OS for i686

* Looks like I finally foung the right os type for i686

* Add `tcp` feature to `hyper` to get tests compiling.

* Enable verbose logging to debug CI failure in cross.

* Use pre-built openSSL on i686

* Fix empty spaces.

* Set environment variables based on matrix.target

* Remove all usages of `ring` from `aws-sigv4`. It ensures broader platform compatibility and higher performance.

* Update changelog entries.

* Remove redundant dev dependencies.

Co-authored-by: Luca Palmieri <[email protected]>
  • Loading branch information
2 people authored and aws-sdk-rust-ci committed Dec 14, 2022
1 parent a1ba5f5 commit c801e96
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 34 deletions.
10 changes: 9 additions & 1 deletion sdk/aws-sigv4/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
[[bench]]
name = "hmac"
harness = false

[package]
name = "aws-sigv4"
version = "0.51.0"
Expand All @@ -22,9 +26,10 @@ default = ["sign-http"]
hex = "0.4"
once_cell = "1.8"
regex = "1.5"
ring = "0.16"
time = "0.3.5"
tracing = "0.1"
hmac = "0.12"
sha2 = "0.10"

[dependencies.aws-smithy-eventstream]
path = "../aws-smithy-eventstream"
Expand Down Expand Up @@ -52,6 +57,7 @@ version = "2.1"
optional = true

[dev-dependencies]
criterion = "0.4"
bytes = "1"
httparse = "1.5"
pretty_assertions = "1.0"
Expand All @@ -60,3 +66,5 @@ proptest = "1"
[dev-dependencies.time]
version = "0.3.4"
features = ["parsing"]
[target."cfg(not(any(target_arch = \"powerpc\", target_arch = \"powerpc64\")))".dev-dependencies]
ring = "0.16"
69 changes: 69 additions & 0 deletions sdk/aws-sigv4/benches/hmac.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use criterion::{criterion_group, criterion_main, Criterion};
use hmac::digest::FixedOutput;
use hmac::{Hmac, Mac};
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
use ring::hmac::{sign, Context, Key, HMAC_SHA256};
use sha2::Sha256;

pub fn hmac(c: &mut Criterion) {
c.bench_function("hmac", |b| {
b.iter(|| {
let mut mac = Hmac::<Sha256>::new_from_slice(b"secret").unwrap();

mac.update(b"hello, world");
mac.finalize_fixed()
})
});
}

#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
pub fn ring_multipart(c: &mut Criterion) {
c.bench_function("ring_multipart", |b| {
b.iter(|| {
let k = Key::new(HMAC_SHA256, b"secret");
let mut ctx = Context::with_key(&k);

for slice in ["hello", ", ", "world"] {
ctx.update(slice.as_ref());
}

ctx.sign()
})
});
}

#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
pub fn ring_one_shot(c: &mut Criterion) {
c.bench_function("ring_one_shot", |b| {
b.iter(|| {
let k = Key::new(HMAC_SHA256, b"secret");

sign(&k, b"hello, world")
})
});
}

#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
criterion_group! {
name = benches;

config = Criterion::default();

targets = hmac, ring_multipart, ring_one_shot
}

#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
criterion_group! {
name = benches;

config = Criterion::default();

targets = hmac
}

criterion_main!(benches);
3 changes: 0 additions & 3 deletions sdk/aws-sigv4/external-types.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ allowed_external_types = [
"http::request::Request",
"http::uri::Uri",

# TODO(https://github.com/awslabs/smithy-rs/issues/1193): Don't expose on `ring`
"ring::hmac::Tag",

# TODO(https://github.com/awslabs/smithy-rs/issues/1193): Once tooling permits it, only allow the following types in the `event-stream` feature
"aws_smithy_eventstream::frame::Message",
]
6 changes: 6 additions & 0 deletions sdk/aws-sigv4/src/date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ mod tests {
use crate::date_time::test_parsers::{parse_date, parse_date_time};
use time::format_description::well_known::Rfc3339;

// TODO(https://github.com/awslabs/smithy-rs/issues/1857)
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn date_format() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
Expand All @@ -107,6 +109,8 @@ mod tests {
assert_eq!("01000102", format_date(time));
}

// TODO(https://github.com/awslabs/smithy-rs/issues/1857)
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn date_time_format() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
Expand All @@ -131,6 +135,8 @@ mod tests {
assert_eq!("20150830", format_date(time));
}

// TODO(https://github.com/awslabs/smithy-rs/issues/1857)
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn test_truncate_subsecs() {
let time: SystemTime = OffsetDateTime::parse("2039-02-04T23:01:09.104Z", &Rfc3339)
Expand Down
43 changes: 24 additions & 19 deletions sdk/aws-sigv4/src/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
//! Functions to create signing keys and calculate signatures.
use crate::date_time::format_date;
use ring::{
digest::{self},
hmac::{self, Key, Tag},
};
use hmac::{digest::FixedOutput, Hmac, Mac};
use sha2::{Digest, Sha256};
use std::time::SystemTime;

/// HashedPayload = Lowercase(HexEncode(Hash(requestPayload)))
#[allow(dead_code)] // Unused when compiling without certain features
pub(crate) fn sha256_hex_string(bytes: impl AsRef<[u8]>) -> String {
// hex::encode returns a lowercase string
hex::encode(digest::digest(&digest::SHA256, bytes.as_ref()))
let mut hasher = Sha256::new();
hasher.update(bytes);
hex::encode(hasher.finalize_fixed())
}

/// Calculates a Sigv4 signature
pub fn calculate_signature(signing_key: Tag, string_to_sign: &[u8]) -> String {
let s_key = Key::new(hmac::HMAC_SHA256, signing_key.as_ref());
let tag = hmac::sign(&s_key, string_to_sign);
hex::encode(tag)
pub fn calculate_signature(signing_key: impl AsRef<[u8]>, string_to_sign: &[u8]) -> String {
let mut mac = Hmac::<Sha256>::new_from_slice(signing_key.as_ref())
.expect("HMAC can take key of any size");
mac.update(string_to_sign);
hex::encode(mac.finalize_fixed())
}

/// Generates a signing key for Sigv4
Expand All @@ -32,28 +32,33 @@ pub fn generate_signing_key(
time: SystemTime,
region: &str,
service: &str,
) -> hmac::Tag {
) -> impl AsRef<[u8]> {
// kSecret = your secret access key
// kDate = HMAC("AWS4" + kSecret, Date)
// kRegion = HMAC(kDate, Region)
// kService = HMAC(kRegion, Service)
// kSigning = HMAC(kService, "aws4_request")

let secret = format!("AWS4{}", secret);
let secret = hmac::Key::new(hmac::HMAC_SHA256, secret.as_bytes());
let tag = hmac::sign(&secret, format_date(time).as_bytes());
let mut mac =
Hmac::<Sha256>::new_from_slice(secret.as_ref()).expect("HMAC can take key of any size");
mac.update(format_date(time).as_bytes());
let tag = mac.finalize_fixed();

// sign region
let key = hmac::Key::new(hmac::HMAC_SHA256, tag.as_ref());
let tag = hmac::sign(&key, region.as_bytes());
let mut mac = Hmac::<Sha256>::new_from_slice(&tag).expect("HMAC can take key of any size");
mac.update(region.as_bytes());
let tag = mac.finalize_fixed();

// sign service
let key = hmac::Key::new(hmac::HMAC_SHA256, tag.as_ref());
let tag = hmac::sign(&key, service.as_bytes());
let mut mac = Hmac::<Sha256>::new_from_slice(&tag).expect("HMAC can take key of any size");
mac.update(service.as_bytes());
let tag = mac.finalize_fixed();

// sign request
let key = hmac::Key::new(hmac::HMAC_SHA256, tag.as_ref());
hmac::sign(&key, "aws4_request".as_bytes())
let mut mac = Hmac::<Sha256>::new_from_slice(&tag).expect("HMAC can take key of any size");
mac.update("aws4_request".as_bytes());
mac.finalize_fixed()
}

#[cfg(test)]
Expand Down
3 changes: 3 additions & 0 deletions sdk/aws-smithy-checksums/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ mod tests {
assert_eq!(decoded_checksum, expected_checksum);
}

// TODO(https://github.com/zowens/crc32c/issues/34)
// TODO(https://github.com/awslabs/smithy-rs/issues/1857)
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
#[test]
fn test_crc32c_checksum() {
let mut checksum = Crc32c::default();
Expand Down
8 changes: 2 additions & 6 deletions sdk/aws-smithy-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ version = "0.51.0"

[dependencies.hyper]
version = "0.14.12"
features = ["client", "http2", "http1"]
features = ["client", "http2", "http1", "tcp"]
optional = true

[dependencies.hyper-rustls]
version = "0.23.0"
optional = true
features = ["rustls-native-certs", "http2"]
features = ["rustls-native-certs", "http2", "webpki-roots"]

[dependencies.hyper-tls]
version = "0.5.0"
Expand Down Expand Up @@ -91,10 +91,6 @@ path = "../aws-smithy-async"
features = ["rt-tokio"]
version = "0.51.0"

[dev-dependencies.hyper-rustls]
version = "0.23.0"
features = ["webpki-roots"]

[dev-dependencies.serde]
version = "1"
features = ["derive"]
Expand Down
2 changes: 2 additions & 0 deletions sdk/aws-smithy-types/src/date_time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ mod test {
assert!(DateTime::from_nanos(10_000_000_000_000_000_000_999_999_999_i128).is_err());
}

// TODO(https://github.com/awslabs/smithy-rs/issues/1857)
#[cfg(not(any(target_arch = "powerpc", target_arch = "x86")))]
#[test]
fn system_time_conversions() {
// Check agreement
Expand Down
10 changes: 5 additions & 5 deletions versions.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
smithy_rs_revision = '6b3e31123571ec64656724c94c50415a2b2e0aab'
smithy_rs_revision = '7e666dab8bbec977ff88dd885cd7d50c31a10908'
aws_doc_sdk_examples_revision = 'f88a0edba3961f9d978bf1727054c9414e4fca2b'

[manual_interventions]
Expand Down Expand Up @@ -1921,7 +1921,7 @@ source_hash = 'e85895bbe46b96359ca3f040197e39feee127491eea6dff5353bfea316e2cc13'
[crates.aws-sigv4]
category = 'AwsRuntime'
version = '0.51.0'
source_hash = '50462d0f34c6e69dec204a4402600c45c3fee7ce2881939b78ee2c0182d35360'
source_hash = 'a90f3a3a415f816929d8bc1a0ca26c3f616ce97e886e0cec5f08cd43bb4d3915'

[crates.aws-smithy-async]
category = 'SmithyRuntime'
Expand All @@ -1931,12 +1931,12 @@ source_hash = '85826c9beec513a917bd13d5691af14f3baabdcff7402837d2a4859b493b8b69'
[crates.aws-smithy-checksums]
category = 'SmithyRuntime'
version = '0.51.0'
source_hash = 'f0a1257468bcfa5b2a129e47bef9512258ba444b362ae84a7fcf53452d4b5388'
source_hash = '7039fcd68d5630bbd0398f9d6f1abb25d2d41b001daa3510012a131393ecad18'

[crates.aws-smithy-client]
category = 'SmithyRuntime'
version = '0.51.0'
source_hash = '065493c6ebb0e87a3ecee96704a1739d0fa7876bbd73f409ecb852c9df855cf8'
source_hash = 'b778d51593083a4cd5676d8b77beced8c5feda67cc52fe453b1d6f27e0975d52'

[crates.aws-smithy-eventstream]
category = 'SmithyRuntime'
Expand Down Expand Up @@ -1971,7 +1971,7 @@ source_hash = '774f83e0e31d9f4c0f1158e87c39438d60280bac0f2e1e1ef1d993bc9594cc25'
[crates.aws-smithy-types]
category = 'SmithyRuntime'
version = '0.51.0'
source_hash = '190fb14415d84f16856d01fa9b6b275e5ce56e448dd496114cffeb5387e0e09c'
source_hash = '468361bba3a588959443cb5fb71680a6688f7cccb2f2e3201edc9613ee6d5952'

[crates.aws-smithy-types-convert]
category = 'SmithyRuntime'
Expand Down

0 comments on commit c801e96

Please sign in to comment.