From 3387f6d8a22efc4c7fd0d9b65cfb3fbf8b2f110b Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Thu, 19 Oct 2023 20:49:58 +0000 Subject: [PATCH 01/11] Comment out FIPS related sections for now --- aws-lc-rs/src/aead.rs | 152 +++++++++--------- .../src/aead/chacha20_poly1305_openssh.rs | 18 +-- aws-lc-rs/src/agreement.rs | 24 +-- aws-lc-rs/src/cipher.rs | 40 ++--- aws-lc-rs/src/digest.rs | 36 ++--- aws-lc-rs/src/ec/key_pair.rs | 10 +- aws-lc-rs/src/ed25519.rs | 18 +-- aws-lc-rs/src/hkdf.rs | 60 +++---- aws-lc-rs/src/hmac.rs | 81 +++++----- aws-lc-rs/src/pbkdf2.rs | 44 ++--- aws-lc-rs/src/rand.rs | 12 +- aws-lc-rs/src/rsa.rs | 10 +- aws-lc-rs/src/signature.rs | 36 ++--- 13 files changed, 269 insertions(+), 272 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index c9e41f5f5fa..4fc9e022875 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -176,8 +176,8 @@ pub trait BoundKey: Debug { /// Intentionally not `Clone` or `Copy` since cloning would allow duplication /// of the nonce sequence. /// -/// # FIPS -/// Prefer [`RandomizedNonceKey`] for opening operations. +// # FIPS +// Prefer [`RandomizedNonceKey`] for opening operations. pub struct OpeningKey { key: UnboundKey, nonce_sequence: N, @@ -215,14 +215,14 @@ impl OpeningKey { /// has been overwritten by the plaintext; `plaintext` will refer to the /// plaintext without the tag. /// - /// # FIPS - /// Use this method with one of the following algorithms: - /// * `AES_128_GCM` - /// * `AES_256_GCM` - /// - /// Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry - /// with sealing operations. - /// + // # FIPS + // Use this method with one of the following algorithms: + // * `AES_128_GCM` + // * `AES_256_GCM` + // + // Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry + // with sealing operations. + // /// # Errors /// `error::Unspecified` when ciphertext is invalid. In this case, `in_out` may have been /// overwritten in an unspecified way. @@ -280,14 +280,14 @@ impl OpeningKey { /// /// This reassembly be accomplished with three calls to `open_within()`. /// - /// # FIPS - /// Use this method with one of the following algorithms: - /// * `AES_128_GCM` - /// * `AES_256_GCM` - /// - /// Prefer [`RandomizedNonceKey::open_within`], as it provides API symmetry - /// with sealing operations. - /// + // # FIPS + // Use this method with one of the following algorithms: + // * `AES_128_GCM` + // * `AES_256_GCM` + // + // Prefer [`RandomizedNonceKey::open_within`], as it provides API symmetry + // with sealing operations. + // /// # Errors /// `error::Unspecified` when ciphertext is invalid. In this case, `in_out` may have been /// overwritten in an unspecified way. @@ -360,7 +360,6 @@ fn open_within<'in_out, A: AsRef<[u8]>>( /// Intentionally not `Clone` or `Copy` since cloning would allow duplication /// of the nonce sequence. /// -/// # FIPS /// Prefer [`RandomizedNonceKey`] for sealing operations. pub struct SealingKey { key: UnboundKey, @@ -392,11 +391,11 @@ impl Debug for SealingKey { impl SealingKey { /// Deprecated. Renamed to `seal_in_place_append_tag`. /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_append_tag`]. - /// + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_append_tag`]. + // /// # Errors /// See `seal_in_place_append_tag` #[deprecated(note = "Renamed to `seal_in_place_append_tag`.")] @@ -423,11 +422,11 @@ impl SealingKey { /// .map(|tag| in_out.extend(tag.as_ref())) /// ``` /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_append_tag`]. - /// + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_append_tag`]. + // /// # Errors /// `error::Unspecified` when `nonce_sequence` cannot be advanced. #[inline] @@ -463,11 +462,11 @@ impl SealingKey { /// For most protocols, the caller must append the tag to the ciphertext. /// The tag will be `self.algorithm.tag_len()` bytes long. /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_separate_tag`]. - /// + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_separate_tag`]. + // /// # Errors /// `error::Unspecified` when `nonce_sequence` cannot be advanced. #[inline] @@ -688,13 +687,13 @@ impl hkdf::KeyType for &'static Algorithm { /// /// Prefer [`RandomizedNonceKey`] when practical. /// -/// # FIPS -/// The following conditions must be met: -/// * `UnboundKey`'s algorithm is one of: -/// * `AES_128_GCM` -/// * `AES_256_GCM` -/// * Use `open_in_place` or `open_within` only. -/// +// # FIPS +// The following conditions must be met: +// * `UnboundKey`'s algorithm is one of: +// * `AES_128_GCM` +// * `AES_256_GCM` +// * Use `open_in_place` or `open_within` only. +// /// Use [`RandomizedNonceKey`]. pub struct LessSafeKey { key: UnboundKey, @@ -711,14 +710,14 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to open data. /// - /// # FIPS - /// Use this method with one of the following algorithms: - /// * `AES_128_GCM` - /// * `AES_256_GCM` - /// - /// Prefer [`RandomizedNonceKey::open_in_place`] as it provides API symmetry with - /// sealing operations. - /// + // # FIPS + // Use this method with one of the following algorithms: + // * `AES_128_GCM` + // * `AES_256_GCM` + // + // Prefer [`RandomizedNonceKey::open_in_place`] as it provides API symmetry with + // sealing operations. + // /// # Errors /// `error::Unspecified` when ciphertext is invalid. #[inline] @@ -738,14 +737,14 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to open data. /// - /// # FIPS - /// Use this method with one of the following algorithms: - /// * `AES_128_GCM` - /// * `AES_256_GCM` - /// - /// Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry - /// with sealing operations. - /// + // # FIPS + // Use this method with one of the following algorithms: + // * `AES_128_GCM` + // * `AES_256_GCM` + // + // Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry + // with sealing operations. + // /// # Errors /// `error::Unspecified` when ciphertext is invalid. #[inline] @@ -771,10 +770,10 @@ impl LessSafeKey { /// Deprecated. Renamed to `seal_in_place_append_tag()`. /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_append_tag`]. + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_append_tag`]. #[deprecated(note = "Renamed to `seal_in_place_append_tag`.")] #[inline] #[allow(clippy::missing_errors_doc)] @@ -796,11 +795,11 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to seal data. /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_append_tag`]. - /// + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_append_tag`]. + // /// # Errors /// `error::Unspecified` if encryption operation fails. #[inline] @@ -830,11 +829,11 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to seal data. /// - /// # FIPS - /// This method must not be used. - /// - /// See [`RandomizedNonceKey::seal_in_place_separate_tag`]. - /// + // # FIPS + // This method must not be used. + // + // See [`RandomizedNonceKey::seal_in_place_separate_tag`]. + // /// # Errors /// `error::Unspecified` if encryption operation fails. #[inline] @@ -872,10 +871,10 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to seal data. /// - /// # FIPS - /// This method must not be used. - /// - /// # Errors + // # FIPS + // This method must not be used. + // + // # Errors /// `error::Unspecified` if encryption operation fails. #[inline] #[allow(clippy::needless_pass_by_value)] @@ -925,7 +924,6 @@ impl Debug for LessSafeKey { /// * `AES_128_GCM` /// * `AES_256_GCM` /// -/// # FIPS /// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. pub struct RandomizedNonceKey { ctx: AeadCtx, @@ -1105,7 +1103,6 @@ pub enum TlsProtocolId { /// * `AES_128_GCM` /// * `AES_256_GCM` /// -/// # FIPS /// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. pub struct TlsRecordSealingKey { // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! @@ -1243,7 +1240,6 @@ impl TlsRecordSealingKey { /// * `AES_128_GCM` /// * `AES_256_GCM` /// -/// # FIPS /// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. pub struct TlsRecordOpeningKey { // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! diff --git a/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs b/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs index c4969f46cd3..a39a4c949fa 100644 --- a/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs +++ b/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs @@ -51,9 +51,9 @@ impl SealingKey { /// `padding_length||payload||random padding`. It will be overwritten by /// `encrypted_packet_length||ciphertext`, where `encrypted_packet_length` /// is encrypted with `K_1` and `ciphertext` is encrypted by `K_2`. - /// - /// # FIPS - /// This method must not be used. + // + // # FIPS + // This method must not be used. #[inline] pub fn seal_in_place( &self, @@ -98,9 +98,9 @@ impl OpeningKey { /// /// Importantly, the result won't be authenticated until `open_in_place` is /// called. - /// - /// # FIPS - /// This method must not be used. + // + // # FIPS + // This method must not be used. #[inline] #[must_use] pub fn decrypt_packet_length( @@ -128,9 +128,9 @@ impl OpeningKey { /// /// # Errors /// `error::Unspecified` when ciphertext is invalid - /// - /// # FIPS - /// This method must not be used. + // + // # FIPS + // This method must not be used. #[inline] pub fn open_in_place<'a>( &self, diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index c23b66388b1..88308e127ec 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -210,12 +210,12 @@ impl EphemeralPrivateKey { /// # *ring* Compatibility /// Our implementation ignores the `SecureRandom` parameter. /// - /// # FIPS - /// Use this function with one of the following algorithms: - /// * `ECDH_P256` - /// * `ECDH_P384` - /// * `ECDH_P521` - /// + // # FIPS + // Use this function with one of the following algorithms: + // * `ECDH_P256` + // * `ECDH_P384` + // * `ECDH_P521` + // /// # Errors /// `error::Unspecified` when operation fails due to internal error. pub fn generate(alg: &'static Algorithm, _rng: &dyn SecureRandom) -> Result { @@ -502,12 +502,12 @@ impl> UnparsedPublicKey { /// key material from the key agreement operation and then returns what `kdf` /// returns. /// -/// # FIPS -/// Use this function with one of the following key algorithms: -/// * `ECDH_P256` -/// * `ECDH_P384` -/// * `ECDH_P521` -/// +// # FIPS +// Use this function with one of the following key algorithms: +// * `ECDH_P256` +// * `ECDH_P384` +// * `ECDH_P521` +// /// # Errors /// `error_value` on internal failure. #[inline] diff --git a/aws-lc-rs/src/cipher.rs b/aws-lc-rs/src/cipher.rs index 1bcf8735fb3..a3d445cb1a4 100644 --- a/aws-lc-rs/src/cipher.rs +++ b/aws-lc-rs/src/cipher.rs @@ -419,11 +419,11 @@ impl PaddedBlockEncryptingKey { /// Constructs a new `PaddedBlockEncryptingKey` cipher with chaining block cipher (CBC) mode. /// Plaintext data is padded following the PKCS#7 scheme. /// - /// # FIPS - /// Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: - /// * `AES_128` - /// * `AES_256` - /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // /// # Errors /// * [`Unspecified`]: Returned if there is an error cosntructing a `PaddedBlockEncryptingKey`. pub fn cbc_pkcs7(key: UnboundCipherKey) -> Result { @@ -512,11 +512,11 @@ impl PaddedBlockDecryptingKey { /// Constructs a new `PaddedBlockDecryptingKey` cipher with chaining block cipher (CBC) mode. /// Decrypted data is unpadded following the PKCS#7 scheme. /// - /// # FIPS - /// Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: - /// * `AES_128` - /// * `AES_256` - /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // /// # Errors /// * [`Unspecified`]: Returned if there is an error constructing the `PaddedBlockDecryptingKey`. pub fn cbc_pkcs7(key: UnboundCipherKey) -> Result { @@ -589,11 +589,11 @@ pub struct EncryptingKey { impl EncryptingKey { /// Constructs an `EncryptingKey` operating in counter (CTR) mode using the provided key. /// - /// # FIPS - /// Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: - /// * `AES_128` - /// * `AES_256` - /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // /// # Errors /// * [`Unspecified`]: Returned if there is an error constructing the `EncryptingKey`. pub fn ctr(key: UnboundCipherKey) -> Result { @@ -668,11 +668,11 @@ pub struct DecryptingKey { impl DecryptingKey { /// Constructs a cipher decrypting key operating in counter (CTR) mode using the provided key and context. /// - /// # FIPS - /// Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: - /// * `AES_128` - /// * `AES_256` - /// + // # FIPS + // Use this function with an `UnboundCipherKey` constructed with one of the following algorithms: + // * `AES_128` + // * `AES_256` + // /// # Errors /// * [`Unspecified`]: Returned if there is an error during decryption. pub fn ctr(key: UnboundCipherKey) -> Result { diff --git a/aws-lc-rs/src/digest.rs b/aws-lc-rs/src/digest.rs index 8c716ae05fb..901487b67c2 100644 --- a/aws-lc-rs/src/digest.rs +++ b/aws-lc-rs/src/digest.rs @@ -49,15 +49,15 @@ use std::mem::MaybeUninit; use std::os::raw::c_uint; /// A context for multi-step (Init-Update-Finish) digest calculations. -/// -/// # FIPS -/// Context must be used with one of the following algorithms: -/// * `SHA1_FOR_LEGACY_USE_ONLY` -/// * `SHA224` -/// * `SHA256` -/// * `SHA384` -/// * `SHA512` -/// * `SHA512_256` +// +// # FIPS +// Context must be used with one of the following algorithms: +// * `SHA1_FOR_LEGACY_USE_ONLY` +// * `SHA224` +// * `SHA256` +// * `SHA384` +// * `SHA512` +// * `SHA512_256` #[derive(Clone)] pub struct Context { /// The context's algorithm. @@ -168,15 +168,15 @@ impl Context { /// Returns the digest of `data` using the given digest algorithm. /// -/// # FIPS -/// This function must only be used with one of the following algorithms: -/// * `SHA1_FOR_LEGACY_USE_ONLY` -/// * `SHA224` -/// * `SHA256` -/// * `SHA384` -/// * `SHA512` -/// * `SHA512_256` -/// +// # FIPS +// This function must only be used with one of the following algorithms: +// * `SHA1_FOR_LEGACY_USE_ONLY` +// * `SHA224` +// * `SHA256` +// * `SHA384` +// * `SHA512` +// * `SHA512_256` +// /// # Examples: /// /// ``` diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index 15fc5d69b29..05f37f0ad11 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -146,11 +146,11 @@ impl EcdsaKeyPair { /// /// # Errors /// `error::Unspecified` on internal error. - /// - /// # FIPS - /// The following conditions must be met: - /// * NIST Elliptic Curves: P256, P384, P521 - /// * Digest Algorithms: SHA256, SHA384, SHA512 + // + // # FIPS + // The following conditions must be met: + // * NIST Elliptic Curves: P256, P384, P521 + // * Digest Algorithms: SHA256, SHA384, SHA512 #[inline] pub fn sign(&self, _rng: &dyn SecureRandom, message: &[u8]) -> Result { let mut md_ctx = DigestContext::new_uninit(); diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 680bdbbb3b6..e58049ac381 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -153,9 +153,9 @@ impl Ed25519KeyPair { /// /// Our implementation ignores the `SecureRandom` parameter. /// - /// # FIPS - /// This function must not be used. - /// + // # FIPS + // This function must not be used. + // /// # Errors /// `error::Unspecified` if `rng` cannot provide enough bits or if there's an internal error. pub fn generate_pkcs8(_rng: &dyn SecureRandom) -> Result { @@ -172,9 +172,9 @@ impl Ed25519KeyPair { /// # *ring* Compatibility /// Our implementation ignores the `SecureRandom` parameter. /// - /// # FIPS - /// This function must not be used. - /// + // # FIPS + // This function must not be used. + // /// # Errors /// `error::Unspecified` if `rng` cannot provide enough bits or if there's an internal error. pub fn generate_pkcs8v1(_rng: &dyn SecureRandom) -> Result { @@ -292,9 +292,9 @@ impl Ed25519KeyPair { /// Returns the signature of the message msg. /// - /// # FIPS - /// This method must not be used. - /// + // # FIPS + // This method must not be used. + // /// # Panics /// Panics if the message is unable to be signed #[inline] diff --git a/aws-lc-rs/src/hkdf.rs b/aws-lc-rs/src/hkdf.rs index c72273b72f7..c12a80820ef 100644 --- a/aws-lc-rs/src/hkdf.rs +++ b/aws-lc-rs/src/hkdf.rs @@ -119,15 +119,15 @@ impl Salt { /// Constructing a `Salt` is relatively expensive so it is good to reuse a /// `Salt` object instead of re-constructing `Salt`s with the same value. /// - /// # FIPS - /// The following conditions must be met: - /// * Algorithm is one of the following: - /// * `HKDF_SHA1_FOR_LEGACY_USE_ONLY` - /// * `HKDF_SHA256` - /// * `HKDF_SHA384` - /// * `HKDF_SHA512` - /// * `value.len() > 0` is true - /// + // # FIPS + // The following conditions must be met: + // * Algorithm is one of the following: + // * `HKDF_SHA1_FOR_LEGACY_USE_ONLY` + // * `HKDF_SHA256` + // * `HKDF_SHA384` + // * `HKDF_SHA512` + // * `value.len() > 0` is true + // /// # Panics /// `new` panics if the salt length exceeds the limit #[must_use] @@ -313,11 +313,11 @@ impl Prk { /// intentionally wants to leak the PRK secret, e.g. to implement /// `SSLKEYLOGFILE` functionality. /// - /// # FIPS - /// This function must not be used. - /// - /// See [`Salt::extract`]. - /// + // # FIPS + // This function must not be used. + // + // See [`Salt::extract`]. + // /// # Panics /// Panics if the given Prk length exceeds the limit #[must_use] @@ -345,11 +345,11 @@ impl Prk { /// # Errors /// `error::Unspecified` if (and only if) `len` is too large. /// - /// # FIPS - /// The following conditions must be met: - /// * `Prk` must be constructed using `Salt::extract` prior to calling - /// this method. - /// * After concatination of the `info` slices the resulting `[u8].len() > 0` is true. + // # FIPS + // The following conditions must be met: + // * `Prk` must be constructed using `Salt::extract` prior to calling + // this method. + // * After concatination of the `info` slices the resulting `[u8].len() > 0` is true. #[inline] pub fn expand<'a, L: KeyType>( &'a self, @@ -426,17 +426,17 @@ impl Okm<'_, L> { /// Fills `out` with the output of the HKDF-Expand operation for the given /// inputs. /// - /// # FIPS - /// The following conditions must be met: - /// * Algorithm is one of the following: - /// * `HKDF_SHA1_FOR_LEGACY_USE_ONLY` - /// * `HKDF_SHA256` - /// * `HKDF_SHA384` - /// * `HKDF_SHA512` - /// * The [`Okm`] was constructed from a [`Prk`] created with [`Salt::extract`] and: - /// * The `value.len()` passed to [`Salt::new`] was non-zero. - /// * The `info_len` from [`Prk::expand`] was non-zero. - /// + // # FIPS + // The following conditions must be met: + // * Algorithm is one of the following: + // * `HKDF_SHA1_FOR_LEGACY_USE_ONLY` + // * `HKDF_SHA256` + // * `HKDF_SHA384` + // * `HKDF_SHA512` + // * The [`Okm`] was constructed from a [`Prk`] created with [`Salt::extract`] and: + // * The `value.len()` passed to [`Salt::new`] was non-zero. + // * The `info_len` from [`Prk::expand`] was non-zero. + // /// # Errors /// `error::Unspecified` if the requested output length differs from the length specified by /// `L: KeyType`. diff --git a/aws-lc-rs/src/hmac.rs b/aws-lc-rs/src/hmac.rs index 6eb213551ea..ea937ec97e8 100644 --- a/aws-lc-rs/src/hmac.rs +++ b/aws-lc-rs/src/hmac.rs @@ -200,14 +200,14 @@ impl Clone for LcHmacCtx { } /// A key to use for HMAC signing. -/// -/// # FIPS -/// Use this type with one of the following algorithms: -/// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` -/// * `HMAC_SHA224` -/// * `HMAC_SHA256` -/// * `HMAC_SHA384` -/// * `HMAC_SHA512` +// +// # FIPS +// Use this type with one of the following algorithms: +// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` +// * `HMAC_SHA224` +// * `HMAC_SHA256` +// * `HMAC_SHA384` +// * `HMAC_SHA512` #[derive(Clone)] pub struct Key { pub(crate) algorithm: Algorithm, @@ -236,16 +236,17 @@ impl Key { /// /// [RFC 2104 Section 3]: https://tools.ietf.org/html/rfc2104#section-3 /// + // + // # FIPS + // Use this function with one of the following algorithms: + // * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` + // * `HMAC_SHA224` + // * `HMAC_SHA256` + // * `HMAC_SHA384` + // * `HMAC_SHA512` + // /// # Errors /// `error::Unspecified` is the `rng` fails. - /// - /// # FIPS - /// Use this function with one of the following algorithms: - /// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` - /// * `HMAC_SHA224` - /// * `HMAC_SHA256` - /// * `HMAC_SHA384` - /// * `HMAC_SHA512` pub fn generate( algorithm: Algorithm, rng: &dyn crate::rand::SecureRandom, @@ -401,14 +402,14 @@ impl Context { /// the return value of `sign` to a tag. Use `verify` for verification /// instead. /// - /// # FIPS - /// Use this method with one of the following algorithms: - /// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` - /// * `HMAC_SHA224` - /// * `HMAC_SHA256` - /// * `HMAC_SHA384` - /// * `HMAC_SHA512` - /// + // # FIPS + // Use this method with one of the following algorithms: + // * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` + // * `HMAC_SHA224` + // * `HMAC_SHA256` + // * `HMAC_SHA384` + // * `HMAC_SHA512` + // /// # Panics /// Panics if the HMAC calculation cannot be finalized #[inline] @@ -442,14 +443,14 @@ impl Context { /// /// It is generally not safe to implement HMAC verification by comparing the /// return value of `sign` to a tag. Use `verify` for verification instead. -/// -/// # FIPS -/// Use this function with one of the following algorithms: -/// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` -/// * `HMAC_SHA224` -/// * `HMAC_SHA256` -/// * `HMAC_SHA384` -/// * `HMAC_SHA512` +// +// # FIPS +// Use this function with one of the following algorithms: +// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` +// * `HMAC_SHA224` +// * `HMAC_SHA256` +// * `HMAC_SHA384` +// * `HMAC_SHA512` #[inline] #[must_use] pub fn sign(key: &Key, data: &[u8]) -> Tag { @@ -468,14 +469,14 @@ pub fn sign(key: &Key, data: &[u8]) -> Tag { /// /// # Errors /// `error::Unspecified` if the inputs are not verified. -/// -/// # FIPS -/// Use this function with one of the following algorithms: -/// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` -/// * `HMAC_SHA224` -/// * `HMAC_SHA256` -/// * `HMAC_SHA384` -/// * `HMAC_SHA512` +// +// # FIPS +// Use this function with one of the following algorithms: +// * `HMAC_SHA1_FOR_LEGACY_USE_ONLY` +// * `HMAC_SHA224` +// * `HMAC_SHA256` +// * `HMAC_SHA384` +// * `HMAC_SHA512` #[inline] pub fn verify(key: &Key, data: &[u8], tag: &[u8]) -> Result<(), Unspecified> { constant_time::verify_slices_are_equal(sign(key, data).as_ref(), tag) diff --git a/aws-lc-rs/src/pbkdf2.rs b/aws-lc-rs/src/pbkdf2.rs index 599d369a1f2..cba6c4bc156 100644 --- a/aws-lc-rs/src/pbkdf2.rs +++ b/aws-lc-rs/src/pbkdf2.rs @@ -166,17 +166,17 @@ const MAX_USIZE32: u64 = u32::MAX as u64; /// /// `derive` panics if `out.len()` is larger than (2**32 - 1) * the digest /// algorithm's output length, per the PBKDF2 specification. -/// -/// # FIPS -/// The following conditions must be met: -/// * Algorithm is one of the following: -/// * `PBKDF2_HMAC_SHA1` -/// * `PBKDF2_HMAC_SHA256` -/// * `PBKDF2_HMAC_SHA384` -/// * `PBKDF2_HMAC_SHA512` -/// * `salt.len()` >= 16 -/// * `sercet.len()` >= 14 -/// * `iterations` >= 1000 +// +// # FIPS +// The following conditions must be met: +// * Algorithm is one of the following: +// * `PBKDF2_HMAC_SHA1` +// * `PBKDF2_HMAC_SHA256` +// * `PBKDF2_HMAC_SHA384` +// * `PBKDF2_HMAC_SHA512` +// * `salt.len()` >= 16 +// * `sercet.len()` >= 14 +// * `iterations` >= 1000 #[inline] pub fn derive( algorithm: Algorithm, @@ -241,17 +241,17 @@ fn try_derive( /// /// `verify` panics if `previously_derived.len()` is larger than (2**32 - 1) * the digest /// algorithm's output length, per the PBKDF2 specification. -/// -/// # FIPS -/// The following conditions must be met: -/// * Algorithm is one of the following: -/// * `PBKDF2_HMAC_SHA1` -/// * `PBKDF2_HMAC_SHA256` -/// * `PBKDF2_HMAC_SHA384` -/// * `PBKDF2_HMAC_SHA512` -/// * `salt.len()` >= 16 -/// * `secret.len()` >= 14 -/// * `iterations` >= 1000 +// +// # FIPS +// The following conditions must be met: +// * Algorithm is one of the following: +// * `PBKDF2_HMAC_SHA1` +// * `PBKDF2_HMAC_SHA256` +// * `PBKDF2_HMAC_SHA384` +// * `PBKDF2_HMAC_SHA512` +// * `salt.len()` >= 16 +// * `secret.len()` >= 14 +// * `iterations` >= 1000 #[inline] pub fn verify( algorithm: Algorithm, diff --git a/aws-lc-rs/src/rand.rs b/aws-lc-rs/src/rand.rs index 8a93ca5dfe6..ecda7d0767c 100644 --- a/aws-lc-rs/src/rand.rs +++ b/aws-lc-rs/src/rand.rs @@ -121,9 +121,9 @@ impl RandomlyConstructable for T where T: sealed::RandomlyConstructable {} /// underlying *AWS-LC* libcrypto. /// /// A single `SystemRandom` may be shared across multiple threads safely. -/// -/// # FIPS -/// Use this implementation for retrieving random bytes. +// +// # FIPS +// Use this implementation for retrieving random bytes. #[derive(Clone, Debug)] pub struct SystemRandom(()); @@ -153,9 +153,9 @@ impl sealed::SecureRandom for SystemRandom { /// Fills `dest` with random bytes. /// -/// # FIPS -/// Use this for retrieving random bytes or [`SystemRandom`]. -/// +// # FIPS +// Use this for retrieving random bytes or [`SystemRandom`]. +// /// # Errors /// `error::Unspecified` if unable to fill `dest`. pub fn fill(dest: &mut [u8]) -> Result<(), error::Unspecified> { diff --git a/aws-lc-rs/src/rsa.rs b/aws-lc-rs/src/rsa.rs index be6c0138ec1..01acfbd1a5a 100644 --- a/aws-lc-rs/src/rsa.rs +++ b/aws-lc-rs/src/rsa.rs @@ -227,11 +227,11 @@ impl RsaKeyPair { /// # *ring* Compatibility /// Our implementation ignores the `SecureRandom` parameter. /// - /// # FIPS - /// The following conditions must be met: - /// * RSA Key Sizes: 2048, 3072, 4096 - /// * Digest Algorithms: SHA256, SHA384, SHA512 - /// + // # FIPS + // The following conditions must be met: + // * RSA Key Sizes: 2048, 3072, 4096 + // * Digest Algorithms: SHA256, SHA384, SHA512 + // /// # Errors /// `error::Unspecified` on error. /// With "fips" feature enabled, errors if digest length is greater than `u32::MAX`. diff --git a/aws-lc-rs/src/signature.rs b/aws-lc-rs/src/signature.rs index bfefd420a87..0276789ed3b 100644 --- a/aws-lc-rs/src/signature.rs +++ b/aws-lc-rs/src/signature.rs @@ -305,12 +305,12 @@ pub trait VerificationAlgorithm: Debug + Sync + sealed::Sealed { /// Verify the signature `signature` of message `msg` with the public key /// `public_key`. /// - /// # FIPS - /// The following conditions must be met: - /// * RSA Key Sizes: 1024, 2048, 3072, 4096 - /// * NIST Elliptic Curves: P256, P384, P521 - /// * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 - /// + // # FIPS + // The following conditions must be met: + // * RSA Key Sizes: 1024, 2048, 3072, 4096 + // * NIST Elliptic Curves: P256, P384, P521 + // * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 + // /// # Errors /// `error::Unspecified` if inputs not verified. #[cfg(feature = "ring-sig-verify")] @@ -325,12 +325,12 @@ pub trait VerificationAlgorithm: Debug + Sync + sealed::Sealed { /// Verify the signature `signature` of message `msg` with the public key /// `public_key`. /// - /// # FIPS - /// The following conditions must be met: - /// * RSA Key Sizes: 1024, 2048, 3072, 4096 - /// * NIST Elliptic Curves: P256, P384, P521 - /// * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 - /// + // # FIPS + // The following conditions must be met: + // * RSA Key Sizes: 1024, 2048, 3072, 4096 + // * NIST Elliptic Curves: P256, P384, P521 + // * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 + // /// # Errors /// `error::Unspecified` if inputs not verified. fn verify_sig( @@ -374,12 +374,12 @@ impl> UnparsedPublicKey { /// /// See the [`crate::signature`] module-level documentation for examples. /// - /// # FIPS - /// The following conditions must be met: - /// * RSA Key Sizes: 1024, 2048, 3072, 4096 - /// * NIST Elliptic Curves: P256, P384, P521 - /// * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 - /// + // # FIPS + // The following conditions must be met: + // * RSA Key Sizes: 1024, 2048, 3072, 4096 + // * NIST Elliptic Curves: P256, P384, P521 + // * Digest Algorithms: SHA1, SHA256, SHA384, SHA512 + // /// # Errors /// `error::Unspecified` if inputs not verified. #[inline] From 3e6d73e1aaf3ea57a7a228268e5516d4fa29f0ef Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Thu, 19 Oct 2023 20:53:50 +0000 Subject: [PATCH 02/11] Remove open_within from new types --- aws-lc-rs/src/aead.rs | 56 ++----------------------------------------- 1 file changed, 2 insertions(+), 54 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index 4fc9e022875..c59abd8af82 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -971,36 +971,7 @@ impl RandomizedNonceKey { where A: AsRef<[u8]>, { - self.open_within(nonce, aad, in_out, 0..) - } - - /// Authenticates and decrypts (“opens”) data in place, with a shift. - /// - /// `aad` is the additional authenticated data (AAD), if any. - /// - /// See [`OpeningKey::open_within`] for details on `ciphertext_and_tag` argument usage. - /// - /// # Errors - /// `error::Unspecified` when ciphertext is invalid. - #[inline] - pub fn open_within<'in_out, A>( - &self, - nonce: Nonce, - aad: Aad, - in_out: &'in_out mut [u8], - ciphertext_and_tag: RangeFrom, - ) -> Result<&'in_out mut [u8], Unspecified> - where - A: AsRef<[u8]>, - { - open_within( - self.algorithm, - &self.ctx, - nonce, - aad, - in_out, - ciphertext_and_tag, - ) + open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) } /// Encrypts and signs (“seals”) data in place, appending the tag to the @@ -1306,34 +1277,11 @@ impl TlsRecordOpeningKey { aad: Aad, in_out: &'in_out mut [u8], ) -> Result<&'in_out mut [u8], Unspecified> - where - A: AsRef<[u8]>, - { - self.open_within(nonce, aad, in_out, 0..) - } - - /// Accepts a Noce and Aad construction that is unique for this TLS record - /// opening operation. - /// - /// `nonce` must be unique for every use of the key to open data. - /// - /// See [`OpeningKey::open_within`] for details on `ciphertext_and_tag` argument usage. - /// - /// # Errors - /// `error::Unspecified` when ciphertext is invalid. - #[inline] - pub fn open_within<'in_out, A>( - &self, - nonce: Nonce, - aad: Aad, - in_out: &'in_out mut [u8], - ciphertext_and_tag: RangeFrom, - ) -> Result<&'in_out mut [u8], Unspecified> where A: AsRef<[u8]>, { let ctx = self.ctx.lock().map_err(|_| Unspecified)?; - open_within(self.algorithm, &ctx, nonce, aad, in_out, ciphertext_and_tag) + open_within(self.algorithm, &ctx, nonce, aad, in_out, 0..) } /// The key's AEAD algorithm. From 4ebfbc1fb3e5fe457fa96f83d3c35ab693ee2650 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Thu, 19 Oct 2023 20:56:05 +0000 Subject: [PATCH 03/11] Remove mutex from TlsRecordOpeningKey, TlsRecordSealingKey --- aws-lc-rs/src/aead.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index c59abd8af82..7549fe7d6db 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -1137,7 +1137,7 @@ impl TlsRecordSealingKey { #[inline] #[allow(clippy::needless_pass_by_value)] pub fn seal_in_place_append_tag( - &self, + &mut self, nonce: Nonce, aad: Aad, in_out: &mut InOut, @@ -1176,7 +1176,7 @@ impl TlsRecordSealingKey { #[inline] #[allow(clippy::needless_pass_by_value)] pub fn seal_in_place_separate_tag( - &self, + &mut self, nonce: Nonce, aad: Aad, in_out: &mut [u8], @@ -1205,7 +1205,6 @@ impl TlsRecordSealingKey { /// AEAD Encryption key used for TLS protocol record encryption. /// /// This type encapsulates decryption operations for TLS AEAD algorithms. -/// It validates that the provided nonce values are monotonically increasing for each invocation. /// /// The following algorithms are supported: /// * `AES_128_GCM` @@ -1217,7 +1216,7 @@ pub struct TlsRecordOpeningKey { // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, // or force this type to !Sync. Since this is an implementation detail of AWS-LC // we have optex to manage this behavior internally. - ctx: Mutex, + ctx: AeadCtx, algorithm: &'static Algorithm, } @@ -1232,7 +1231,7 @@ impl TlsRecordOpeningKey { protocol: TlsProtocolId, key_bytes: &[u8], ) -> Result { - let ctx = Mutex::new(match (algorithm.id, protocol) { + let ctx = match (algorithm.id, protocol) { (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( key_bytes, algorithm.tag_len(), @@ -1259,7 +1258,7 @@ impl TlsRecordOpeningKey { | AlgorithmID::CHACHA20_POLY1305, _, ) => Err(Unspecified), - }?); + }?; Ok(Self { ctx, algorithm }) } @@ -1280,8 +1279,7 @@ impl TlsRecordOpeningKey { where A: AsRef<[u8]>, { - let ctx = self.ctx.lock().map_err(|_| Unspecified)?; - open_within(self.algorithm, &ctx, nonce, aad, in_out, 0..) + open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) } /// The key's AEAD algorithm. @@ -1831,7 +1829,7 @@ mod tests { paste! { #[test] fn []() { - let sealing_key = + let mut sealing_key = TlsRecordSealingKey::new($alg, $proto, $key).unwrap(); let opening_key = From 6ac2cfcf3e0ae2ca0bb442c63beb818540d73743 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 18:28:24 +0000 Subject: [PATCH 04/11] More documentation tweaks --- aws-lc-rs/src/aead.rs | 48 +++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index 7549fe7d6db..2b067fcef65 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -176,8 +176,7 @@ pub trait BoundKey: Debug { /// Intentionally not `Clone` or `Copy` since cloning would allow duplication /// of the nonce sequence. /// -// # FIPS -// Prefer [`RandomizedNonceKey`] for opening operations. +/// Prefer [`RandomizedNonceKey`] for opening operations. pub struct OpeningKey { key: UnboundKey, nonce_sequence: N, @@ -215,14 +214,13 @@ impl OpeningKey { /// has been overwritten by the plaintext; `plaintext` will refer to the /// plaintext without the tag. /// + /// Prefer [`RandomizedNonceKey::open_in_place`]. + /// // # FIPS // Use this method with one of the following algorithms: // * `AES_128_GCM` // * `AES_256_GCM` // - // Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry - // with sealing operations. - // /// # Errors /// `error::Unspecified` when ciphertext is invalid. In this case, `in_out` may have been /// overwritten in an unspecified way. @@ -280,14 +278,13 @@ impl OpeningKey { /// /// This reassembly be accomplished with three calls to `open_within()`. /// + /// Prefer [`RandomizedNonceKey::open_within`]. + /// // # FIPS // Use this method with one of the following algorithms: // * `AES_128_GCM` // * `AES_256_GCM` // - // Prefer [`RandomizedNonceKey::open_within`], as it provides API symmetry - // with sealing operations. - // /// # Errors /// `error::Unspecified` when ciphertext is invalid. In this case, `in_out` may have been /// overwritten in an unspecified way. @@ -390,12 +387,12 @@ impl Debug for SealingKey { impl SealingKey { /// Deprecated. Renamed to `seal_in_place_append_tag`. + /// + /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_append_tag`]. - // /// # Errors /// See `seal_in_place_append_tag` #[deprecated(note = "Renamed to `seal_in_place_append_tag`.")] @@ -421,12 +418,12 @@ impl SealingKey { /// key.seal_in_place_separate_tag(aad, in_out.as_mut()) /// .map(|tag| in_out.extend(tag.as_ref())) /// ``` + /// + /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_append_tag`]. - // /// # Errors /// `error::Unspecified` when `nonce_sequence` cannot be advanced. #[inline] @@ -462,11 +459,11 @@ impl SealingKey { /// For most protocols, the caller must append the tag to the ciphertext. /// The tag will be `self.algorithm.tag_len()` bytes long. /// + /// Prefer [`RandomizedNonceKey::seal_in_place_separate_tag`]. + /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_separate_tag`]. - // /// # Errors /// `error::Unspecified` when `nonce_sequence` cannot be advanced. #[inline] @@ -693,8 +690,6 @@ impl hkdf::KeyType for &'static Algorithm { // * `AES_128_GCM` // * `AES_256_GCM` // * Use `open_in_place` or `open_within` only. -// -/// Use [`RandomizedNonceKey`]. pub struct LessSafeKey { key: UnboundKey, } @@ -710,14 +705,13 @@ impl LessSafeKey { /// /// `nonce` must be unique for every use of the key to open data. /// + /// Prefer [`RandomizedNonceKey::open_in_place`]. + /// // # FIPS // Use this method with one of the following algorithms: // * `AES_128_GCM` // * `AES_256_GCM` // - // Prefer [`RandomizedNonceKey::open_in_place`] as it provides API symmetry with - // sealing operations. - // /// # Errors /// `error::Unspecified` when ciphertext is invalid. #[inline] @@ -736,15 +730,14 @@ impl LessSafeKey { /// Like [`OpeningKey::open_within()`], except it accepts an arbitrary nonce. /// /// `nonce` must be unique for every use of the key to open data. + /// + /// Prefer [`RandomizedNonceKey::open_in_place`]. /// // # FIPS // Use this method with one of the following algorithms: // * `AES_128_GCM` // * `AES_256_GCM` // - // Prefer [`RandomizedNonceKey::open_in_place`], as it provides API symmetry - // with sealing operations. - // /// # Errors /// `error::Unspecified` when ciphertext is invalid. #[inline] @@ -770,10 +763,11 @@ impl LessSafeKey { /// Deprecated. Renamed to `seal_in_place_append_tag()`. /// + /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. + /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_append_tag`]. #[deprecated(note = "Renamed to `seal_in_place_append_tag`.")] #[inline] #[allow(clippy::missing_errors_doc)] @@ -794,12 +788,12 @@ impl LessSafeKey { /// arbitrary nonce. /// /// `nonce` must be unique for every use of the key to seal data. + /// + /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_append_tag`]. - // /// # Errors /// `error::Unspecified` if encryption operation fails. #[inline] @@ -828,12 +822,12 @@ impl LessSafeKey { /// arbitrary nonce. /// /// `nonce` must be unique for every use of the key to seal data. + /// + /// Prefer [`RandomizedNonceKey::seal_in_place_separate_tag`]. /// // # FIPS // This method must not be used. // - // See [`RandomizedNonceKey::seal_in_place_separate_tag`]. - // /// # Errors /// `error::Unspecified` if encryption operation fails. #[inline] From 4866916d2a5c9d559b20a1acd9f7626226c45e86 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 18:32:39 +0000 Subject: [PATCH 05/11] Remove leftover Mutex from TlsRecordSealingKey --- aws-lc-rs/src/aead.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index 2b067fcef65..e3552ba79e5 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -115,7 +115,7 @@ //! ``` use crate::{derive_debug_via_id, fips::indicator_check, hkdf, iv::FixedLength}; -use std::{fmt::Debug, ptr::null, sync::Mutex}; +use std::{fmt::Debug, ptr::null}; use crate::error::Unspecified; use aead_ctx::AeadCtx; @@ -387,7 +387,7 @@ impl Debug for SealingKey { impl SealingKey { /// Deprecated. Renamed to `seal_in_place_append_tag`. - /// + /// /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS @@ -418,7 +418,7 @@ impl SealingKey { /// key.seal_in_place_separate_tag(aad, in_out.as_mut()) /// .map(|tag| in_out.extend(tag.as_ref())) /// ``` - /// + /// /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS @@ -460,7 +460,7 @@ impl SealingKey { /// The tag will be `self.algorithm.tag_len()` bytes long. /// /// Prefer [`RandomizedNonceKey::seal_in_place_separate_tag`]. - /// + /// // # FIPS // This method must not be used. // @@ -706,7 +706,7 @@ impl LessSafeKey { /// `nonce` must be unique for every use of the key to open data. /// /// Prefer [`RandomizedNonceKey::open_in_place`]. - /// + /// // # FIPS // Use this method with one of the following algorithms: // * `AES_128_GCM` @@ -730,7 +730,7 @@ impl LessSafeKey { /// Like [`OpeningKey::open_within()`], except it accepts an arbitrary nonce. /// /// `nonce` must be unique for every use of the key to open data. - /// + /// /// Prefer [`RandomizedNonceKey::open_in_place`]. /// // # FIPS @@ -764,7 +764,7 @@ impl LessSafeKey { /// Deprecated. Renamed to `seal_in_place_append_tag()`. /// /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. - /// + /// // # FIPS // This method must not be used. // @@ -788,7 +788,7 @@ impl LessSafeKey { /// arbitrary nonce. /// /// `nonce` must be unique for every use of the key to seal data. - /// + /// /// Prefer [`RandomizedNonceKey::seal_in_place_append_tag`]. /// // # FIPS @@ -822,7 +822,7 @@ impl LessSafeKey { /// arbitrary nonce. /// /// `nonce` must be unique for every use of the key to seal data. - /// + /// /// Prefer [`RandomizedNonceKey::seal_in_place_separate_tag`]. /// // # FIPS @@ -1074,7 +1074,7 @@ pub struct TlsRecordSealingKey { // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, // or force this type to !Sync. Since this is an implementation detail of AWS-LC // we have optex to manage this behavior internally. - ctx: Mutex, + ctx: AeadCtx, algorithm: &'static Algorithm, } @@ -1089,7 +1089,7 @@ impl TlsRecordSealingKey { protocol: TlsProtocolId, key_bytes: &[u8], ) -> Result { - let ctx = Mutex::new(match (algorithm.id, protocol) { + let ctx = match (algorithm.id, protocol) { (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( key_bytes, algorithm.tag_len(), @@ -1116,7 +1116,7 @@ impl TlsRecordSealingKey { | AlgorithmID::CHACHA20_POLY1305, _, ) => Err(Unspecified), - }?); + }?; Ok(Self { ctx, algorithm }) } @@ -1140,10 +1140,9 @@ impl TlsRecordSealingKey { A: AsRef<[u8]>, InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, { - let ctx = self.ctx.lock().map_err(|_| Unspecified)?; seal_in_place_append_tag( self.algorithm, - &ctx, + &self.ctx, Some(nonce), Aad::from(aad.as_ref()), in_out, @@ -1178,10 +1177,9 @@ impl TlsRecordSealingKey { where A: AsRef<[u8]>, { - let ctx = self.ctx.lock().map_err(|_| Unspecified)?; seal_in_place_separate_tag( self.algorithm, - &ctx, + &self.ctx, Some(nonce), Aad::from(aad.as_ref()), in_out, From 36a72e0668d54c070ba798adc7c87cc93dd0e728 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 18:40:26 +0000 Subject: [PATCH 06/11] Move RandomizedNonceKey to seperate module --- aws-lc-rs/src/aead.rs | 201 +-------------------------- aws-lc-rs/src/aead/rand_nonce.rs | 229 +++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 199 deletions(-) create mode 100644 aws-lc-rs/src/aead/rand_nonce.rs diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index e3552ba79e5..d4492ca0ee7 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -133,11 +133,13 @@ mod nonce; pub mod nonce_sequence; mod poly1305; pub mod quic; +mod rand_nonce; pub use self::{ aes_gcm::{AES_128_GCM, AES_128_GCM_SIV, AES_256_GCM, AES_256_GCM_SIV}, chacha::CHACHA20_POLY1305, nonce::{Nonce, NONCE_LEN}, + rand_nonce::RandomizedNonceKey, }; /// A sequences of unique nonces. @@ -910,146 +912,6 @@ impl Debug for LessSafeKey { } } -/// AEAD Cipher key using a randomized nonce. -/// -/// `RandomizedNonceKey` handles generation random nonce values. -/// -/// The following algorithms are supported: -/// * `AES_128_GCM` -/// * `AES_256_GCM` -/// -/// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. -pub struct RandomizedNonceKey { - ctx: AeadCtx, - algorithm: &'static Algorithm, -} - -impl RandomizedNonceKey { - /// New Random Nonce Sequence - /// # Errors - pub fn new(algorithm: &'static Algorithm, key_bytes: &[u8]) -> Result { - let ctx = match algorithm.id { - AlgorithmID::AES_128_GCM => AeadCtx::aes_128_gcm_randnonce( - key_bytes, - algorithm.tag_len(), - algorithm.nonce_len(), - ), - AlgorithmID::AES_256_GCM => AeadCtx::aes_256_gcm_randnonce( - key_bytes, - algorithm.tag_len(), - algorithm.nonce_len(), - ), - AlgorithmID::AES_128_GCM_SIV - | AlgorithmID::AES_256_GCM_SIV - | AlgorithmID::CHACHA20_POLY1305 => return Err(Unspecified), - }?; - Ok(Self { ctx, algorithm }) - } - - /// Authenticates and decrypts (“opens”) data in place. - // - // aad is the additional authenticated data (AAD), if any. - // - // On input, in_out must be the ciphertext followed by the tag. When open_in_place() returns Ok(plaintext), - // the input ciphertext has been overwritten by the plaintext; plaintext will refer to the plaintext without the tag. - /// - /// # Errors - /// `error::Unspecified` when ciphertext is invalid. - #[inline] - pub fn open_in_place<'in_out, A>( - &self, - nonce: Nonce, - aad: Aad, - in_out: &'in_out mut [u8], - ) -> Result<&'in_out mut [u8], Unspecified> - where - A: AsRef<[u8]>, - { - open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) - } - - /// Encrypts and signs (“seals”) data in place, appending the tag to the - /// resulting ciphertext. - /// - /// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to: - /// - /// ```skip - /// key.seal_in_place_separate_tag(aad, in_out.as_mut()) - /// .map(|tag| in_out.extend(tag.as_ref())) - /// ``` - /// - /// The Nonce used for the operation is randomly generated, and returned to the caller. - /// - /// # Errors - /// `error::Unspecified` if encryption operation fails. - #[inline] - #[allow(clippy::needless_pass_by_value)] - pub fn seal_in_place_append_tag<'a, A, InOut>( - &self, - aad: Aad, - in_out: &'a mut InOut, - ) -> Result - where - A: AsRef<[u8]>, - InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, - { - seal_in_place_append_tag( - self.algorithm, - &self.ctx, - None, - Aad::from(aad.as_ref()), - in_out, - ) - } - - /// Encrypts and signs (“seals”) data in place. - /// - /// `aad` is the additional authenticated data (AAD), if any. This is - /// authenticated but not encrypted. The type `A` could be a byte slice - /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec`, etc. - /// If there is no AAD then use `Aad::empty()`. - /// - /// The plaintext is given as the input value of `in_out`. `seal_in_place()` - /// will overwrite the plaintext with the ciphertext and return the tag. - /// For most protocols, the caller must append the tag to the ciphertext. - /// The tag will be `self.algorithm.tag_len()` bytes long. - /// - /// The Nonce used for the operation is randomly generated, and returned to the caller. - /// - /// # Errors - /// `error::Unspecified` if encryption operation fails. - #[inline] - #[allow(clippy::needless_pass_by_value)] - pub fn seal_in_place_separate_tag( - &self, - aad: Aad, - in_out: &mut [u8], - ) -> Result<(Nonce, Tag), Unspecified> - where - A: AsRef<[u8]>, - { - let nonce = if let AlgorithmID::CHACHA20_POLY1305 = self.algorithm.id { - Some(Nonce(FixedLength::::new()?)) - } else { - None - }; - seal_in_place_separate_tag( - self.algorithm, - &self.ctx, - nonce, - Aad::from(aad.as_ref()), - in_out, - ) - } - - /// The key's AEAD algorithm. - #[inline] - #[must_use] - pub fn algorithm(&self) -> &'static Algorithm { - self.algorithm - } -} - /// The Transport Layer Security (TLS) protocol version. pub enum TlsProtocolId { /// TLS 1.2 (RFC 5246) @@ -1728,65 +1590,6 @@ mod tests { assert_eq!(plaintext, in_out[..plaintext.len()]); } - macro_rules! test_randnonce { - ($name:ident, $alg:expr, $key:expr) => { - paste! { - #[test] - fn []() { - assert!(RandomizedNonceKey::new($alg, $key).is_err()); - } - } - }; - ($name:ident, $alg:expr, $key:expr, $expect_tag_len:expr, $expect_nonce_len:expr) => { - paste! { - #[test] - fn []() { - let plaintext = from_hex("00112233445566778899aabbccddeeff").unwrap(); - let rand_nonce_key = - RandomizedNonceKey::new($alg, $key).unwrap(); - - assert_eq!($alg, rand_nonce_key.algorithm()); - assert_eq!(*$expect_tag_len, $alg.tag_len()); - assert_eq!(*$expect_nonce_len, $alg.nonce_len()); - - let mut in_out = Vec::from(plaintext.as_slice()); - - let nonce = rand_nonce_key - .seal_in_place_append_tag(Aad::empty(), &mut in_out) - .unwrap(); - - assert_ne!(plaintext, in_out[..plaintext.len()]); - - rand_nonce_key - .open_in_place(nonce, Aad::empty(), &mut in_out) - .unwrap(); - - assert_eq!(plaintext, in_out[..plaintext.len()]); - - let mut in_out = Vec::from(plaintext.as_slice()); - - let (nonce, tag) = rand_nonce_key - .seal_in_place_separate_tag(Aad::empty(), &mut in_out) - .unwrap(); - - assert_ne!(plaintext, in_out[..plaintext.len()]); - - in_out.extend(tag.as_ref()); - - rand_nonce_key - .open_in_place(nonce, Aad::empty(), &mut in_out) - .unwrap(); - - assert_eq!(plaintext, in_out[..plaintext.len()]); - } - } - }; - } - - test_randnonce!(aes_128_gcm, &AES_128_GCM, TEST_128_BIT_KEY, &16, &12); - test_randnonce!(aes_256_gcm, &AES_256_GCM, TEST_256_BIT_KEY, &16, &12); - test_randnonce!(chacha20_poly1305, &CHACHA20_POLY1305, TEST_256_BIT_KEY); - struct TlsNonceTestCase { nonce: &'static str, expect_err: bool, diff --git a/aws-lc-rs/src/aead/rand_nonce.rs b/aws-lc-rs/src/aead/rand_nonce.rs new file mode 100644 index 00000000000..cc09c5698fa --- /dev/null +++ b/aws-lc-rs/src/aead/rand_nonce.rs @@ -0,0 +1,229 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +use crate::{error::Unspecified, iv::FixedLength}; + +use super::{ + aead_ctx::AeadCtx, open_within, seal_in_place_append_tag, seal_in_place_separate_tag, Aad, + Algorithm, AlgorithmID, Nonce, Tag, NONCE_LEN, +}; + +/// AEAD Cipher key using a randomized nonce. +/// +/// `RandomizedNonceKey` handles generation random nonce values. +/// +/// The following algorithms are supported: +/// * `AES_128_GCM` +/// * `AES_256_GCM` +/// +/// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. +pub struct RandomizedNonceKey { + ctx: AeadCtx, + algorithm: &'static Algorithm, +} + +impl RandomizedNonceKey { + /// New Random Nonce Sequence + /// # Errors + pub fn new(algorithm: &'static Algorithm, key_bytes: &[u8]) -> Result { + let ctx = match algorithm.id { + AlgorithmID::AES_128_GCM => AeadCtx::aes_128_gcm_randnonce( + key_bytes, + algorithm.tag_len(), + algorithm.nonce_len(), + ), + AlgorithmID::AES_256_GCM => AeadCtx::aes_256_gcm_randnonce( + key_bytes, + algorithm.tag_len(), + algorithm.nonce_len(), + ), + AlgorithmID::AES_128_GCM_SIV + | AlgorithmID::AES_256_GCM_SIV + | AlgorithmID::CHACHA20_POLY1305 => return Err(Unspecified), + }?; + Ok(Self { ctx, algorithm }) + } + + /// Authenticates and decrypts (“opens”) data in place. + // + // aad is the additional authenticated data (AAD), if any. + // + // On input, in_out must be the ciphertext followed by the tag. When open_in_place() returns Ok(plaintext), + // the input ciphertext has been overwritten by the plaintext; plaintext will refer to the plaintext without the tag. + /// + /// # Errors + /// `error::Unspecified` when ciphertext is invalid. + #[inline] + pub fn open_in_place<'in_out, A>( + &self, + nonce: Nonce, + aad: Aad, + in_out: &'in_out mut [u8], + ) -> Result<&'in_out mut [u8], Unspecified> + where + A: AsRef<[u8]>, + { + open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) + } + + /// Encrypts and signs (“seals”) data in place, appending the tag to the + /// resulting ciphertext. + /// + /// `key.seal_in_place_append_tag(aad, in_out)` is equivalent to: + /// + /// ```skip + /// key.seal_in_place_separate_tag(aad, in_out.as_mut()) + /// .map(|tag| in_out.extend(tag.as_ref())) + /// ``` + /// + /// The Nonce used for the operation is randomly generated, and returned to the caller. + /// + /// # Errors + /// `error::Unspecified` if encryption operation fails. + #[inline] + #[allow(clippy::needless_pass_by_value)] + pub fn seal_in_place_append_tag<'a, A, InOut>( + &self, + aad: Aad, + in_out: &'a mut InOut, + ) -> Result + where + A: AsRef<[u8]>, + InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, + { + seal_in_place_append_tag( + self.algorithm, + &self.ctx, + None, + Aad::from(aad.as_ref()), + in_out, + ) + } + + /// Encrypts and signs (“seals”) data in place. + /// + /// `aad` is the additional authenticated data (AAD), if any. This is + /// authenticated but not encrypted. The type `A` could be a byte slice + /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec`, etc. + /// If there is no AAD then use `Aad::empty()`. + /// + /// The plaintext is given as the input value of `in_out`. `seal_in_place()` + /// will overwrite the plaintext with the ciphertext and return the tag. + /// For most protocols, the caller must append the tag to the ciphertext. + /// The tag will be `self.algorithm.tag_len()` bytes long. + /// + /// The Nonce used for the operation is randomly generated, and returned to the caller. + /// + /// # Errors + /// `error::Unspecified` if encryption operation fails. + #[inline] + #[allow(clippy::needless_pass_by_value)] + pub fn seal_in_place_separate_tag( + &self, + aad: Aad, + in_out: &mut [u8], + ) -> Result<(Nonce, Tag), Unspecified> + where + A: AsRef<[u8]>, + { + let nonce = if let AlgorithmID::CHACHA20_POLY1305 = self.algorithm.id { + Some(Nonce(FixedLength::::new()?)) + } else { + None + }; + seal_in_place_separate_tag( + self.algorithm, + &self.ctx, + nonce, + Aad::from(aad.as_ref()), + in_out, + ) + } + + /// The key's AEAD algorithm. + #[inline] + #[must_use] + pub fn algorithm(&self) -> &'static Algorithm { + self.algorithm + } +} + +#[cfg(test)] +mod tests { + use super::{Aad, RandomizedNonceKey}; + use crate::{ + aead::{AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305}, + test::from_hex, + }; + use paste::paste; + + const TEST_128_BIT_KEY: &[u8] = &[ + 0xb0, 0x37, 0x9f, 0xf8, 0xfb, 0x8e, 0xa6, 0x31, 0xf4, 0x1c, 0xe6, 0x3e, 0xb5, 0xc5, 0x20, + 0x7c, + ]; + + const TEST_256_BIT_KEY: &[u8] = &[ + 0x56, 0xd8, 0x96, 0x68, 0xbd, 0x96, 0xeb, 0xff, 0x5e, 0xa2, 0x0b, 0x34, 0xf2, 0x79, 0x84, + 0x6e, 0x2b, 0x13, 0x01, 0x3d, 0xab, 0x1d, 0xa4, 0x07, 0x5a, 0x16, 0xd5, 0x0b, 0x53, 0xb0, + 0xcc, 0x88, + ]; + + macro_rules! test_randnonce { + ($name:ident, $alg:expr, $key:expr) => { + paste! { + #[test] + fn []() { + assert!(RandomizedNonceKey::new($alg, $key).is_err()); + } + } + }; + ($name:ident, $alg:expr, $key:expr, $expect_tag_len:expr, $expect_nonce_len:expr) => { + paste! { + #[test] + fn []() { + let plaintext = from_hex("00112233445566778899aabbccddeeff").unwrap(); + let rand_nonce_key = + RandomizedNonceKey::new($alg, $key).unwrap(); + + assert_eq!($alg, rand_nonce_key.algorithm()); + assert_eq!(*$expect_tag_len, $alg.tag_len()); + assert_eq!(*$expect_nonce_len, $alg.nonce_len()); + + let mut in_out = Vec::from(plaintext.as_slice()); + + let nonce = rand_nonce_key + .seal_in_place_append_tag(Aad::empty(), &mut in_out) + .unwrap(); + + assert_ne!(plaintext, in_out[..plaintext.len()]); + + rand_nonce_key + .open_in_place(nonce, Aad::empty(), &mut in_out) + .unwrap(); + + assert_eq!(plaintext, in_out[..plaintext.len()]); + + let mut in_out = Vec::from(plaintext.as_slice()); + + let (nonce, tag) = rand_nonce_key + .seal_in_place_separate_tag(Aad::empty(), &mut in_out) + .unwrap(); + + assert_ne!(plaintext, in_out[..plaintext.len()]); + + in_out.extend(tag.as_ref()); + + rand_nonce_key + .open_in_place(nonce, Aad::empty(), &mut in_out) + .unwrap(); + + assert_eq!(plaintext, in_out[..plaintext.len()]); + } + } + }; + } + + test_randnonce!(aes_128_gcm, &AES_128_GCM, TEST_128_BIT_KEY, &16, &12); + test_randnonce!(aes_256_gcm, &AES_256_GCM, TEST_256_BIT_KEY, &16, &12); + test_randnonce!(chacha20_poly1305, &CHACHA20_POLY1305, TEST_256_BIT_KEY); +} From 68f9c14bda7e8dfcdf95a60da117f1fa5dd9bc29 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 19:13:18 +0000 Subject: [PATCH 07/11] Move TLS AEAD types to seperate module. Implement Debug --- aws-lc-rs/src/aead.rs | 373 +------------------------------- aws-lc-rs/src/aead/tls.rs | 438 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 440 insertions(+), 371 deletions(-) create mode 100644 aws-lc-rs/src/aead/tls.rs diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index d4492ca0ee7..3f7250d2376 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -134,12 +134,14 @@ pub mod nonce_sequence; mod poly1305; pub mod quic; mod rand_nonce; +mod tls; pub use self::{ aes_gcm::{AES_128_GCM, AES_128_GCM_SIV, AES_256_GCM, AES_256_GCM_SIV}, chacha::CHACHA20_POLY1305, nonce::{Nonce, NONCE_LEN}, rand_nonce::RandomizedNonceKey, + tls::{TlsProtocolId, TlsRecordOpeningKey, TlsRecordSealingKey}, }; /// A sequences of unique nonces. @@ -912,238 +914,6 @@ impl Debug for LessSafeKey { } } -/// The Transport Layer Security (TLS) protocol version. -pub enum TlsProtocolId { - /// TLS 1.2 (RFC 5246) - TLS12, - - /// TLS 1.3 (RFC 8446) - TLS13, -} - -/// AEAD Encryption key used for TLS protocol record encryption. -/// -/// This type encapsulates encryption operations for TLS AEAD algorithms. -/// It validates that the provides nonce values are monotonically increasing for each invocation. -/// -/// The following algorithms are supported: -/// * `AES_128_GCM` -/// * `AES_256_GCM` -/// -/// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. -pub struct TlsRecordSealingKey { - // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! - // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, - // or force this type to !Sync. Since this is an implementation detail of AWS-LC - // we have optex to manage this behavior internally. - ctx: AeadCtx, - algorithm: &'static Algorithm, -} - -impl TlsRecordSealingKey { - /// New TLS record sealing key. Only supports `AES_128_GCM` and `AES_256_GCM`. - /// - /// # Errors - /// * `Unspecified`: Returned if the length of `key_bytes` does not match the chosen algorithm, - /// or if an unsupported algorithm is provided. - pub fn new( - algorithm: &'static Algorithm, - protocol: TlsProtocolId, - key_bytes: &[u8], - ) -> Result { - let ctx = match (algorithm.id, protocol) { - (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Seal, - ), - (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_128_gcm_tls13( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Seal, - ), - (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_256_gcm_tls12( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Seal, - ), - (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_256_gcm_tls13( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Seal, - ), - ( - AlgorithmID::AES_128_GCM_SIV - | AlgorithmID::AES_256_GCM_SIV - | AlgorithmID::CHACHA20_POLY1305, - _, - ) => Err(Unspecified), - }?; - Ok(Self { ctx, algorithm }) - } - - /// Accepts a `Nonce` and `Aad` construction that is unique for this key and - /// TLS record sealing operation for the configured TLS protocol version. - /// - /// `nonce` must be unique and incremented per each sealing operation, - /// otherwise an error is returned. - /// - /// # Errors - /// `error::Unspecified` if encryption operation fails. - #[inline] - #[allow(clippy::needless_pass_by_value)] - pub fn seal_in_place_append_tag( - &mut self, - nonce: Nonce, - aad: Aad, - in_out: &mut InOut, - ) -> Result<(), Unspecified> - where - A: AsRef<[u8]>, - InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, - { - seal_in_place_append_tag( - self.algorithm, - &self.ctx, - Some(nonce), - Aad::from(aad.as_ref()), - in_out, - ) - .map(|_| ()) - } - - /// Encrypts and signs (“seals”) data in place. - /// - /// `aad` is the additional authenticated data (AAD), if any. This is - /// authenticated but not encrypted. The type `A` could be a byte slice - /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec`, etc. - /// If there is no AAD then use `Aad::empty()`. - /// - /// The plaintext is given as the input value of `in_out`. `seal_in_place()` - /// will overwrite the plaintext with the ciphertext and return the tag. - /// For most protocols, the caller must append the tag to the ciphertext. - /// The tag will be `self.algorithm.tag_len()` bytes long. - /// - /// The Nonce used for the operation is randomly generated, and returned to the caller. - /// - /// # Errors - /// `error::Unspecified` if encryption operation fails. - #[inline] - #[allow(clippy::needless_pass_by_value)] - pub fn seal_in_place_separate_tag( - &mut self, - nonce: Nonce, - aad: Aad, - in_out: &mut [u8], - ) -> Result<(Nonce, Tag), Unspecified> - where - A: AsRef<[u8]>, - { - seal_in_place_separate_tag( - self.algorithm, - &self.ctx, - Some(nonce), - Aad::from(aad.as_ref()), - in_out, - ) - } - - /// The key's AEAD algorithm. - #[inline] - #[must_use] - pub fn algorithm(&self) -> &'static Algorithm { - self.algorithm - } -} - -/// AEAD Encryption key used for TLS protocol record encryption. -/// -/// This type encapsulates decryption operations for TLS AEAD algorithms. -/// -/// The following algorithms are supported: -/// * `AES_128_GCM` -/// * `AES_256_GCM` -/// -/// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. -pub struct TlsRecordOpeningKey { - // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! - // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, - // or force this type to !Sync. Since this is an implementation detail of AWS-LC - // we have optex to manage this behavior internally. - ctx: AeadCtx, - algorithm: &'static Algorithm, -} - -impl TlsRecordOpeningKey { - /// New TLS record opening key. Only supports `AES_128_GCM` and `AES_256_GCM` Algorithms. - /// - /// # Errors - /// * `Unspecified`: Returned if the length of `key_bytes` does not match the chosen algorithm, - /// or if an unsupported algorithm is provided. - pub fn new( - algorithm: &'static Algorithm, - protocol: TlsProtocolId, - key_bytes: &[u8], - ) -> Result { - let ctx = match (algorithm.id, protocol) { - (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Open, - ), - (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_128_gcm_tls13( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Open, - ), - (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_256_gcm_tls12( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Open, - ), - (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_256_gcm_tls13( - key_bytes, - algorithm.tag_len(), - aead_ctx::AeadDirection::Open, - ), - ( - AlgorithmID::AES_128_GCM_SIV - | AlgorithmID::AES_256_GCM_SIV - | AlgorithmID::CHACHA20_POLY1305, - _, - ) => Err(Unspecified), - }?; - Ok(Self { ctx, algorithm }) - } - - /// Accepts a Noce and Aad construction that is unique for this TLS record - /// opening operation. - /// - /// `nonce` must be unique for every use of the key to open data. - /// - /// # Errors - /// `error::Unspecified` when ciphertext is invalid. - #[inline] - pub fn open_in_place<'in_out, A>( - &self, - nonce: Nonce, - aad: Aad, - in_out: &'in_out mut [u8], - ) -> Result<&'in_out mut [u8], Unspecified> - where - A: AsRef<[u8]>, - { - open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) - } - - /// The key's AEAD algorithm. - #[inline] - #[must_use] - pub fn algorithm(&self) -> &'static Algorithm { - self.algorithm - } -} - /// An AEAD Algorithm. pub struct Algorithm { init: fn(key: &[u8], tag_len: usize) -> Result, @@ -1528,17 +1298,6 @@ mod tests { #[cfg(feature = "fips")] mod fips; - const TEST_128_BIT_KEY: &[u8] = &[ - 0xb0, 0x37, 0x9f, 0xf8, 0xfb, 0x8e, 0xa6, 0x31, 0xf4, 0x1c, 0xe6, 0x3e, 0xb5, 0xc5, 0x20, - 0x7c, - ]; - - const TEST_256_BIT_KEY: &[u8] = &[ - 0x56, 0xd8, 0x96, 0x68, 0xbd, 0x96, 0xeb, 0xff, 0x5e, 0xa2, 0x0b, 0x34, 0xf2, 0x79, 0x84, - 0x6e, 0x2b, 0x13, 0x01, 0x3d, 0xab, 0x1d, 0xa4, 0x07, 0x5a, 0x16, 0xd5, 0x0b, 0x53, 0xb0, - 0xcc, 0x88, - ]; - #[test] fn test_aes_128() { let key = from_hex("000102030405060708090a0b0c0d0e0f").unwrap(); @@ -1589,132 +1348,4 @@ mod tests { assert_eq!(plaintext, in_out[..plaintext.len()]); } - - struct TlsNonceTestCase { - nonce: &'static str, - expect_err: bool, - } - - const TLS_NONCE_TEST_CASES: &[TlsNonceTestCase] = &[ - TlsNonceTestCase { - nonce: "9fab40177c900aad9fc28cc3", - expect_err: false, - }, - TlsNonceTestCase { - nonce: "9fab40177c900aad9fc28cc4", - expect_err: false, - }, - TlsNonceTestCase { - nonce: "9fab40177c900aad9fc28cc2", - expect_err: true, - }, - ]; - - macro_rules! test_tls_aead { - ($name:ident, $alg:expr, $proto:expr, $key:expr) => { - paste! { - #[test] - fn []() { - assert!(TlsRecordSealingKey::new($alg, $proto, $key).is_err()); - assert!(TlsRecordOpeningKey::new($alg, $proto, $key).is_err()); - } - } - }; - ($name:ident, $alg:expr, $proto:expr, $key:expr, $expect_tag_len:expr, $expect_nonce_len:expr) => { - paste! { - #[test] - fn []() { - let mut sealing_key = - TlsRecordSealingKey::new($alg, $proto, $key).unwrap(); - - let opening_key = - TlsRecordOpeningKey::new($alg, $proto, $key).unwrap(); - - for case in TLS_NONCE_TEST_CASES { - let plaintext = from_hex("00112233445566778899aabbccddeeff").unwrap(); - - assert_eq!($alg, sealing_key.algorithm()); - assert_eq!(*$expect_tag_len, $alg.tag_len()); - assert_eq!(*$expect_nonce_len, $alg.nonce_len()); - - let mut in_out = Vec::from(plaintext.as_slice()); - - let nonce = from_hex(case.nonce).unwrap(); - - let nonce_bytes = nonce.as_slice(); - - let result = sealing_key.seal_in_place_append_tag( - Nonce::try_assume_unique_for_key(nonce_bytes).unwrap(), - Aad::empty(), - &mut in_out, - ); - - match (result, case.expect_err) { - (Ok(()), true) => panic!("expected error for seal_in_place_append_tag"), - (Ok(()), false) => {} - (Err(_), true) => return, - (Err(e), false) => panic!("{e}"), - } - - assert_ne!(plaintext, in_out[..plaintext.len()]); - - opening_key - .open_in_place( - Nonce::try_assume_unique_for_key(nonce_bytes).unwrap(), - Aad::empty(), - &mut in_out, - ) - .unwrap(); - - assert_eq!(plaintext, in_out[..plaintext.len()]); - } - } - } - }; - } - - test_tls_aead!( - aes_128_gcm_tls12, - &AES_128_GCM, - TlsProtocolId::TLS12, - TEST_128_BIT_KEY, - &16, - &12 - ); - test_tls_aead!( - aes_128_gcm_tls13, - &AES_128_GCM, - TlsProtocolId::TLS13, - TEST_128_BIT_KEY, - &16, - &12 - ); - test_tls_aead!( - aes_256_gcm_tls12, - &AES_256_GCM, - TlsProtocolId::TLS12, - TEST_256_BIT_KEY, - &16, - &12 - ); - test_tls_aead!( - aes_256_gcm_tls13, - &AES_256_GCM, - TlsProtocolId::TLS13, - TEST_256_BIT_KEY, - &16, - &12 - ); - test_tls_aead!( - chacha20_poly1305_tls12, - &CHACHA20_POLY1305, - TlsProtocolId::TLS12, - TEST_256_BIT_KEY - ); - test_tls_aead!( - chacha20_poly1305_tls13, - &CHACHA20_POLY1305, - TlsProtocolId::TLS13, - TEST_256_BIT_KEY - ); } diff --git a/aws-lc-rs/src/aead/tls.rs b/aws-lc-rs/src/aead/tls.rs new file mode 100644 index 00000000000..d302d4f6142 --- /dev/null +++ b/aws-lc-rs/src/aead/tls.rs @@ -0,0 +1,438 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR ISC + +use std::fmt::Debug; + +use crate::error::Unspecified; + +use super::{ + aead_ctx::{self, AeadCtx}, + open_within, seal_in_place_append_tag, seal_in_place_separate_tag, Aad, Algorithm, AlgorithmID, + Nonce, Tag, +}; + +/// The Transport Layer Security (TLS) protocol version. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TlsProtocolId { + /// TLS 1.2 (RFC 5246) + TLS12, + + /// TLS 1.3 (RFC 8446) + TLS13, +} + +/// AEAD Encryption key used for TLS protocol record encryption. +/// +/// This type encapsulates encryption operations for TLS AEAD algorithms. +/// It validates that the provides nonce values are monotonically increasing for each invocation. +/// +/// The following algorithms are supported: +/// * `AES_128_GCM` +/// * `AES_256_GCM` +/// +/// Prefer this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey` for TLS protocol implementations. +pub struct TlsRecordSealingKey { + // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! + // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, + // or force this type to !Sync. Since this is an implementation detail of AWS-LC + // we have optex to manage this behavior internally. + ctx: AeadCtx, + algorithm: &'static Algorithm, + protocol: TlsProtocolId, +} + +impl TlsRecordSealingKey { + /// New TLS record sealing key. Only supports `AES_128_GCM` and `AES_256_GCM`. + /// + /// # Errors + /// * `Unspecified`: Returned if the length of `key_bytes` does not match the chosen algorithm, + /// or if an unsupported algorithm is provided. + pub fn new( + algorithm: &'static Algorithm, + protocol: TlsProtocolId, + key_bytes: &[u8], + ) -> Result { + let ctx = match (algorithm.id, protocol) { + (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Seal, + ), + (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_128_gcm_tls13( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Seal, + ), + (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_256_gcm_tls12( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Seal, + ), + (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_256_gcm_tls13( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Seal, + ), + ( + AlgorithmID::AES_128_GCM_SIV + | AlgorithmID::AES_256_GCM_SIV + | AlgorithmID::CHACHA20_POLY1305, + _, + ) => Err(Unspecified), + }?; + Ok(Self { + ctx, + algorithm, + protocol, + }) + } + + /// Accepts a `Nonce` and `Aad` construction that is unique for this key and + /// TLS record sealing operation for the configured TLS protocol version. + /// + /// `nonce` must be unique and incremented per each sealing operation, + /// otherwise an error is returned. + /// + /// # Errors + /// `error::Unspecified` if encryption operation fails. + #[inline] + #[allow(clippy::needless_pass_by_value)] + pub fn seal_in_place_append_tag( + &mut self, + nonce: Nonce, + aad: Aad, + in_out: &mut InOut, + ) -> Result<(), Unspecified> + where + A: AsRef<[u8]>, + InOut: AsMut<[u8]> + for<'in_out> Extend<&'in_out u8>, + { + seal_in_place_append_tag( + self.algorithm, + &self.ctx, + Some(nonce), + Aad::from(aad.as_ref()), + in_out, + ) + .map(|_| ()) + } + + /// Encrypts and signs (“seals”) data in place. + /// + /// `aad` is the additional authenticated data (AAD), if any. This is + /// authenticated but not encrypted. The type `A` could be a byte slice + /// `&[u8]`, a byte array `[u8; N]` for some constant `N`, `Vec`, etc. + /// If there is no AAD then use `Aad::empty()`. + /// + /// The plaintext is given as the input value of `in_out`. `seal_in_place()` + /// will overwrite the plaintext with the ciphertext and return the tag. + /// For most protocols, the caller must append the tag to the ciphertext. + /// The tag will be `self.algorithm.tag_len()` bytes long. + /// + /// The Nonce used for the operation is randomly generated, and returned to the caller. + /// + /// # Errors + /// `error::Unspecified` if encryption operation fails. + #[inline] + #[allow(clippy::needless_pass_by_value)] + pub fn seal_in_place_separate_tag( + &mut self, + nonce: Nonce, + aad: Aad, + in_out: &mut [u8], + ) -> Result + where + A: AsRef<[u8]>, + { + seal_in_place_separate_tag( + self.algorithm, + &self.ctx, + Some(nonce), + Aad::from(aad.as_ref()), + in_out, + ) + .map(|(_, tag)| tag) + } + + /// The key's AEAD algorithm. + #[inline] + #[must_use] + pub fn algorithm(&self) -> &'static Algorithm { + self.algorithm + } + + /// The key's associated `TlsProtocolId`. + #[must_use] + pub fn tls_protocol_id(&self) -> TlsProtocolId { + self.protocol + } +} + +#[allow(clippy::missing_fields_in_debug)] +impl Debug for TlsRecordSealingKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TlsRecordSealingKey") + .field("algorithm", &self.algorithm) + .field("protocol", &self.protocol) + .finish() + } +} + +/// AEAD Encryption key used for TLS protocol record encryption. +/// +/// This type encapsulates decryption operations for TLS AEAD algorithms. +/// +/// The following algorithms are supported: +/// * `AES_128_GCM` +/// * `AES_256_GCM` +/// +/// Prefer this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey` for TLS protocol implementations. +pub struct TlsRecordOpeningKey { + // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! + // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, + // or force this type to !Sync. Since this is an implementation detail of AWS-LC + // we have optex to manage this behavior internally. + ctx: AeadCtx, + algorithm: &'static Algorithm, + protocol: TlsProtocolId, +} + +impl TlsRecordOpeningKey { + /// New TLS record opening key. Only supports `AES_128_GCM` and `AES_256_GCM` Algorithms. + /// + /// # Errors + /// * `Unspecified`: Returned if the length of `key_bytes` does not match the chosen algorithm, + /// or if an unsupported algorithm is provided. + pub fn new( + algorithm: &'static Algorithm, + protocol: TlsProtocolId, + key_bytes: &[u8], + ) -> Result { + let ctx = match (algorithm.id, protocol) { + (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_128_gcm_tls12( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Open, + ), + (AlgorithmID::AES_128_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_128_gcm_tls13( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Open, + ), + (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS12) => AeadCtx::aes_256_gcm_tls12( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Open, + ), + (AlgorithmID::AES_256_GCM, TlsProtocolId::TLS13) => AeadCtx::aes_256_gcm_tls13( + key_bytes, + algorithm.tag_len(), + aead_ctx::AeadDirection::Open, + ), + ( + AlgorithmID::AES_128_GCM_SIV + | AlgorithmID::AES_256_GCM_SIV + | AlgorithmID::CHACHA20_POLY1305, + _, + ) => Err(Unspecified), + }?; + Ok(Self { + ctx, + algorithm, + protocol, + }) + } + + /// Accepts a Noce and Aad construction that is unique for this TLS record + /// opening operation. + /// + /// `nonce` must be unique for every use of the key to open data. + /// + /// # Errors + /// `error::Unspecified` when ciphertext is invalid. + #[inline] + pub fn open_in_place<'in_out, A>( + &self, + nonce: Nonce, + aad: Aad, + in_out: &'in_out mut [u8], + ) -> Result<&'in_out mut [u8], Unspecified> + where + A: AsRef<[u8]>, + { + open_within(self.algorithm, &self.ctx, nonce, aad, in_out, 0..) + } + + /// The key's AEAD algorithm. + #[inline] + #[must_use] + pub fn algorithm(&self) -> &'static Algorithm { + self.algorithm + } + + /// The key's associated `TlsProtocolId`. + #[must_use] + pub fn tls_protocol_id(&self) -> TlsProtocolId { + self.protocol + } +} + +#[allow(clippy::missing_fields_in_debug)] +impl Debug for TlsRecordOpeningKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("TlsRecordOpeningKey") + .field("algorithm", &self.algorithm) + .field("protocol", &self.protocol) + .finish() + } +} + +#[cfg(test)] +mod tests { + use super::{TlsProtocolId, TlsRecordOpeningKey, TlsRecordSealingKey}; + use crate::{ + aead::Aad, + aead::{Nonce, AES_128_GCM, AES_256_GCM, CHACHA20_POLY1305}, + test::from_hex, + }; + use paste::paste; + + const TEST_128_BIT_KEY: &[u8] = &[ + 0xb0, 0x37, 0x9f, 0xf8, 0xfb, 0x8e, 0xa6, 0x31, 0xf4, 0x1c, 0xe6, 0x3e, 0xb5, 0xc5, 0x20, + 0x7c, + ]; + + const TEST_256_BIT_KEY: &[u8] = &[ + 0x56, 0xd8, 0x96, 0x68, 0xbd, 0x96, 0xeb, 0xff, 0x5e, 0xa2, 0x0b, 0x34, 0xf2, 0x79, 0x84, + 0x6e, 0x2b, 0x13, 0x01, 0x3d, 0xab, 0x1d, 0xa4, 0x07, 0x5a, 0x16, 0xd5, 0x0b, 0x53, 0xb0, + 0xcc, 0x88, + ]; + + struct TlsNonceTestCase { + nonce: &'static str, + expect_err: bool, + } + + const TLS_NONCE_TEST_CASES: &[TlsNonceTestCase] = &[ + TlsNonceTestCase { + nonce: "9fab40177c900aad9fc28cc3", + expect_err: false, + }, + TlsNonceTestCase { + nonce: "9fab40177c900aad9fc28cc4", + expect_err: false, + }, + TlsNonceTestCase { + nonce: "9fab40177c900aad9fc28cc2", + expect_err: true, + }, + ]; + + macro_rules! test_tls_aead { + ($name:ident, $alg:expr, $proto:expr, $key:expr) => { + paste! { + #[test] + fn []() { + assert!(TlsRecordSealingKey::new($alg, $proto, $key).is_err()); + assert!(TlsRecordOpeningKey::new($alg, $proto, $key).is_err()); + } + } + }; + ($name:ident, $alg:expr, $proto:expr, $key:expr, $expect_tag_len:expr, $expect_nonce_len:expr) => { + paste! { + #[test] + fn []() { + let mut sealing_key = + TlsRecordSealingKey::new($alg, $proto, $key).unwrap(); + + let opening_key = + TlsRecordOpeningKey::new($alg, $proto, $key).unwrap(); + + for case in TLS_NONCE_TEST_CASES { + let plaintext = from_hex("00112233445566778899aabbccddeeff").unwrap(); + + assert_eq!($alg, sealing_key.algorithm()); + assert_eq!(*$expect_tag_len, $alg.tag_len()); + assert_eq!(*$expect_nonce_len, $alg.nonce_len()); + + let mut in_out = Vec::from(plaintext.as_slice()); + + let nonce = from_hex(case.nonce).unwrap(); + + let nonce_bytes = nonce.as_slice(); + + let result = sealing_key.seal_in_place_append_tag( + Nonce::try_assume_unique_for_key(nonce_bytes).unwrap(), + Aad::empty(), + &mut in_out, + ); + + match (result, case.expect_err) { + (Ok(()), true) => panic!("expected error for seal_in_place_append_tag"), + (Ok(()), false) => {} + (Err(_), true) => return, + (Err(e), false) => panic!("{e}"), + } + + assert_ne!(plaintext, in_out[..plaintext.len()]); + + opening_key + .open_in_place( + Nonce::try_assume_unique_for_key(nonce_bytes).unwrap(), + Aad::empty(), + &mut in_out, + ) + .unwrap(); + + assert_eq!(plaintext, in_out[..plaintext.len()]); + } + } + } + }; + } + + test_tls_aead!( + aes_128_gcm_tls12, + &AES_128_GCM, + TlsProtocolId::TLS12, + TEST_128_BIT_KEY, + &16, + &12 + ); + test_tls_aead!( + aes_128_gcm_tls13, + &AES_128_GCM, + TlsProtocolId::TLS13, + TEST_128_BIT_KEY, + &16, + &12 + ); + test_tls_aead!( + aes_256_gcm_tls12, + &AES_256_GCM, + TlsProtocolId::TLS12, + TEST_256_BIT_KEY, + &16, + &12 + ); + test_tls_aead!( + aes_256_gcm_tls13, + &AES_256_GCM, + TlsProtocolId::TLS13, + TEST_256_BIT_KEY, + &16, + &12 + ); + test_tls_aead!( + chacha20_poly1305_tls12, + &CHACHA20_POLY1305, + TlsProtocolId::TLS12, + TEST_256_BIT_KEY + ); + test_tls_aead!( + chacha20_poly1305_tls13, + &CHACHA20_POLY1305, + TlsProtocolId::TLS13, + TEST_256_BIT_KEY + ); +} From 8a9023bc962d93528bcbb3b4e8dc250aaf0c8287 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 19:13:35 +0000 Subject: [PATCH 08/11] Implement Debug for RandomizedNonceKey --- aws-lc-rs/src/aead/rand_nonce.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/aws-lc-rs/src/aead/rand_nonce.rs b/aws-lc-rs/src/aead/rand_nonce.rs index cc09c5698fa..287549f1f1f 100644 --- a/aws-lc-rs/src/aead/rand_nonce.rs +++ b/aws-lc-rs/src/aead/rand_nonce.rs @@ -2,10 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 OR ISC use crate::{error::Unspecified, iv::FixedLength}; +use std::fmt::Debug; use super::{ aead_ctx::AeadCtx, open_within, seal_in_place_append_tag, seal_in_place_separate_tag, Aad, - Algorithm, AlgorithmID, Nonce, Tag, NONCE_LEN, + Algorithm, AlgorithmID, Nonce, Tag, TlsRecordSealingKey, NONCE_LEN, }; /// AEAD Cipher key using a randomized nonce. @@ -16,7 +17,7 @@ use super::{ /// * `AES_128_GCM` /// * `AES_256_GCM` /// -/// Use this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. +/// Prefer this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey`. pub struct RandomizedNonceKey { ctx: AeadCtx, algorithm: &'static Algorithm, @@ -148,6 +149,15 @@ impl RandomizedNonceKey { } } +#[allow(clippy::missing_fields_in_debug)] +impl Debug for RandomizedNonceKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("RandomizedNonceKey") + .field("algorithm", &self.algorithm) + .finish() + } +} + #[cfg(test)] mod tests { use super::{Aad, RandomizedNonceKey}; From ac90c8fda4eb9d05c3cbc664c9fe9e029625db2b Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 19:15:41 +0000 Subject: [PATCH 09/11] Clippy cleanup --- aws-lc-rs/src/aead.rs | 3 +-- aws-lc-rs/src/aead/rand_nonce.rs | 2 +- aws-lc-rs/src/aead/tls.rs | 3 +++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/aws-lc-rs/src/aead.rs b/aws-lc-rs/src/aead.rs index 3f7250d2376..d78d86da2df 100644 --- a/aws-lc-rs/src/aead.rs +++ b/aws-lc-rs/src/aead.rs @@ -872,7 +872,7 @@ impl LessSafeKey { // # FIPS // This method must not be used. // - // # Errors + /// # Errors /// `error::Unspecified` if encryption operation fails. #[inline] #[allow(clippy::needless_pass_by_value)] @@ -1293,7 +1293,6 @@ pub(crate) fn aead_open_combined_randnonce( mod tests { use super::*; use crate::{iv::FixedLength, test::from_hex}; - use paste::paste; #[cfg(feature = "fips")] mod fips; diff --git a/aws-lc-rs/src/aead/rand_nonce.rs b/aws-lc-rs/src/aead/rand_nonce.rs index 287549f1f1f..67f75357cef 100644 --- a/aws-lc-rs/src/aead/rand_nonce.rs +++ b/aws-lc-rs/src/aead/rand_nonce.rs @@ -6,7 +6,7 @@ use std::fmt::Debug; use super::{ aead_ctx::AeadCtx, open_within, seal_in_place_append_tag, seal_in_place_separate_tag, Aad, - Algorithm, AlgorithmID, Nonce, Tag, TlsRecordSealingKey, NONCE_LEN, + Algorithm, AlgorithmID, Nonce, Tag, NONCE_LEN, }; /// AEAD Cipher key using a randomized nonce. diff --git a/aws-lc-rs/src/aead/tls.rs b/aws-lc-rs/src/aead/tls.rs index d302d4f6142..6002087adf1 100644 --- a/aws-lc-rs/src/aead/tls.rs +++ b/aws-lc-rs/src/aead/tls.rs @@ -12,6 +12,7 @@ use super::{ }; /// The Transport Layer Security (TLS) protocol version. +#[allow(clippy::module_name_repetitions)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum TlsProtocolId { /// TLS 1.2 (RFC 5246) @@ -31,6 +32,7 @@ pub enum TlsProtocolId { /// * `AES_256_GCM` /// /// Prefer this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey` for TLS protocol implementations. +#[allow(clippy::module_name_repetitions)] pub struct TlsRecordSealingKey { // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, @@ -187,6 +189,7 @@ impl Debug for TlsRecordSealingKey { /// * `AES_256_GCM` /// /// Prefer this type in place of `LessSafeKey`, `OpeningKey`, `SealingKey` for TLS protocol implementations. +#[allow(clippy::module_name_repetitions)] pub struct TlsRecordOpeningKey { // The TLS specific construction for TLS ciphers in AWS-LC are not thread-safe! // The choice here was either wrap the underlying EVP_AEAD_CTX in a Mutex as done here, From b6ad4a6b35899deac7b7edacd8a6878346afe1d2 Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 19:22:41 +0000 Subject: [PATCH 10/11] Add Debug traits for tls_prf module --- aws-lc-rs/src/tls_prf.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/aws-lc-rs/src/tls_prf.rs b/aws-lc-rs/src/tls_prf.rs index 9f216d5e998..7c47e55777d 100644 --- a/aws-lc-rs/src/tls_prf.rs +++ b/aws-lc-rs/src/tls_prf.rs @@ -25,6 +25,8 @@ //! # } //! ``` +use std::fmt::Debug; + use crate::{ digest::match_digest_type, digest::AlgorithmID, error::Unspecified, fips::indicator_check, }; @@ -35,6 +37,12 @@ use aws_lc::CRYPTO_tls1_prf; /// The TLS PRF `P_hash` Algorithm pub struct Algorithm(AlgorithmID); +impl Debug for Algorithm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&self.0, f) + } +} + /// SHA-256 `P_hash` algorithm pub const P_SHA256: Algorithm = Algorithm(AlgorithmID::SHA256); @@ -121,6 +129,15 @@ impl TryFrom for [u8; L] { } } +#[allow(clippy::missing_fields_in_debug)] +impl Debug for Secret { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Secret") + .field("algorithm", &self.algorithm) + .finish() + } +} + fn prf( algorithm: &'static Algorithm, secret: &[u8], From 648abc8891e633ff5943afbd5420806c8e27b1ff Mon Sep 17 00:00:00 2001 From: Sean McGrail Date: Fri, 20 Oct 2023 19:37:43 +0000 Subject: [PATCH 11/11] Fix FIPS indicator tests with TlsRecordSealingKey &mut self --- aws-lc-rs/src/aead/tests/fips.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-lc-rs/src/aead/tests/fips.rs b/aws-lc-rs/src/aead/tests/fips.rs index 03545b0fb93..13b681fe634 100644 --- a/aws-lc-rs/src/aead/tests/fips.rs +++ b/aws-lc-rs/src/aead/tests/fips.rs @@ -191,7 +191,7 @@ macro_rules! tls_nonce_api { ($name:ident, $alg:expr, $proto:expr, $key:expr) => { #[test] fn $name() { - let key = TlsRecordSealingKey::new($alg, $proto, $key).unwrap(); + let mut key = TlsRecordSealingKey::new($alg, $proto, $key).unwrap(); let mut in_out = Vec::from(TEST_MESSAGE);