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

//! TLS context builder and context type

use alloc::boxed::Box;
use core::{
    marker::PhantomData,
    mem::forget,
    ptr::NonNull, //
};

use bssl_crypto::FfiSlice;

use crate::{
    check_lib_error,
    config::{
        ConfigurationError,
        KeyExchangeGroupFlag,
        KeyExchangeGroups,
        ProtocolVersion, //
    },
    connection::{
        TlsConnectionBuilder,
        methods::HasTlsConnectionMethod, //
    },
    context::methods::{
        HasPrivateKeyMethods,
        HasTlsContextMethod, //
    },
    errors::Error,
    has_duplicates, //
};

pub use crate::connection::{
    Client,
    Server, //
};

mod credentials;
mod methods;
mod sessions;

/// TLS or DTLS mode
pub enum TlsMode {}

/// DTLS mode
pub enum DtlsMode {}

/// QUIC mode
pub enum QuicMode {}

/// TLS mode without built-in X.509 support.
///
/// This mode uses `TLS_with_buffers_method`, which avoids all use of crypto/x509.
/// All client connections will fail unless a certificate verifier is installed with
/// [`TlsContextBuilder::with_certificate_verifier`].
pub enum TlsExternalVerifierMode {}

/// DTLS mode without built-in X.509 support.
///
/// This mode uses `DTLS_with_buffers_method`, which avoids all use of crypto/x509.
/// All client connections will fail unless a certificate verifier is installed with
/// [`TlsContextBuilder::with_certificate_verifier`].
pub enum DtlsExternalVerifierMode {}

pub(crate) trait HasBasicIo {}

/// A marker trait for modes that have built-in X.509 support.
pub trait UseBuiltinX509 {}

impl UseBuiltinX509 for TlsMode {}
impl UseBuiltinX509 for DtlsMode {}

/// A collection of supported mode of operations.
pub trait SupportedMode:
    HasTlsContextMethod + HasTlsConnectionMethod + HasPrivateKeyMethods
{
}

impl SupportedMode for TlsMode {}
impl SupportedMode for DtlsMode {}
impl SupportedMode for QuicMode {}
impl SupportedMode for TlsExternalVerifierMode {}
impl SupportedMode for DtlsExternalVerifierMode {}

impl HasBasicIo for TlsMode {}
impl HasBasicIo for DtlsMode {}
impl HasBasicIo for TlsExternalVerifierMode {}
impl HasBasicIo for DtlsExternalVerifierMode {}

/// General TLS configuration
///
/// The `Mode` generic can be either [`TlsMode`] or [`QuicMode`].
/// This generic governs the kind of [`crate::connection::TlsConnection`] that can be constructed.
pub struct TlsContextBuilder<Mode = TlsMode> {
    ptr: NonNull<bssl_sys::SSL_CTX>,
    _p: PhantomData<fn() -> Mode>,
}

impl<M> TlsContextBuilder<M> {
    fn ptr(&self) -> *mut bssl_sys::SSL_CTX {
        self.ptr.as_ptr()
    }
}

impl<M> TlsContextBuilder<M>
where
    M: HasTlsContextMethod,
{
    fn new_inner(method: *const bssl_sys::SSL_METHOD) -> Self {
        let Some(ptr) = NonNull::new(unsafe {
            // Safety: this call only makes allocations
            bssl_sys::SSL_CTX_new(method)
        }) else {
            panic!("allocation failure")
        };
        let this = TlsContextBuilder {
            ptr,
            _p: PhantomData,
        };
        let rc = unsafe {
            // Safety: `ctx` is still valid
            bssl_sys::SSL_CTX_set_ex_data(
                ptr.as_ptr(),
                M::registration(),
                Box::into_raw(Box::new(methods::RustContextMethods::<M>::new())) as _,
            )
        };
        assert!(rc == 1);
        this
    }
}

/// # Make a TLS context builder
impl TlsContextBuilder<TlsMode> {
    /// Creates a new TLS context builder.
    pub fn new_tls() -> Self {
        Self::new_inner(unsafe {
            // Safety: this call returns a static immutable data
            bssl_sys::TLS_method()
        })
    }
}

/// # Make a DTLS context builder operating in pure DTLS mode
impl TlsContextBuilder<DtlsMode> {
    /// Creates a new DTLS context builder.
    pub fn new_dtls() -> Self {
        Self::new_inner(unsafe {
            // Safety: this call returns a static immutable data
            bssl_sys::DTLS_method()
        })
    }
}

/// # Make a TLS context builder without built-in X.509 support
impl TlsContextBuilder<TlsExternalVerifierMode> {
    /// Creates a new TLS context builder without X.509 support.
    ///
    /// All client connections will fail unless a certificate verifier is installed
    /// with [`TlsContextBuilder::with_certificate_verifier`].
    pub fn new_tls_no_x509() -> Self {
        Self::new_inner(unsafe {
            // Safety: this call returns a static immutable data
            bssl_sys::TLS_with_buffers_method()
        })
    }
}

/// # Make a DTLS context builder without built-in X.509 support
impl TlsContextBuilder<DtlsExternalVerifierMode> {
    /// Creates a new DTLS context builder without X.509 support.
    ///
    /// All client connections will fail unless a certificate verifier is installed
    /// with [`TlsContextBuilder::with_certificate_verifier`].
    pub fn new_dtls_no_x509() -> Self {
        Self::new_inner(unsafe {
            // Safety: this call returns a static immutable data
            bssl_sys::DTLS_with_buffers_method()
        })
    }
}

/// # Configure the context through a context builder
impl<M> TlsContextBuilder<M>
where
    M: HasTlsContextMethod,
{
    /// Builds and returns the configured TLS context.
    pub fn build(self) -> TlsContext<M> {
        let ptr = self.ptr;
        // We must disarm the drop activated by the builder and pass on the ownership.
        // Now `self` has no destructors to call.
        forget(self);
        TlsContext {
            ptr,
            _p: PhantomData,
        }
    }

    fn get_context_methods(&mut self) -> &mut methods::RustContextMethods<M> {
        let methods = unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_get_ex_data(self.ptr(), M::registration())
        };
        if methods.is_null() {
            panic!("context method goes missing")
        }
        unsafe {
            // Safety: `methods` must be constructed by `new_inner`
            &mut *(methods as *mut methods::RustContextMethods<M>)
        }
    }

    /// Set the minimum acceptable protocol.
    ///
    /// If `version` is set to `None`, the library will choose a default minimum version.
    /// - For TLS, it is TLS 1.3
    /// - For DTLS, it is DTLS 1.2
    ///
    /// This configuration fails if the protocol version is incompatible with the selected TLS
    /// flavour, such as setting TLS 1.3 for DTLS flavour.
    pub fn with_min_protocol(
        &mut self,
        version: Option<ProtocolVersion>,
    ) -> Result<&mut Self, Error> {
        let version = version.map_or(0, |ver| ver as u16);
        check_lib_error!(unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`
            bssl_sys::SSL_CTX_set_min_proto_version(self.ptr(), version)
        });
        Ok(self)
    }

    /// Set the maximum acceptable protocol.
    ///
    /// If `version` is set to `None`, the library will choose a default maximum version.
    /// - For TLS, it is TLS 1.3
    /// - For DTLS, it is DTLS 1.2
    ///
    /// This configuration fails if the protocol version is incompatible with the selected TLS
    /// flavour, such as setting TLS 1.3 for DTLS flavour.
    pub fn with_max_protocol(
        &mut self,
        version: Option<ProtocolVersion>,
    ) -> Result<&mut Self, Error> {
        let version = version.map_or(0, |ver| ver as u16);
        check_lib_error!(unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`
            bssl_sys::SSL_CTX_set_max_proto_version(self.ptr(), version)
        });
        Ok(self)
    }

    /// Set acceptable key exchange groups.
    ///
    /// This method sets up the acceptable key exchange groups and the list of groups advertised by
    /// the client.
    ///
    /// If the supplied list is empty, the context will revert back to a default list of groups.
    ///
    /// If the `flags` list is not empty, its length must match that of `groups`.
    ///
    /// This method returns [`ConfigurationError::InvalidParameters`] if the key exchange groups are not unique in the list.
    pub fn with_key_exchange_groups(
        &mut self,
        groups: &[KeyExchangeGroups],
        flags: &[KeyExchangeGroupFlag],
    ) -> Result<&mut Self, Error> {
        // TODO(@xfding): maybe we should use zerocopy here when v0.9 is finalised
        let groups: &[u16] = unsafe {
            // Safety: `KeyExchangeGroups` has the same layout as a `u16`,
            // so `&[KeyExchangeGroups]` and `&[u16]` has the same layout.
            core::mem::transmute(groups)
        };
        let flags: &[u32] = unsafe {
            // Safety: `KeyExchangeGroupFlag` has the same layout as a `u32` through
            // `repr(transparent)`.
            core::mem::transmute(flags)
        };
        if !flags.is_empty() && groups.len() != flags.len() {
            return Err(Error::Configuration(ConfigurationError::InvalidParameters));
        }
        if has_duplicates(groups) {
            return Err(Error::Configuration(
                ConfigurationError::DuplicatedParameters,
            ));
        }

        check_lib_error!(unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`
            if flags.is_empty() {
                bssl_sys::SSL_CTX_set1_group_ids(self.ptr(), groups.as_ffi_ptr(), groups.len())
            } else {
                bssl_sys::SSL_CTX_set1_group_ids_with_flags(
                    self.ptr(),
                    groups.as_ffi_ptr(),
                    flags.as_ffi_ptr(),
                    groups.len(),
                )
            }
        });
        Ok(self)
    }

    /// Set a list of cipher suites, in the order of descending preference.
    ///
    /// This method accepts a string that conforms to OpenSSL [cipher suite configuration] language
    /// specification.
    ///
    /// # Available cipher rules are:
    ///
    /// - `ALL` matches all ciphers, except for deprecated ciphers which must be
    ///   named explicitly.
    ///
    /// - `kRSA`, `kDHE`, `kECDHE`, and `kPSK` match ciphers using plain RSA, DHE,
    ///   ECDHE, and plain PSK key exchanges, respectively. Note that ECDHE_PSK is
    ///   matched by `kECDHE` and not `kPSK`.
    ///
    /// - `aRSA`, `aECDSA`, and `aPSK` match ciphers authenticated by RSA, ECDSA, and
    ///   a pre-shared key, respectively.
    ///
    /// - `RSA`, `DHE`, `ECDHE`, `PSK`, `ECDSA`, and `PSK` are aliases for the
    ///   corresponding `k*` or `a*` cipher rule. `RSA` is an alias for `kRSA`, not
    ///   `aRSA`.
    ///
    /// - `3DES`, `AES128`, `AES256`, `AES`, `AESGCM`, `CHACHA20` match ciphers
    ///   whose bulk cipher use the corresponding encryption scheme. Note that
    ///   `AES`, `AES128`, and `AES256` match both CBC and GCM ciphers.
    ///
    /// - `SHA1`, and its alias `SHA`, match legacy cipher suites using HMAC-SHA1.
    ///
    /// # Deprecated cipher rules:
    ///
    /// - `kEDH`, `EDH`, `kEECDH`, and `EECDH` are legacy aliases for `kDHE`, `DHE`,
    ///   `kECDHE`, and `ECDHE`, respectively.
    ///
    /// - `HIGH` is an alias for `ALL`.
    ///
    /// - `FIPS` is an alias for `HIGH`.
    ///
    /// - `SSLv3` and `TLSv1` match ciphers available in TLS 1.1 or earlier.
    ///   `TLSv1_2` matches ciphers new in TLS 1.2. This is confusing and should not
    ///   be used.
    ///
    /// [cipher suite configuration]: <https://docs.openssl.org/3.0/man1/openssl-ciphers/#cipher-list-format>
    pub fn with_ciphers(&mut self, cipher_ops: &str) -> Result<&mut Self, Error> {
        let Ok(cipher_ops) = alloc::ffi::CString::new(cipher_ops) else {
            return Err(Error::Configuration(ConfigurationError::InvalidString));
        };
        check_lib_error!(unsafe {
            // Safety:
            // - the validity of the handle `self.0` is witnessed by `self`;
            // - the string has been checked for internal NUL bytes and NUL-terminated.
            bssl_sys::SSL_CTX_set_strict_cipher_list(self.ptr(), cipher_ops.as_ptr())
        });
        Ok(self)
    }

    /// Set TLS 1.2 session lifetime in seconds.
    ///
    /// If 0 seconds are specified, BoringSSL will pick a default timeout for the connections.
    pub fn with_tls12_timeout(&mut self, seconds: u32) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_timeout(self.ptr(), seconds)
        };
        self
    }

    /// Set TLS 1.3 session lifetime in seconds.
    ///
    /// If 0 seconds are specified, BoringSSL will pick a default timeout for the connections.
    pub fn with_tls13_timeout(&mut self, seconds: u32) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_session_psk_dhe_timeout(self.ptr(), seconds)
        };
        self
    }

    /// Set whether shutting down the connection sends out a `close_notify` alert.
    pub fn with_quiet_shutdown(&mut self, quiet: bool) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.0` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_quiet_shutdown(self.ptr(), if quiet { 1 } else { 0 });
        }
        self
    }

    /// Set whether only the SHA-256 hash of the peer's certificate should be saved in the session.
    ///
    /// This can save memory, ticket size and session cache space.
    pub fn with_retain_only_sha256_of_client_certs(&mut self, enable: bool) -> &mut Self {
        unsafe {
            // Safety: the validity of the handle `self.ptr` is witnessed by `self`.
            bssl_sys::SSL_CTX_set_retain_only_sha256_of_client_certs(
                self.ptr(),
                if enable { 1 } else { 0 },
            );
        }
        self
    }
}

#[cfg(feature = "std")]
impl TlsContextBuilder<TlsMode> {
    /// Builds and returns a synchronous `TlsConnector` using the configured context.
    pub fn build_connector(self) -> crate::sync_io::TlsConnector {
        crate::sync_io::TlsConnector::new(self.build())
    }

    /// Builds and returns a synchronous `TlsAcceptor` using the configured context.
    pub fn build_acceptor(self) -> crate::sync_io::TlsAcceptor {
        crate::sync_io::TlsAcceptor::new(self.build())
    }
}

impl<M> Drop for TlsContextBuilder<M> {
    fn drop(&mut self) {
        unsafe {
            // Safety: self.0 is created from SSL_CTX_new so it is a valid pointer
            bssl_sys::SSL_CTX_free(self.ptr());
        }
    }
}

/// A TLS context that is finalised and can be shared across connections
#[repr(transparent)]
pub struct TlsContext<M = TlsMode> {
    ptr: NonNull<bssl_sys::SSL_CTX>,
    _p: PhantomData<fn() -> M>,
}

impl<M> TlsContext<M> {
    pub(crate) fn ptr(&self) -> *mut bssl_sys::SSL_CTX {
        self.ptr.as_ptr()
    }
}

/// # Create new connections associated to a context
impl<M> TlsContext<M>
where
    M: HasTlsContextMethod + HasTlsConnectionMethod,
{
    fn new_connection(&self) -> NonNull<bssl_sys::SSL> {
        let conn = unsafe {
            // Safety: in this type-state, our SSL_CTX is effectively immutable,
            // so we can freely alias.
            bssl_sys::SSL_new(self.ptr())
        };
        NonNull::new(conn).expect("allocation failure")
    }

    /// Make a new client-half connection inheriting the configuration of this context
    ///
    /// By default, this method will configure the connection to request certificates
    /// from the server.
    /// To override this default, use
    /// [`TlsConnectionBuilder::with_certificate_verification_mode`].
    pub fn new_client_connection(&self) -> TlsConnectionBuilder<Client, M> {
        let conn = self.new_connection();
        unsafe {
            // Safety: the connection is still valid here
            bssl_sys::SSL_set_connect_state(conn.as_ptr());
        }
        let mut builder = TlsConnectionBuilder::from_ssl(conn);
        // The safe default is that the client should perform at least
        // some certification verification.
        builder.with_certificate_verification_mode(
            crate::credentials::CertificateVerificationMode::PeerCertRequested,
        );
        builder
    }

    /// Make a new server-half connection inheriting the configuration of this context
    pub fn new_server_connection(&self) -> TlsConnectionBuilder<Server, M> {
        let conn = self.new_connection();
        unsafe {
            // Safety: the connection is still valid here
            bssl_sys::SSL_set_accept_state(conn.as_ptr());
        }
        TlsConnectionBuilder::from_ssl(conn)
    }

    /// Expose the fully built BoringSSL's `SSL_CTX` pointer.
    ///
    /// # Safety
    /// - `SSL_CTX` is **not fully thread-safe**; do not invoke any BoringSSL mutating functions
    ///   on the returned handle; otherwise, it is **undefined behaviour**.
    /// - interacting with the `ex_data` of the `SSL_CTX` instance that this method returns is
    ///   **undefined behaviour**.
    /// - `self` must outlive all uses of the returned handle;
    /// - this handle must be used with functions from the BoringSSL library this crate is linked
    ///   to; otherwise, it is **undefined behaviour**.
    ///
    /// # Recommendation
    /// If the handle is used to interface BoringSSL library functions, please consider using a
    /// corresponding Rust safe binding or contact BoringSSL Authors for support.
    pub unsafe fn as_mut_ptr(&mut self) -> *mut bssl_sys::SSL_CTX {
        self.ptr()
    }
}

/// Safety: at this type state, most of the underlying context is immutable,
/// while methods on shared accesses are protected behind a mutex, so they are thread-safe.
unsafe impl<M> Send for TlsContext<M> {}
unsafe impl<M> Sync for TlsContext<M> {}

impl<M> Drop for TlsContext<M> {
    fn drop(&mut self) {
        unsafe {
            // Safety: this handle is taken from the builder, so it must be
            // live and valid.
            bssl_sys::SSL_CTX_free(self.ptr());
        }
    }
}

impl<M> Clone for TlsContext<M> {
    fn clone(&self) -> Self {
        unsafe {
            // Safety: this handle is already valid by the witness of self.
            bssl_sys::SSL_CTX_up_ref(self.ptr());
            // BoringSSL will always return success on bumping reference.
        }
        TlsContext {
            ptr: self.ptr,
            _p: PhantomData,
        }
    }
}

/// A reusable certificate cache shared across [`TlsContext`]
pub struct CertificateCache(pub(crate) NonNull<bssl_sys::CRYPTO_BUFFER_POOL>);

// Safety: `CRYPTO_BUFFER_POOL` is mutex-protected
unsafe impl Send for CertificateCache {}
unsafe impl Sync for CertificateCache {}

impl CertificateCache {
    /// Construct a new certificate cache.
    pub fn new() -> Self {
        let pool = unsafe {
            // Safety: this call does not have side-effect other than allocation
            bssl_sys::CRYPTO_BUFFER_POOL_new()
        };
        Self(NonNull::new(pool).expect("allocation failure"))
    }

    pub(crate) fn ptr(&self) -> *mut bssl_sys::CRYPTO_BUFFER_POOL {
        self.0.as_ptr()
    }
}

impl Drop for CertificateCache {
    fn drop(&mut self) {
        unsafe {
            // Safety: the validity of `self.0` is witnessed by `self`
            bssl_sys::CRYPTO_BUFFER_POOL_free(self.ptr());
        }
    }
}

impl Clone for CertificateCache {
    fn clone(&self) -> Self {
        unsafe {
            // Safety: the validity of `self.0` is witnessed by `self`
            bssl_sys::CRYPTO_BUFFER_POOL_up_ref(self.ptr());
        }
        Self(self.0)
    }
}
