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

use bssl_x509::keys::PrivateKeyAlgorithm;
use futures::future::try_join;

use super::*;
use crate::{
    context::TlsMode,
    tests::create_mock_pipe, //
};

#[test]
fn parse_none() {
    let certs = Certificate::parse_all_from_pem(b"", None).unwrap();
    assert!(certs.is_empty());
}

#[test]
fn parse_one() {
    const PEM: &'_ [u8] = b"
Hello world!
-----BEGIN CERTIFICATE-----
SGVsbG8gV29ybGQh
-----END CERTIFICATE-----
";
    let certs = Certificate::parse_all_from_pem(PEM, None).unwrap();
    assert_eq!(certs.len(), 1);
    assert_eq!(certs[0].as_der_bytes(), b"Hello World!");
}

#[test]
fn parse_all_pems() {
    const PEM: &'_ [u8] = b"
Hello world!
-----BEGIN CERTIFICATE-----
SGVsbG8gV29ybGQh
-----END CERTIFICATE-----
BoringSSL is ...
-----BEGIN CERTIFICATE-----
QXdlc29tZSBCb3JpbmdTU0wh
-----END CERTIFICATE-----
Trailing bits ...
";
    let certs = Certificate::parse_all_from_pem(PEM, None).unwrap();
    assert_eq!(certs.len(), 2);
    assert_eq!(certs[0].as_der_bytes(), b"Hello World!");
    assert_eq!(certs[1].as_der_bytes(), b"Awesome BoringSSL!");
}

#[test]
fn parse_all_pems_fail() {
    const PEM: &'_ [u8] = b"
Hello world!
-----BEGIN CERTIFICATE-----
SGVsbG8gV29ybGQh
-----END CERTIFICATE-----
BoringSSL is ...
-----BEGIN CERTIFICATE-----
QXdlc29tZSBCb3JpbmdTU0wh
-----END CERTIFICATE-----
But something badddd...
-----BEGIN CERTIFICATE-----
";
    let _ = Certificate::parse_all_from_pem(PEM, None).unwrap_err();
}

#[test]
fn parse_private_key() {
    const PEM: &'_ [u8] = b"-----BEGIN ENCRYPTED PRIVATE KEY-----
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
-----END ENCRYPTED PRIVATE KEY-----
";
    let priv_key = PrivateKey::from_pem(PEM, || b"Hello BoringSSL!").unwrap();
    assert!(matches!(
        priv_key.algorithm(),
        Some(PrivateKeyAlgorithm::Rsa)
    ));
}

#[test]
fn psk_tls13_handshake() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let key = b"test-key-test-key-test-key-test-key";
    let identity = b"test-identity";
    let context = b"test-context";

    let cred = TlsCredential::new_pre_shared_key(key, identity, PskHash::Sha256, context)?;

    let mut server_ctx = crate::context::TlsContextBuilder::new_tls();
    server_ctx.with_credential(cred.clone())?;

    let mut client_ctx = crate::context::TlsContextBuilder::new_tls();
    client_ctx.with_credential(cred)?;

    let server_ctx = server_ctx.build();
    let client_ctx = client_ctx.build();

    let (client_socket, server_socket, mut executor) = create_mock_pipe();

    let mut client_conn = client_ctx.new_client_connection(None)?.build();
    let mut server_conn = server_ctx.new_server_connection(None)?.build();

    client_conn.set_io(client_socket)?;
    server_conn.set_io(server_socket)?;

    let test_future = async {
        let client_handshake = async {
            let mut in_handshake = client_conn.in_handshake().unwrap();
            in_handshake.async_handshake().await?;
            Ok::<(), crate::errors::Error>(())
        };

        let server_handshake = async {
            let mut in_handshake = server_conn.in_handshake().unwrap();
            in_handshake.async_handshake().await?;
            Ok::<(), crate::errors::Error>(())
        };

        try_join(client_handshake, server_handshake).await?;
        Ok::<(), crate::errors::Error>(())
    };

    executor.run(test_future)?;

    Ok(())
}

#[cfg(all(unix, feature = "std"))]
#[test]
fn psk_tls13_handshake_sync() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    use crate::io::sync_io::{NoAsync, StdIoWithReactor};
    use std::io::pipe;

    let (server_rx, client_tx) = pipe().unwrap();
    let (client_rx, server_tx) = pipe().unwrap();

    let client_reader = StdIoWithReactor::new(client_rx, NoAsync);
    let client_writer = StdIoWithReactor::new(client_tx, NoAsync);
    let server_reader = StdIoWithReactor::new(server_rx, NoAsync);
    let server_writer = StdIoWithReactor::new(server_tx, NoAsync);

    let key = b"test-key-test-key-test-key-test-key";
    let identity = b"test-identity";
    let context = b"test-context";

    let cred = TlsCredential::new_pre_shared_key(key, identity, PskHash::Sha256, context)?;

    let mut server_ctx = crate::context::TlsContextBuilder::new_tls();
    server_ctx.with_credential(cred.clone())?;
    let server_ctx = server_ctx.build();

    let mut client_ctx = crate::context::TlsContextBuilder::new_tls();
    client_ctx.with_credential(cred)?;
    let client_ctx = client_ctx.build();

    let mut client_conn = client_ctx.new_client_connection(None)?.build();
    let mut server_conn = server_ctx.new_server_connection(None)?.build();

    client_conn.set_split_io(client_reader, client_writer)?;
    server_conn.set_split_io(server_reader, server_writer)?;

    let server_thread = std::thread::spawn(move || {
        let mut in_handshake = server_conn.in_handshake().unwrap();
        in_handshake.do_handshake().unwrap();
        server_conn
    });

    let mut in_handshake = client_conn.in_handshake().unwrap();
    in_handshake.do_handshake().unwrap();

    let _server_conn = server_thread.join().unwrap();

    Ok(())
}

unsafe extern "C" fn accept_any_verify(
    _ssl: *mut bssl_sys::SSL,
    _out_alert: *mut u8,
) -> bssl_sys::ssl_verify_result_t {
    bssl_sys::ssl_verify_result_t_ssl_verify_ok
}

#[test]
fn rpk_tls13_handshake() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    use bssl_x509::keys::PrivateKey;

    let priv_key = PrivateKey::from_pem(crate::tests::RSA_SERVER_KEY, || unreachable!()).unwrap();

    let cred = TlsCredentialBuilder::<RawPublicKeyMode>::new_raw_public_key(priv_key)
        .build()
        .unwrap();

    let mut server_ctx = crate::context::TlsContextBuilder::new_tls();
    server_ctx.with_credential(cred.clone())?;
    let server_ctx = server_ctx.build();

    let mut client_ctx = crate::context::TlsContextBuilder::new_tls();
    client_ctx.with_accepted_peer_cert_types(&[CertificateType::Rpk])?;
    let client_ctx = client_ctx.build();

    let mut client_conn_builder = client_ctx.new_client_connection(None)?;
    client_conn_builder.with_certificate_verification_mode(CertificateVerificationMode::None);
    let mut client_conn = client_conn_builder.build();
    unsafe {
        // Safety:
        // - `client_conn.ptr()` is a valid `SSL` handle.
        // - `accept_any_verify` is a valid callback.
        bssl_sys::SSL_set_custom_verify(
            client_conn.ptr(),
            bssl_sys::SSL_VERIFY_PEER as _,
            Some(accept_any_verify),
        );
    }
    let mut server_conn = server_ctx.new_server_connection(None)?.build();

    let (sock_client, sock_server, mut executor) = create_mock_pipe();

    client_conn.set_io(sock_client)?;
    server_conn.set_io(sock_server)?;

    executor.run(try_join(
        Pin::new(&mut client_conn).async_write(b"hello"),
        Pin::new(&mut server_conn).async_write(b"world"),
    ))?;

    assert_eq!(
        client_conn.get_peer_certificate_type(),
        Some(CertificateType::Rpk)
    );

    Ok(())
}

struct AcceptAnyVerifier;

impl VerifyCertificate for AcceptAnyVerifier {
    fn verify<'a>(
        &self,
        _: &'a VerifyCertificateContext,
        _: crate::credentials::CertificateChainIterator<'a>,
    ) -> Box<dyn VerifyCertificateTask> {
        Box::new(crate::credentials::VerifyCertificateAccepted)
    }
}

struct RpkVerifier {
    expected_spki_der: Vec<u8>,
}

impl VerifyCertificate for RpkVerifier {
    fn verify<'a>(
        &self,
        ctx: &'a VerifyCertificateContext,
        _: crate::credentials::CertificateChainIterator<'a>,
    ) -> Box<dyn VerifyCertificateTask> {
        let Some(der) = ctx.get_peer_raw_public_key() else {
            return Box::new(VerifyCertificateRejected(None));
        };
        if der != self.expected_spki_der {
            return Box::new(VerifyCertificateRejected(None));
        }

        Box::new(crate::credentials::VerifyCertificateAccepted)
    }
}

#[test]
fn psk_rpk_fallback_test() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    use std::sync::{
        Arc,
        atomic::{AtomicBool, Ordering},
    };

    use bssl_x509::keys::PrivateKey;

    use crate::{
        context::TlsContextBuilder,
        credentials::{
            CertificateType, CertificateVerificationMode, PskHash, RawPublicKeyMode, TlsCredential,
            TlsCredentialBuilder,
            early_callback::{ClientHello, EarlyCallback, EarlyCallbackResult, ExtensionType},
        },
        io::IoStatus,
    };

    let priv_key = PrivateKey::from_pem(crate::tests::RSA_SERVER_KEY, || unreachable!())?;

    let rpk_cred = TlsCredentialBuilder::<RawPublicKeyMode>::new_raw_public_key(priv_key.clone())
        .build()
        .ok_or("raw public key failed to parse".to_string())?;

    let server_certs =
        crate::credentials::Certificate::parse_all_from_pem(crate::tests::RSA_SERVER_CERT, None)?;
    let mut server_cred_builder = TlsCredentialBuilder::<crate::credentials::X509Mode>::new();
    server_cred_builder
        .with_certificate_chain(&server_certs)?
        .with_private_key(priv_key.clone())?;
    let server_cred = server_cred_builder
        .build()
        .ok_or("credential is incomplete".to_string())?;

    let x509_cert = bssl_x509::certificates::X509Certificate::parse_one_from_pem(
        crate::tests::RSA_SERVER_CERT,
    )?;
    let expected_rpk_der = x509_cert
        .public_key()
        .ok_or("public key is missing in x509".to_string())?
        .to_der();

    let key = b"test-key-test-key-test-key-test-key";
    let identity = b"test-identity";
    let context = b"test-context";
    let psk_cred = TlsCredential::new_pre_shared_key(key, identity, PskHash::Sha256, context)?;

    type AtomicFlag = Arc<AtomicBool>;
    struct ServerSelectCallback {
        server_cred: TlsCredential,
        psk_cred: TlsCredential,
        selected_rpk: AtomicFlag,
        selected_psk: AtomicFlag,
        failed: AtomicFlag,
    }

    impl EarlyCallback<TlsMode> for ServerSelectCallback {
        fn process(&self, client_hello: &mut ClientHello<'_, TlsMode>) -> EarlyCallbackResult {
            let offered_rpk = client_hello
                .get_extension(ExtensionType::CLIENT_CERT_TYPE)
                .is_some();
            let offered_psk = client_hello
                .get_extension(ExtensionType::PRE_SHARED_KEY)
                .is_some();

            if offered_rpk {
                if (|| {
                    client_hello
                        .connection_mut()
                        .add_credential(&self.server_cred)?
                        .set_certificate_verification_mode(
                            CertificateVerificationMode::PeerCertMandatory,
                        );
                    Ok::<_, crate::errors::Error>(())
                })()
                .is_err()
                {
                    return EarlyCallbackResult::ErrorResult;
                };
                self.selected_rpk.store(true, Ordering::SeqCst);
                EarlyCallbackResult::Success
            } else if offered_psk {
                let Ok(_) = client_hello.connection_mut().add_credential(&self.psk_cred) else {
                    return EarlyCallbackResult::ErrorResult;
                };
                self.selected_psk.store(true, Ordering::SeqCst);
                EarlyCallbackResult::Success
            } else {
                self.failed.store(true, Ordering::SeqCst);
                EarlyCallbackResult::ErrorResult
            }
        }
    }

    for &(offer_psk, offer_rpk) in &[(true, false), (false, true), (true, true), (false, false)] {
        let selected_rpk = AtomicFlag::default();
        let selected_psk = AtomicFlag::default();
        let failed = AtomicFlag::default();

        let cb = ServerSelectCallback {
            server_cred: server_cred.clone(),
            psk_cred: psk_cred.clone(),
            selected_rpk: selected_rpk.clone(),
            selected_psk: selected_psk.clone(),
            failed: failed.clone(),
        };

        let mut server_ctx_builder = TlsContextBuilder::new_tls();
        server_ctx_builder
            .with_accepted_peer_cert_types(&[CertificateType::Rpk])?
            .with_early_callback(cb)
            .with_certificate_verifier(
                CertificateVerificationMode::None,
                RpkVerifier {
                    expected_spki_der: expected_rpk_der.clone(),
                },
            );
        let server_ctx = server_ctx_builder.build();

        let mut client_ctx_builder = TlsContextBuilder::new_tls();
        if offer_psk {
            client_ctx_builder.with_credential(psk_cred.clone())?;
        }
        if offer_rpk {
            client_ctx_builder
                .with_credential(rpk_cred.clone())?
                .with_available_client_cert_types(&[CertificateType::Rpk])?;
        }
        let client_ctx = client_ctx_builder.build();

        let (sock_client, sock_server, mut executor) = create_mock_pipe();

        let mut server_conn = server_ctx.new_server_connection(None)?.build();
        server_conn.set_io(sock_server)?;

        let mut client_conn_builder = client_ctx.new_client_connection(None)?;
        client_conn_builder
            .with_certificate_verification_mode(CertificateVerificationMode::None)
            .with_certificate_verifier(
                CertificateVerificationMode::PeerCertRequested,
                AcceptAnyVerifier,
            );
        let mut client_conn = client_conn_builder.build();
        client_conn.set_io(sock_client)?;

        let test_future = async {
            let client_handshake = async {
                if let Some(mut in_handshake) = client_conn.in_handshake() {
                    in_handshake.async_handshake().await?;
                }
                Ok::<(), crate::errors::Error>(())
            };

            let server_handshake = async {
                if let Some(mut in_handshake) = server_conn.in_handshake() {
                    in_handshake.async_handshake().await?;
                }
                Ok::<(), crate::errors::Error>(())
            };

            let handshake_result =
                futures::future::try_join(client_handshake, server_handshake).await;

            if !offer_psk && !offer_rpk {
                assert!(handshake_result.is_err(), "Handshake should have failed");
                return Ok::<(), crate::errors::Error>(());
            }

            handshake_result?;

            client_conn.as_pin_mut().async_write(b"hello").await?;

            let mut server_buf = [0u8; 5];
            let read_len = server_conn.as_pin_mut().async_read(&mut server_buf).await?;
            assert!(matches!(read_len, IoStatus::Ok(5)));
            assert_eq!(&server_buf, b"hello");

            server_conn.as_pin_mut().async_write(b"world").await?;

            let mut client_buf = [0u8; 5];
            let read_len = client_conn.as_pin_mut().async_read(&mut client_buf).await?;
            assert!(matches!(read_len, IoStatus::Ok(5)));
            assert_eq!(&client_buf, b"world");

            Ok::<(), crate::errors::Error>(())
        };

        executor.run(test_future)?;

        if !offer_psk && !offer_rpk {
            assert!(
                failed.load(Ordering::SeqCst),
                "Should fail if no valid credentials offered"
            );
            continue;
        }

        if offer_rpk {
            assert!(
                selected_rpk.load(Ordering::SeqCst),
                "Should select RPK if offered"
            );
            assert_eq!(
                server_conn.get_peer_certificate_type(),
                Some(CertificateType::Rpk)
            );
        } else if offer_psk {
            assert!(
                selected_psk.load(Ordering::SeqCst),
                "Should fallback to PSK if only PSK offered"
            );
        }
    }

    Ok(())
}
