From 0cc8d67d62faf1a6214c5edcaff83b903d42f04d Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 10 Nov 2023 19:16:38 +0100 Subject: [PATCH 01/12] Constant time comparison for SigV4a Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/Cargo.toml | 1 + aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 25 +++++++++------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index 07766f202a..40ee8c57db 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -33,6 +33,7 @@ percent-encoding = { version = "2.1", optional = true } regex = "1.5" ring = { version = "0.17.5", optional = true } sha2 = "0.10" +crypto-bigint = "0.5" time = "0.3.5" tracing = "0.1" zeroize = { version = "^1", optional = true } diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index 9c2b8cb980..e4fba44c8a 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -5,8 +5,7 @@ use aws_smithy_runtime_api::client::identity::Identity; use bytes::{BufMut, BytesMut}; -use num_bigint::BigInt; -use once_cell::sync::Lazy; +use crypto_bigint::{U256, Encoding, CheckedAdd}; use p256::ecdsa::signature::Signer; use p256::ecdsa::{Signature, SigningKey}; use std::io::Write; @@ -14,17 +13,13 @@ use std::time::SystemTime; use zeroize::Zeroizing; const ALGORITHM: &[u8] = b"AWS4-ECDSA-P256-SHA256"; -static BIG_N_MINUS_2: Lazy = Lazy::new(|| { +static BIG_N_MINUS_2: U256 = { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* - const ORDER: &[u32] = &[ - 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xBCE6FAAD, 0xA7179E84, 0xF3B9CAC2, - 0xFC632551, - ]; - let big_n = BigInt::from_slice(num_bigint::Sign::Plus, ORDER); - big_n - BigInt::from(2i32) -}); + const ORDER: U256 = U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); + ORDER.shr_vartime(1) +}; /// Calculates a Sigv4a signature pub fn calculate_signature(signing_key: impl AsRef<[u8]>, string_to_sign: &[u8]) -> String { @@ -64,14 +59,14 @@ pub fn generate_signing_key(access_key: &str, secret_access_key: &str) -> impl A let tag = ring::hmac::sign(&key, &buf); let tag = &tag.as_ref()[0..32]; - let k0 = BigInt::from_bytes_be(num_bigint::Sign::Plus, tag); + let k0 = U256::from_be_bytes(tag.try_into().expect("convert to [u8; 32]")); // It would be more secure for this to be a constant time comparison, but because this // is for client usage, that's not as big a deal. - if k0 <= *BIG_N_MINUS_2 { - let pk = k0 + BigInt::from(1i32); - let d = Zeroizing::new(pk.to_bytes_be().1); - break SigningKey::from_bytes(&d).unwrap(); + if k0 <= BIG_N_MINUS_2 { + let pk = k0.checked_add(&U256::ONE).unwrap_or(U256::ZERO); + let d = Zeroizing::new(pk.to_be_bytes()); + break SigningKey::from_bytes(d.as_ref()).unwrap(); } *counter = counter From 0555a908bdf37d9315de291663f8c7348cf247ee Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 10 Nov 2023 20:40:58 +0100 Subject: [PATCH 02/12] Use const Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index e4fba44c8a..d866f20996 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -13,7 +13,7 @@ use std::time::SystemTime; use zeroize::Zeroizing; const ALGORITHM: &[u8] = b"AWS4-ECDSA-P256-SHA256"; -static BIG_N_MINUS_2: U256 = { +const BIG_N_MINUS_2: U256 = { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* From 3a22c95b4baab76b2852aec3053030cde7e25b05 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Mon, 13 Nov 2023 09:36:34 +0100 Subject: [PATCH 03/12] Update Cargo.toml Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index 40ee8c57db..bd4f1878a5 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -13,7 +13,7 @@ default = ["sign-http"] http0-compat = ["dep:http"] sign-http = ["dep:http", "dep:percent-encoding", "dep:form_urlencoded"] sign-eventstream = ["dep:aws-smithy-eventstream"] -sigv4a = ["dep:p256", "dep:num-bigint", "dep:zeroize", "dep:ring"] +sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:zeroize", "dep:ring"] [dependencies] aws-credential-types = { path = "../aws-credential-types" } @@ -33,7 +33,7 @@ percent-encoding = { version = "2.1", optional = true } regex = "1.5" ring = { version = "0.17.5", optional = true } sha2 = "0.10" -crypto-bigint = "0.5" +crypto-bigint = { version = "0.5", optional = true } time = "0.3.5" tracing = "0.1" zeroize = { version = "^1", optional = true } From 6d7d6450d3759e8fa7b83a854bbdc9447779d46a Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Mon, 13 Nov 2023 09:37:34 +0100 Subject: [PATCH 04/12] Update init of BIG_N-2 Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index d866f20996..f93a223510 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -5,7 +5,8 @@ use aws_smithy_runtime_api::client::identity::Identity; use bytes::{BufMut, BytesMut}; -use crypto_bigint::{U256, Encoding, CheckedAdd}; +use crypto_bigint::{U256, Encoding, CheckedAdd, CheckedSub}; +use once_cell::sync::Lazy; use p256::ecdsa::signature::Signer; use p256::ecdsa::{Signature, SigningKey}; use std::io::Write; @@ -13,13 +14,13 @@ use std::time::SystemTime; use zeroize::Zeroizing; const ALGORITHM: &[u8] = b"AWS4-ECDSA-P256-SHA256"; -const BIG_N_MINUS_2: U256 = { +const BIG_N_MINUS_2: Lazy = Lazy::new(|| { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* const ORDER: U256 = U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); - ORDER.shr_vartime(1) -}; + ORDER.checked_sub(&U256::from(2u32)).unwrap() +}); /// Calculates a Sigv4a signature pub fn calculate_signature(signing_key: impl AsRef<[u8]>, string_to_sign: &[u8]) -> String { @@ -63,7 +64,7 @@ pub fn generate_signing_key(access_key: &str, secret_access_key: &str) -> impl A // It would be more secure for this to be a constant time comparison, but because this // is for client usage, that's not as big a deal. - if k0 <= BIG_N_MINUS_2 { + if k0 <= *BIG_N_MINUS_2 { let pk = k0.checked_add(&U256::ONE).unwrap_or(U256::ZERO); let d = Zeroizing::new(pk.to_be_bytes()); break SigningKey::from_bytes(d.as_ref()).unwrap(); From 6f19eca5c1c171de3cc9674abf52e458fc411f83 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:03:49 +0100 Subject: [PATCH 05/12] Fix lint Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index f93a223510..dfcd3c1308 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -18,7 +18,8 @@ const BIG_N_MINUS_2: Lazy = Lazy::new(|| { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* - const ORDER: U256 = U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); + const ORDER: U256 = + U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); ORDER.checked_sub(&U256::from(2u32)).unwrap() }); From dc15f07de8af79e8ec7b285ca0a2981bea2fa089 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:31:18 +0100 Subject: [PATCH 06/12] Use static Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index dfcd3c1308..1e7d189f28 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -14,7 +14,7 @@ use std::time::SystemTime; use zeroize::Zeroizing; const ALGORITHM: &[u8] = b"AWS4-ECDSA-P256-SHA256"; -const BIG_N_MINUS_2: Lazy = Lazy::new(|| { +static BIG_N_MINUS_2: Lazy = Lazy::new(|| { // The N value from section 3.2.1.3 of https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf // Used as the N value for the algorithm described in section A.2.2 of https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf // *(Basically a prime number blessed by the NSA for use in p256)* From 359f169003ee8904899c476da45e306ecd03d897 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:51:28 +0100 Subject: [PATCH 07/12] Fix lint Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index 1e7d189f28..a762ed5f09 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -5,7 +5,7 @@ use aws_smithy_runtime_api::client::identity::Identity; use bytes::{BufMut, BytesMut}; -use crypto_bigint::{U256, Encoding, CheckedAdd, CheckedSub}; +use crypto_bigint::{CheckedAdd, CheckedSub, Encoding, U256}; use once_cell::sync::Lazy; use p256::ecdsa::signature::Signer; use p256::ecdsa::{Signature, SigningKey}; From 0574c7ffb6c9d70c2b445fcdf81acf26ef5c6961 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 14 Nov 2023 08:57:30 +0100 Subject: [PATCH 08/12] expect() computation Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index a762ed5f09..ce80e83512 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -66,7 +66,7 @@ pub fn generate_signing_key(access_key: &str, secret_access_key: &str) -> impl A // It would be more secure for this to be a constant time comparison, but because this // is for client usage, that's not as big a deal. if k0 <= *BIG_N_MINUS_2 { - let pk = k0.checked_add(&U256::ONE).unwrap_or(U256::ZERO); + let pk = k0.checked_add(&U256::ONE).expect("k0 is always less than U256::MAX"); let d = Zeroizing::new(pk.to_be_bytes()); break SigningKey::from_bytes(d.as_ref()).unwrap(); } From 294ed8bb7511d951e071d7dbec21e767a4b29520 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Tue, 14 Nov 2023 09:31:36 +0100 Subject: [PATCH 09/12] Run rustfmt Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/src/sign/v4a.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs index ce80e83512..a8cb3f9538 100644 --- a/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs +++ b/aws/rust-runtime/aws-sigv4/src/sign/v4a.rs @@ -66,7 +66,9 @@ pub fn generate_signing_key(access_key: &str, secret_access_key: &str) -> impl A // It would be more secure for this to be a constant time comparison, but because this // is for client usage, that's not as big a deal. if k0 <= *BIG_N_MINUS_2 { - let pk = k0.checked_add(&U256::ONE).expect("k0 is always less than U256::MAX"); + let pk = k0 + .checked_add(&U256::ONE) + .expect("k0 is always less than U256::MAX"); let d = Zeroizing::new(pk.to_be_bytes()); break SigningKey::from_bytes(d.as_ref()).unwrap(); } From 86d9a5b1e2c6c7ce6bb3ec5fb3587290f9054366 Mon Sep 17 00:00:00 2001 From: Russell Cohen Date: Tue, 14 Nov 2023 16:48:47 -0500 Subject: [PATCH 10/12] Specify the latest Crypto-Bigint version to ensure the latest version of subtle --- aws/rust-runtime/aws-sigv4/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index bd4f1878a5..e48e661946 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -33,7 +33,7 @@ percent-encoding = { version = "2.1", optional = true } regex = "1.5" ring = { version = "0.17.5", optional = true } sha2 = "0.10" -crypto-bigint = { version = "0.5", optional = true } +crypto-bigint = { version = "0.5.4", optional = true } time = "0.3.5" tracing = "0.1" zeroize = { version = "^1", optional = true } From 935f27f86acaa3b442a6fe0655fbddb3b9a843ce Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Wed, 15 Nov 2023 10:12:36 +0100 Subject: [PATCH 11/12] Run CI manually From 8f1e694863fe5b2d21d471e0b48e1aec8617ce60 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 16 Nov 2023 20:31:09 +0100 Subject: [PATCH 12/12] Pin subtle 2.5 Signed-off-by: Daniele Ahmed --- aws/rust-runtime/aws-sigv4/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws/rust-runtime/aws-sigv4/Cargo.toml b/aws/rust-runtime/aws-sigv4/Cargo.toml index 33b9a5a4d6..1e628da528 100644 --- a/aws/rust-runtime/aws-sigv4/Cargo.toml +++ b/aws/rust-runtime/aws-sigv4/Cargo.toml @@ -13,7 +13,7 @@ default = ["sign-http"] http0-compat = ["dep:http"] sign-http = ["dep:http", "dep:percent-encoding", "dep:form_urlencoded"] sign-eventstream = ["dep:aws-smithy-eventstream"] -sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:zeroize", "dep:ring"] +sigv4a = ["dep:p256", "dep:crypto-bigint", "dep:subtle", "dep:zeroize", "dep:ring"] [dependencies] aws-credential-types = { path = "../aws-credential-types" } @@ -34,6 +34,7 @@ regex = "1.5" ring = { version = "0.17.5", optional = true } sha2 = "0.10" crypto-bigint = { version = "0.5.4", optional = true } +subtle = { version = "2.5.0", optional = true } time = "0.3.5" tracing = "0.1" zeroize = { version = "^1", optional = true }