/* Copyright (c) 2024, Google Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

//! Hybrid Public Key Encryption
//!
//! HPKE provides public key encryption of arbitrary-length messages. It
//! establishes contexts that produce/consume an ordered sequence of
//! ciphertexts that are both encrypted and authenticated.
//!
//! See RFC 9180 for more details.
//!
//! ```
//! use bssl_crypto::hpke;
//!
//! let kem = hpke::Kem::X25519HkdfSha256;
//! let (pub_key, priv_key) = kem.generate_keypair();
//! // Distribute `pub_key` to people who want to send you messages.
//!
//! // On the sending side...
//! let params = hpke::Params::new(kem, hpke::Kdf::HkdfSha256, hpke::Aead::Aes128Gcm);
//! let info : &[u8] = b"mutual context";
//! let (mut sender_ctx, encapsulated_key) =
//!     hpke::SenderContext::new(&params, &pub_key, info).unwrap();
//! // Transmit the `encapsulated_key` to the receiver, followed by one or
//! // more ciphertexts...
//! let aad = b"associated_data";
//! let plaintext1 : &[u8] = b"plaintext1";
//! let msg1 = sender_ctx.seal(plaintext1, aad);
//! let plaintext2 : &[u8] = b"plaintext2";
//! let msg2 = sender_ctx.seal(plaintext2, aad);
//!
//! // On the receiving side...
//! let mut recipient_ctx = hpke::RecipientContext::new(
//!     &params,
//!     &priv_key,
//!     &encapsulated_key,
//!     info,
//! ).unwrap();
//!
//! let received_plaintext1 = recipient_ctx.open(&msg1, aad).unwrap();
//! assert_eq!(plaintext1, &received_plaintext1);
//! let received_plaintext2 = recipient_ctx.open(&msg2, aad).unwrap();
//! assert_eq!(plaintext2, &received_plaintext2);
//!
//! // Messages must be processed in order, so trying to `open` the second
//! // message first will fail.
//! let mut recipient_ctx = hpke::RecipientContext::new(
//!     &params,
//!     &priv_key,
//!     &encapsulated_key,
//!     info,
//! ).unwrap();
//!
//! let received_plaintext2 = recipient_ctx.open(&msg2, aad);
//! assert!(received_plaintext2.is_none());
//! ```

use crate::{scoped, with_output_vec, with_output_vec_fallible, FfiSlice};
use alloc::vec::Vec;

/// Supported KEM algorithms with values detailed in RFC 9180.
#[derive(Clone, Copy)]
pub enum Kem {
    #[allow(missing_docs)]
    X25519HkdfSha256 = 32,
}

impl Kem {
    fn as_ffi_ptr(&self) -> *const bssl_sys::EVP_HPKE_KEM {
        // Safety: this function returns a pointer to static data.
        unsafe {
            match self {
                Kem::X25519HkdfSha256 => bssl_sys::EVP_hpke_x25519_hkdf_sha256(),
            }
        }
    }

    /// Generate a public and private key for this KEM.
    pub fn generate_keypair(&self) -> (Vec<u8>, Vec<u8>) {
        let mut key = scoped::EvpHpkeKey::new();
        // Safety: `key` and `self` must be valid and this function doesn't
        // take ownership of either.
        let ret =
            unsafe { bssl_sys::EVP_HPKE_KEY_generate(key.as_mut_ffi_ptr(), self.as_ffi_ptr()) };
        // Key generation currently never fails, and out-of-memory is not
        // handled by this crate.
        assert_eq!(ret, 1);

        fn get_value_from_key(
            key: &scoped::EvpHpkeKey,
            accessor: unsafe extern "C" fn(
                *const bssl_sys::EVP_HPKE_KEY,
                // Output buffer.
                *mut u8,
                // Number of bytes written.
                *mut usize,
                // Maximum output size.
                usize,
            ) -> core::ffi::c_int,
            max_len: usize,
        ) -> Vec<u8> {
            unsafe {
                with_output_vec(max_len, |out| {
                    let mut out_len = 0usize;
                    let ret = accessor(key.as_ffi_ptr(), out, &mut out_len, max_len);
                    // If `max_len` is correct then these functions never fail.
                    assert_eq!(ret, 1);
                    assert!(out_len <= max_len);
                    // Safety: `out_len` bytes have been written, as required.
                    out_len
                })
            }
        }

        let pub_key = get_value_from_key(
            &key,
            bssl_sys::EVP_HPKE_KEY_public_key,
            bssl_sys::EVP_HPKE_MAX_PUBLIC_KEY_LENGTH as usize,
        );
        let priv_key = get_value_from_key(
            &key,
            bssl_sys::EVP_HPKE_KEY_private_key,
            bssl_sys::EVP_HPKE_MAX_PRIVATE_KEY_LENGTH as usize,
        );
        (pub_key, priv_key)
    }
}

/// Supported KDF algorithms with values detailed in RFC 9180.
#[derive(Clone, Copy)]
pub enum Kdf {
    #[allow(missing_docs)]
    HkdfSha256 = 1,
}

/// Supported AEAD algorithms with values detailed in RFC 9180.
#[derive(Clone, Copy)]
#[allow(missing_docs)]
pub enum Aead {
    Aes128Gcm = 1,
    Aes256Gcm = 2,
    Chacha20Poly1305 = 3,
}

impl Aead {
    fn from_rfc_id(n: u16) -> Option<Aead> {
        let ret = match n {
            1 => Aead::Aes128Gcm,
            2 => Aead::Aes256Gcm,
            3 => Aead::Chacha20Poly1305,
            _ => return None,
        };
        // The mapping above must agree with the values in the enum.
        assert_eq!(n, ret as u16);
        Some(ret)
    }

    fn as_ffi_ptr(&self) -> *const bssl_sys::EVP_HPKE_AEAD {
        // Safety: these functions all return pointers to static data.
        unsafe {
            match self {
                Aead::Aes128Gcm => bssl_sys::EVP_hpke_aes_128_gcm(),
                Aead::Aes256Gcm => bssl_sys::EVP_hpke_aes_256_gcm(),
                Aead::Chacha20Poly1305 => bssl_sys::EVP_hpke_chacha20_poly1305(),
            }
        }
    }
}

/// Maximum length of the encapsulated key for all currently supported KEMs.
const MAX_ENCAPSULATED_KEY_LEN: usize = bssl_sys::EVP_HPKE_MAX_ENC_LENGTH as usize;

/// HPKE parameters, including KEM, KDF, and AEAD.
pub struct Params {
    kem: *const bssl_sys::EVP_HPKE_KEM,
    kdf: *const bssl_sys::EVP_HPKE_KDF,
    aead: *const bssl_sys::EVP_HPKE_AEAD,
}

impl Params {
    /// New `Params` from KEM, KDF, and AEAD enums.
    pub fn new(_kem: Kem, _kdf: Kdf, aead: Aead) -> Self {
        // Safety: EVP_hpke_x25519_hkdf_sha256 and EVP_hpke_hkdf_sha256 just
        // return pointers to static data.
        unsafe {
            Self {
                // Only one KEM and KDF are supported thus far.
                kem: bssl_sys::EVP_hpke_x25519_hkdf_sha256(),
                kdf: bssl_sys::EVP_hpke_hkdf_sha256(),
                aead: aead.as_ffi_ptr(),
            }
        }
    }

    /// New `Params` from KEM, KDF, and AEAD IDs as detailed in RFC 9180.
    pub fn new_from_rfc_ids(kem_id: u16, kdf_id: u16, aead_id: u16) -> Option<Self> {
        let kem = Kem::X25519HkdfSha256;
        let kdf = Kdf::HkdfSha256;
        let aead = Aead::from_rfc_id(aead_id)?;

        if kem_id != kem as u16 || kdf_id != kdf as u16 {
            return None;
        }
        Some(Self::new(kem, kdf, aead))
    }
}

/// HPKE sender context. Callers may use `seal()` to encrypt messages for the recipient.
pub struct SenderContext(scoped::EvpHpkeCtx);

impl SenderContext {
    /// Performs the SetupBaseS HPKE operation and returns a sender context
    /// plus an encapsulated shared secret for `recipient_pub_key`.
    ///
    /// Returns `None` if `recipient_pub_key` is invalid.
    ///
    /// On success, callers may use `seal()` to encrypt messages for the recipient.
    pub fn new(params: &Params, recipient_pub_key: &[u8], info: &[u8]) -> Option<(Self, Vec<u8>)> {
        let mut ctx = scoped::EvpHpkeCtx::new();
        unsafe {
            with_output_vec_fallible(MAX_ENCAPSULATED_KEY_LEN, |enc_key_buf| {
                let mut enc_key_len = 0usize;
                // Safety: EVP_HPKE_CTX_setup_sender
                // - is called with context created from EVP_HPKE_CTX_new,
                // - is called with valid buffers with corresponding pointer and length, and
                // - returns 0 on error.
                let ret = bssl_sys::EVP_HPKE_CTX_setup_sender(
                    ctx.as_mut_ffi_ptr(),
                    enc_key_buf,
                    &mut enc_key_len,
                    MAX_ENCAPSULATED_KEY_LEN,
                    params.kem,
                    params.kdf,
                    params.aead,
                    recipient_pub_key.as_ffi_ptr(),
                    recipient_pub_key.len(),
                    info.as_ffi_ptr(),
                    info.len(),
                );
                if ret == 1 {
                    Some(enc_key_len)
                } else {
                    None
                }
            })
        }
        .map(|enc_key| (Self(ctx), enc_key))
    }

    /// Seal encrypts `plaintext`, and authenticates `aad`, returning the resulting ciphertext.
    ///
    /// Note that HPKE encryption is stateful and ordered. The sender's first call to `seal()` must
    /// correspond to the recipient's first call to `open()`, etc.
    ///
    /// This function panics if adding the `plaintext` length and
    /// `bssl_sys::EVP_HPKE_CTX_max_overhead` overflows.
    pub fn seal(&mut self, plaintext: &[u8], aad: &[u8]) -> Vec<u8> {
        // Safety: EVP_HPKE_CTX_max_overhead panics if ctx is not set up as a sender.
        #[allow(clippy::expect_used)]
        let max_out_len = plaintext
            .len()
            .checked_add(unsafe { bssl_sys::EVP_HPKE_CTX_max_overhead(self.0.as_ffi_ptr()) })
            .expect("Maximum output length calculation overflow");
        unsafe {
            with_output_vec(max_out_len, |out_buf| {
                let mut out_len = 0usize;
                // Safety: EVP_HPKE_CTX_seal
                // - is called with context created from EVP_HPKE_CTX_new and
                // - is called with valid buffers with corresponding pointer and length.
                let result = bssl_sys::EVP_HPKE_CTX_seal(
                    self.0.as_mut_ffi_ptr(),
                    out_buf,
                    &mut out_len,
                    max_out_len,
                    plaintext.as_ffi_ptr(),
                    plaintext.len(),
                    aad.as_ffi_ptr(),
                    aad.len(),
                );
                assert_eq!(result, 1);
                out_len
            })
        }
    }
}

/// HPKE recipient context. Callers may use `open()` to decrypt messages from the sender.
pub struct RecipientContext(scoped::EvpHpkeCtx);

impl RecipientContext {
    /// New implements the SetupBaseR HPKE operation, which decapsulates the shared secret in
    /// `encapsulated_key` with `recipient_priv_key` and sets up a recipient context. These are
    /// stored and returned in the newly created RecipientContext.
    ///
    /// Note that `encapsulated_key` may be invalid, in which case this function will return an
    /// error.
    ///
    /// On success, callers may use `open()` to decrypt messages from the sender.
    pub fn new(
        params: &Params,
        recipient_priv_key: &[u8],
        encapsulated_key: &[u8],
        info: &[u8],
    ) -> Option<Self> {
        let mut hpke_key = scoped::EvpHpkeKey::new();

        // Safety: EVP_HPKE_KEY_init returns 0 on error.
        let result = unsafe {
            bssl_sys::EVP_HPKE_KEY_init(
                hpke_key.as_mut_ffi_ptr(),
                params.kem,
                recipient_priv_key.as_ffi_ptr(),
                recipient_priv_key.len(),
            )
        };
        if result != 1 {
            return None;
        }

        let mut ctx = scoped::EvpHpkeCtx::new();

        // Safety: EVP_HPKE_CTX_setup_recipient
        // - is called with context created from EVP_HPKE_CTX_new,
        // - is called with HPKE key created from EVP_HPKE_KEY_init,
        // - is called with valid buffers with corresponding pointer and length, and
        // - returns 0 on error.
        let result = unsafe {
            bssl_sys::EVP_HPKE_CTX_setup_recipient(
                ctx.as_mut_ffi_ptr(),
                hpke_key.as_ffi_ptr(),
                params.kdf,
                params.aead,
                encapsulated_key.as_ffi_ptr(),
                encapsulated_key.len(),
                info.as_ffi_ptr(),
                info.len(),
            )
        };
        if result == 1 {
            Some(Self(ctx))
        } else {
            None
        }
    }

    /// Open authenticates `aad` and decrypts `ciphertext`. It returns an error on failure.
    ///
    /// Note that HPKE encryption is stateful and ordered. The sender's first call to `seal()` must
    /// correspond to the recipient's first call to `open()`, etc.
    pub fn open(&mut self, ciphertext: &[u8], aad: &[u8]) -> Option<Vec<u8>> {
        let max_out_len = ciphertext.len();
        unsafe {
            with_output_vec_fallible(max_out_len, |out_buf| {
                let mut out_len = 0usize;
                // Safety: EVP_HPKE_CTX_open
                // - is called with context created from EVP_HPKE_CTX_new and
                // - is called with valid buffers with corresponding pointer and length.
                let result = bssl_sys::EVP_HPKE_CTX_open(
                    self.0.as_mut_ffi_ptr(),
                    out_buf,
                    &mut out_len,
                    max_out_len,
                    ciphertext.as_ffi_ptr(),
                    ciphertext.len(),
                    aad.as_ffi_ptr(),
                    aad.len(),
                );
                if result == 1 {
                    Some(out_len)
                } else {
                    None
                }
            })
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::test_helpers::decode_hex;

    struct TestVector {
        kem_id: u16,
        kdf_id: u16,
        aead_id: u16,
        info: [u8; 20],
        seed_for_testing: [u8; 32],   // skEm
        recipient_pub_key: [u8; 32],  // pkRm
        recipient_priv_key: [u8; 32], // skRm
        encapsulated_key: [u8; 32],   // enc
        plaintext: [u8; 29],          // pt
        associated_data: [u8; 7],     // aad
        ciphertext: [u8; 45],         // ct
    }

    // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.1
    fn x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm() -> TestVector {
        TestVector {
            kem_id: 32,
            kdf_id: 1,
            aead_id: 1,
            info: decode_hex("4f6465206f6e2061204772656369616e2055726e"),
            seed_for_testing: decode_hex("52c4a758a802cd8b936eceea314432798d5baf2d7e9235dc084ab1b9cfa2f736"),
            recipient_pub_key: decode_hex("3948cfe0ad1ddb695d780e59077195da6c56506b027329794ab02bca80815c4d"),
            recipient_priv_key: decode_hex("4612c550263fc8ad58375df3f557aac531d26850903e55a9f23f21d8534e8ac8"),
            encapsulated_key: decode_hex("37fda3567bdbd628e88668c3c8d7e97d1d1253b6d4ea6d44c150f741f1bf4431"),
            plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"),
            associated_data: decode_hex("436f756e742d30"),
            ciphertext: decode_hex("f938558b5d72f1a23810b4be2ab4f84331acc02fc97babc53a52ae8218a355a96d8770ac83d07bea87e13c512a"),
        }
    }

    // https://www.rfc-editor.org/rfc/rfc9180.html#appendix-A.2
    fn x25519_hkdf_sha256_hkdf_sha256_chacha20_poly1305() -> TestVector {
        TestVector {
            kem_id: 32,
            kdf_id: 1,
            aead_id: 3,
            info: decode_hex("4f6465206f6e2061204772656369616e2055726e"),
            seed_for_testing: decode_hex("f4ec9b33b792c372c1d2c2063507b684ef925b8c75a42dbcbf57d63ccd381600"),
            recipient_pub_key: decode_hex("4310ee97d88cc1f088a5576c77ab0cf5c3ac797f3d95139c6c84b5429c59662a"),
            recipient_priv_key: decode_hex("8057991eef8f1f1af18f4a9491d16a1ce333f695d4db8e38da75975c4478e0fb"),
            encapsulated_key: decode_hex("1afa08d3dec047a643885163f1180476fa7ddb54c6a8029ea33f95796bf2ac4a"),
            plaintext: decode_hex("4265617574792069732074727574682c20747275746820626561757479"),
            associated_data: decode_hex("436f756e742d30"),
            ciphertext: decode_hex("1c5250d8034ec2b784ba2cfd69dbdb8af406cfe3ff938e131f0def8c8b60b4db21993c62ce81883d2dd1b51a28"),
        }
    }

    #[test]
    fn all_algorithms() {
        let kems = vec![Kem::X25519HkdfSha256];
        let kdfs = vec![Kdf::HkdfSha256];
        let aeads = vec![Aead::Aes128Gcm, Aead::Aes256Gcm, Aead::Chacha20Poly1305];
        let plaintext: &[u8] = b"plaintext";
        let aad: &[u8] = b"aad";
        let info: &[u8] = b"info";

        for kem in &kems {
            let (pub_key, priv_key) = kem.generate_keypair();
            for kdf in &kdfs {
                for aead in &aeads {
                    let params =
                        Params::new_from_rfc_ids(*kem as u16, *kdf as u16, *aead as u16).unwrap();

                    let (mut send_ctx, encapsulated_key) =
                        SenderContext::new(&params, &pub_key, info).unwrap();
                    let mut recv_ctx =
                        RecipientContext::new(&params, &priv_key, &encapsulated_key, info).unwrap();
                    assert_eq!(
                        plaintext,
                        recv_ctx
                            .open(send_ctx.seal(plaintext, aad).as_ref(), aad)
                            .unwrap()
                    );
                    assert_eq!(
                        plaintext,
                        recv_ctx
                            .open(send_ctx.seal(plaintext, aad).as_ref(), aad)
                            .unwrap()
                    );
                    assert!(recv_ctx.open(b"nonsense", aad).is_none());
                }
            }
        }
    }

    fn new_sender_context_for_testing(
        params: &Params,
        recipient_pub_key: &[u8],
        info: &[u8],
        seed_for_testing: &[u8],
    ) -> (SenderContext, Vec<u8>) {
        let mut ctx = scoped::EvpHpkeCtx::new();

        let encapsulated_key = unsafe {
            with_output_vec_fallible(MAX_ENCAPSULATED_KEY_LEN, |enc_key_buf| {
                let mut enc_key_len = 0usize;
                // Safety: EVP_HPKE_CTX_setup_sender_with_seed_for_testing
                // - is called with context created from EVP_HPKE_CTX_new,
                // - is called with valid buffers with corresponding pointer and length, and
                // - returns 0 on error.
                let result = bssl_sys::EVP_HPKE_CTX_setup_sender_with_seed_for_testing(
                    ctx.as_mut_ffi_ptr(),
                    enc_key_buf,
                    &mut enc_key_len,
                    MAX_ENCAPSULATED_KEY_LEN,
                    params.kem,
                    params.kdf,
                    params.aead,
                    recipient_pub_key.as_ffi_ptr(),
                    recipient_pub_key.len(),
                    info.as_ffi_ptr(),
                    info.len(),
                    seed_for_testing.as_ffi_ptr(),
                    seed_for_testing.len(),
                );
                if result == 1 {
                    Some(enc_key_len)
                } else {
                    None
                }
            })
        }
        .unwrap();
        (SenderContext(ctx), encapsulated_key)
    }

    #[test]
    fn seal_with_vector() {
        for test in vec![
            x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(),
            x25519_hkdf_sha256_hkdf_sha256_chacha20_poly1305(),
        ] {
            let params = Params::new_from_rfc_ids(test.kem_id, test.kdf_id, test.aead_id).unwrap();

            let (mut ctx, encapsulated_key) = new_sender_context_for_testing(
                &params,
                &test.recipient_pub_key,
                &test.info,
                &test.seed_for_testing,
            );

            assert_eq!(encapsulated_key, test.encapsulated_key.to_vec());

            let ciphertext = ctx.seal(&test.plaintext, &test.associated_data);
            assert_eq!(&ciphertext, test.ciphertext.as_ref());
        }
    }

    #[test]
    fn open_with_vector() {
        for test in vec![
            x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm(),
            x25519_hkdf_sha256_hkdf_sha256_chacha20_poly1305(),
        ] {
            let params = Params::new_from_rfc_ids(test.kem_id, test.kdf_id, test.aead_id).unwrap();

            let mut ctx = RecipientContext::new(
                &params,
                &test.recipient_priv_key,
                &test.encapsulated_key,
                &test.info,
            )
            .unwrap();

            let plaintext = ctx.open(&test.ciphertext, &test.associated_data).unwrap();
            assert_eq!(&plaintext, test.plaintext.as_ref());
        }
    }

    #[test]
    fn disallowed_params_fail() {
        let vec: TestVector = x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm();

        assert!(Params::new_from_rfc_ids(0, vec.kdf_id, vec.aead_id).is_none());
        assert!(Params::new_from_rfc_ids(vec.kem_id, 0, vec.aead_id).is_none());
        assert!(Params::new_from_rfc_ids(vec.kem_id, vec.kdf_id, 0).is_none());
    }

    #[test]
    fn bad_recipient_pub_key_fails() {
        let vec: TestVector = x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm();
        let params = Params::new_from_rfc_ids(vec.kem_id, vec.kdf_id, vec.aead_id).unwrap();

        assert!(SenderContext::new(&params, b"", &vec.info).is_none());
    }

    #[test]
    fn bad_recipient_priv_key_fails() {
        let vec: TestVector = x25519_hkdf_sha256_hkdf_sha256_aes_128_gcm();
        let params = Params::new_from_rfc_ids(vec.kem_id, vec.kdf_id, vec.aead_id).unwrap();

        assert!(RecipientContext::new(&params, b"", &vec.encapsulated_key, &vec.info).is_none());
    }
}
