diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index b292ca0850e..191f4a831ea 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -40,15 +40,11 @@ jobs: strategy: fail-fast: false matrix: - crate_dir: [ "aws-lc-sys", "aws-lc-fips-sys", "aws-lc-rs" ] + # By default, Clippy will lint he dependencies + crate_dir: ["aws-lc-rs"] features: - - "--features bindgen" - - "--features bindgen,fips" - exclude: - - crate_dir: aws-lc-sys - features: "--features bindgen,fips" - - crate_dir: aws-lc-fips-sys - features: "--features bindgen,fips" + - "--features bindgen,unstable" + - "--features bindgen,unstable,fips" steps: - uses: actions/checkout@v3 with: diff --git a/aws-lc-rs/Cargo.toml b/aws-lc-rs/Cargo.toml index 29baa934c37..1c02ec714cc 100644 --- a/aws-lc-rs/Cargo.toml +++ b/aws-lc-rs/Cargo.toml @@ -47,9 +47,9 @@ aws-lc-sys = { version = "0.13.0", path = "../aws-lc-sys", optional = true } aws-lc-fips-sys = { version = "0.12.0", path = "../aws-lc-fips-sys", optional = true } zeroize = "1.7" mirai-annotations = "1.12.0" +paste = "1.0" [dev-dependencies] -paste = "1.0" regex = "1.6.0" lazy_static = "1.4.0" clap = { version = "4.1.8", features = ["derive"] } diff --git a/aws-lc-rs/Makefile b/aws-lc-rs/Makefile index f6e3e3d153f..352b15f3d1a 100644 --- a/aws-lc-rs/Makefile +++ b/aws-lc-rs/Makefile @@ -39,6 +39,9 @@ endif msrv: cargo msrv verify +clippy: + cargo +nightly clippy --all-targets --features bindgen,fips,unstable -- -W clippy::all -W clippy::pedantic + ci: format clippy msrv test coverage api-diff-pub -.PHONY: asan asan-fips asan-release ci clippy coverage test msrv +.PHONY: asan asan-fips asan-release ci clippy coverage test msrv clippy diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index 43c023b1ac1..6ccfcb9ff3c 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -68,7 +68,6 @@ use aws_lc::{ NID_secp521r1, BIGNUM, EVP_PKEY, EVP_PKEY_X25519, NID_X25519, }; -use crate::buffer::Buffer; use crate::encoding::{ AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der, }; @@ -456,7 +455,7 @@ impl AsDer> for PrivateKey { let length = usize::try_from(unsafe { aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp) }) .map_err(|_| Unspecified)?; let outp = LcPtr::new(outp)?; - Ok(Buffer::take_from_slice(unsafe { + Ok(EcPrivateKeyRfc5915Der::take_from_slice(unsafe { std::slice::from_raw_parts_mut(*outp, length) })) } diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 8aa58f3e235..227fa657dfc 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -31,7 +31,6 @@ use aws_lc::{ EVP_PKEY_EC, }; -use crate::buffer::Buffer; use crate::digest::digest_ctx::DigestContext; use crate::encoding::{AsDer, EcPublicKeyX509Der}; use crate::error::{KeyRejected, Unspecified}; @@ -148,7 +147,7 @@ impl AsDer> for PublicKey { let buffer = LcPtr::new(buffer)?; let der = unsafe { std::slice::from_raw_parts(*buffer, len.try_into()?) }.to_owned(); - Ok(Buffer::new(der)) + Ok(EcPublicKeyX509Der::new(der)) } } @@ -641,7 +640,7 @@ mod tests { let result = EcdsaKeyPair::from_pkcs8(&ECDSA_P256_SHA256_FIXED_SIGNING, &input); assert!(result.is_ok()); let key_pair = result.unwrap(); - assert_eq!("EcdsaKeyPair { public_key: EcdsaPublicKey(\"04cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724\") }", + assert_eq!("EcdsaKeyPair { public_key: EcdsaPublicKey(\"04cf0d13a3a7577231ea1b66cf4021cd54f21f4ac4f5f2fdd28e05bc7d2bd099d1374cd08d2ef654d6f04498db462f73e0282058dd661a4c9b0437af3f7af6e724\") }", format!("{key_pair:?}")); assert_eq!( "EcdsaPrivateKey(ECDSA_P256)", diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index c0ce9ef5174..c4b9759ae3e 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -10,7 +10,6 @@ use std::ptr::{null, null_mut}; use aws_lc::{EVP_DigestSign, EVP_DigestSignInit, EVP_PKEY_get0_EC_KEY, EVP_PKEY}; -use crate::buffer::Buffer; use crate::digest::digest_ctx::DigestContext; #[cfg(feature = "fips")] use crate::ec::validate_evp_key; @@ -320,9 +319,9 @@ impl AsDer> for PrivateKey<'_> { let length = usize::try_from(aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp)) .map_err(|_| Unspecified)?; let outp = LcPtr::new(outp)?; - Ok(Buffer::take_from_slice(std::slice::from_raw_parts_mut( - *outp, length, - ))) + Ok(EcPrivateKeyRfc5915Der::take_from_slice( + std::slice::from_raw_parts_mut(*outp, length), + )) } } } diff --git a/aws-lc-rs/src/encoding.rs b/aws-lc-rs/src/encoding.rs index f01f9562aed..11689d9f2d9 100644 --- a/aws-lc-rs/src/encoding.rs +++ b/aws-lc-rs/src/encoding.rs @@ -4,34 +4,58 @@ //! Serialization formats use crate::buffer::Buffer; -use crate::encoding::types::{ - Curve25519SeedBufferType, EcPrivateKeyBinType, EcPrivateKeyRfc5915DerType, - EcPublicKeyX509DerType, -}; +use paste::paste; -use self::types::Pkcs8V1DerType; +macro_rules! generated_encodings { + ($($name:ident),*) => { paste! { + use core::fmt::{Debug, Error, Formatter}; + use core::ops::Deref; + mod buffer_type { + $( + pub struct [<$name Type>] { + _priv: (), + } + )* + } + $( + /// Serialized bytes + pub struct $name<'a>(Buffer<'a, buffer_type::[<$name Type>]>); -mod types { - pub struct EcPrivateKeyBinType { - _priv: (), - } + impl<'a> Deref for $name<'a> { + type Target = Buffer<'a, buffer_type::[<$name Type>]>; - pub struct EcPrivateKeyRfc5915DerType { - _priv: (), - } + fn deref(&self) -> &Self::Target { + &self.0 + } + } - pub struct EcPublicKeyX509DerType { - _priv: (), - } + impl $name<'static> { + #[allow(dead_code)] + pub(crate) fn new(owned: Vec) -> Self { + Self(Buffer::new(owned)) + } + #[allow(dead_code)] + pub(crate) fn take_from_slice(owned: &mut [u8]) -> Self { + Self(Buffer::take_from_slice(owned)) + } + } - pub struct Curve25519SeedBufferType { - _priv: (), - } - - pub struct Pkcs8V1DerType { - _priv: (), - } + impl Debug for $name<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + f.debug_struct(stringify!($name)).finish() + } + } + )* + }} } +pub(crate) use generated_encodings; +generated_encodings!( + EcPrivateKeyBin, + EcPrivateKeyRfc5915Der, + EcPublicKeyX509Der, + Curve25519SeedBin, + Pkcs8V1Der +); /// Trait for types that can be serialized into a DER format. pub trait AsDer { @@ -50,18 +74,3 @@ pub trait AsBigEndian { /// Returns Unspecified if serialization fails. fn as_be_bytes(&self) -> Result; } - -/// Elliptic curve private key data encoded as a big-endian fixed-length integer. -pub type EcPrivateKeyBin<'a> = Buffer<'a, EcPrivateKeyBinType>; - -/// Elliptic curve private key as a DER-encoded `ECPrivateKey` (RFC 5915) structure. -pub type EcPrivateKeyRfc5915Der<'a> = Buffer<'a, EcPrivateKeyRfc5915DerType>; - -/// An elliptic curve public key as a DER-encoded (X509) `SubjectPublicKeyInfo` structure -pub type EcPublicKeyX509Der<'a> = Buffer<'a, EcPublicKeyX509DerType>; - -/// Elliptic curve private key data encoded as a big-endian fixed-length integer. -pub type Curve25519SeedBin<'a> = Buffer<'a, Curve25519SeedBufferType>; - -/// A PKCS#8 v1 (RFC 5208) DER encoded structure. -pub type Pkcs8V1Der<'a> = Buffer<'a, Pkcs8V1DerType>; diff --git a/aws-lc-rs/src/kem.rs b/aws-lc-rs/src/kem.rs index a3ab3f0f65e..6c8f5000ba7 100644 --- a/aws-lc-rs/src/kem.rs +++ b/aws-lc-rs/src/kem.rs @@ -50,6 +50,7 @@ //! ``` use crate::{ buffer::Buffer, + encoding::generated_encodings, error::{KeyRejected, Unspecified}, ptr::LcPtr, ptr::Pointer, @@ -60,7 +61,7 @@ use aws_lc::{ EVP_PKEY_kem_new_raw_public_key, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_up_ref, EVP_PKEY, EVP_PKEY_KEM, }; -use std::{borrow::Cow, cmp::Ordering, fmt::Debug, ptr::null_mut}; +use std::{borrow::Cow, cmp::Ordering, ptr::null_mut}; use zeroize::Zeroize; /// An identifier for a KEM algorithm. @@ -256,14 +257,8 @@ where } } -mod types { - pub struct EncapsulationKeyBytesType { - _priv: (), - } -} - -/// KEM Encapsulation Key Bytes. -pub type EncapsulationKeyBytes = Buffer<'static, types::EncapsulationKeyBytesType>; +use paste::paste; +generated_encodings!(EncapsulationKeyBytes); /// A serializable encapsulation key usable with KEM algorithms. Constructed /// from either a `DecapsulationKey` or raw bytes. @@ -330,7 +325,7 @@ where /// /// # Errors /// * `Unspecified`: Any failure to retrieve the `EnscapsulationKey` bytes. - pub fn key_bytes(&self) -> Result { + pub fn key_bytes(&self) -> Result, Unspecified> { let mut encapsulate_key_size = self.algorithm.encapsulate_key_size(); let mut encapsulate_bytes = vec![0u8; encapsulate_key_size]; if 1 != unsafe { @@ -350,7 +345,7 @@ where debug_assert_eq!(encapsulate_key_size, encapsulate_bytes.len()); encapsulate_bytes.truncate(encapsulate_key_size); - Ok(Buffer::new(encapsulate_bytes)) + Ok(EncapsulationKeyBytes::new(encapsulate_bytes)) } /// Creates a new KEM encapsulation key from raw bytes. This method MUST NOT be used to generate diff --git a/aws-lc-rs/src/rsa/key.rs b/aws-lc-rs/src/rsa/key.rs index 3f920424e93..8ae4053f2d2 100644 --- a/aws-lc-rs/src/rsa/key.rs +++ b/aws-lc-rs/src/rsa/key.rs @@ -11,7 +11,6 @@ use core::{ }; use crate::{ - buffer::Buffer, encoding::{AsDer, Pkcs8V1Der}, fips::indicator_check, }; @@ -363,7 +362,9 @@ impl crate::signature::KeyPair for KeyPair { impl AsDer> for KeyPair { fn as_der(&self) -> Result, Unspecified> { - Ok(Buffer::new(encoding::pkcs8::encode_v1_der(&self.evp_pkey)?)) + Ok(Pkcs8V1Der::new(encoding::pkcs8::encode_v1_der( + &self.evp_pkey, + )?)) } } diff --git a/aws-lc-rs/tests/ecdsa_tests.rs b/aws-lc-rs/tests/ecdsa_tests.rs index ec6f6be058f..07bede3ffce 100644 --- a/aws-lc-rs/tests/ecdsa_tests.rs +++ b/aws-lc-rs/tests/ecdsa_tests.rs @@ -476,7 +476,7 @@ fn test_private_key() { } { let private_key_der: EcPrivateKeyRfc5915Der = key_pair.private_key().as_der().unwrap(); - assert_eq!("Buffer(...)", format!("{private_key_der:?}")); + assert_eq!("EcPrivateKeyRfc5915Der", format!("{private_key_der:?}")); assert!(EcdsaKeyPair::from_pkcs8(signing_alg, private_key_der.as_ref()).is_err()); let key_pair_copy =