use x25519_dalek::EphemeralSecret;
use crate::bytes::{ByteBuffer, BytePool, DynamicByteBuffer, FixedByteBuffer};
use crate::certificate::ClientCertificate;
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
use crate::certificate::ObfuscationBufferContainer;
use crate::crypto::error::{CryptoError, HandshakeError};
use crate::crypto::symmetric::{ObfuscationTranscript, Symmetric};
use crate::tailer::IdentityType;
pub(crate) struct ClientData {
pub ephemeral_key: EphemeralSecret,
pub shared_secret: FixedByteBuffer<32>,
pub nonce: FixedByteBuffer<32>,
pub initial_key: FixedByteBuffer<32>,
}
#[derive(Clone)]
pub struct ClientCryptoTool<T: IdentityType + Clone> {
cert: ClientCertificate,
identity: T,
key: Symmetric,
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
obfuscation_key: Symmetric,
}
impl<T: IdentityType + Clone> ClientCryptoTool<T> {
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub(crate) fn new(cert: ClientCertificate, identity: T, initial_key: &impl ByteBuffer) -> Self {
let obfs_buffer = cert.obfuscation_buffer();
Self {
cert,
identity,
key: Symmetric::new(initial_key),
obfuscation_key: Symmetric::new_split(&obfs_buffer, initial_key),
}
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub(crate) fn new(cert: ClientCertificate, identity: T, initial_key: &impl ByteBuffer) -> Self {
Self {
cert,
identity,
key: Symmetric::new(initial_key),
}
}
#[inline]
pub fn identity(&self) -> T {
self.identity.clone()
}
pub(crate) fn create_handshake(&self, pool: &BytePool, initial_data: &[u8]) -> (ClientData, DynamicByteBuffer, FixedByteBuffer<32>) {
self.cert.encapsulate_handshake_client(pool, initial_data)
}
pub(crate) fn process_handshake_response(&self, data: ClientData, handshake_secret: DynamicByteBuffer, pool: &BytePool) -> Result<(FixedByteBuffer<32>, DynamicByteBuffer), HandshakeError> {
self.cert.decapsulate_handshake_client(data, handshake_secret, pool)
}
pub fn encrypt_payload(&mut self, plaintext: DynamicByteBuffer, additional_data: Option<&DynamicByteBuffer>) -> Result<DynamicByteBuffer, CryptoError> {
self.key.encrypt_auth(plaintext, additional_data)
}
pub fn decrypt_payload(&mut self, ciphertext: DynamicByteBuffer, additional_data: Option<&DynamicByteBuffer>) -> Result<DynamicByteBuffer, CryptoError> {
self.key.decrypt_auth(ciphertext, additional_data)
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn obfuscate_tailer(&mut self, plaintext: DynamicByteBuffer, _: &BytePool) -> Result<DynamicByteBuffer, CryptoError> {
self.obfuscation_key.encrypt_auth(plaintext, None::<&DynamicByteBuffer>)
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn obfuscate_tailer(&mut self, plaintext: DynamicByteBuffer, pool: &BytePool) -> Result<DynamicByteBuffer, CryptoError> {
self.cert.encrypt_obfuscate(plaintext, pool).map_err(|e| CryptoError::authentication_error(&e.to_string()))
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn deobfuscate_tailer(&mut self, ciphertext: DynamicByteBuffer, pool: &BytePool) -> Result<(DynamicByteBuffer, ObfuscationTranscript), CryptoError> {
self.obfuscation_key.decrypt_no_verify(ciphertext, pool)
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn deobfuscate_tailer(&mut self, ciphertext: DynamicByteBuffer, _pool: &BytePool) -> Result<(DynamicByteBuffer, ObfuscationTranscript), CryptoError> {
self.key.decrypt_auth(ciphertext, None::<&DynamicByteBuffer>).map(|r| (r, ObfuscationTranscript {}))
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn verify_tailer(&mut self, transcript: ObfuscationTranscript) -> Result<(), CryptoError> {
self.obfuscation_key.verify_decrypted(transcript, None::<&DynamicByteBuffer>)
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn verify_tailer(&mut self, _: ObfuscationTranscript) -> Result<(), CryptoError> {
Ok(())
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn with_key(&self, new_key: &impl ByteBuffer) -> Self {
let obfs_buffer = self.cert.obfuscation_buffer();
Self {
cert: self.cert.clone(),
identity: self.identity.clone(),
key: Symmetric::new(new_key),
obfuscation_key: Symmetric::new_split(&obfs_buffer, new_key),
}
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn with_key(&self, new_key: &impl ByteBuffer) -> Self {
Self {
cert: self.cert.clone(),
identity: self.identity.clone(),
key: Symmetric::new(new_key),
}
}
#[cfg(any(feature = "fast_software", feature = "fast_hardware"))]
pub fn with_key_and_identity(&self, new_key: &impl ByteBuffer, new_identity: T) -> Self {
let obfs_buffer = self.cert.obfuscation_buffer();
Self {
cert: self.cert.clone(),
identity: new_identity,
key: Symmetric::new(new_key),
obfuscation_key: Symmetric::new_split(&obfs_buffer, new_key),
}
}
#[cfg(any(feature = "full_software", feature = "full_hardware"))]
pub fn with_key_and_identity(&self, new_key: &impl ByteBuffer, new_identity: T) -> Self {
Self {
cert: self.cert.clone(),
identity: new_identity,
key: Symmetric::new(new_key),
}
}
}