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

//! Select Certificate Callback types

use core::{
    marker::PhantomData,
    mem::transmute,
    ptr::{
        NonNull, //
        null,
    }, //
};

use bssl_crypto::FromFfiSlice;

use crate::{
    EarlyCallbackMethods,
    abort_on_panic,
    config::CipherSuite,
    connection::{
        Server,
        lifecycle::TlsConnectionInHandshake, //
    }, //
};

bssl_macros::bssl_enum! {
    /// Results from selecting a certificate in the callback.
    pub enum EarlyCallbackResult: i32 {
        /// The certificate selection was successful.
        Success = bssl_sys::ssl_select_cert_result_t_ssl_select_cert_success as i32,
        /// The operation could not be immediately completed and must be reattempted at a later point.
        Retry = bssl_sys::ssl_select_cert_result_t_ssl_select_cert_retry as i32,
        /// A fatal error occurred and the handshake should be terminated.
        ErrorResult = bssl_sys::ssl_select_cert_result_t_ssl_select_cert_error as i32,
        /// Disable ECH.
        /// The callback should return this result when an encrypted `ClientHelloInner` was
        /// decrypted but should be discarded.
        /// In this case, the callback will be called again with `ClientHelloOuter` as input
        /// instead and the handshake will proceed with `retry_config`s to signal to the client that
        /// ECH is disabled.
        /// This value may only be returned when `SSL_ech_accepted` returns one.
        /// It may be useful if the `ClientHelloInner` indicated lack of ECH support in the service,
        /// for example if it is a TLS-1.2 only service.
        DisableEch = bssl_sys::ssl_select_cert_result_t_ssl_select_cert_disable_ech as i32,
    }
}

/// TLS Extension Types.
///
/// See [IANA assignment](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-extensiontype-values-1)
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[repr(transparent)]
pub struct ExtensionType(pub u16);

impl ExtensionType {
    /// Server Name Indication
    ///
    /// [RFC 6066, §3](https://datatracker.ietf.org/doc/html/rfc6066#section-3)
    pub const SERVER_NAME: Self = Self(bssl_sys::TLSEXT_TYPE_server_name as u16);

    /// Status Request
    ///
    /// [RFC 6066, §8](https://datatracker.ietf.org/doc/html/rfc6066#section-8)
    pub const STATUS_REQUEST: Self = Self(bssl_sys::TLSEXT_TYPE_status_request as u16);

    /// Supported Groups
    ///
    /// [RFC 8446, §4.2.7](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.7)
    pub const SUPPORTED_GROUPS: Self = Self(bssl_sys::TLSEXT_TYPE_supported_groups as u16);

    /// Signature Algorithms
    ///
    /// [RFC 8446, §4.2.3](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.3)
    pub const SIGNATURE_ALGORITHMS: Self = Self(bssl_sys::TLSEXT_TYPE_signature_algorithms as u16);

    /// Application Layer Protocol Negotiation
    ///
    /// [RFC 7301, §3](https://datatracker.ietf.org/doc/html/rfc7301#section-3)
    pub const ALPN: Self =
        Self(bssl_sys::TLSEXT_TYPE_application_layer_protocol_negotiation as u16);

    /// Key Share
    ///
    /// [RFC 8446, §4.2.8](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8)
    pub const KEY_SHARE: Self = Self(bssl_sys::TLSEXT_TYPE_key_share as u16);

    /// Supported Versions
    ///
    /// [RFC 8446, §4.2.1](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.1)
    pub const SUPPORTED_VERSIONS: Self = Self(bssl_sys::TLSEXT_TYPE_supported_versions as u16);

    /// Pre-Shared Key
    ///
    /// [RFC 8446, §4.2.11](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.11)
    pub const PRE_SHARED_KEY: Self = Self(bssl_sys::TLSEXT_TYPE_pre_shared_key as u16);

    /// Cookie
    ///
    /// [RFC 8446, §4.2.2](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.2)
    pub const COOKIE: Self = Self(bssl_sys::TLSEXT_TYPE_cookie as u16);

    /// PSK Key Exchange Modes
    ///
    /// [RFC 8446, §4.2.9](https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.9)
    pub const PSK_KEY_EXCHANGE_MODES: Self =
        Self(bssl_sys::TLSEXT_TYPE_psk_key_exchange_modes as u16);

    /// Certificate Compression
    ///
    /// [RFC 8879](https://datatracker.ietf.org/doc/html/rfc8879)
    pub const CERT_COMPRESSION: Self = Self(bssl_sys::TLSEXT_TYPE_cert_compression as u16);

    /// Session Ticket
    ///
    /// [RFC 5077](https://datatracker.ietf.org/doc/html/rfc5077)
    pub const SESSION_TICKET: Self = Self(bssl_sys::TLSEXT_TYPE_session_ticket as u16);

    /// Extended Master Secret
    ///
    /// [RFC 7627](https://datatracker.ietf.org/doc/html/rfc7627)
    pub const EXTENDED_MASTER_SECRET: Self =
        Self(bssl_sys::TLSEXT_TYPE_extended_master_secret as u16);

    /// Client Certificate Type
    ///
    /// [RFC 7250](https://datatracker.ietf.org/doc/html/rfc7250)
    pub const CLIENT_CERT_TYPE: Self = Self(bssl_sys::TLSEXT_TYPE_client_cert_type as u16);

    /// Server Certificate Type
    ///
    /// [RFC 7250](https://datatracker.ietf.org/doc/html/rfc7250)
    pub const SERVER_CERT_TYPE: Self = Self(bssl_sys::TLSEXT_TYPE_server_cert_type as u16);
}

/// A wrapper around the `ClientHello` data passed to the select certificate callback.
///
/// The structure is prescribed in [RFC 8446] §4.1.2.
///
/// [RFC 8446]: <https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2>
pub struct ClientHello<'a, M> {
    ptr: *const bssl_sys::SSL_CLIENT_HELLO,
    conn: NonNull<bssl_sys::SSL>,
    _p: PhantomData<&'a M>,
}

macro_rules! client_hello_getter {
    ($client_hello:expr, $data:ident, $len:ident) => {
        unsafe {
            // Safety: `$client_hello` is a valid pointer
            u8::from_ffi_ptr($client_hello.$data, $client_hello.$len)
        }
    };
}

impl<'a, M> ClientHello<'a, M> {
    /// Exposes a mutable reference to the associated server connection in handshake.
    ///
    /// The return handle has full capability to configure your server-side connection for the
    /// subsequent handshake.
    /// This handle can be used to set connection-specific credentials or certificates during the
    /// callback, for example.
    pub fn connection_mut(&mut self) -> TlsConnectionInHandshake<'_, Server, M> {
        unsafe {
            // Safety: `self.conn` is a `repr(transparent)` wrapper around a `NonNull<SSL>`.
            let conn_ref = transmute(&mut self.conn);
            TlsConnectionInHandshake(conn_ref)
        }
    }

    /// Get the client random bytes of length 32.
    ///
    /// This method returns [`None`] if the random bytes are absent or of wrong length.
    pub fn random(&self) -> Option<[u8; 32]> {
        let random = client_hello_getter!(*self.ptr, random, random_len);
        random.try_into().ok()
    }

    /// Get the legacy session ID bytes.
    pub fn legacy_session_id(&self) -> Option<[u8; 32]> {
        let session_id = client_hello_getter!(*self.ptr, session_id, session_id_len);
        session_id.try_into().ok()
    }

    /// Get the cipher suites bytes.
    ///
    /// This method returns [`None`] if the `cipher_suites` field is absent or contains error while
    /// parsing.
    pub fn cipher_suites(&self) -> Option<Vec<CipherSuite>> {
        let cipher_suites = client_hello_getter!(*self.ptr, cipher_suites, cipher_suites_len);
        if cipher_suites.len() % 2 != 0 {
            return None;
        }
        let mut result = Vec::with_capacity(cipher_suites.len() / 2);
        for suite in cipher_suites.chunks_exact(2) {
            let suite = u16::from_be_bytes(
                suite
                    .try_into()
                    .expect("we have checked that length of cipher_suites is multiple of 2"),
            );
            result.push(CipherSuite(suite));
        }
        Some(result)
    }

    /// Get the legacy compression methods bytes.
    pub fn legacy_compression_methods(&self) -> &'a [u8] {
        client_hello_getter!(*self.ptr, compression_methods, compression_methods_len)
    }

    /// Get the extensions bytes.
    pub fn extensions(&self) -> &'a [u8] {
        client_hello_getter!(*self.ptr, extensions, extensions_len)
    }

    /// Extract a specific extension from the client hello.
    ///
    /// The returned slice contains the raw extension data, excluding the
    /// extension type and length headers. The format of these bytes depends
    /// on the specific extension type as defined in the relevant RFCs.
    pub fn get_extension(&self, extension_type: ExtensionType) -> Option<&'a [u8]> {
        let mut out_data = null();
        let mut out_len = 0;
        let ret = unsafe {
            // Safety: `self.ptr` is a valid pointer to `SSL_CLIENT_HELLO` provided by BoringSSL.
            bssl_sys::SSL_early_callback_ctx_extension_get(
                self.ptr,
                extension_type.0,
                &mut out_data,
                &mut out_len,
            )
        };
        if ret == 1 {
            unsafe {
                // Safety: `out_data` and `out_len` are valid if the function returns 1.
                Some(u8::from_ffi_ptr(out_data, out_len))
            }
        } else {
            None
        }
    }
}

/// Early callback handler.
///
/// This callback happens before TLS server state machine makes progress when [`ClientHello`] is
/// received.
/// A good use case is when a TLS server could make further configuration in response to the client
/// requests.
pub trait EarlyCallback<M>: Send + Sync {
    /// Decide whether a certificate can be selected.
    ///
    /// The connection handle is accessible through [`ClientHello::connection_mut`].
    fn process(&self, client_hello: &mut ClientHello<'_, M>) -> EarlyCallbackResult;
}

// For this callback, MethodsT could only be RustContextMethods<Mode>.
pub(crate) unsafe extern "C" fn early_cb<Mode, MethodsT>(
    client_hello: *const bssl_sys::SSL_CLIENT_HELLO,
) -> bssl_sys::ssl_select_cert_result_t
where
    MethodsT: EarlyCallbackMethods<Mode>,
{
    let Some(client_hello_ptr) = NonNull::new(client_hello as *mut bssl_sys::SSL_CLIENT_HELLO)
    else {
        return bssl_sys::ssl_select_cert_result_t_ssl_select_cert_error;
    };
    let ssl = unsafe {
        // Safety: By BoringSSL invariant the `SSL_CLIENT_HELLO` handle must be valid
        // and only contains object handles that are managed by this crate or their derivatives.
        (*client_hello_ptr.as_ptr()).ssl
    };
    let Some(ssl_ptr) = NonNull::new(ssl) else {
        return bssl_sys::ssl_select_cert_result_t_ssl_select_cert_error;
    };

    let Some(methods) = (unsafe {
        // Safety: the connection handle must be originated from this crate
        MethodsT::from_ssl(ssl_ptr.as_ptr())
    }) else {
        return bssl_sys::ssl_select_cert_result_t_ssl_select_cert_error;
    };

    let Some(handler) = methods.early_callback_handler() else {
        return bssl_sys::ssl_select_cert_result_t_ssl_select_cert_success;
    };

    let mut wrapped_hello = ClientHello {
        ptr: client_hello_ptr.as_ptr(),
        conn: ssl_ptr,
        _p: PhantomData,
    };

    let res = abort_on_panic(move || handler.process(&mut wrapped_hello));
    res as bssl_sys::ssl_select_cert_result_t
}
