/* Copyright (c) 2023, 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.
 */

use core::marker::PhantomData;

use crate::ForeignTypeRef;

/// The SHA-256 digest algorithm.
#[derive(Clone)]
pub struct Sha256 {}

/// The SHA-512 digest algorithm.
#[derive(Clone)]
pub struct Sha512 {}

/// A reference to an [`Md`], which abstracts the details of a specific hash function allowing code
/// to deal with the concept of a "hash function" without needing to know exactly which hash function
/// it is.
#[non_exhaustive]
pub struct MdRef;

unsafe impl ForeignTypeRef for MdRef {
    type CType = bssl_sys::EVP_MD;
}

/// Used internally to get a BoringSSL internal MD
pub trait Md {
    /// The output size of the hash operation.
    const OUTPUT_SIZE: usize;

    /// Gets a reference to a message digest algorithm to be used by the HKDF implementation.
    fn get_md() -> &'static MdRef;
}

impl Md for Sha256 {
    const OUTPUT_SIZE: usize = bssl_sys::SHA256_DIGEST_LENGTH as usize;

    fn get_md() -> &'static MdRef {
        // Safety:
        // - this always returns a valid pointer to an EVP_MD
        unsafe { MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _) }
    }
}

impl Sha256 {
    /// Creates a new [Digest] to compute a SHA-256 hash.
    pub fn new_digest() -> Digest<Self, { Self::OUTPUT_SIZE }> {
        // Note: This cannot be in the trait because using associated constants exprs there
        // requires nightly.
        Digest::<Self, { Self::OUTPUT_SIZE }>::new()
    }
}

impl Md for Sha512 {
    const OUTPUT_SIZE: usize = bssl_sys::SHA512_DIGEST_LENGTH as usize;

    fn get_md() -> &'static MdRef {
        // Safety:
        // - this always returns a valid pointer to an EVP_MD
        unsafe { MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _) }
    }
}

impl Sha512 {
    /// Create a new [Digest] to compute a SHA-512 hash.
    pub fn new_digest() -> Digest<Self, { Self::OUTPUT_SIZE }> {
        // Note: This cannot be in the trait because using associated constants exprs there
        // requires nightly.
        Digest::<Self, { Self::OUTPUT_SIZE }>::new()
    }
}

/// A pending digest operation.
pub struct Digest<M: Md, const OUTPUT_SIZE: usize>(bssl_sys::EVP_MD_CTX, PhantomData<M>);

impl<M: Md, const OUTPUT_SIZE: usize> Digest<M, OUTPUT_SIZE> {

    /// Creates a new Digest from the given `Md` type parameter.
    ///
    /// Panics:
    /// - If `Md::OUTPUT_SIZE` is not the same as `OUTPUT_SIZE`.
    fn new() -> Self {
        // Note: runtime assertion needed here since using {M::OUTPUT_SIZE} in return type requires
        // unstable Rust feature.
        assert_eq!(M::OUTPUT_SIZE, OUTPUT_SIZE);
        let mut md_ctx_uninit = core::mem::MaybeUninit::<bssl_sys::EVP_MD_CTX>::uninit();
        // Safety:
        // - `EVP_DigestInit` initializes `md_ctx_uninit`
        // - `MdRef` ensures the validity of `md.as_ptr`
        let result =
            unsafe { bssl_sys::EVP_DigestInit(md_ctx_uninit.as_mut_ptr(), M::get_md().as_ptr()) };
        assert_eq!(result, 1, "bssl_sys::EVP_DigestInit failed");
        // Safety:
        // - md_ctx_uninit initialized with EVP_DigestInit, and the function returned 1 (success)
        let md_ctx = unsafe { md_ctx_uninit.assume_init() };
        Self(md_ctx, PhantomData)
    }

    /// Hashes the provided input into the current digest operation.
    pub fn update(&mut self, data: &[u8]) {
        // Safety:
        // - `data` is a slice from safe Rust.
        let result = unsafe {
            bssl_sys::EVP_DigestUpdate(&mut self.0, data.as_ptr() as *const _, data.len())
        };
        assert_eq!(result, 1, "bssl_sys::EVP_DigestUpdate failed");
    }

    /// Computes the final digest value, consuming the object.
    #[allow(clippy::expect_used)]
    pub fn finalize(mut self) -> [u8; OUTPUT_SIZE] {
        let mut digest_uninit =
            core::mem::MaybeUninit::<[u8; bssl_sys::EVP_MAX_MD_SIZE as usize]>::uninit();
        let mut len_uninit = core::mem::MaybeUninit::<u32>::uninit();
        // Safety:
        // - `digest_uninit` is allocated to `EVP_MAX_MD_SIZE` bytes long, as required by
        //   EVP_DigestFinal_ex
        // - `self.0` is owned by `self`, and is going to be cleaned up on drop.
        let result = unsafe {
            bssl_sys::EVP_DigestFinal_ex(
                &mut self.0,
                digest_uninit.as_mut_ptr() as *mut _,
                len_uninit.as_mut_ptr(),
            )
        };
        assert_eq!(result, 1, "bssl_sys::EVP_DigestFinal_ex failed");
        // Safety:
        // - `len_uninit` is initialized by `EVP_DigestFinal_ex`, and we checked the result above
        let len = unsafe { len_uninit.assume_init() };
        assert_eq!(
            OUTPUT_SIZE, len as usize,
            "bssl_sys::EVP_DigestFinal_ex failed"
        );
        // Safety: Result of DigestFinal_ex was checked above
        let digest = unsafe { digest_uninit.assume_init() };
        digest
            .get(..OUTPUT_SIZE)
            .and_then(|digest| digest.try_into().ok())
            .expect("The length of `digest` was checked above")
    }
}

impl<M: Md, const OUTPUT_SIZE: usize> Drop for Digest<M, OUTPUT_SIZE> {
    fn drop(&mut self) {
        // Safety: `self.0` is owned by `self`, and is invalidated after `drop`.
        unsafe {
            bssl_sys::EVP_MD_CTX_cleanup(&mut self.0);
        }
    }
}

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

    use super::*;

    #[test]
    fn test_sha256_c_type() {
        unsafe {
            assert_eq!(
                MdRef::from_ptr(bssl_sys::EVP_sha256() as *mut _).as_ptr(),
                bssl_sys::EVP_sha256() as *mut _
            )
        }
    }

    #[test]
    fn test_sha512_c_type() {
        unsafe {
            assert_eq!(
                MdRef::from_ptr(bssl_sys::EVP_sha512() as *mut _).as_ptr(),
                bssl_sys::EVP_sha512() as *mut _
            )
        }
    }

    #[test]
    fn test_digest_sha256() {
        let mut digest = Sha256::new_digest();
        let msg: [u8; 4] = decode_hex("74ba2521");
        digest.update(&msg);
        let expected_digest: [u8; 32] =
            decode_hex("b16aa56be3880d18cd41e68384cf1ec8c17680c45a02b1575dc1518923ae8b0e");
        assert_eq!(expected_digest, digest.finalize());
    }

    #[test]
    fn test_digest_sha512() {
        let mut digest = Sha512::new_digest();
        let msg: [u8; 4] = decode_hex("23be86d5");
        digest.update(&msg);
        let expected_digest: [u8; 64] = decode_hex(concat!(
            "76d42c8eadea35a69990c63a762f330614a4699977f058adb988f406fb0be8f2",
            "ea3dce3a2bbd1d827b70b9b299ae6f9e5058ee97b50bd4922d6d37ddc761f8eb"
        ));
        assert_eq!(expected_digest, digest.finalize());
    }

    #[test]
    #[should_panic]
    fn test_digest_wrong_size() {
        // This should not happen since we don't externally expose Digest::new
        Digest::<Sha256, 64>::new();
    }
}
