// 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
    }
}
