Skip to content
Draft
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
9 changes: 9 additions & 0 deletions .changelog/aws-sigv4-aws-lc-rs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
applies_to: ["client", "aws-sdk-rust"]
authors: ["jplock"]
references: ["smithy-rs#4681"]
breaking: false
new_feature: true
bug_fix: false
---
Add optional `aws-lc-rs` and `fips` cargo features to `aws-sigv4`. When `aws-lc-rs` is enabled, the SigV4 HMAC-SHA256 / SHA-256 primitives — and, when combined with `sigv4a`, the SigV4a ECDSA-P256 signing path — are routed through `aws-lc-rs` instead of RustCrypto's `hmac` / `sha2` / `p256`. The `fips` feature additionally activates `aws-lc-rs/fips`, routing those primitives through `aws-lc-fips-sys`. The default build is unchanged.
141 changes: 140 additions & 1 deletion aws/rust-runtime/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion aws/rust-runtime/aws-sigv4/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,19 @@ sign-http = ["dep:percent-encoding", "dep:form_urlencoded"]
sign-eventstream = ["dep:aws-smithy-eventstream"]
sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:subtle", "dep:zeroize"]

# Internal feature used to gate code that depends on aws-lc-rs being linked.
# Users should not enable this directly; choose `aws-lc-rs` or `fips` instead.
__aws-lc-rs = ["dep:aws-lc-rs"]
# Route SigV4 (and, with `sigv4a`, SigV4a) cryptographic primitives through
# `aws-lc-rs` (non-FIPS, backed by `aws-lc-sys`) instead of RustCrypto's
# `hmac` / `sha2` / `p256`.
aws-lc-rs = ["__aws-lc-rs", "aws-lc-rs?/aws-lc-sys"]
# Same as `aws-lc-rs`, but backed by the FIPS-validated `aws-lc-fips-sys`.
fips = ["__aws-lc-rs", "aws-lc-rs?/fips"]

[dependencies]
aws-credential-types = { path = "../aws-credential-types" }
aws-lc-rs = { version = "1", default-features = false, optional = true }
aws-smithy-eventstream = { path = "../../../rust-runtime/aws-smithy-eventstream", optional = true }
aws-smithy-http = { path = "../../../rust-runtime/aws-smithy-http" }
aws-smithy-runtime-api = { path = "../../../rust-runtime/aws-smithy-runtime-api", features = ["client"] }
Expand Down Expand Up @@ -67,7 +78,8 @@ harness = false
required-features = ["sigv4a"]

[package.metadata.docs.rs]
all-features = true
all-features = false
features = ["aws-lc-rs", "sigv4a", "sign-http", "http1", "sign-eventstream", "http0-compat"]
targets = ["x86_64-unknown-linux-gnu"]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
rustdoc-args = ["--cfg", "docsrs"]
Expand Down
14 changes: 14 additions & 0 deletions aws/rust-runtime/aws-sigv4/benches/hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
*/

use criterion::{criterion_group, criterion_main, Criterion};
#[cfg(not(feature = "__aws-lc-rs"))]
use hmac::digest::FixedOutput;
#[cfg(not(feature = "__aws-lc-rs"))]
use hmac::{Hmac, KeyInit, Mac};
#[cfg(not(feature = "__aws-lc-rs"))]
use sha2::Sha256;

#[cfg(not(feature = "__aws-lc-rs"))]
pub fn hmac(c: &mut Criterion) {
c.bench_function("hmac", |b| {
b.iter(|| {
Expand All @@ -19,6 +23,16 @@ pub fn hmac(c: &mut Criterion) {
});
}

#[cfg(feature = "__aws-lc-rs")]
pub fn hmac(c: &mut Criterion) {
c.bench_function("hmac", |b| {
b.iter(|| {
let key = aws_lc_rs::hmac::Key::new(aws_lc_rs::hmac::HMAC_SHA256, b"secret");
aws_lc_rs::hmac::sign(&key, b"hello, world")
})
});
}

criterion_group! {
name = benches;

Expand Down
33 changes: 28 additions & 5 deletions aws/rust-runtime/aws-sigv4/src/http_request/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,9 @@ pub(crate) mod v4a {
sign, PayloadChecksumKind, SessionTokenMode, SignatureLocation, SigningSettings,
};
use crate::sign::v4a;
#[cfg(not(feature = "__aws-lc-rs"))]
use p256::ecdsa::signature::Verifier;
#[cfg(not(feature = "__aws-lc-rs"))]
use p256::ecdsa::{DerSignature, SigningKey};
use std::time::Duration;
use time::format_description::well_known::Rfc3339;
Expand Down Expand Up @@ -369,12 +371,33 @@ pub(crate) mod v4a {
let creds = params.credentials().unwrap();
let signing_key =
v4a::generate_signing_key(creds.access_key_id(), creds.secret_access_key());
let sig = DerSignature::try_from(hex::decode(out.signature).unwrap().as_slice()).unwrap();

let signing_key = SigningKey::from_slice(signing_key.as_ref()).unwrap();
let peer_public_key = signing_key.verifying_key();
let sig_bytes = hex::decode(out.signature).unwrap();
let sts = actual_string_to_sign.as_bytes();
peer_public_key.verify(sts, &sig).unwrap();

#[cfg(not(feature = "__aws-lc-rs"))]
{
let sig = DerSignature::try_from(sig_bytes.as_slice()).unwrap();
let signing_key = SigningKey::from_slice(signing_key.as_ref()).unwrap();
let peer_public_key = signing_key.verifying_key();
peer_public_key.verify(sts, &sig).unwrap();
}
#[cfg(feature = "__aws-lc-rs")]
{
use aws_lc_rs::signature::KeyPair as _;
let scalar: &[u8; 32] = signing_key.as_ref().try_into().unwrap();
let der = v4a::scalar_to_sec1_p256_der(scalar);
let key_pair = aws_lc_rs::signature::EcdsaKeyPair::from_private_key_der(
&aws_lc_rs::signature::ECDSA_P256_SHA256_ASN1_SIGNING,
&der,
)
.unwrap();
let pub_key = key_pair.public_key().as_ref();
let upk = aws_lc_rs::signature::UnparsedPublicKey::new(
&aws_lc_rs::signature::ECDSA_P256_SHA256_ASN1,
pub_key,
);
upk.verify(sts, &sig_bytes).unwrap();
}
// TODO(sigv4a) - use public.key.json as verifying key?
}

Expand Down
Loading
Loading