| // Copyright 2026 The BoringSSL Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| use alloc::boxed::Box; |
| use core::marker::PhantomData; |
| |
| use rustls::{ |
| ConnectionTrafficSecrets, ContentType, Error, ProtocolVersion, |
| crypto::cipher::{ |
| AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape, MessageDecrypter, |
| MessageEncrypter, OutboundOpaqueMessage, OutboundPlainMessage, PrefixedPayload, |
| Tls12AeadAlgorithm, Tls13AeadAlgorithm, UnsupportedOperationError, make_tls12_aad, |
| make_tls13_aad, |
| }, |
| }; |
| |
| use bssl_crypto::aead; |
| |
| struct Tls12AdditionalData; |
| |
| impl TlsAdditionalData for Tls12AdditionalData { |
| #[inline] |
| fn build_additional_data( |
| seq: u64, |
| typ: ContentType, |
| version: ProtocolVersion, |
| len: usize, |
| ad_buf: &mut [u8], |
| ) -> Option<&[u8]> { |
| let ad_buf: &mut [u8; 13] = ad_buf.try_into().ok()?; |
| ad_buf.copy_from_slice(&make_tls12_aad(seq, typ, version, len)); |
| Some(ad_buf) |
| } |
| } |
| |
| const NONCE_LEN: usize = 12; |
| |
| enum AeadKind { |
| Aes128Gcm, |
| Aes256Gcm, |
| Chacha20Poly1305, |
| } |
| |
| trait AeadConstructible: aead::Aead + Sized { |
| const KEY_LEN: usize; |
| const TAG_LEN: usize; |
| const KIND: AeadKind; |
| fn new_with_key(key: &AeadKey) -> Option<Self>; |
| fn nonce_from_buf(buf: &[u8]) -> Option<&Self::Nonce>; |
| fn tag_from_buf(buf: &[u8]) -> Option<&Self::Tag>; |
| fn tag_to_buf(tag: &Self::Tag) -> &[u8]; |
| } |
| |
| fn make_nonce_from_iv_seq(iv: [u8; NONCE_LEN], seq: u64) -> [u8; NONCE_LEN] { |
| let mut buf = [0; NONCE_LEN]; |
| buf[4..].copy_from_slice(&seq.to_be_bytes()); |
| for i in 0..NONCE_LEN { |
| buf[i] ^= iv[i]; |
| } |
| buf |
| } |
| |
| macro_rules! aead_ctor { |
| ($($algo:ty : { |
| key = $key_len:literal, |
| tag = $tag_len:literal, |
| kind = $kind:expr |
| }),+) => { $( |
| impl AeadConstructible for $algo { |
| const KEY_LEN: usize = $key_len; |
| const TAG_LEN: usize = $tag_len; |
| const KIND: AeadKind = $kind; |
| fn new_with_key(key: &AeadKey) -> Option<Self> { |
| let key: [u8; $key_len] = key.as_ref().try_into().ok()?; |
| Some(Self::new(&key)) |
| } |
| fn nonce_from_buf(buf: &[u8]) -> Option<&[u8; NONCE_LEN]> { |
| buf.try_into().ok() |
| } |
| fn tag_from_buf(buf: &[u8]) -> Option<&[u8; $tag_len]> { |
| buf.try_into().ok() |
| } |
| fn tag_to_buf(tag: &[u8; $tag_len]) -> &[u8] { |
| &*tag |
| } |
| } |
| )+ }; |
| () => {}; |
| ($($algo:ty : $tt:tt),+,) => { aead_ctor!($($algo : $tt),+); } |
| } |
| |
| aead_ctor!( |
| aead::Aes128Gcm : {key = 16, tag = 16, kind = AeadKind::Aes128Gcm}, |
| aead::Aes256Gcm : {key = 32, tag = 16, kind = AeadKind::Aes256Gcm}, |
| aead::Chacha20Poly1305 : {key = 32, tag = 16, kind = AeadKind::Chacha20Poly1305}, |
| ); |
| |
| trait Gcm: AeadConstructible {} |
| impl Gcm for aead::Aes128Gcm {} |
| impl Gcm for aead::Aes256Gcm {} |
| |
| trait Chacha20: AeadConstructible {} |
| impl Chacha20 for aead::Chacha20Poly1305 {} |
| |
| // =================================================== |
| // TLS 1.2 AES GCM cipher |
| // =================================================== |
| |
| enum MaybeValidByteArray<const N: usize> { |
| Valid([u8; N]), |
| Invalid, |
| } |
| |
| impl<const N: usize> From<&'_ [u8]> for MaybeValidByteArray<N> { |
| fn from(value: &[u8]) -> Self { |
| if let Ok(value) = value.try_into() { |
| Self::Valid(value) |
| } else { |
| Self::Invalid |
| } |
| } |
| } |
| |
| struct Tls12GcmMessageEncrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<4>, |
| explicit_nonce: MaybeValidByteArray<8>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| trait TlsAdditionalData { |
| fn build_additional_data( |
| seq: u64, |
| typ: ContentType, |
| version: ProtocolVersion, |
| len: usize, |
| ad_buf: &mut [u8], |
| ) -> Option<&[u8]>; |
| } |
| |
| const TLS12_AAD_SIZE: usize = 13; |
| const TLS12_GCM_EXTRA_NONCE_SIZE: usize = 8; |
| |
| #[inline] |
| fn gcm_iv(iv: &[u8; 4], extra: &[u8; TLS12_GCM_EXTRA_NONCE_SIZE]) -> [u8; NONCE_LEN] { |
| let mut gcm_iv = [0; NONCE_LEN]; |
| gcm_iv[..4].copy_from_slice(iv); |
| gcm_iv[4..].copy_from_slice(extra); |
| gcm_iv |
| } |
| |
| const GCM_EXPLICIT_NONCE_LEN: usize = 8; |
| |
| impl<A: Gcm, AD: TlsAdditionalData> MessageEncrypter for Tls12GcmMessageEncrypter<A, AD> { |
| fn encrypt( |
| &mut self, |
| msg: OutboundPlainMessage<'_>, |
| seq: u64, |
| ) -> Result<OutboundOpaqueMessage, Error> { |
| let payload_len = msg.payload.len(); |
| let mut payload = PrefixedPayload::with_capacity(self.encrypted_payload_len(payload_len)); |
| let aead = A::new_with_key(&self.key).ok_or(Error::EncryptError)?; |
| let (MaybeValidByteArray::Valid(iv), MaybeValidByteArray::Valid(explicit_nonce)) = |
| (&self.iv, &self.explicit_nonce) |
| else { |
| return Err(Error::DecryptError); |
| }; |
| let write_iv = gcm_iv(iv, explicit_nonce); |
| let nonce = make_nonce_from_iv_seq(write_iv, seq); |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::EncryptError)?; |
| let mut ad_buf = [0; TLS12_AAD_SIZE]; |
| let ad = AD::build_additional_data(seq, msg.typ, msg.version, payload_len, &mut ad_buf) |
| .ok_or(Error::EncryptError)?; |
| payload.extend_from_slice(&nonce.as_ref()[4..]); |
| payload.extend_from_chunks(&msg.payload); |
| let tag = aead.seal_in_place( |
| &nonce, |
| &mut payload.as_mut()[GCM_EXPLICIT_NONCE_LEN..GCM_EXPLICIT_NONCE_LEN + payload_len], |
| ad, |
| ); |
| payload.extend_from_slice(A::tag_to_buf(&tag)); |
| Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload)) |
| } |
| |
| fn encrypted_payload_len(&self, payload_len: usize) -> usize { |
| payload_len + GCM_EXPLICIT_NONCE_LEN + A::TAG_LEN |
| } |
| } |
| |
| struct Tls12GcmMessageDecrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<4>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| impl<A: Gcm, AD: TlsAdditionalData> MessageDecrypter for Tls12GcmMessageDecrypter<A, AD> { |
| fn decrypt<'a>( |
| &mut self, |
| mut msg: InboundOpaqueMessage<'a>, |
| seq: u64, |
| ) -> Result<InboundPlainMessage<'a>, Error> { |
| let aead = A::new_with_key(&self.key).ok_or(Error::DecryptError)?; |
| let InboundOpaqueMessage { |
| typ, |
| version, |
| ref mut payload, |
| } = msg; |
| let Some((explicit_nonce, payload)) = payload.split_at_mut_checked(GCM_EXPLICIT_NONCE_LEN) |
| else { |
| return Err(Error::DecryptError); |
| }; |
| let Ok(extra) = explicit_nonce.try_into() else { |
| unreachable!("length should be 8") |
| }; |
| let MaybeValidByteArray::Valid(iv) = &self.iv else { |
| return Err(Error::DecryptError); |
| }; |
| let nonce = gcm_iv(iv, &extra); |
| let Some(ctxt_len) = payload.len().checked_sub(A::TAG_LEN) else { |
| return Err(Error::DecryptError); |
| }; |
| // TODO(@xfding) Should we check the fragment size? |
| let Some((ciphertext, tag)) = payload.split_at_mut_checked(ctxt_len) else { |
| return Err(Error::DecryptError); |
| }; |
| let mut ad_buf = [0; TLS12_AAD_SIZE]; |
| let ad = AD::build_additional_data(seq, typ, version, ctxt_len, &mut ad_buf) |
| .ok_or(Error::DecryptError)?; |
| let tag = A::tag_from_buf(tag).ok_or(Error::DecryptError)?; |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::DecryptError)?; |
| aead.open_in_place(&nonce, ciphertext, &tag, ad) |
| .map_err(|_| Error::DecryptError)?; |
| Ok(msg.into_plain_message_range(GCM_EXPLICIT_NONCE_LEN..GCM_EXPLICIT_NONCE_LEN + ctxt_len)) |
| } |
| } |
| |
| struct Tls12GcmAeadAlgorithm<A>(PhantomData<fn() -> A>); |
| |
| impl<A> Tls12GcmAeadAlgorithm<A> {} |
| |
| impl<A: 'static + Gcm> Tls12AeadAlgorithm for Tls12GcmAeadAlgorithm<A> { |
| fn encrypter(&self, key: AeadKey, iv: &[u8], extra: &[u8]) -> Box<dyn MessageEncrypter> { |
| Box::new(Tls12GcmMessageEncrypter::<A, Tls12AdditionalData> { |
| key, |
| iv: iv.into(), |
| explicit_nonce: extra.into(), |
| _p: PhantomData, |
| }) |
| } |
| |
| fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> { |
| Box::new(Tls12GcmMessageDecrypter::<A, Tls12AdditionalData> { |
| key, |
| iv: iv.into(), |
| _p: PhantomData, |
| }) |
| } |
| |
| fn key_block_shape(&self) -> KeyBlockShape { |
| KeyBlockShape { |
| enc_key_len: A::KEY_LEN, |
| fixed_iv_len: 4, |
| explicit_nonce_len: 8, |
| } |
| } |
| |
| fn extract_keys( |
| &self, |
| key: AeadKey, |
| iv: &[u8], |
| explicit: &[u8], |
| ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> { |
| let iv = Iv::new(gcm_iv( |
| iv.try_into().map_err(|_| UnsupportedOperationError)?, |
| explicit.try_into().map_err(|_| UnsupportedOperationError)?, |
| )); |
| Ok(match A::KEY_LEN { |
| 16 => ConnectionTrafficSecrets::Aes128Gcm { key, iv }, |
| 32 => ConnectionTrafficSecrets::Aes256Gcm { key, iv }, |
| _ => unreachable!(), |
| }) |
| } |
| } |
| |
| /// TLS 1.2 AEAD scheme AES 128 GCM |
| pub(crate) const TLS12_AES_128_GCM_AEAD: &'static dyn Tls12AeadAlgorithm = |
| &Tls12GcmAeadAlgorithm::<aead::Aes128Gcm>(PhantomData); |
| |
| /// TLS 1.2 AEAD scheme AES 256 GCM |
| pub(crate) const TLS12_AES_256_GCM_AEAD: &'static dyn Tls12AeadAlgorithm = |
| &Tls12GcmAeadAlgorithm::<aead::Aes256Gcm>(PhantomData); |
| |
| // =================================================== |
| // TLS 1.2 ChaCha20 cipher |
| // =================================================== |
| |
| struct Tls12Chacha20PolyMessageEncrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<NONCE_LEN>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| impl<A: Chacha20, AD: TlsAdditionalData> MessageEncrypter |
| for Tls12Chacha20PolyMessageEncrypter<A, AD> |
| { |
| fn encrypt( |
| &mut self, |
| msg: OutboundPlainMessage<'_>, |
| seq: u64, |
| ) -> Result<OutboundOpaqueMessage, Error> { |
| let payload_len = msg.payload.len(); |
| let mut payload = PrefixedPayload::with_capacity(self.encrypted_payload_len(payload_len)); |
| let aead = A::new_with_key(&self.key).ok_or(Error::EncryptError)?; |
| let MaybeValidByteArray::Valid(iv) = self.iv else { |
| return Err(Error::EncryptError); |
| }; |
| let nonce = make_nonce_from_iv_seq(iv, seq); |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::EncryptError)?; |
| let mut ad_buf = [0; TLS12_AAD_SIZE]; |
| let ad = AD::build_additional_data(seq, msg.typ, msg.version, payload_len, &mut ad_buf) |
| .ok_or(Error::EncryptError)?; |
| payload.extend_from_chunks(&msg.payload); |
| let tag = aead.seal_in_place(&nonce, &mut payload.as_mut()[..payload_len], ad); |
| payload.extend_from_slice(A::tag_to_buf(&tag)); |
| Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload)) |
| } |
| |
| fn encrypted_payload_len(&self, payload_len: usize) -> usize { |
| payload_len + A::TAG_LEN |
| } |
| } |
| |
| struct Tls12Chacha20PolyMessageDecrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<NONCE_LEN>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| impl<A: Chacha20, AD: TlsAdditionalData> MessageDecrypter |
| for Tls12Chacha20PolyMessageDecrypter<A, AD> |
| { |
| fn decrypt<'a>( |
| &mut self, |
| mut msg: InboundOpaqueMessage<'a>, |
| seq: u64, |
| ) -> Result<InboundPlainMessage<'a>, Error> { |
| let aead = A::new_with_key(&self.key).ok_or(Error::DecryptError)?; |
| let MaybeValidByteArray::Valid(iv) = self.iv else { |
| return Err(Error::DecryptError); |
| }; |
| let nonce = make_nonce_from_iv_seq(iv, seq); |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::DecryptError)?; |
| let mut ad_buf = [0; TLS12_AAD_SIZE]; |
| let Some(ctxt_len) = msg.payload.len().checked_sub(A::TAG_LEN) else { |
| return Err(Error::DecryptError); |
| }; |
| let ad = AD::build_additional_data(seq, msg.typ, msg.version, ctxt_len, &mut ad_buf) |
| .ok_or(Error::DecryptError)?; |
| // TODO(@xfding) Should we check the fragment size? |
| let Some((ciphertext, tag)) = msg.payload.split_at_mut_checked(ctxt_len) else { |
| return Err(Error::DecryptError); |
| }; |
| let tag = A::tag_from_buf(tag).ok_or(Error::DecryptError)?; |
| aead.open_in_place(&nonce, ciphertext, tag, ad) |
| .map_err(|_| Error::DecryptError)?; |
| Ok(msg.into_plain_message_range(0..ctxt_len)) |
| } |
| } |
| |
| struct Tls12Chacha20AeadAlgorithm<A>(PhantomData<fn() -> A>); |
| |
| impl<A: 'static + Chacha20> Tls12AeadAlgorithm for Tls12Chacha20AeadAlgorithm<A> { |
| fn encrypter(&self, key: AeadKey, iv: &[u8], _extra: &[u8]) -> Box<dyn MessageEncrypter> { |
| Box::new( |
| Tls12Chacha20PolyMessageEncrypter::<A, Tls12AdditionalData> { |
| key, |
| iv: iv.into(), |
| _p: PhantomData, |
| }, |
| ) |
| } |
| |
| fn decrypter(&self, key: AeadKey, iv: &[u8]) -> Box<dyn MessageDecrypter> { |
| Box::new( |
| Tls12Chacha20PolyMessageDecrypter::<A, Tls12AdditionalData> { |
| key, |
| iv: iv.into(), |
| _p: PhantomData, |
| }, |
| ) |
| } |
| |
| 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 iv = Iv::new(iv.try_into().map_err(|_| UnsupportedOperationError)?); |
| Ok(ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }) |
| } |
| |
| fn fips(&self) -> bool { |
| false |
| } |
| } |
| |
| /// TLS 1.2 AEAD cipher with Chacha202-Poly1305 |
| pub(crate) static TLS12_CHACHA20_POLY1305_AEAD: &'static dyn Tls12AeadAlgorithm = |
| &Tls12Chacha20AeadAlgorithm::<aead::Chacha20Poly1305>(PhantomData); |
| |
| // =================================================== |
| // TLS 1.3 AEAD cipher family |
| // =================================================== |
| |
| struct Tls13AdditionalData; |
| |
| impl TlsAdditionalData for Tls13AdditionalData { |
| #[inline] |
| fn build_additional_data<'a>( |
| _seq: u64, |
| _typ: ContentType, |
| _version: ProtocolVersion, |
| len: usize, |
| ad_buf: &'a mut [u8], |
| ) -> Option<&'a [u8]> { |
| let ad_buf: &mut [u8; 5] = ad_buf.try_into().ok()?; |
| ad_buf.copy_from_slice(&make_tls13_aad(len)); |
| Some(ad_buf) |
| } |
| } |
| |
| /// TLS 1.3 Cipher suite TLS13_AES_128_GCM |
| pub(crate) const TLS13_AES_128_GCM: &'static dyn Tls13AeadAlgorithm = |
| &Tls13AeadAlgorithmImpl::<aead::Aes128Gcm>(PhantomData); |
| |
| /// TLS 1.3 Cipher suite TLS13_AES_256_GCM |
| pub(crate) const TLS13_AES_256_GCM: &'static dyn Tls13AeadAlgorithm = |
| &Tls13AeadAlgorithmImpl::<aead::Aes256Gcm>(PhantomData); |
| |
| /// TLS 1.3 Cipher suite TLS13_CHACHA20_POLY1305 |
| pub(crate) const TLS13_CHACHA20_POLY1305: &'static dyn Tls13AeadAlgorithm = |
| &Tls13AeadAlgorithmImpl::<aead::Chacha20Poly1305>(PhantomData); |
| |
| const TLS13_AAD_SIZE: usize = 5; |
| |
| struct Tls13MessageEncrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<NONCE_LEN>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| impl<A: AeadConstructible, AD: TlsAdditionalData> MessageEncrypter |
| for Tls13MessageEncrypter<A, AD> |
| { |
| fn encrypt( |
| &mut self, |
| msg: OutboundPlainMessage<'_>, |
| seq: u64, |
| ) -> Result<OutboundOpaqueMessage, Error> { |
| let plaintxt_len = msg.payload.len(); |
| let payload_len = self.encrypted_payload_len(plaintxt_len); |
| let mut payload = PrefixedPayload::with_capacity(payload_len); |
| let aead = A::new_with_key(&self.key).ok_or(Error::EncryptError)?; |
| let MaybeValidByteArray::Valid(iv) = self.iv else { |
| return Err(Error::EncryptError); |
| }; |
| let nonce = make_nonce_from_iv_seq(iv, seq); |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::EncryptError)?; |
| let mut ad_buf = [0; TLS13_AAD_SIZE]; |
| let ad = AD::build_additional_data(seq, msg.typ, msg.version, payload_len, &mut ad_buf) |
| .ok_or(Error::EncryptError)?; |
| // Layout: [<..PAYLOAD, TYPE (size 1)>, TAG (size TAG_LEN)] |
| payload.extend_from_chunks(&msg.payload); |
| payload.extend_from_slice(&msg.typ.to_array()); |
| let tag = aead.seal_in_place(&nonce, &mut payload.as_mut()[0..plaintxt_len + 1], ad); |
| payload.extend_from_slice(A::tag_to_buf(&tag)); |
| Ok(OutboundOpaqueMessage::new(msg.typ, msg.version, payload)) |
| } |
| |
| fn encrypted_payload_len(&self, payload_len: usize) -> usize { |
| payload_len + A::TAG_LEN + 1 |
| } |
| } |
| |
| struct Tls13MessageDecrypter<A, AD> { |
| key: AeadKey, |
| iv: MaybeValidByteArray<NONCE_LEN>, |
| _p: PhantomData<fn() -> (A, AD)>, |
| } |
| |
| impl<A: AeadConstructible, AD: TlsAdditionalData> MessageDecrypter |
| for Tls13MessageDecrypter<A, AD> |
| { |
| fn decrypt<'a>( |
| &mut self, |
| mut msg: InboundOpaqueMessage<'a>, |
| seq: u64, |
| ) -> Result<InboundPlainMessage<'a>, Error> { |
| let aead = A::new_with_key(&self.key).ok_or(Error::DecryptError)?; |
| let MaybeValidByteArray::Valid(iv) = self.iv else { |
| return Err(Error::DecryptError); |
| }; |
| let nonce = make_nonce_from_iv_seq(iv, seq); |
| let nonce = A::nonce_from_buf(&nonce).ok_or(Error::DecryptError)?; |
| let InboundOpaqueMessage { |
| typ, |
| version, |
| ref mut payload, |
| } = msg; |
| // Layout: [<..PAYLOAD, TYPE (size 1)>, TAG (size TAG_LEN)] |
| let total_len = payload.len(); |
| let Some(ctxt_len) = total_len.checked_sub(A::TAG_LEN) else { |
| return Err(Error::DecryptError); |
| }; |
| let Some((ciphertext, tag)) = payload.split_at_mut_checked(ctxt_len) else { |
| return Err(Error::DecryptError); |
| }; |
| let mut ad_buf = [0; TLS13_AAD_SIZE]; |
| let ad = AD::build_additional_data(seq, typ, version, total_len, &mut ad_buf) |
| .ok_or(Error::DecryptError)?; |
| let tag = A::tag_from_buf(tag).ok_or(Error::DecryptError)?; |
| aead.open_in_place(&nonce, ciphertext, tag, ad) |
| .map_err(|_| Error::DecryptError)?; |
| payload.truncate(ctxt_len); |
| msg.into_tls13_unpadded_message() |
| } |
| } |
| |
| struct Tls13AeadAlgorithmImpl<A>(PhantomData<fn() -> A>); |
| |
| impl<A: 'static + AeadConstructible> Tls13AeadAlgorithm for Tls13AeadAlgorithmImpl<A> { |
| fn encrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageEncrypter> { |
| Box::new(Tls13MessageEncrypter::<A, Tls13AdditionalData> { |
| key, |
| iv: iv.as_ref().into(), |
| _p: PhantomData, |
| }) |
| } |
| |
| fn decrypter(&self, key: AeadKey, iv: Iv) -> Box<dyn MessageDecrypter> { |
| Box::new(Tls13MessageDecrypter::<A, Tls13AdditionalData> { |
| key, |
| iv: iv.as_ref().into(), |
| _p: PhantomData, |
| }) |
| } |
| |
| fn key_len(&self) -> usize { |
| A::KEY_LEN |
| } |
| |
| fn extract_keys( |
| &self, |
| key: AeadKey, |
| iv: Iv, |
| ) -> Result<ConnectionTrafficSecrets, UnsupportedOperationError> { |
| Ok(match A::KIND { |
| AeadKind::Aes128Gcm => ConnectionTrafficSecrets::Aes128Gcm { key, iv }, |
| AeadKind::Aes256Gcm => ConnectionTrafficSecrets::Aes256Gcm { key, iv }, |
| AeadKind::Chacha20Poly1305 => ConnectionTrafficSecrets::Chacha20Poly1305 { key, iv }, |
| }) |
| } |
| |
| fn fips(&self) -> bool { |
| false |
| } |
| } |