// 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_crypto::FromFfiSlice;
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,
        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)]
#[non_exhaustive]
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`.
            Some(u8::from_ffi_ptr(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 contents = unsafe {
                // Safety: the slice is only used within the loop and we will copy the contents
                // when constructing the certificate object.
                u8::from_ffi_ptr(data.0, len)
            };
            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`
            u8::from_ffi_ptr(data, len)
        }
    }
}

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)]
    #[non_exhaustive]
    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)]
    #[non_exhaustive]
    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;
