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

use alloc::{
    boxed::Box,
    vec,
    vec::Vec, //
};
use core::{
    ffi::{
        CStr,
        c_int, //
    },
    fmt::Debug,
    future::Future,
    iter::FusedIterator,
    marker::PhantomData,
    mem::forget,
    pin::Pin,
    ptr::{
        NonNull,
        null_mut, //
    },
    task::{
        Context,
        Poll, //
    }, //
};

use bssl_x509::{
    errors::PemReason,
    keys::{PrivateKey, PublicKey},
};

use crate::{
    VerifyCertificateMethods,
    abort_on_panic,
    alerts::AlertDescription,
    call_slice_getter,
    check_lib_error,
    config::ConfigurationError,
    connection::methods::{
        verify_cert_task_from_ssl,
        waker_data_from_ssl, //
    },
    context::CertificateCache,
    crypto_buffer_wrapper,
    errors::{
        Error,
        IoError, //
    },
    ffi::{
        Alloc,
        Bio,
        CryptoBufferWrapper,
        Stack,
        StackIterator,
        sanitize_slice,
        slice_into_ffi_raw_parts, //
    },
    has_duplicates, //
};

pub mod early_callback;
pub(crate) mod methods;
pub mod select_cert;

/// TLS credentials builder
pub struct TlsCredentialBuilder<Mode>(NonNull<bssl_sys::SSL_CREDENTIAL>, PhantomData<fn() -> Mode>);

/// X.509 credential
pub enum X509Mode {}

/// Raw Public Key credential
pub enum RawPublicKeyMode {}

pub(crate) trait HasPrivateKey {}

impl HasPrivateKey for X509Mode {}
impl HasPrivateKey for RawPublicKeyMode {}

// Safety: At this type state, the credential handle is exclusively owned.
unsafe impl<M> Send for TlsCredentialBuilder<M> {}

impl<M> Drop for TlsCredentialBuilder<M> {
    fn drop(&mut self) {
        unsafe {
            // Safety: `self.0` is still valid at dropping.
            bssl_sys::SSL_CREDENTIAL_free(self.0.as_ptr());
        }
    }
}

impl<M> TlsCredentialBuilder<M> {
    fn ptr(&mut self) -> *mut bssl_sys::SSL_CREDENTIAL {
        self.0.as_ptr()
    }

    fn set_ex_data(mut self) -> Self {
        let rc = unsafe {
            // Safety:
            // - this method is called exactly once during construction.
            // - the ex_data index will be generated correctly and exactly once.
            // - the `SSL_CREDENTIAL*` handle is already valid, witnessed by `self`.
            bssl_sys::SSL_CREDENTIAL_set_ex_data(
                self.ptr(),
                *methods::TLS_CREDENTIAL_METHOD,
                Box::into_raw(Box::new(methods::RustCredentialMethods::default())) as _,
            )
        };
        assert_eq!(rc, 1);
        self
    }

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

impl TlsCredentialBuilder<X509Mode> {
    /// Construct X.509-powered credential instance.
    pub fn new() -> Self {
        let this = Self(
            NonNull::new(unsafe {
                // Safety: this call has no side-effect other than allocation.
                bssl_sys::SSL_CREDENTIAL_new_x509()
            })
            .expect("allocation failure"),
            PhantomData,
        );
        this.set_ex_data()
    }

    /// Set private key delegate.
    ///
    /// This will override the `TlsConnection` private key delegate.
    pub fn with_private_key_delegate<T: 'static + PrivateKeyDelegate>(
        &mut self,
        key_method: Option<T>,
    ) -> &mut Self {
        let cred = self.ptr();
        if let Some(key_method) = key_method {
            unsafe {
                // Safety: we only install our own vtable.
                bssl_sys::SSL_CREDENTIAL_set_private_key_method(cred, methods::PRIVATE_KEY_METHODS);
            }
            self.get_credential_methods().private_key_methods = Some(Box::new(key_method) as _);
        } else {
            unsafe {
                // Safety: we only uninstall the vtable.
                bssl_sys::SSL_CREDENTIAL_set_private_key_method(cred, core::ptr::null());
            }
            self.get_credential_methods().private_key_methods.take();
        }
        self
    }

    /// Set a private key.
    ///
    /// **NOTE**: Call this method after setting the certificates with
    /// [`Self::with_certificate_chain`].
    ///
    /// This method errs when the private key does not match the public key in the leaf certificate
    /// as configured through [`Self::with_certificate_chain`].
    pub fn with_private_key(&mut self, mut key: PrivateKey) -> Result<&mut Self, Error> {
        let rc = unsafe {
            // Safety:
            // - both `key.0` and `self.0` are still valid.
            // - `bssl-tls` uses the same BoringSSL as that is linked to `bssl-sys` and `bssl-x509`.
            // - the `EVP_PKEY` handle will outlive `key` because this call will claim ownership.
            bssl_sys::SSL_CREDENTIAL_set1_private_key(self.ptr(), key.as_mut_ptr())
        };
        if rc != 1 {
            Err(Error::Configuration(ConfigurationError::MismatchingKeyPair))
        } else {
            Ok(self)
        }
    }
    /// Set certificate chain.
    ///
    /// The leaf, also known as end-entity, certificate **must come first** in `certs`.
    /// This method returns [`ConfigurationError::InvalidParameters`] if `certs` are empty.
    pub fn with_certificate_chain(&mut self, certs: &[Certificate]) -> Result<&mut Self, Error> {
        if certs.is_empty() {
            return Err(Error::Configuration(ConfigurationError::InvalidParameters));
        }
        let certs: &[*mut bssl_sys::CRYPTO_BUFFER] = unsafe {
            // Safety: `Certificate` is a `repr(transparent)` wrapper around
            // `*mut bssl_sys::CRYPTO_BUFFER`.
            core::mem::transmute(certs)
        };
        let (ptr, len) = slice_into_ffi_raw_parts(certs);
        check_lib_error!(unsafe {
            // Safety
            bssl_sys::SSL_CREDENTIAL_set1_cert_chain(self.ptr(), ptr, len)
        });
        Ok(self)
    }

    /// Set Online Certificate Status Protocol Response.
    pub fn with_ocsp_response(&mut self, ocsp: &OcspResponse) -> Result<&mut Self, Error> {
        check_lib_error!(unsafe {
            // Safety: both `self.0` and `ocsp.0` are still live witnessed by the wrapper types.
            bssl_sys::SSL_CREDENTIAL_set1_ocsp_response(self.ptr(), ocsp.ptr())
        });
        Ok(self)
    }

    /// Set Signed Certificate Timestamp List.
    pub fn with_scts(&mut self, scts: &SignedCertificateTimestampList) -> Result<&mut Self, Error> {
        check_lib_error!(unsafe {
            // Safety: both `self.0` and `scts.0` are still live.
            bssl_sys::SSL_CREDENTIAL_set1_signed_cert_timestamp_list(self.ptr(), scts.ptr())
        });
        Ok(self)
    }

    /// Enforce a check if the peer supports the issuer of the configured certificate chain.
    ///
    /// This setting can be used for certificate chains that may not be usable by all peers.
    /// This scenario could happen with chains with fewer cross-signs or issued from a newer CA.
    /// When in force, the credential list is tried in order, so more specific credentials that
    /// enable issuer matching should generally be ordered before less specific credentials that
    /// do not.
    pub fn must_match_issuer(&mut self, match_: bool) -> Result<&mut Self, Error> {
        unsafe {
            // Safety: `self.0` is still valid.
            bssl_sys::SSL_CREDENTIAL_set_must_match_issuer(self.ptr(), if match_ { 1 } else { 0 });
        }
        Ok(self)
    }
}

impl TlsCredentialBuilder<RawPublicKeyMode> {
    /// Construct raw public key credential instance.
    ///
    /// TLS connection may use this credential to perform authentication per [RFC 7250].
    ///
    /// [RFC 7250]: <https://tools.ietf.org/html/rfc7250>
    pub fn new_raw_public_key(mut key: PrivateKey) -> Self {
        let this = Self(
            NonNull::new(unsafe {
                // Safety:
                // - the `PrivateKey` type already contains both public and private key parts.
                // - the constructor call also claims the ownership of the key.
                bssl_sys::SSL_CREDENTIAL_new_raw_public_key(key.as_mut_ptr())
            })
            .expect("allocation failure"),
            PhantomData,
        );
        this.set_ex_data()
    }

    /// Construct raw public key credential, with a private key delegate.
    ///
    /// This credential is suitable for cases where the private key is stored off the device or in a
    /// credential store.
    /// TLS connection may use this credential to perform authentication per [RFC 7250].
    ///
    /// [RFC 7250]: <https://tools.ietf.org/html/rfc7250>
    pub fn new_raw_public_key_with_delegate<T: PrivateKeyDelegate + 'static>(
        mut key: PublicKey,
        delegate: T,
    ) -> Self {
        let mut this = Self(
            NonNull::new(unsafe {
                // Safety:
                // - the `PublicKey` type contains the public key part.
                // - the constructor bumps the ref-count on the public key.
                bssl_sys::SSL_CREDENTIAL_new_raw_public_key_custom(
                    key.as_mut_ptr(),
                    methods::PRIVATE_KEY_METHODS,
                )
            })
            .expect("allocation failure"),
            PhantomData,
        )
        .set_ex_data();
        this.get_credential_methods().private_key_methods = Some(Box::new(delegate) as _);
        this
    }
}

impl<M> TlsCredentialBuilder<M>
where
    M: HasPrivateKey,
{
    /// Set [`SignatureAlgorithm`] preferences.
    ///
    /// This controls which signature algorithms will be used with this credential.
    pub fn with_signing_algorithm_preferences(
        &mut self,
        algs: &[SignatureAlgorithm],
    ) -> Result<&mut Self, Error> {
        let algs: &[u16] = unsafe {
            // Safety: `SignatureAlgorithm` has a `repr(u16)`
            core::mem::transmute(algs)
        };
        if has_duplicates(algs) {
            return Err(Error::Configuration(
                ConfigurationError::DuplicatedParameters,
            ));
        }
        let (ptr, len) = slice_into_ffi_raw_parts(algs);
        check_lib_error!(unsafe {
            // Safety
            bssl_sys::SSL_CREDENTIAL_set1_signing_algorithm_prefs(self.ptr(), ptr, len)
        });
        Ok(self)
    }
}

impl<M> TlsCredentialBuilder<M> {
    /// Finalise the credential.
    pub fn build(mut self) -> Option<TlsCredential> {
        if unsafe {
            // Safety: `self.0` is still valid.
            bssl_sys::SSL_CREDENTIAL_is_complete(self.ptr()) == 1
        } {
            let Self(cred, _) = self;
            forget(self);
            Some(TlsCredential(cred))
        } else {
            None
        }
    }
}

/// Supported hash algorithms for TLS 1.3 PSK
///
/// See [RFC 9258] § 5.1.
///
/// [RFC 9258]: <https://datatracker.ietf.org/doc/html/rfc9258#section-5.1>
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub enum PskHash {
    /// SHA-256
    Sha256,
    /// SHA-384
    Sha384,
}

impl PskHash {
    pub(crate) fn as_evp_md(&self) -> *const bssl_sys::EVP_MD {
        match self {
            PskHash::Sha256 => unsafe {
                // Safety: `EVP_sha256` returns a valid pointer to a static `EVP_MD`.
                bssl_sys::EVP_sha256()
            },
            PskHash::Sha384 => unsafe {
                // Safety: `EVP_sha384` returns a valid pointer to a static `EVP_MD`.
                bssl_sys::EVP_sha384()
            },
        }
    }
}
/// A completely constructed TLS credential.
pub struct TlsCredential(NonNull<bssl_sys::SSL_CREDENTIAL>);

// Safety: `TlsCredential` is locked as immutable at this type state.
unsafe impl Send for TlsCredential {}
unsafe impl Sync for TlsCredential {}

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

    pub(crate) fn from_raw_and_upref(cred: NonNull<bssl_sys::SSL_CREDENTIAL>) -> Self {
        unsafe {
            // Safety: we are only bumping the ref-count.
            bssl_sys::SSL_CREDENTIAL_up_ref(cred.as_ptr());
        }
        Self(cred)
    }

    /// Create a new pre-shared key credential for TLS 1.3.
    ///
    /// See [RFC 9258](https://datatracker.ietf.org/doc/html/rfc9258) for details.
    pub fn new_pre_shared_key(
        key: &[u8],
        identity: &[u8],
        hash: PskHash,
        context: &[u8],
    ) -> Result<Self, Error> {
        let (key_ptr, key_len) = slice_into_ffi_raw_parts(key);
        let (id_ptr, id_len) = slice_into_ffi_raw_parts(identity);
        let (ctx_ptr, ctx_len) = slice_into_ffi_raw_parts(context);
        let cred = unsafe {
            // Safety:
            // - `key_ptr` and `key_len` are valid for the duration of the call.
            // - `id_ptr` and `id_len` are valid for the duration of the call.
            // - `hash.as_ptr()` returns a valid static `EVP_MD` pointer.
            // - `ctx_ptr` and `ctx_len` are valid for the duration of the call.
            // - The function returns a newly allocated `SSL_CREDENTIAL` or NULL.
            bssl_sys::SSL_CREDENTIAL_new_pre_shared_key(
                key_ptr,
                key_len,
                id_ptr,
                id_len,
                hash.as_evp_md(),
                ctx_ptr,
                ctx_len,
            )
        };
        let cred = NonNull::new(cred).ok_or_else(|| Error::extract_lib_err())?;
        Ok(TlsCredential(cred))
    }

    /// Return the external identity of this pre-shared key credential.
    ///
    /// Returns `None` if this credential is not a pre-shared key credential.
    pub fn get_pre_shared_key_id(&self) -> Option<&[u8]> {
        let mut id_len: usize = 0;
        let id_ptr = unsafe {
            // Safety: `self.0` is a valid `SSL_CREDENTIAL` handle.
            bssl_sys::SSL_CREDENTIAL_get0_pre_shared_key_id(self.ptr(), &mut id_len)
        };
        if id_ptr.is_null() {
            return None;
        }
        unsafe {
            // Safety: `id_ptr` will be outlived by `self`.
            sanitize_slice(id_ptr, id_len)
        }
    }
}

impl Clone for TlsCredential {
    fn clone(&self) -> Self {
        unsafe {
            // Safety: this handle is already valid by the witness of self.
            bssl_sys::SSL_CREDENTIAL_up_ref(self.ptr());
        }
        Self(self.0)
    }
}

impl Drop for TlsCredential {
    fn drop(&mut self) {
        unsafe {
            // Safety: `self.0` is still valid at dropping.
            bssl_sys::SSL_CREDENTIAL_free(self.ptr());
        }
    }
}

crypto_buffer_wrapper! {
    /// A dumb handle to a **possibly valid** TLS certificate.
    pub struct Certificate
}

impl Certificate {
    /// Parse certificates from PEM-encoded blocks.
    ///
    /// The parsing will skip anything that is not a certificate or empty.
    /// However, this method does not verify if the content is actually a valid, correctly signed
    /// DER-encoded X.509 certificate.
    /// The method returns at the first error encountered.
    pub fn parse_all_from_pem(
        cert: &[u8],
        cache: Option<&CertificateCache>,
    ) -> Result<Vec<Self>, Error> {
        let mut bio = Bio::from_bytes(cert).unwrap();
        let mut res = vec![];
        loop {
            match Self::parse_one(&mut bio, cache) {
                Ok((cert, eos)) => {
                    res.push(cert);
                    if eos {
                        return Ok(res);
                    }
                }
                Err(Error::PemReason(PemReason::NoStartLine)) => return Ok(res),
                Err(err) => return Err(err),
            }
        }
    }

    /// Parse the first certificate from the PEM-encoded data.
    pub fn parse_one_from_pem(
        cert: &[u8],
        cache: Option<&CertificateCache>,
    ) -> Result<Self, Error> {
        let mut bio = Bio::from_bytes(cert)?;
        let (cert, _) = Self::parse_one(&mut bio, cache)?;
        Ok(cert)
    }

    fn parse_one(bio: &mut Bio, cache: Option<&CertificateCache>) -> Result<(Self, bool), Error> {
        loop {
            let mut name = null_mut();
            let mut header = null_mut();
            let mut data = null_mut();
            let mut len = 0;
            let ret = unsafe {
                // Safety:
                // - `name`, `header`, `data` and `len` are valid and aligned.
                // - `bio` is still valid.
                bssl_sys::PEM_read_bio(
                    bio.ptr(),
                    &raw mut name,
                    &raw mut header,
                    &raw mut data,
                    &raw mut len,
                )
            };
            let eof = unsafe {
                // Safety: `bio` is still valid.
                bssl_sys::BIO_eof(bio.ptr()) != 0
            };
            let name = Alloc(name);
            let header = Alloc(header);
            let data = Alloc(data);
            if name.0.is_null() || header.0.is_null() || data.0.is_null() || ret == 0 {
                return Err(Error::extract_lib_err());
            }
            if len == 0 {
                continue;
            }
            let Ok(len) = usize::try_from(len) else {
                return Err(Error::Io(IoError::TooLong));
            };
            let buf = unsafe {
                // Safety:
                // - `name.0` is NUL-terminated by BoringSSL invariant.
                // - the lifetime of `buf` is outlived by `name.0`.
                CStr::from_ptr(name.0)
            };
            if buf.to_bytes() != b"CERTIFICATE" {
                continue;
            }
            let Some(contents) = (unsafe {
                // Safety: the slice is only used within the loop and we will copy the contents
                // when constructing the certificate object.
                sanitize_slice(data.0, len)
            }) else {
                return Err(Error::Io(IoError::TooLong));
            };
            let cert = Certificate::from_bytes(contents, cache)?;
            return Ok((cert, eof));
        }
    }

    /// Extract the DER encoded certificate.
    pub fn as_der_bytes(&self) -> &[u8] {
        let (data, len) = unsafe {
            // Safety: `self.0` is still valid.
            (
                bssl_sys::CRYPTO_BUFFER_data(self.ptr()),
                bssl_sys::CRYPTO_BUFFER_len(self.ptr()),
            )
        };
        unsafe {
            // Safety: `data` will be outlived by `self`
            sanitize_slice(data, len).expect("buffer is too large")
        }
    }
}

crypto_buffer_wrapper! {
    /// A dumb handle to a **possibly valid** OCSP Response.
    pub struct OcspResponse
}

crypto_buffer_wrapper! {
    /// A dumb handle to a **possibly valid** certificate property list.
    pub struct CertificatePropertyList
}

crypto_buffer_wrapper! {
    /// A dumb handle to a **possibly valid** certificate timestamp list.
    ///
    /// This list must contain at least one Signed Certificate Timestamp, or SCT for short,
    /// serialised as *[SignedCertificateTimestampList]*.
    ///
    /// The list begins with a length encoded as a big-endian 16-byte unsigned integer.
    /// Thereon follows a simple concatenation of SCTs.
    /// Each SCT is prefixed with a length encoded as a big-endian 16-byte unsigned integer.
    ///
    /// [SignedCertificateTimestampList]: <https://tools.ietf.org/html/rfc6962#section-3.3>
    pub struct SignedCertificateTimestampList
}

crypto_buffer_wrapper! {
    /// A dumb handle to a **possibly valid** delegated credential.
    ///
    /// By construction we do not validate if the contained bytes actually conforms to
    /// the structure of `DelegatedCredential` as stipulated by [RFC 9345].
    ///
    /// [RFC 9345]: <https://tools.ietf.org/html/rfc9345>
    pub struct DelegatedCredential
}

/// Private key operation result.
pub enum PrivateKeyOperationResult {
    /// Private key operation is still in-flight.
    Pending,
    /// Private key operation has successfully completed, with a result of a certain size.
    Success(usize),
    /// Private key operation has failed.
    Error,
}

/// Signature operation parameters.
#[non_exhaustive]
pub struct SignatureOperation<'a> {
    /// Output location of the signature.
    pub output: &'a mut [u8],
    /// Input message to be signed.
    pub message: &'a [u8],
    /// Signature algorithm to use.
    pub algorithm: SignatureAlgorithm,
}

/// Decryption operation parameters.
#[non_exhaustive]
pub struct DecryptionOperation<'a> {
    /// Output location of the plaintext.
    pub output: &'a mut [u8],
    /// Input ciphertext.
    pub ciphertext: &'a [u8],
}

/// Private key operation delegate.
///
/// This protocol allows for asynchronous signing and decryption operations.
/// BoringSSL will call one of [`Self::sign`] or [`Self::decrypt`] for operation initiation,
/// and call [`PrivateKeyOperation::complete`] to poll for completion as long as
/// [`PrivateKeyOperationResult::Pending`] is returned.
pub trait PrivateKeyDelegate: Send + Sync {
    /// Sign operation.
    ///
    /// The underlying task will be immediately polled once as optimisation,
    /// in case the operation becomes ready instantly.
    fn sign(&self, sign_op: SignatureOperation<'_>) -> Box<dyn PrivateKeyOperation>;
    /// Decryption operation.
    ///
    /// The underlying task will be immediately polled once as optimisation,
    /// in case the operation becomes ready instantly.
    fn decrypt(&self, decrypt_op: DecryptionOperation<'_>) -> Box<dyn PrivateKeyOperation>;
}

// NOTE: only `Send` bound is necessary; BoringSSL will not drive an operation from
// multiple threads.
/// An outstanding private key operation.
pub trait PrivateKeyOperation: Send {
    /// Try to complete the operation.
    ///
    /// To complete the operation, the implementation should write the results into `output` and
    /// signal success by returning [`PrivateKeyOperationResult::Success`] with the number of bytes
    /// written to the `output`.
    fn complete(
        &mut self,
        context: Option<&mut Context<'_>>,
        output: &mut [u8],
    ) -> PrivateKeyOperationResult;
}

// NOTE: we require `Send + Sync + Unpin` mostly due to practicality of working with
// async futures.
/// Asynchronous privatge key operation delegate.
///
/// This is the `async` analogue of [`PrivateKeyDelegate`].
pub trait AsyncPrivateKeyDelegate: Send + Sync + Unpin {
    /// The future to drive the signing operation.
    type SignOp: 'static + Unpin + Send + Sync + Future<Output = Option<Vec<u8>>>;
    /// The future to drive the decryption operation.
    type DecryptOp: 'static + Unpin + Send + Sync + Future<Output = Option<Vec<u8>>>;
    /// Sign operation.
    ///
    /// The underlying future will be immediately polled once as optimisation,
    /// in case the operation becomes ready immediately.
    fn sign(&self, message: &[u8], algorithm: SignatureAlgorithm) -> Self::SignOp;
    /// Decryption operations.
    ///
    /// The underlying future will be immediately polled once as optimisation,
    /// in case the operation becomes ready immediately.
    fn decrypt(&self, ciphertext: &[u8]) -> Self::DecryptOp;
}

/// A convenient asynchronous private key decrypter adapter.
pub struct AsyncPrivateKeyDelegateAdapter<Inner>(pub Inner);

impl<Inner> PrivateKeyDelegate for AsyncPrivateKeyDelegateAdapter<Inner>
where
    Inner: AsyncPrivateKeyDelegate,
{
    fn sign(&self, sign_op: SignatureOperation<'_>) -> Box<dyn PrivateKeyOperation> {
        Box::new(AsyncPrivateKeyOperationAdapter(
            self.0.sign(sign_op.message, sign_op.algorithm),
        ))
    }

    fn decrypt(&self, decrypt_op: DecryptionOperation<'_>) -> Box<dyn PrivateKeyOperation> {
        Box::new(AsyncPrivateKeyOperationAdapter(
            self.0.decrypt(decrypt_op.ciphertext),
        ))
    }
}

struct AsyncPrivateKeyOperationAdapter<Fut>(Fut);

impl<Fut> PrivateKeyOperation for AsyncPrivateKeyOperationAdapter<Fut>
where
    Fut: Unpin + Send + Sync + Future<Output = Option<Vec<u8>>>,
{
    fn complete(
        &mut self,
        context: Option<&mut Context<'_>>,
        output: &mut [u8],
    ) -> PrivateKeyOperationResult {
        let Some(cx) = context else {
            return PrivateKeyOperationResult::Error;
        };
        match Pin::new(&mut self.0).poll(cx) {
            Poll::Ready(None) => PrivateKeyOperationResult::Error,
            Poll::Ready(Some(res)) => {
                if res.len() > output.len() {
                    PrivateKeyOperationResult::Error
                } else {
                    output[..res.len()].copy_from_slice(&res);
                    PrivateKeyOperationResult::Success(res.len())
                }
            }
            Poll::Pending => PrivateKeyOperationResult::Pending,
        }
    }
}

bssl_macros::bssl_enum! {
    /// [IANA] designation of TLS signature algorithms.
    ///
    /// [IANA]: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-16
    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
    pub enum SignatureAlgorithm: u16 {
        /// IANA entry `rsa_pkcs1_sha256`
        RsaPkcs1Sha256 = bssl_sys::SSL_SIGN_RSA_PKCS1_SHA256 as u16,
        /// IANA entry `rsa_pkcs1_sha384`
        RsaPkcs1Sha384 = bssl_sys::SSL_SIGN_RSA_PKCS1_SHA384 as u16,
        /// IANA entry `rsa_pkcs1_sha512`
        RsaPkcs1Sha512 = bssl_sys::SSL_SIGN_RSA_PKCS1_SHA512 as u16,
        /// IANA entry `ecdsa_secp256r1_sha256`
        EcdsaSecp256r1Sha256 = bssl_sys::SSL_SIGN_ECDSA_SECP256R1_SHA256 as u16,
        /// IANA entry `ecdsa_secp384r1_sha384`
        EcdsaSecp384r1Sha384 = bssl_sys::SSL_SIGN_ECDSA_SECP384R1_SHA384 as u16,
        /// IANA entry `ecdsa_secp521r1_sha512`
        EcdsaSecp521r1Sha512 = bssl_sys::SSL_SIGN_ECDSA_SECP521R1_SHA512 as u16,
        /// IANA entry `rsa_pss_rsae_sha256`
        RsaPssRsaeSha256 = bssl_sys::SSL_SIGN_RSA_PSS_RSAE_SHA256 as u16,
        /// IANA entry `rsa_pss_rsae_sha384`
        RsaPssRsaeSha384 = bssl_sys::SSL_SIGN_RSA_PSS_RSAE_SHA384 as u16,
        /// IANA entry `rsa_pss_rsae_sha512`
        RsaPssRsaeSha512 = bssl_sys::SSL_SIGN_RSA_PSS_RSAE_SHA512 as u16,
        /// IANA entry `ed25519`
        Ed25519 = bssl_sys::SSL_SIGN_ED25519 as u16,
        /// IANA entry `ML-DSA-44`
        Mldsa44 = bssl_sys::SSL_SIGN_ML_DSA_44 as u16,
        /// IANA entry `ML-DSA-65`
        Mldsa65 = bssl_sys::SSL_SIGN_ML_DSA_65 as u16,
        /// IANA entry `ML-DSA-87`
        Mldsa87 = bssl_sys::SSL_SIGN_ML_DSA_87 as u16,
    }
}

// NOTE: this context does not own the connection.
/// A verification context handle.
#[repr(transparent)]
pub struct VerifyCertificateContext(NonNull<bssl_sys::SSL>);

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

    /// Get Encrypted `ClientHello` name override, specifically a DNS name per
    /// [RFC 5280], which a character set stipulated by [RFC 1034] §3.5.
    ///
    /// The returned name should be interpreted first as an opaque byte string.
    ///
    /// # Interaction with custom certificate verification
    ///
    /// If the return value is [`Some`], the end-entity certificate must be
    /// verified against the name reported by this call.
    ///
    /// [RFC 5280]: <https://datatracker.ietf.org/doc/html/rfc5280>
    /// [RFC 1034]: <https://datatracker.ietf.org/doc/html/rfc1034#section-3.5>
    pub fn get_ech_name_override(&self) -> Option<&str> {
        let name: &[u8] = unsafe {
            // Safety:
            // - `self` outlives the slice.
            // - transmuting i8 to u8 preserve the character value.
            core::mem::transmute(call_slice_getter!(
                bssl_sys::SSL_get0_ech_name_override,
                self.ptr()
            )?)
        };
        if name.is_empty() || !name.is_ascii() {
            return None;
        }
        // A DNS name has to be an IA5String, specifically ASCII first.
        str::from_utf8(name).ok()
    }

    /// Get the stapled OCSP response, if any.
    ///
    /// The response may not be a valid OCSPResponse from the server as per
    /// [RFC 2560].
    ///
    /// [RFC 2560]: <https://datatracker.ietf.org/doc/html/rfc6960>
    pub fn get_ocsp_response(&self) -> Option<&[u8]> {
        // Safety: response, when it exists, is outlived by the connection.
        let response = call_slice_getter!(bssl_sys::SSL_get0_ocsp_response, self.ptr())?;
        (!response.is_empty()).then_some(response)
    }

    /// Get the Signed Certificate Timestamp list, if any, as per [RFC 6962] §3.2.
    ///
    /// [RFC 6962]: <https://datatracker.ietf.org/doc/html/rfc6962#section-3.2>
    pub fn get_signed_cert_timestamp_list(&self) -> Option<&[u8]> {
        // Safety: list, when it exists, is outlived by the connection.
        let list = call_slice_getter!(bssl_sys::SSL_get0_signed_cert_timestamp_list, self.ptr())?;
        (!list.is_empty()).then_some(list)
    }

    /// Get the Raw Public Key offered by the peer in the `ClientHello`.
    pub fn get_peer_raw_public_key(&self) -> Option<Vec<u8>> {
        let pkey = unsafe {
            // Safety:
            // - `self.ptr()` is a valid `SSL` handle.
            // - `pkey` does not escape the current function frame.
            NonNull::new(bssl_sys::SSL_get0_peer_rpk(self.ptr()))?
        };
        Some(marshal_evp_into_spki(pkey))
    }
}

/// Custom certificate verification callback.
///
/// It is recommended to avoid panicking in the trait implementation.
/// A panic in this callback will lead to abort.
///
/// As a return value, one could use [`VerifyCertificateAccepted`] or [`VerifyCertificateRejected`]
/// to deliver the results if the decision can be made immediately and synchronously.
pub trait VerifyCertificate: Send + Sync {
    /// Decide whether a certificate chain is acceptable.
    ///
    /// The peer certificate chain is supplied in `certs`, in which the first certificate is
    /// the End Entity certificate, if any.
    ///
    /// This method may be called more than once if the verification is asynchronous.
    /// To signal suspension, this method should return [`VerifyResult::Pending`].
    fn verify<'a>(
        &self,
        ctx: &'a VerifyCertificateContext,
        certs: CertificateChainIterator<'a>,
    ) -> Box<dyn VerifyCertificateTask>;
}

/// An outstanding certificate verification task.
pub trait VerifyCertificateTask: Send {
    /// Try to complete the verification task.
    fn complete(&mut self, async_ctx: Option<&mut Context<'_>>) -> VerifyResult;
}

/// Custom certificate verification result.
pub enum VerifyResult {
    /// The certificate chain is accepted.
    Accept,
    /// The certification chain is pending asynchronous result.
    Pending,
    /// The certificate chain is rejected possibly with an alert.
    Reject(Option<AlertDescription>),
}

/// Certificate verifier accepts the offered certificates.
#[derive(Debug, Clone, Copy)]
pub struct VerifyCertificateAccepted;

impl VerifyCertificateTask for VerifyCertificateAccepted {
    fn complete(&mut self, _: Option<&mut Context<'_>>) -> VerifyResult {
        VerifyResult::Accept
    }
}

/// Certificate verifier rejects the offered certificates.
#[derive(Debug, Clone, Copy)]
pub struct VerifyCertificateRejected(pub Option<AlertDescription>);

impl VerifyCertificateTask for VerifyCertificateRejected {
    fn complete(&mut self, _: Option<&mut Context<'_>>) -> VerifyResult {
        VerifyResult::Reject(self.0)
    }
}

/// Asynchronous custom certificate verification.
///
/// This is the `async` analogue of [`VerifyCertificate`].
pub trait AsyncVerifyCertificate: Send + Sync + Unpin {
    /// The future type of the verification process.
    type VerifyFuture: 'static + Unpin + Send + Sync + Future<Output = bool>;

    /// Decide whether a certificate chain is acceptable.
    fn verify(
        &self,
        ctx: &VerifyCertificateContext,
        certs: CertificateChainIterator<'_>,
    ) -> Self::VerifyFuture;
}

/// Adapter to run certificate verification asynchronously.
pub struct AsyncVerifyCertificateAdapter<T>(pub T);

impl<T, Fut> VerifyCertificate for AsyncVerifyCertificateAdapter<T>
where
    T: AsyncVerifyCertificate<VerifyFuture = Fut>,
    Fut: 'static + Unpin + Send + Sync + Future<Output = bool>,
{
    fn verify<'a>(
        &self,
        ctx: &'a VerifyCertificateContext,
        certs: CertificateChainIterator<'a>,
    ) -> Box<dyn VerifyCertificateTask> {
        Box::new(AsyncVerifyCertificateTask(self.0.verify(ctx, certs)))
    }
}

struct AsyncVerifyCertificateTask<Fut>(Fut);

impl<Fut> VerifyCertificateTask for AsyncVerifyCertificateTask<Fut>
where
    Fut: 'static + Unpin + Send + Sync + Future<Output = bool>,
{
    fn complete(&mut self, async_ctx: Option<&mut Context<'_>>) -> VerifyResult {
        let Some(cx) = async_ctx else {
            return VerifyResult::Reject(Some(AlertDescription::InternalError));
        };
        let outstanding_task = Pin::new(&mut self.0);
        match outstanding_task.poll(cx) {
            Poll::Ready(accept) => {
                if accept {
                    VerifyResult::Accept
                } else {
                    VerifyResult::Reject(Some(AlertDescription::BadCertificate))
                }
            }
            Poll::Pending => VerifyResult::Pending,
        }
    }
}

/// Certificate chain iterator.
///
/// This iterator will supply the peer leaf certificate as the first element in the chain, if any.
pub type CertificateChainIterator<'a> = CryptoBufferIterator<'a, Certificate>;

#[derive(Clone, Copy)]
#[doc(hidden)]
pub struct CryptoBufferIterator<'a, T> {
    inner: StackIterator<'a, bssl_sys::CRYPTO_BUFFER>,
    _p: PhantomData<fn() -> T>,
}

impl<T: CryptoBufferWrapper> CryptoBufferIterator<'_, T> {
    /// Safety: caller must ensure that `sk` outlives `'a`.
    pub(crate) unsafe fn new(sk: *const bssl_sys::stack_st_CRYPTO_BUFFER) -> Self {
        Self {
            inner: unsafe {
                // Safety: `sk` outlives `'a` per pre-condition.
                StackIterator::new(sk)
            },
            _p: PhantomData,
        }
    }
}

impl<T: CryptoBufferWrapper> Iterator for CryptoBufferIterator<'_, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .next()
            .map(|buf| unsafe {
                // Safety: we are only bumping the ref-count
                bssl_sys::CRYPTO_BUFFER_dup_ref(buf)
            })
            .and_then(|ptr| NonNull::new(ptr as *mut _))
            .map(|buf| {
                unsafe {
                    // Safety: `buf` is now exclusively owned.
                    T::from_crypto_buffer(buf)
                }
            })
    }
}

impl<T: CryptoBufferWrapper> ExactSizeIterator for CryptoBufferIterator<'_, T> {
    fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<T: CryptoBufferWrapper> FusedIterator for CryptoBufferIterator<'_, T> {}

/// Safety: this callback stub must be installed with a context object allocated
/// as a `Box<dyn VerifyCertificate>`.
pub(crate) unsafe extern "C" fn cert_cb<M: VerifyCertificateMethods>(
    ssl: *mut bssl_sys::SSL,
    alert: *mut u8,
) -> bssl_sys::ssl_verify_result_t {
    let Some(ssl) = NonNull::new(ssl) else {
        return bssl_sys::ssl_verify_result_t_ssl_verify_invalid;
    };
    let Some(methods) = (unsafe {
        // Safety: `ssl` outlives `methods`
        M::from_ssl(ssl.as_ptr())
    }) else {
        return bssl_sys::ssl_verify_result_t_ssl_verify_invalid;
    };
    let waker = unsafe {
        // Safety:
        // - this callback must be installed by `TlsContextBuilder` or `TlsConnection`,
        //   so the associated data must have been set up correctly.
        // - the caller of this callback must own the connection exclusively.
        waker_data_from_ssl(ssl)
    };
    let mut context = waker.as_ref().map(Context::from_waker);
    let Some(verify) = methods.verify_certificate_methods() else {
        return bssl_sys::ssl_verify_result_t_ssl_verify_invalid;
    };
    let cert_chain = unsafe {
        // Safety: `ssl` is still alive in handshake mode and will outlive `cert_chain`.
        bssl_sys::SSL_get0_peer_certificates(ssl.as_ptr())
    };
    let certs = unsafe {
        // Safety: `cert_chain` is outlived by `ssl` whose lifetime is annotated as `'a`.
        CertificateChainIterator::new(cert_chain)
    };
    let ctx = &VerifyCertificateContext(ssl);
    let async_ctx = context.as_mut();

    let outstanding_task = unsafe {
        // Safety: `ssl` outlives the in-flight task and exclusively owned by the caller of
        // this callback.
        verify_cert_task_from_ssl(ssl)
    };

    abort_on_panic(move || {
        if let Some(task) = outstanding_task {
            match task.complete(async_ctx) {
                VerifyResult::Pending => bssl_sys::ssl_verify_result_t_ssl_verify_retry,
                VerifyResult::Accept => {
                    let _ = outstanding_task.take();
                    bssl_sys::ssl_verify_result_t_ssl_verify_ok
                }
                VerifyResult::Reject(ad) => {
                    let _ = outstanding_task.take();
                    if let Some(ad) = ad {
                        unsafe {
                            // Safety: `alert` is valid per BoringSSL invariants.
                            alert.write(ad as _);
                        }
                    }
                    bssl_sys::ssl_verify_result_t_ssl_verify_invalid
                }
            }
        } else {
            let mut task = verify.verify(ctx, certs);
            match task.complete(async_ctx) {
                VerifyResult::Pending => {
                    *outstanding_task = Some(task);
                    bssl_sys::ssl_verify_result_t_ssl_verify_retry
                }
                VerifyResult::Accept => bssl_sys::ssl_verify_result_t_ssl_verify_ok,
                VerifyResult::Reject(ad) => {
                    if let Some(ad) = ad {
                        unsafe {
                            // Safety: `alert` is valid per BoringSSL invariants.
                            alert.write(ad as _);
                        }
                    }
                    bssl_sys::ssl_verify_result_t_ssl_verify_invalid
                }
            }
        }
    })
}

bssl_macros::bssl_enum! {
    /// [IANA] designation of TLS certificate types.
    ///
    /// [IANA]: https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#tls-extensiontype-values-3
    #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
    pub enum CertificateType: u8 {
        /// X.509 certificate type.
        X509 = bssl_sys::TLSEXT_cert_type_x509 as u8,
        /// Raw Public Key certificate type per [RFC 7250].
        ///
        /// [RFC 7250]: https://datatracker.ietf.org/doc/html/rfc7250
        Rpk = bssl_sys::TLSEXT_cert_type_rpk as u8,
    }
}

bssl_macros::bssl_enum! {
    /// Certificate verification mode
    pub enum CertificateVerificationMode: i8 {
        /// Verifies the server certificate on a client but does not make errors fatal.
        None = bssl_sys::SSL_VERIFY_NONE as i8,
        /// Verifies the server certificate on a client and makes errors fatal.
        PeerCertRequested = bssl_sys::SSL_VERIFY_PEER as i8,
        /// Configures a server to request a client certificate and **reject** connections if
        /// the client declines to send a certificate.
        PeerCertMandatory =
            (bssl_sys::SSL_VERIFY_FAIL_IF_NO_PEER_CERT | bssl_sys::SSL_VERIFY_PEER) as i8,
    }
}

impl TryFrom<c_int> for CertificateVerificationMode {
    type Error = c_int;
    fn try_from(mode: c_int) -> Result<Self, Self::Error> {
        let Ok(value) = i8::try_from(mode) else {
            return Err(mode);
        };
        if let Ok(mode) = Self::try_from(value) {
            Ok(mode)
        } else {
            Err(mode)
        }
    }
}

pub(crate) fn marshal_evp_into_spki(pkey: NonNull<bssl_sys::EVP_PKEY>) -> Vec<u8> {
    let buffer = bssl_crypto::cbb_to_buffer(64, |cbb| {
        assert_eq!(
            unsafe {
                // Safety:
                // - `cbb` is a valid pointer to `CBB` provided by `cbb_to_buffer`.
                // - `pkey` is a valid pointer to `EVP_PKEY`.
                bssl_sys::EVP_marshal_public_key(cbb, pkey.as_ptr())
            },
            1
        );
    });
    buffer.as_ref().to_vec()
}

/// Get the peer's [`CertificateType`] from a valid SSL handle.
///
/// # Safety
/// `ssl` must be a valid `SSL` pointer.
pub(crate) fn get_peer_certificate_type(ssl: *mut bssl_sys::SSL) -> Option<CertificateType> {
    let ty = unsafe {
        // Safety: `ssl` is a valid `SSL` handle by caller invariant.
        bssl_sys::SSL_get_peer_cert_type(ssl)
    };
    ty.try_into().ok().and_then(|ty: u8| ty.try_into().ok())
}

/// Get the peer's raw public key as DER-encoded `SubjectPublicKeyInfo` from a valid SSL handle.
///
/// # Safety
/// `ssl` must be a valid `SSL` pointer.
pub(crate) fn get_peer_raw_public_key(ssl: *mut bssl_sys::SSL) -> Option<Vec<u8>> {
    let pkey = unsafe {
        // Safety: `ssl` is a valid `SSL` handle by caller invariant.
        // `pkey` does not escape the current function frame.
        NonNull::new(bssl_sys::SSL_get0_peer_rpk(ssl))?
    };
    Some(marshal_evp_into_spki(pkey))
}

crypto_buffer_wrapper! {
    /// A name `DistinguishedName` encoded into DER per [RFC 5280].
    /// Typically this is used to enclose a certificate authority name.
    ///
    /// [RFC 5280]: <https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1>
    pub struct DistinguishedName
}

impl DistinguishedName {
    pub(crate) fn into_crypto_buffer_stack(
        names: impl IntoIterator<Item = Self>,
    ) -> *mut bssl_sys::stack_st_CRYPTO_BUFFER {
        let mut sk = Stack::new();
        for name in names {
            unsafe {
                // Safety: `name` is owned at the moment.
                sk.push(name.into_raw());
            }
        }
        sk.into_raw()
    }
}

#[cfg(test)]
mod tests;
