//! Low level Elliptic Curve Digital Signature Algorithm (ECDSA) functions.

use cfg_if::cfg_if;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
use std::mem;
use std::ptr;

use crate::bn::{BigNum, BigNumRef};
use crate::ec::EcKeyRef;
use crate::error::ErrorStack;
use crate::pkey::{HasPrivate, HasPublic};
use crate::util::ForeignTypeRefExt;
use crate::{cvt_n, cvt_p, LenType};
use openssl_macros::corresponds;

foreign_type_and_impl_send_sync! {
    type CType = ffi::ECDSA_SIG;
    fn drop = ffi::ECDSA_SIG_free;

    /// A low level interface to ECDSA.
    pub struct EcdsaSig;
    /// A reference to an [`EcdsaSig`].
    pub struct EcdsaSigRef;
}

impl EcdsaSig {
    /// Computes a digital signature of the hash value `data` using the private EC key eckey.
    #[corresponds(ECDSA_do_sign)]
    pub fn sign<T>(data: &[u8], eckey: &EcKeyRef<T>) -> Result<EcdsaSig, ErrorStack>
    where
        T: HasPrivate,
    {
        unsafe {
            assert!(data.len() <= c_int::max_value() as usize);
            let sig = cvt_p(ffi::ECDSA_do_sign(
                data.as_ptr(),
                data.len() as LenType,
                eckey.as_ptr(),
            ))?;
            Ok(EcdsaSig::from_ptr(sig))
        }
    }

    /// Returns a new `EcdsaSig` by setting the `r` and `s` values associated with an ECDSA signature.
    #[corresponds(ECDSA_SIG_set0)]
    pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> {
        unsafe {
            let sig = cvt_p(ffi::ECDSA_SIG_new())?;
            ECDSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
            mem::forget((r, s));
            Ok(EcdsaSig::from_ptr(sig))
        }
    }

    from_der! {
        /// Decodes a DER-encoded ECDSA signature.
        #[corresponds(d2i_ECDSA_SIG)]
        from_der,
        EcdsaSig,
        ffi::d2i_ECDSA_SIG
    }
}

impl EcdsaSigRef {
    to_der! {
        /// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure.
        #[corresponds(i2d_ECDSA_SIG)]
        to_der,
        ffi::i2d_ECDSA_SIG
    }

    /// Verifies if the signature is a valid ECDSA signature using the given public key.
    #[corresponds(ECDSA_do_verify)]
    pub fn verify<T>(&self, data: &[u8], eckey: &EcKeyRef<T>) -> Result<bool, ErrorStack>
    where
        T: HasPublic,
    {
        unsafe {
            assert!(data.len() <= c_int::max_value() as usize);
            cvt_n(ffi::ECDSA_do_verify(
                data.as_ptr(),
                data.len() as LenType,
                self.as_ptr(),
                eckey.as_ptr(),
            ))
            .map(|x| x == 1)
        }
    }

    /// Returns internal component: `r` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
    #[corresponds(ECDSA_SIG_get0)]
    pub fn r(&self) -> &BigNumRef {
        unsafe {
            let mut r = ptr::null();
            ECDSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
            BigNumRef::from_const_ptr(r)
        }
    }

    /// Returns internal components: `s` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
    #[corresponds(ECDSA_SIG_get0)]
    pub fn s(&self) -> &BigNumRef {
        unsafe {
            let mut s = ptr::null();
            ECDSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
            BigNumRef::from_const_ptr(s)
        }
    }
}

cfg_if! {
    if #[cfg(any(ossl110, libressl273, boringssl))] {
        use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
    } else {
        #[allow(bad_style)]
        unsafe fn ECDSA_SIG_set0(
            sig: *mut ffi::ECDSA_SIG,
            r: *mut ffi::BIGNUM,
            s: *mut ffi::BIGNUM,
        ) -> c_int {
            if r.is_null() || s.is_null() {
                return 0;
            }
            ffi::BN_clear_free((*sig).r);
            ffi::BN_clear_free((*sig).s);
            (*sig).r = r;
            (*sig).s = s;
            1
        }

        #[allow(bad_style)]
        unsafe fn ECDSA_SIG_get0(
            sig: *const ffi::ECDSA_SIG,
            pr: *mut *const ffi::BIGNUM,
            ps: *mut *const ffi::BIGNUM)
        {
            if !pr.is_null() {
                (*pr) = (*sig).r;
            }
            if !ps.is_null() {
                (*ps) = (*sig).s;
            }
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::ec::EcGroup;
    use crate::ec::EcKey;
    use crate::nid::Nid;
    use crate::pkey::{Private, Public};

    fn get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack> {
        EcKey::from_public_key(group, x.public_key())
    }

    #[test]
    #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
    fn sign_and_verify() {
        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let private_key = EcKey::generate(&group).unwrap();
        let public_key = get_public_key(&group, &private_key).unwrap();

        let private_key2 = EcKey::generate(&group).unwrap();
        let public_key2 = get_public_key(&group, &private_key2).unwrap();

        let data = String::from("hello");
        let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();

        // Signature can be verified using the correct data & correct public key
        let verification = res.verify(data.as_bytes(), &public_key).unwrap();
        assert!(verification);

        // Signature will not be verified using the incorrect data but the correct public key
        let verification2 = res
            .verify(String::from("hello2").as_bytes(), &public_key)
            .unwrap();
        assert!(!verification2);

        // Signature will not be verified using the correct data but the incorrect public key
        let verification3 = res.verify(data.as_bytes(), &public_key2).unwrap();
        assert!(!verification3);
    }

    #[test]
    #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
    fn check_private_components() {
        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let private_key = EcKey::generate(&group).unwrap();
        let public_key = get_public_key(&group, &private_key).unwrap();
        let data = String::from("hello");
        let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();

        let verification = res.verify(data.as_bytes(), &public_key).unwrap();
        assert!(verification);

        let r = res.r().to_owned().unwrap();
        let s = res.s().to_owned().unwrap();

        let res2 = EcdsaSig::from_private_components(r, s).unwrap();
        let verification2 = res2.verify(data.as_bytes(), &public_key).unwrap();
        assert!(verification2);
    }

    #[test]
    #[cfg_attr(osslconf = "OPENSSL_NO_EC2M", ignore)]
    fn serialize_deserialize() {
        let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
        let private_key = EcKey::generate(&group).unwrap();
        let public_key = get_public_key(&group, &private_key).unwrap();

        let data = String::from("hello");
        let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();

        let der = res.to_der().unwrap();
        let sig = EcdsaSig::from_der(&der).unwrap();

        let verification = sig.verify(data.as_bytes(), &public_key).unwrap();
        assert!(verification);
    }
}
