Skip to content

Commit

Permalink
Support for AES 192 (#622)
Browse files Browse the repository at this point in the history
* Add aead::AES_192_GCM

* Testing for AES_192_GCM

* Add cipher::AES_192

* Testing for AES_192

* Cleanup SymmetricCipherKey construction

* Update FIPS test & example

* PR feedback
  • Loading branch information
justsmth authored Dec 13, 2024
1 parent 0a697c5 commit c75bc5c
Show file tree
Hide file tree
Showing 16 changed files with 603 additions and 100 deletions.
4 changes: 3 additions & 1 deletion aws-lc-rs/examples/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ use aws_lc_rs::{
cipher::{
DecryptingKey, DecryptionContext, EncryptingKey, EncryptionContext,
PaddedBlockDecryptingKey, PaddedBlockEncryptingKey, UnboundCipherKey, AES_128,
AES_128_KEY_LEN, AES_256, AES_256_KEY_LEN, AES_CBC_IV_LEN, AES_CTR_IV_LEN,
AES_128_KEY_LEN, AES_192, AES_192_KEY_LEN, AES_256, AES_256_KEY_LEN, AES_CBC_IV_LEN,
AES_CTR_IV_LEN,
},
iv::FixedLength,
};
Expand Down Expand Up @@ -262,6 +263,7 @@ fn aes_cbc_decrypt(key: String, iv: String, ciphertext: String) -> Result<(), &'
fn new_unbound_key(key: &[u8]) -> Result<UnboundCipherKey, &'static str> {
let alg = match key.len() {
AES_128_KEY_LEN => &AES_128,
AES_192_KEY_LEN => &AES_192,
AES_256_KEY_LEN => &AES_256,
_ => {
return Err("invalid aes key length");
Expand Down
3 changes: 2 additions & 1 deletion aws-lc-rs/src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ mod tls;
mod unbound_key;

pub use self::{
aes_gcm::{AES_128_GCM, AES_128_GCM_SIV, AES_256_GCM, AES_256_GCM_SIV},
aes_gcm::{AES_128_GCM, AES_128_GCM_SIV, AES_192_GCM, AES_256_GCM, AES_256_GCM_SIV},
chacha::CHACHA20_POLY1305,
nonce::{Nonce, NONCE_LEN},
rand_nonce::RandomizedNonceKey,
Expand Down Expand Up @@ -972,6 +972,7 @@ derive_debug_via_id!(Algorithm);
#[allow(non_camel_case_types)]
enum AlgorithmID {
AES_128_GCM,
AES_192_GCM,
AES_256_GCM,
AES_128_GCM_SIV,
AES_256_GCM_SIV,
Expand Down
31 changes: 27 additions & 4 deletions aws-lc-rs/src/aead/aead_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ use core::ptr::null_mut;

use crate::cipher::chacha;

use crate::cipher::aes::{AES_128_KEY_LEN, AES_256_KEY_LEN};
use crate::cipher::aes::{AES_128_KEY_LEN, AES_192_KEY_LEN, AES_256_KEY_LEN};
use crate::error::Unspecified;
use crate::ptr::LcPtr;
use aws_lc::{
evp_aead_direction_t, evp_aead_direction_t_evp_aead_open, evp_aead_direction_t_evp_aead_seal,
EVP_AEAD_CTX_init, EVP_AEAD_CTX_init_with_direction, EVP_AEAD_CTX_zero, EVP_aead_aes_128_gcm,
EVP_aead_aes_128_gcm_randnonce, EVP_aead_aes_128_gcm_siv, EVP_aead_aes_128_gcm_tls12,
EVP_aead_aes_128_gcm_tls13, EVP_aead_aes_256_gcm, EVP_aead_aes_256_gcm_randnonce,
EVP_aead_aes_256_gcm_siv, EVP_aead_aes_256_gcm_tls12, EVP_aead_aes_256_gcm_tls13,
EVP_aead_chacha20_poly1305, OPENSSL_malloc, EVP_AEAD_CTX,
EVP_aead_aes_128_gcm_tls13, EVP_aead_aes_192_gcm, EVP_aead_aes_256_gcm,
EVP_aead_aes_256_gcm_randnonce, EVP_aead_aes_256_gcm_siv, EVP_aead_aes_256_gcm_tls12,
EVP_aead_aes_256_gcm_tls13, EVP_aead_chacha20_poly1305, OPENSSL_malloc, EVP_AEAD_CTX,
};

pub(crate) enum AeadDirection {
Expand All @@ -39,6 +39,7 @@ impl From<AeadDirection> for evp_aead_direction_t {
)]
pub(crate) enum AeadCtx {
AES_128_GCM(LcPtr<EVP_AEAD_CTX>),
AES_192_GCM(LcPtr<EVP_AEAD_CTX>),
AES_256_GCM(LcPtr<EVP_AEAD_CTX>),

AES_128_GCM_SIV(LcPtr<EVP_AEAD_CTX>),
Expand Down Expand Up @@ -78,6 +79,15 @@ impl AeadCtx {
)?))
}

pub(crate) fn aes_192_gcm(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
Ok(AeadCtx::AES_192_GCM(AeadCtx::aes_192_context(
EVP_aead_aes_192_gcm,
key_bytes,
tag_len,
None,
)?))
}

pub(crate) fn aes_256_gcm(key_bytes: &[u8], tag_len: usize) -> Result<Self, Unspecified> {
Ok(AeadCtx::AES_256_GCM(AeadCtx::aes_256_context(
EVP_aead_aes_256_gcm,
Expand Down Expand Up @@ -198,6 +208,18 @@ impl AeadCtx {
AeadCtx::build_context(aead, key_bytes, tag_len, direction)
}

fn aes_192_context(
aead: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
key_bytes: &[u8],
tag_len: usize,
direction: Option<AeadDirection>,
) -> Result<LcPtr<EVP_AEAD_CTX>, Unspecified> {
if AES_192_KEY_LEN != key_bytes.len() {
return Err(Unspecified);
}
AeadCtx::build_context(aead, key_bytes, tag_len, direction)
}

fn aes_256_context(
aead: unsafe extern "C" fn() -> *const aws_lc::evp_aead_st,
key_bytes: &[u8],
Expand Down Expand Up @@ -258,6 +280,7 @@ impl AsRef<LcPtr<EVP_AEAD_CTX>> for AeadCtx {
fn as_ref(&self) -> &LcPtr<EVP_AEAD_CTX> {
match self {
AeadCtx::AES_128_GCM(ctx)
| AeadCtx::AES_192_GCM(ctx)
| AeadCtx::AES_256_GCM(ctx)
| AeadCtx::AES_128_GCM_SIV(ctx)
| AeadCtx::AES_256_GCM_SIV(ctx)
Expand Down
15 changes: 14 additions & 1 deletion aws-lc-rs/src/aead/aes_gcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::aead::{Algorithm, AlgorithmID};

use crate::aead::aead_ctx::AeadCtx;
use crate::cipher::aes::{AES_128_KEY_LEN, AES_256_KEY_LEN};
use crate::cipher::aes::{AES_128_KEY_LEN, AES_192_KEY_LEN, AES_256_KEY_LEN};
use crate::error::Unspecified;

/// AES-128 in GCM mode with 128-bit tags and 96 bit nonces.
Expand All @@ -15,6 +15,14 @@ pub const AES_128_GCM: Algorithm = Algorithm {
max_input_len: u64::MAX,
};

/// AES-192 in GCM mode with 128-bit tags and 96 bit nonces.
pub const AES_192_GCM: Algorithm = Algorithm {
init: init_192_aead,
key_len: AES_192_KEY_LEN,
id: AlgorithmID::AES_192_GCM,
max_input_len: u64::MAX,
};

/// AES-256 in GCM mode with 128-bit tags and 96 bit nonces.
pub const AES_256_GCM: Algorithm = Algorithm {
init: init_256_aead,
Expand Down Expand Up @@ -44,6 +52,11 @@ fn init_128_aead(key: &[u8], tag_len: usize) -> Result<AeadCtx, Unspecified> {
AeadCtx::aes_128_gcm(key, tag_len)
}

#[inline]
fn init_192_aead(key: &[u8], tag_len: usize) -> Result<AeadCtx, Unspecified> {
AeadCtx::aes_192_gcm(key, tag_len)
}

#[inline]
fn init_256_aead(key: &[u8], tag_len: usize) -> Result<AeadCtx, Unspecified> {
AeadCtx::aes_256_gcm(key, tag_len)
Expand Down
6 changes: 3 additions & 3 deletions aws-lc-rs/src/aead/quic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ fn cipher_new_mask(
let block = block::Block::from(sample);

let encrypted_block = match cipher_key {
SymmetricCipherKey::Aes128 { enc_key, .. } | SymmetricCipherKey::Aes256 { enc_key, .. } => {
encrypt_block(enc_key, block)
}
SymmetricCipherKey::Aes128 { enc_key, .. }
| SymmetricCipherKey::Aes192 { enc_key, .. }
| SymmetricCipherKey::Aes256 { enc_key, .. } => encrypt_block(enc_key, block),
SymmetricCipherKey::ChaCha20 { raw_key } => {
let plaintext = block.as_ref();
let counter_bytes: &[u8; 4] = plaintext[0..=3]
Expand Down
1 change: 1 addition & 0 deletions aws-lc-rs/src/aead/rand_nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl RandomizedNonceKey {
algorithm.nonce_len(),
),
AlgorithmID::AES_128_GCM_SIV
| AlgorithmID::AES_192_GCM
| AlgorithmID::AES_256_GCM_SIV
| AlgorithmID::CHACHA20_POLY1305 => return Err(Unspecified),
}?;
Expand Down
2 changes: 2 additions & 0 deletions aws-lc-rs/src/aead/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl TlsRecordSealingKey {
),
(
AlgorithmID::AES_128_GCM_SIV
| AlgorithmID::AES_192_GCM
| AlgorithmID::AES_256_GCM_SIV
| AlgorithmID::CHACHA20_POLY1305,
_,
Expand Down Expand Up @@ -220,6 +221,7 @@ impl TlsRecordOpeningKey {
),
(
AlgorithmID::AES_128_GCM_SIV
| AlgorithmID::AES_192_GCM
| AlgorithmID::AES_256_GCM_SIV
| AlgorithmID::CHACHA20_POLY1305,
_,
Expand Down
5 changes: 4 additions & 1 deletion aws-lc-rs/src/aead/unbound_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// SPDX-License-Identifier: Apache-2.0 OR ISC

use super::{aead_ctx::AeadCtx, Algorithm, Nonce, MAX_KEY_LEN, MAX_TAG_LEN, NONCE_LEN};
use super::{Tag, AES_128_GCM, AES_128_GCM_SIV, AES_256_GCM, AES_256_GCM_SIV, CHACHA20_POLY1305};
use super::{
Tag, AES_128_GCM, AES_128_GCM_SIV, AES_192_GCM, AES_256_GCM, AES_256_GCM_SIV, CHACHA20_POLY1305,
};
use crate::iv::FixedLength;
use crate::{error::Unspecified, fips::indicator_check, hkdf};
use aws_lc::{
Expand Down Expand Up @@ -479,6 +481,7 @@ impl From<AeadCtx> for UnboundKey {
| AeadCtx::AES_128_GCM_TLS12(_)
| AeadCtx::AES_128_GCM_TLS13(_)
| AeadCtx::AES_128_GCM_RANDNONCE(_) => &AES_128_GCM,
AeadCtx::AES_192_GCM(_) => &AES_192_GCM,
AeadCtx::AES_128_GCM_SIV(_) => &AES_128_GCM_SIV,
AeadCtx::AES_256_GCM(_)
| AeadCtx::AES_256_GCM_RANDNONCE(_)
Expand Down
45 changes: 32 additions & 13 deletions aws-lc-rs/src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,19 @@ use crate::hkdf::KeyType;
use crate::iv::{FixedLength, IV_LEN_128_BIT};
use crate::ptr::ConstPointer;
use aws_lc::{
EVP_aes_128_cbc, EVP_aes_128_cfb128, EVP_aes_128_ctr, EVP_aes_128_ecb, EVP_aes_256_cbc,
EVP_aes_256_cfb128, EVP_aes_256_ctr, EVP_aes_256_ecb, EVP_CIPHER,
EVP_aes_128_cbc, EVP_aes_128_cfb128, EVP_aes_128_ctr, EVP_aes_128_ecb, EVP_aes_192_cbc,
EVP_aes_192_cfb128, EVP_aes_192_ctr, EVP_aes_192_ecb, EVP_aes_256_cbc, EVP_aes_256_cfb128,
EVP_aes_256_ctr, EVP_aes_256_ecb, EVP_CIPHER,
};
use core::fmt::Debug;
use key::SymmetricCipherKey;

/// The number of bytes in an AES 128-bit key
pub use crate::cipher::aes::AES_128_KEY_LEN;

/// The number of bytes in an AES 192-bit key
pub use crate::cipher::aes::AES_192_KEY_LEN;

/// The number of bytes in an AES 256-bit key
pub use crate::cipher::aes::AES_256_KEY_LEN;

Expand Down Expand Up @@ -287,6 +291,10 @@ impl OperatingMode {
(OperatingMode::CTR, AlgorithmId::Aes128) => unsafe { EVP_aes_128_ctr() },
(OperatingMode::CFB128, AlgorithmId::Aes128) => unsafe { EVP_aes_128_cfb128() },
(OperatingMode::ECB, AlgorithmId::Aes128) => unsafe { EVP_aes_128_ecb() },
(OperatingMode::CBC, AlgorithmId::Aes192) => unsafe { EVP_aes_192_cbc() },
(OperatingMode::CTR, AlgorithmId::Aes192) => unsafe { EVP_aes_192_ctr() },
(OperatingMode::CFB128, AlgorithmId::Aes192) => unsafe { EVP_aes_192_cfb128() },
(OperatingMode::ECB, AlgorithmId::Aes192) => unsafe { EVP_aes_192_ecb() },
(OperatingMode::CBC, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cbc() },
(OperatingMode::CTR, AlgorithmId::Aes256) => unsafe { EVP_aes_256_ctr() },
(OperatingMode::CFB128, AlgorithmId::Aes256) => unsafe { EVP_aes_256_cfb128() },
Expand Down Expand Up @@ -351,6 +359,9 @@ pub enum AlgorithmId {

/// AES 256-bit
Aes256,

/// AES 192-bit
Aes192,
}

/// A cipher algorithm.
Expand All @@ -368,6 +379,13 @@ pub static AES_128: Algorithm = Algorithm {
block_len: AES_BLOCK_LEN,
};

/// AES 192-bit cipher
pub static AES_192: Algorithm = Algorithm {
id: AlgorithmId::Aes192,
key_len: AES_192_KEY_LEN,
block_len: AES_BLOCK_LEN,
};

/// AES 256-bit cipher
pub static AES_256: Algorithm = Algorithm {
id: AlgorithmId::Aes256,
Expand All @@ -392,7 +410,7 @@ impl Algorithm {
) -> Result<EncryptionContext, Unspecified> {
match self.id {
// TODO: Hopefully support CFB1, and CFB8
AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
Ok(EncryptionContext::Iv128(FixedLength::new()?))
}
Expand All @@ -404,7 +422,7 @@ impl Algorithm {
fn is_valid_encryption_context(&self, mode: OperatingMode, input: &EncryptionContext) -> bool {
match self.id {
// TODO: Hopefully support CFB1, and CFB8
AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
matches!(input, EncryptionContext::Iv128(_))
}
Expand All @@ -418,7 +436,7 @@ impl Algorithm {
fn is_valid_decryption_context(&self, mode: OperatingMode, input: &DecryptionContext) -> bool {
// TODO: Hopefully support CFB1, and CFB8
match self.id {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => match mode {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => match mode {
OperatingMode::CBC | OperatingMode::CTR | OperatingMode::CFB128 => {
matches!(input, DecryptionContext::Iv128(_))
}
Expand Down Expand Up @@ -489,6 +507,7 @@ impl TryInto<SymmetricCipherKey> for UnboundCipherKey {
fn try_into(self) -> Result<SymmetricCipherKey, Self::Error> {
match self.algorithm.id() {
AlgorithmId::Aes128 => SymmetricCipherKey::aes128(self.key_bytes.as_ref()),
AlgorithmId::Aes192 => SymmetricCipherKey::aes192(self.key_bytes.as_ref()),
AlgorithmId::Aes256 => SymmetricCipherKey::aes256(self.key_bytes.as_ref()),
}
}
Expand Down Expand Up @@ -739,23 +758,23 @@ fn encrypt(

match mode {
OperatingMode::CBC => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::encrypt_cbc_mode(key, context, in_out)
}
},
OperatingMode::CTR => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::encrypt_ctr_mode(key, context, in_out)
}
},
// TODO: Hopefully support CFB1, and CFB8
OperatingMode::CFB128 => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::encrypt_cfb_mode(key, mode, context, in_out)
}
},
OperatingMode::ECB => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::encrypt_ecb_mode(key, context, in_out)
}
},
Expand All @@ -782,23 +801,23 @@ fn decrypt<'in_out>(

match mode {
OperatingMode::CBC => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::decrypt_cbc_mode(key, context, in_out)
}
},
OperatingMode::CTR => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::decrypt_ctr_mode(key, context, in_out)
}
},
// TODO: Hopefully support CFB1, and CFB8
OperatingMode::CFB128 => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::decrypt_cfb_mode(key, mode, context, in_out)
}
},
OperatingMode::ECB => match algorithm.id() {
AlgorithmId::Aes128 | AlgorithmId::Aes256 => {
AlgorithmId::Aes128 | AlgorithmId::Aes192 | AlgorithmId::Aes256 => {
aes::decrypt_ecb_mode(key, context, in_out)
}
},
Expand Down
Loading

0 comments on commit c75bc5c

Please sign in to comment.