// 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 certificate selection hook.

use alloc::{vec, vec::Vec};
use core::{
    ffi::{c_int, c_void},
    marker::PhantomData,
    ptr::{NonNull, null},
    task::Context,
};

use super::{
    CryptoBufferIterator,
    DistinguishedName, //
    SignatureAlgorithm,
    get_peer_certificate_type,
    get_peer_raw_public_key,
};

use crate::{
    CertCallback,
    abort_on_panic,
    config::ProtocolVersion,
    connection::methods::waker_data_from_ssl,
    context::TlsContext,
    ffi::sanitize_slice, //
};

/// Result of certificate selection.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum CertificateSelectionResult {
    /// Certificate selection succeeded.
    Success,
    /// Certificate selection is pending (e.g. waiting for async operation).
    /// The handshake will be paused and can be retried later.
    Pending,
    /// Certificate selection failed. The handshake will be aborted.
    Error,
}

/// Server certificate selection.
///
/// Implementations must be `Send + Sync`. If the selector needs mutable state,
/// use interior mutability (e.g. `Mutex`).
pub trait ServerCertificateSelector<Mode>: Send + Sync {
    /// This method should return `CertificateSelectionResult` to indicate the outcome of the selection.
    fn select(
        &self,
        ctx: ServerCertificateSelectionContext<'_, Mode>,
        waker: Option<&'_ mut Context<'_>>,
    ) -> CertificateSelectionResult;
}

/// Client certificate selection.
///
/// Implementations must be `Send + Sync`. If the selector needs mutable state,
/// use interior mutability (e.g. `Mutex`).
pub trait ClientCertificateSelector<M>: Send + Sync {
    /// This method should return `CertificateSelectionResult` to indicate the outcome of the selection.
    fn select(
        &self,
        ctx: ClientCertificateSelectionContext<'_, M>,
        waker: Option<&'_ mut Context<'_>>,
    ) -> CertificateSelectionResult;
}

/// Certificate selection callback.
pub(crate) unsafe extern "C" fn select_cert_cb<M: CertCallback<Mode>, Mode>(
    ssl: *mut bssl_sys::SSL,
    _ctx: *mut c_void,
) -> c_int {
    let is_server = unsafe {
        // Safety: `ssl` is still valid by BoringSSL invariant.
        bssl_sys::SSL_is_server(ssl) == 1
    };
    let Some(ssl) = NonNull::new(ssl) else {
        return 0;
    };
    let Some(methods) = (unsafe {
        // Safety: this callback is installed by this crate so the ex_data index must be valid.
        M::from_ssl(ssl.as_ptr())
    }) else {
        return 0;
    };
    let waker = unsafe {
        // Safety: this callback is installed by this crate so the associated data must have been
        // set up correctly.
        waker_data_from_ssl(ssl)
    };
    let waker = if let Some(waker) = &waker {
        Some(&mut core::task::Context::from_waker(waker))
    } else {
        None
    };
    if is_server {
        let ctx = ServerCertificateSelectionContext::new(ssl);
        let Some(server_cert_cb) = methods.server_cert_cb() else {
            return 1;
        };
        match abort_on_panic(move || server_cert_cb.select(ctx, waker)) {
            CertificateSelectionResult::Success => 1,
            CertificateSelectionResult::Pending => -1,
            CertificateSelectionResult::Error => 0,
        }
    } else {
        let ctx = ClientCertificateSelectionContext::new(ssl);
        let Some(client_cert_cb) = methods.client_cert_cb() else {
            return 1;
        };
        match abort_on_panic(move || client_cert_cb.select(ctx, waker)) {
            CertificateSelectionResult::Success => 1,
            CertificateSelectionResult::Pending => -1,
            CertificateSelectionResult::Error => 0,
        }
    }
}

/// Server certificate selection context.
#[repr(transparent)]
pub struct ServerCertificateSelectionContext<'a, Mode>(
    NonNull<bssl_sys::SSL>,
    PhantomData<&'a fn() -> Mode>,
);

impl<'a, M> ServerCertificateSelectionContext<'a, M> {
    pub(crate) fn new(ssl: NonNull<bssl_sys::SSL>) -> Self {
        Self(ssl, PhantomData)
    }

    /// Switch context.
    pub fn set_context(&mut self, ctx: &TlsContext<M>) {
        unsafe {
            // Safety: `self.0` is still valid by BoringSSL invariant.
            bssl_sys::SSL_set_SSL_CTX(self.0.as_ptr(), ctx.ptr());
        }
    }

    /// Append `credential` to the list of credentials of this connection.
    ///
    /// Earlier calls to this method append a credential that is preferred over those added
    /// in later calls.
    pub fn add_credential(
        &mut self,
        credential: &super::TlsCredential,
    ) -> Result<(), super::super::errors::Error> {
        crate::check_lib_error!(unsafe {
            // Safety: both `self.0` and `credential` are still valid.
            bssl_sys::SSL_add1_credential(self.0.as_ptr(), credential.ptr())
        });
        Ok(())
    }

    /// Get the peer's [`CertificateType`](super::CertificateType).
    pub fn get_peer_certificate_type(&self) -> Option<super::CertificateType> {
        get_peer_certificate_type(self.0.as_ptr())
    }

    /// Get the peer's raw public key as DER-encoded `SubjectPublicKeyInfo`.
    pub fn get_peer_raw_public_key(&self) -> Option<Vec<u8>> {
        get_peer_raw_public_key(self.0.as_ptr())
    }
}

bssl_macros::bssl_enum! {
    /// Requested certificate types defined in [RFC 5246] §7.4.4.
    ///
    /// [RFC 5246]: <https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.4>
    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
    pub enum RequestedCertificateType: u8 {
        /// RSA signed certificate.
        RsaSign = 1,
        /// DSS signed certificate.
        DssSign = 2,
        /// RSA signed certificate with a static Diffie-Hellman key.
        RsaFixedDh = 3,
        /// DSS signed certificate with a static Diffie-Hellman key.
        DssFixedDh = 4,
        /// Reserved.
        RsaEphemeralDh = 5,
        /// Reserved.
        DssEphemeralDh = 6,
        /// Reserved.
        FortezzaDms = 20,
    }
}

/// Client Certificate Selection.
pub struct ClientCertificateSelectionContext<'a, Mode>(
    NonNull<bssl_sys::SSL>,
    PhantomData<&'a fn() -> Mode>,
);

impl<'a, M> ClientCertificateSelectionContext<'a, M> {
    pub(crate) fn new(ssl: NonNull<bssl_sys::SSL>) -> Self {
        Self(ssl, PhantomData)
    }

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

    /// Protocol version selected.
    ///
    /// This method returns [`None`] if the protocol version is unrecognised.
    pub fn protocol_version(&self) -> Option<ProtocolVersion> {
        ProtocolVersion::try_from(unsafe {
            // Safety: `self.0` is still valid by BoringSSL invariant.
            bssl_sys::SSL_version(self.ptr())
        })
        .ok()
    }
    /// Get verification algorithm from the peer.
    ///
    /// If a signature algorithm is unrecognised, it will be reported as an `Err` value.
    /// This method might return an empty list if the protocol version is not TLS 1.3.
    pub fn get_tls13_peer_verification_algorithms(&self) -> Vec<Result<SignatureAlgorithm, u16>> {
        let mut algs = null();
        let len = unsafe {
            // Safety: `self.0` is still valid by BoringSSL invariant.
            bssl_sys::SSL_get0_peer_verify_algorithms(self.ptr(), &raw mut algs)
        };
        if let Some(slice) = unsafe {
            // Safety: `algs` is only live within this call.
            sanitize_slice(algs, len)
        } {
            slice
                .iter()
                .copied()
                .map(SignatureAlgorithm::try_from)
                .collect()
        } else {
            vec![]
        }
    }

    /// Get TLS 1.2 certificate types.
    ///
    /// If a certificate type is unrecognised, it will be reported as an `Err` value.
    /// This method returns an empty list if the protocol version is TLS 1.3.
    pub fn get_tls12_certificate_types(&self) -> Vec<Result<RequestedCertificateType, u8>> {
        let mut types = null();
        let len = unsafe {
            // Safety: `self.0` is still valid by BoringSSL invariant.
            bssl_sys::SSL_get0_certificate_types(self.ptr(), &raw mut types)
        };
        if let Some(slice) = unsafe {
            // Safety: `types` is only live within this call.
            sanitize_slice(types, len)
        } {
            slice
                .iter()
                .copied()
                .map(RequestedCertificateType::try_from)
                .collect()
        } else {
            vec![]
        }
    }

    /// Get server requested CAs for client authentication.
    ///
    /// These names are sent by the server and they are the acceptable CAs by server.
    pub fn get_server_ca_list(&self) -> Vec<DistinguishedName> {
        let names = unsafe {
            // Safety: `self.ptr()` is still valid by BoringSSL invariant.
            bssl_sys::SSL_get0_server_requested_CAs(self.ptr())
        };
        let names: CryptoBufferIterator<'_, DistinguishedName> = unsafe {
            // Safety: `names` is owned by SSL and only live within this call.
            CryptoBufferIterator::new(names)
        };
        names.collect()
    }

    /// Append `credential` to the list of credentials of this connection.
    ///
    /// Earlier calls to this method append a credential that is preferred over those added
    /// in later calls.
    pub fn add_credential(
        &mut self,
        credential: &super::TlsCredential,
    ) -> Result<(), super::super::errors::Error> {
        crate::check_lib_error!(unsafe {
            // Safety: both `self.0` and `credential` are still valid.
            bssl_sys::SSL_add1_credential(self.0.as_ptr(), credential.ptr())
        });
        Ok(())
    }

    /// Get the peer's [`CertificateType`](super::CertificateType).
    pub fn get_peer_certificate_type(&self) -> Option<super::CertificateType> {
        super::get_peer_certificate_type(self.ptr())
    }

    /// Get the peer's raw public key as DER-encoded `SubjectPublicKeyInfo`.
    pub fn get_peer_raw_public_key(&self) -> Option<Vec<u8>> {
        super::get_peer_raw_public_key(self.ptr())
    }
}
