//! Cryptographic operations. pub mod aead; pub mod keys; pub use seq::{SeqId, SeqIdGen}; use sha2::digest::{typenum::Unsigned, OutputSizeUser}; trait TlsHasher: OutputSizeUser { const ZEROED: &'static [u8]; fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength>; fn extract(salt: &[u8], ikm: &[u8]) -> Vec; } macro_rules! impl_hkdf_hasher { () => { const ZEROED: &'static [u8] = &[0; <::OutputSize as Unsigned>::USIZE]; fn expand(ikm: &[u8], label: &[u8], okm: &mut [u8]) -> Result<(), hkdf::InvalidLength> { hkdf::Hkdf::::new(None, ikm).expand(&label, okm) } fn extract(salt: &[u8], ikm: &[u8]) -> Vec { hkdf::Hkdf::::extract(Some(salt), ikm) .0 .as_slice() .to_vec() } }; } impl TlsHasher for sha2::Sha256 { impl_hkdf_hasher!(); } impl TlsHasher for sha2::Sha384 { impl_hkdf_hasher!(); } pub struct CryptoProvider { zeroed_of_hash_size: &'static [u8], hkdf_extract: fn(salt: &[u8], ikm: &[u8]) -> Vec, } impl CryptoProvider { fn new() -> Self { CryptoProvider { zeroed_of_hash_size: H::ZEROED, hkdf_extract: H::extract, } } } mod seq { use std::cell::Cell; use super::aead::{Nonce, TlsNonce}; /// The sequence ID generator. /// There is a separate one maintained for reading and writing. pub struct SeqIdGen { next: Cell, } impl SeqIdGen { pub fn new() -> SeqIdGen { SeqIdGen { next: Cell::new(0) } } pub fn next(&self) -> SeqId { let next = self.next.get(); self.next.set(next.checked_add(1).unwrap()); SeqId(next) } } // Don't implement `Clone` to ensure every seq id is only used once. pub struct SeqId(u64); impl SeqId { pub fn to_nonce(self) -> TlsNonce { // // 1. The 64-bit record sequence number is encoded in network byte // order and padded to the left with zeros to iv_length. let mut nonce = [0; 12]; nonce[4..12].copy_from_slice(&self.0.to_be_bytes()); let nonce = Nonce::from(nonce); TlsNonce::new(nonce) } } } #[allow(dead_code)] pub struct TlsInnerPlaintext { /// The `TLSPlaintext.fragment`` value pub content: Vec, /// The `TLSPlaintext.type` value pub content_type: u8, pub padding_len: u16, }