Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for AES 192 #622

Merged
merged 7 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading