cryptic: reorganize symmetric ciphers

This commit is contained in:
2025-07-19 19:44:11 +03:00
parent d2c0f8e3fd
commit d08a42d5b2
11 changed files with 505 additions and 638 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ $ env set initrd_addr_r 0x70000000
$ env set bootargs "debug.serial-level=info"
$ tftpboot ${initrd_addr_r} <BUILD-MACHINE-IP-ADDR>:initrd.tar
$ tftpboot ${loadaddr} <BUILD-MACHINE-IP-ADDR>:kernel.bin
$ load mmc 1:3 ${fdt_addr_r} dtbs/...-starfive/starfive/${fdtfile}
$ load mmc 1:3 ${fdt_addr_r} dtbs/6.6.20-starfive/starfive/${fdtfile}
$ fdt resize
$ booti ${loadaddr} ${initrd_addr_r}:<initrd-size> ${fdt_addr_r}
-246
View File
@@ -1,246 +0,0 @@
use std::marker::PhantomData;
use aead::{consts::U16, AeadInPlace};
use aes::cipher::{BlockCipher, BlockEncrypt, BlockSizeUser};
use aes_gcm::{KeyInit, KeySizeUser};
use chacha20poly1305::consts::U12;
use rustls::{
crypto::cipher::{
make_tls12_aad, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv,
KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce, OutboundOpaqueMessage,
OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm,
UnsupportedOperationError,
},
ConnectionTrafficSecrets, ContentType, ProtocolVersion,
};
use crate::cipher::{DecryptBufferAdapter, EncryptBufferAdapter};
pub(crate) struct AesGcm<Aes>(PhantomData<Aes>);
struct Tls13Cipher<Aes>(aes_gcm::AesGcm<Aes, U12>, Iv);
struct Tls12Cipher<Aes>(aes_gcm::AesGcm<Aes, U12>, Iv);
const AES_GCM_OVERHEAD: usize = 16;
pub(crate) static AES128GCM: AesGcm<aes::Aes128> = AesGcm(PhantomData);
pub(crate) static AES256GCM: AesGcm<aes::Aes256> = AesGcm(PhantomData);
pub(crate) trait AesExtractKeys {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets;
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets;
}
impl AesExtractKeys for aes::Aes128 {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes128Gcm { key, iv }
}
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets {
let _ = explicit;
ConnectionTrafficSecrets::Aes128Gcm {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
}
}
}
impl AesExtractKeys for aes::Aes256 {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes256Gcm { key, iv }
}
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets {
let _ = explicit;
ConnectionTrafficSecrets::Aes256Gcm {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
}
}
}
impl<Aes> Tls13AeadAlgorithm for AesGcm<Aes>
where
Aes: Send
+ Sync
+ AesExtractKeys
+ BlockCipher
+ BlockSizeUser<BlockSize = U16>
+ BlockEncrypt
+ 'static,
aes_gcm::AesGcm<Aes, U12>: KeySizeUser + KeyInit,
{
fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
Box::new(Tls13Cipher::<Aes>(
aes_gcm::AesGcm::new_from_slice(key.as_ref()).unwrap(),
iv,
))
}
fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
Box::new(Tls13Cipher::<Aes>(
aes_gcm::AesGcm::new_from_slice(key.as_ref()).unwrap(),
iv,
))
}
fn extract_keys(
&self,
key: AeadKey,
iv: Iv,
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
Ok(Aes::tls13_wrap_keys(key, iv))
}
fn key_len(&self) -> usize {
aes_gcm::AesGcm::<Aes, U12>::key_size()
}
}
impl<Aes> Tls12AeadAlgorithm for AesGcm<Aes>
where
Aes: Send
+ Sync
+ AesExtractKeys
+ BlockCipher
+ BlockSizeUser<BlockSize = U16>
+ BlockEncrypt
+ 'static,
aes_gcm::AesGcm<Aes, U12>: KeySizeUser + KeyInit,
{
fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter> {
let _ = extra;
Box::new(Tls12Cipher::<Aes>(
aes_gcm::AesGcm::new_from_slice(key.as_ref()).unwrap(),
Iv::copy(iv),
))
}
fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
Box::new(Tls12Cipher::<Aes>(
aes_gcm::AesGcm::new_from_slice(key.as_ref()).unwrap(),
Iv::copy(iv),
))
}
fn extract_keys(
&self,
key: AeadKey,
iv: &[u8],
explicit: &[u8],
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
Ok(Aes::tls12_wrap_keys(key, iv, explicit))
}
fn key_block_shape(&self) -> KeyBlockShape {
KeyBlockShape {
enc_key_len: aes_gcm::AesGcm::<Aes, U12>::key_size(),
fixed_iv_len: 12,
explicit_nonce_len: 0,
}
}
}
impl<Aes> MessageEncrypter for Tls13Cipher<Aes>
where
Aes: Send + Sync + BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
{
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
payload.extend_from_slice(&msg.typ.to_array());
let nonce = aes_gcm::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(total_len);
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| {
OutboundOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
)
})
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + 1 + AES_GCM_OVERHEAD
}
}
impl<Aes> MessageDecrypter for Tls13Cipher<Aes>
where
Aes: Send + Sync + BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
{
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &mut msg.payload;
let nonce = aes_gcm::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(payload.len());
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
msg.into_tls13_unpadded_message()
}
}
impl<Aes> MessageEncrypter for Tls12Cipher<Aes>
where
Aes: Send + Sync + BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
{
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
let nonce = chacha20poly1305::Nonce::from(Nonce::new(&self.1, 0).0);
let aad = make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len());
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + AES_GCM_OVERHEAD
}
}
impl<Aes> MessageDecrypter for Tls12Cipher<Aes>
where
Aes: Send + Sync + BlockCipher + BlockSizeUser<BlockSize = U16> + BlockEncrypt,
{
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &msg.payload;
let nonce = chacha20poly1305::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls12_aad(seq, msg.typ, msg.version, payload.len() - AES_GCM_OVERHEAD);
let payload = &mut msg.payload;
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
Ok(msg.into_plain_message())
}
}
@@ -1,183 +0,0 @@
use aead::AeadInPlace;
use chacha20poly1305::{KeyInit, KeySizeUser};
use rustls::{
crypto::cipher::{
make_tls12_aad, make_tls13_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv,
KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce, OutboundOpaqueMessage,
OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm, Tls13AeadAlgorithm,
UnsupportedOperationError,
},
ConnectionTrafficSecrets, ContentType, ProtocolVersion,
};
use crate::cipher::{DecryptBufferAdapter, EncryptBufferAdapter};
pub(crate) struct Chacha20Poly1305;
struct Tls13Cipher(chacha20poly1305::ChaCha20Poly1305, Iv);
struct Tls12Cipher(chacha20poly1305::ChaCha20Poly1305, Iv);
const CHACHA20POLY1305_OVERHEAD: usize = 16;
impl Tls13AeadAlgorithm for Chacha20Poly1305 {
fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
Box::new(Tls13Cipher(
chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()).unwrap(),
iv,
))
}
fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
Box::new(Tls13Cipher(
chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()).unwrap(),
iv,
))
}
fn key_len(&self) -> usize {
chacha20poly1305::ChaCha20Poly1305::key_size()
}
fn extract_keys(
&self,
key: AeadKey,
iv: Iv,
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv })
}
}
impl Tls12AeadAlgorithm for Chacha20Poly1305 {
fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter> {
let _ = extra;
Box::new(Tls12Cipher(
chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()).unwrap(),
Iv::copy(iv),
))
}
fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
Box::new(Tls12Cipher(
chacha20poly1305::ChaCha20Poly1305::new_from_slice(key.as_ref()).unwrap(),
Iv::copy(iv),
))
}
fn key_block_shape(&self) -> KeyBlockShape {
KeyBlockShape {
enc_key_len: 32,
fixed_iv_len: 12,
explicit_nonce_len: 0,
}
}
fn extract_keys(
&self,
key: AeadKey,
iv: &[u8],
explicit: &[u8],
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
let _ = explicit;
Ok(ConnectionTrafficSecrets::Chacha20Poly1305 {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
})
}
}
impl MessageEncrypter for Tls13Cipher {
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
payload.extend_from_slice(&msg.typ.to_array());
let nonce = aes_gcm::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(total_len);
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| {
OutboundOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
)
})
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + 1 + CHACHA20POLY1305_OVERHEAD
}
}
impl MessageDecrypter for Tls13Cipher {
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &mut msg.payload;
let nonce = aes_gcm::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(payload.len());
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
msg.into_tls13_unpadded_message()
}
}
impl MessageEncrypter for Tls12Cipher {
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
let nonce = chacha20poly1305::Nonce::from(Nonce::new(&self.1, 0).0);
let aad = make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len());
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + CHACHA20POLY1305_OVERHEAD
}
}
impl MessageDecrypter for Tls12Cipher {
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &msg.payload;
let nonce = chacha20poly1305::Nonce::from(Nonce::new(&self.1, seq).0);
let aad = make_tls12_aad(
seq,
msg.typ,
msg.version,
payload.len() - CHACHA20POLY1305_OVERHEAD,
);
let payload = &mut msg.payload;
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
Ok(msg.into_plain_message())
}
}
+69
View File
@@ -0,0 +1,69 @@
use std::marker::PhantomData;
use aes::cipher::typenum;
use rustls::{
crypto::cipher::{AeadKey, Iv},
ConnectionTrafficSecrets,
};
use crate::{
cipher::TlsAeadCipherAlgorithm,
traits::{AeadDataInput, TlsExtractKeys},
};
pub static TLS_AES128GCM: TlsAeadCipherAlgorithm<aes_gcm::AesGcm<aes::Aes128, typenum::U12>> =
TlsAeadCipherAlgorithm(PhantomData);
pub static TLS_AES256GCM: TlsAeadCipherAlgorithm<aes_gcm::AesGcm<aes::Aes256, typenum::U12>> =
TlsAeadCipherAlgorithm(PhantomData);
pub static TLS_CHACHA20POLY1305: TlsAeadCipherAlgorithm<chacha20poly1305::ChaCha20Poly1305> =
TlsAeadCipherAlgorithm(PhantomData);
impl TlsExtractKeys for aes_gcm::AesGcm<aes::Aes128, typenum::U12> {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes128Gcm { key, iv }
}
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets {
let _ = explicit;
ConnectionTrafficSecrets::Aes128Gcm {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
}
}
}
impl TlsExtractKeys for aes_gcm::AesGcm<aes::Aes256, typenum::U12> {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Aes256Gcm { key, iv }
}
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets {
let _ = explicit;
ConnectionTrafficSecrets::Aes256Gcm {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
}
}
}
impl TlsExtractKeys for chacha20poly1305::ChaCha20Poly1305 {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets {
ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }
}
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets {
let _ = explicit;
ConnectionTrafficSecrets::Chacha20Poly1305 {
key,
iv: Iv::new(iv[..].try_into().unwrap()),
}
}
}
impl<Aes> AeadDataInput for aes_gcm::AesGcm<Aes, typenum::U12> {
const ENCRYPTED_OVERHEAD: usize = 16;
}
impl AeadDataInput for chacha20poly1305::ChaCha20Poly1305 {
const ENCRYPTED_OVERHEAD: usize = 16;
}
+200 -3
View File
@@ -1,7 +1,26 @@
use rustls::crypto::cipher::{BorrowedPayload, PrefixedPayload};
use std::marker::PhantomData;
pub mod aes_gcm;
pub mod chacha20poly1305;
use aead::{generic_array::GenericArray, AeadInPlace, KeyInit};
use rustls::{
crypto::cipher::{
make_tls12_aad, make_tls13_aad, AeadKey, BorrowedPayload, InboundOpaqueMessage,
InboundPlainMessage, Iv, KeyBlockShape, MessageDecrypter, MessageEncrypter, Nonce,
OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, Tls12AeadAlgorithm,
Tls13AeadAlgorithm, UnsupportedOperationError,
},
ConnectionTrafficSecrets, ContentType, ProtocolVersion,
};
use crate::traits::{AeadDataInput, TlsExtractKeys};
mod imp;
pub use imp::*;
pub(crate) struct Tls13Cipher<Aead>(pub Aead, pub Iv);
pub(crate) struct Tls12Cipher<Aead>(pub Aead, pub Iv);
pub struct TlsAeadCipherAlgorithm<Aead>(PhantomData<Aead>);
struct EncryptBufferAdapter<'a>(&'a mut PrefixedPayload);
struct DecryptBufferAdapter<'a, 'p>(&'a mut BorrowedPayload<'p>);
@@ -51,3 +70,181 @@ impl aead::Buffer for DecryptBufferAdapter<'_, '_> {
self.0.truncate(len);
}
}
impl<Aead> MessageEncrypter for Tls13Cipher<Aead>
where
Aead: Send + Sync + AeadInPlace + AeadDataInput + 'static,
GenericArray<u8, Aead::NonceSize>: From<[u8; 12]>,
{
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
payload.extend_from_slice(&msg.typ.to_array());
let nonce = aead::Nonce::<Aead>::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(total_len);
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| {
OutboundOpaqueMessage::new(
ContentType::ApplicationData,
ProtocolVersion::TLSv1_2,
payload,
)
})
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + Aead::ENCRYPTED_OVERHEAD + 1
}
}
impl<Aead> MessageDecrypter for Tls13Cipher<Aead>
where
Aead: Send + Sync + AeadInPlace + AeadDataInput + 'static,
GenericArray<u8, Aead::NonceSize>: From<[u8; 12]>,
{
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &mut msg.payload;
let nonce = aead::Nonce::<Aead>::from(Nonce::new(&self.1, seq).0);
let aad = make_tls13_aad(payload.len());
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
msg.into_tls13_unpadded_message()
}
}
impl<Aead> MessageEncrypter for Tls12Cipher<Aead>
where
Aead: Send + Sync + AeadInPlace + AeadDataInput + 'static,
GenericArray<u8, Aead::NonceSize>: From<[u8; 12]>,
{
fn encrypt(
&mut self,
msg: OutboundPlainMessage<'_>,
seq: u64,
) -> Result<OutboundOpaqueMessage, rustls::Error> {
let total_len = self.encrypted_payload_len(msg.payload.len());
let mut payload = PrefixedPayload::with_capacity(total_len);
payload.extend_from_chunks(&msg.payload);
let nonce = aead::Nonce::<Aead>::from(Nonce::new(&self.1, 0).0);
let aad = make_tls12_aad(seq, msg.typ, msg.version, msg.payload.len());
self.0
.encrypt_in_place(&nonce, &aad, &mut EncryptBufferAdapter(&mut payload))
.map_err(|_| rustls::Error::EncryptError)
.map(|_| OutboundOpaqueMessage::new(msg.typ, msg.version, payload))
}
fn encrypted_payload_len(&self, payload_len: usize) -> usize {
payload_len + Aead::ENCRYPTED_OVERHEAD
}
}
impl<Aead> MessageDecrypter for Tls12Cipher<Aead>
where
Aead: Send + Sync + AeadInPlace + AeadDataInput + 'static,
GenericArray<u8, Aead::NonceSize>: From<[u8; 12]>,
{
fn decrypt<'a>(
&mut self,
mut msg: InboundOpaqueMessage<'a>,
seq: u64,
) -> Result<InboundPlainMessage<'a>, rustls::Error> {
let payload = &msg.payload;
let nonce = aead::Nonce::<Aead>::from(Nonce::new(&self.1, seq).0);
let aad = make_tls12_aad(
seq,
msg.typ,
msg.version,
payload.len() - Aead::ENCRYPTED_OVERHEAD,
);
let payload = &mut msg.payload;
self.0
.decrypt_in_place(&nonce, &aad, &mut DecryptBufferAdapter(payload))
.map_err(|_| rustls::Error::DecryptError)?;
Ok(msg.into_plain_message())
}
}
impl<Aead> Tls13AeadAlgorithm for TlsAeadCipherAlgorithm<Aead>
where
Aead: Send + Sync + TlsExtractKeys + KeyInit + 'static,
Tls13Cipher<Aead>: MessageEncrypter + MessageDecrypter,
{
fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> {
let aead = Aead::new_from_slice(key.as_ref()).unwrap();
let cipher = Tls13Cipher::<Aead>(aead, iv);
Box::new(cipher)
}
fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> {
let aead = Aead::new_from_slice(key.as_ref()).unwrap();
let cipher = Tls13Cipher::<Aead>(aead, iv);
Box::new(cipher)
}
fn key_len(&self) -> usize {
Aead::key_size()
}
fn extract_keys(
&self,
key: AeadKey,
iv: Iv,
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
Ok(Aead::tls13_wrap_keys(key, iv))
}
}
impl<Aead> Tls12AeadAlgorithm for TlsAeadCipherAlgorithm<Aead>
where
Aead: Send + Sync + TlsExtractKeys + KeyInit + 'static,
Tls12Cipher<Aead>: MessageEncrypter + MessageDecrypter,
{
fn encrypter(&self, key: AeadKey, iv: &[u8], _extra: &[u8]) -> Box<dyn MessageEncrypter> {
let aead = Aead::new_from_slice(key.as_ref()).unwrap();
let cipher = Tls12Cipher::<Aead>(aead, Iv::copy(iv));
Box::new(cipher)
}
fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> {
let aead = Aead::new_from_slice(key.as_ref()).unwrap();
let cipher = Tls12Cipher::<Aead>(aead, Iv::copy(iv));
Box::new(cipher)
}
fn key_block_shape(&self) -> KeyBlockShape {
KeyBlockShape {
enc_key_len: Aead::key_size(),
fixed_iv_len: 12,
explicit_nonce_len: 0,
}
}
fn extract_keys(
&self,
key: AeadKey,
iv: &[u8],
explicit: &[u8],
) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> {
Ok(Aead::tls12_wrap_keys(key, iv, explicit))
}
}
+1
View File
@@ -11,6 +11,7 @@ pub mod hash;
pub mod hmac;
pub mod kx;
pub mod rustls;
pub mod traits;
pub mod verify;
pub fn rustls_client() -> ConfigBuilder<ClientConfig, WantsVersions> {
-205
View File
@@ -1,205 +0,0 @@
use std::sync::Arc;
use rand::RngCore;
use rustls::{
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
crypto::{
tls12, tls13, CryptoProvider, GetRandomFailed, KeyExchangeAlgorithm, KeyProvider,
SecureRandom, SupportedKxGroup, WebPkiSupportedAlgorithms,
},
pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime},
sign::SigningKey,
CipherSuite, CipherSuiteCommon, DigitallySignedStruct, SignatureScheme, SupportedCipherSuite,
Tls12CipherSuite, Tls13CipherSuite,
};
use crate::{cipher, hash, hmac, kx, verify};
#[derive(Debug)]
struct Provider;
#[derive(Debug)]
pub(crate) struct InsecureServerCertificateVerifier;
impl ServerCertVerifier for InsecureServerCertificateVerifier {
fn verify_server_cert(
&self,
end_entity: &CertificateDer<'_>,
intermediates: &[CertificateDer<'_>],
server_name: &ServerName<'_>,
ocsp_response: &[u8],
now: UnixTime,
) -> Result<ServerCertVerified, rustls::Error> {
let _ = (end_entity, intermediates, server_name, ocsp_response, now);
Ok(ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
let _ = (message, cert, dss);
Ok(HandshakeSignatureValid::assertion())
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
let _ = (message, cert, dss);
Ok(HandshakeSignatureValid::assertion())
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
SUPPORTED_SIGNATURE_SCHEMES.to_vec()
}
fn requires_raw_public_keys(&self) -> bool {
false
}
}
pub fn provider() -> CryptoProvider {
CryptoProvider {
cipher_suites: CIPHER_SUITES.to_vec(),
kx_groups: KX_GROUPS.to_vec(),
signature_verification_algorithms: SIGNATURE_VERIFICATION_ALGORITHMS,
secure_random: &Provider,
key_provider: &Provider,
}
}
impl SecureRandom for Provider {
fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
rand_core::OsRng
.try_fill_bytes(buf)
.map_err(|_| GetRandomFailed)
}
}
impl KeyProvider for Provider {
fn load_private_key(
&self,
key_der: PrivateKeyDer<'static>,
) -> Result<Arc<dyn SigningKey>, rustls::Error> {
let _ = key_der;
todo!("TODO: implement signing key provider for TLS")
}
}
static CIPHER_SUITES: &[SupportedCipherSuite] = &[
// TLSv1.3 suites
TLS13_CHACHA20POLY1305_SHA256,
TLS13_AES256GCM_SHA384,
TLS13_AES128GCM_SHA256,
// TLSv1.2 suites
TLS_ECDHE_RSA_WITH_CHACHA20POLY1305_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
];
static KX_GROUPS: &[&dyn SupportedKxGroup] = &[&kx::X25519];
static SIGNATURE_VERIFICATION_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
all: &[
verify::RSA_PSS_SHA256,
verify::RSA_PKCS1_SHA256,
verify::ECDSA_NISTP256_SHA256,
verify::ECDSA_NISTP384_SHA384,
],
mapping: &[
(SignatureScheme::RSA_PSS_SHA256, &[verify::RSA_PSS_SHA256]),
(
SignatureScheme::RSA_PKCS1_SHA256,
&[verify::RSA_PKCS1_SHA256],
),
(
SignatureScheme::ECDSA_NISTP256_SHA256,
&[verify::ECDSA_NISTP256_SHA256],
),
(
SignatureScheme::ECDSA_NISTP384_SHA384,
&[verify::ECDSA_NISTP384_SHA384],
),
],
};
static SUPPORTED_SIGNATURE_SCHEMES: &[SignatureScheme] = &[
SignatureScheme::RSA_PSS_SHA256,
SignatureScheme::RSA_PKCS1_SHA256,
SignatureScheme::ECDSA_NISTP256_SHA256,
SignatureScheme::ECDSA_NISTP384_SHA384,
];
// TLSv1.3
pub static TLS13_CHACHA20POLY1305_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: u64::MAX,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA256),
aead_alg: &cipher::chacha20poly1305::Chacha20Poly1305,
quic: None,
});
pub static TLS13_AES128GCM_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: 1 << 24,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA256),
aead_alg: &cipher::aes_gcm::AES128GCM,
quic: None,
});
pub static TLS13_AES256GCM_SHA384: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
hash_provider: &hash::SHA384,
confidentiality_limit: 1 << 24,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA384),
aead_alg: &cipher::aes_gcm::AES256GCM,
quic: None,
});
// TLSv1.2
pub static TLS_ECDHE_RSA_WITH_CHACHA20POLY1305_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: u64::MAX,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA256),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::chacha20poly1305::Chacha20Poly1305,
});
pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: 1 << 24,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA256),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::aes_gcm::AES128GCM,
});
pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
hash_provider: &hash::SHA384,
confidentiality_limit: 1 << 24,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA384),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::aes_gcm::AES256GCM,
});
@@ -0,0 +1,121 @@
use rustls::{
crypto::{tls12, tls13, KeyExchangeAlgorithm, SupportedKxGroup, WebPkiSupportedAlgorithms},
CipherSuite, CipherSuiteCommon, SignatureScheme, SupportedCipherSuite, Tls12CipherSuite,
Tls13CipherSuite,
};
use crate::{cipher, hash, hmac, kx, verify};
pub(super) static CIPHER_SUITES: &[SupportedCipherSuite] = &[
// TLSv1.3 suites
TLS13_CHACHA20POLY1305_SHA256,
TLS13_AES256GCM_SHA384,
TLS13_AES128GCM_SHA256,
// TLSv1.2 suites
TLS_ECDHE_RSA_WITH_CHACHA20POLY1305_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
];
pub(super) static KX_GROUPS: &[&dyn SupportedKxGroup] = &[&kx::X25519];
pub(super) static SIGNATURE_VERIFICATION_ALGORITHMS: WebPkiSupportedAlgorithms =
WebPkiSupportedAlgorithms {
all: &[
verify::RSA_PSS_SHA256,
verify::RSA_PKCS1_SHA256,
verify::ECDSA_NISTP256_SHA256,
verify::ECDSA_NISTP384_SHA384,
],
mapping: &[
(SignatureScheme::RSA_PSS_SHA256, &[verify::RSA_PSS_SHA256]),
(
SignatureScheme::RSA_PKCS1_SHA256,
&[verify::RSA_PKCS1_SHA256],
),
(
SignatureScheme::ECDSA_NISTP256_SHA256,
&[verify::ECDSA_NISTP256_SHA256],
),
(
SignatureScheme::ECDSA_NISTP384_SHA384,
&[verify::ECDSA_NISTP384_SHA384],
),
],
};
pub(super) static SUPPORTED_SIGNATURE_SCHEMES: &[SignatureScheme] = &[
SignatureScheme::RSA_PSS_SHA256,
SignatureScheme::RSA_PKCS1_SHA256,
SignatureScheme::ECDSA_NISTP256_SHA256,
SignatureScheme::ECDSA_NISTP384_SHA384,
];
// TLSv1.3
pub static TLS13_CHACHA20POLY1305_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: u64::MAX,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA256),
aead_alg: &cipher::TLS_CHACHA20POLY1305,
quic: None,
});
pub static TLS13_AES128GCM_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_AES_128_GCM_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: 1 << 24,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA256),
aead_alg: &cipher::TLS_AES128GCM,
quic: None,
});
pub static TLS13_AES256GCM_SHA384: SupportedCipherSuite =
SupportedCipherSuite::Tls13(&Tls13CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS13_AES_256_GCM_SHA384,
hash_provider: &hash::SHA384,
confidentiality_limit: 1 << 24,
},
hkdf_provider: &tls13::HkdfUsingHmac(&hmac::HMAC_SHA384),
aead_alg: &cipher::TLS_AES256GCM,
quic: None,
});
// TLSv1.2
pub static TLS_ECDHE_RSA_WITH_CHACHA20POLY1305_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: u64::MAX,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA256),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::TLS_CHACHA20POLY1305,
});
pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
hash_provider: &hash::SHA256,
confidentiality_limit: 1 << 24,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA256),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::TLS_AES128GCM,
});
pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
SupportedCipherSuite::Tls12(&Tls12CipherSuite {
common: CipherSuiteCommon {
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
hash_provider: &hash::SHA384,
confidentiality_limit: 1 << 24,
},
prf_provider: &tls12::PrfUsingHmac(&hmac::HMAC_SHA384),
kx: KeyExchangeAlgorithm::ECDHE,
sign: SUPPORTED_SIGNATURE_SCHEMES,
aead_alg: &cipher::TLS_AES256GCM,
});
+44
View File
@@ -0,0 +1,44 @@
use std::sync::Arc;
use rand::RngCore;
use rustls::{
crypto::{CryptoProvider, GetRandomFailed, KeyProvider, SecureRandom},
pki_types::PrivateKeyDer,
sign::SigningKey,
};
pub(crate) use verifier::InsecureServerCertificateVerifier;
mod algorithms;
mod verifier;
#[derive(Debug)]
struct Provider;
pub fn provider() -> CryptoProvider {
CryptoProvider {
cipher_suites: algorithms::CIPHER_SUITES.to_vec(),
kx_groups: algorithms::KX_GROUPS.to_vec(),
signature_verification_algorithms: algorithms::SIGNATURE_VERIFICATION_ALGORITHMS,
secure_random: &Provider,
key_provider: &Provider,
}
}
impl SecureRandom for Provider {
fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed> {
rand_core::OsRng
.try_fill_bytes(buf)
.map_err(|_| GetRandomFailed)
}
}
impl KeyProvider for Provider {
fn load_private_key(
&self,
key_der: PrivateKeyDer<'static>,
) -> Result<Arc<dyn SigningKey>, rustls::Error> {
let _ = key_der;
todo!("TODO: implement signing key provider for TLS")
}
}
@@ -0,0 +1,52 @@
use rustls::{
client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
pki_types::{CertificateDer, ServerName, UnixTime},
DigitallySignedStruct, SignatureScheme,
};
use crate::rustls::algorithms;
#[derive(Debug)]
pub(crate) struct InsecureServerCertificateVerifier;
impl ServerCertVerifier for InsecureServerCertificateVerifier {
fn verify_server_cert(
&self,
end_entity: &CertificateDer<'_>,
intermediates: &[CertificateDer<'_>],
server_name: &ServerName<'_>,
ocsp_response: &[u8],
now: UnixTime,
) -> Result<ServerCertVerified, rustls::Error> {
let _ = (end_entity, intermediates, server_name, ocsp_response, now);
Ok(ServerCertVerified::assertion())
}
fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
let _ = (message, cert, dss);
Ok(HandshakeSignatureValid::assertion())
}
fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
let _ = (message, cert, dss);
Ok(HandshakeSignatureValid::assertion())
}
fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
algorithms::SUPPORTED_SIGNATURE_SCHEMES.to_vec()
}
fn requires_raw_public_keys(&self) -> bool {
false
}
}
+17
View File
@@ -0,0 +1,17 @@
use rustls::{
crypto::cipher::{AeadKey, Iv},
ConnectionTrafficSecrets,
};
pub trait AeadDataInput {
const ENCRYPTED_OVERHEAD: usize;
}
pub trait IntoNonce<A: aead::AeadCore> {
fn into_nonce(self, seq: u64) -> aead::Nonce<A>;
}
pub trait TlsExtractKeys {
fn tls13_wrap_keys(key: AeadKey, iv: Iv) -> ConnectionTrafficSecrets;
fn tls12_wrap_keys(key: AeadKey, iv: &[u8], explicit: &[u8]) -> ConnectionTrafficSecrets;
}