Commit c706d911 authored by Steven Fackler's avatar Steven Fackler
Browse files

Fix EcdsaSig method flexibility

Closes #1323
parent 5cf2c2d5
Loading
Loading
Loading
Loading
+36 −28
Original line number Diff line number Diff line
//! Low level Elliptic Curve Digital Signature Algorithm (ECDSA) functions.

use ffi;
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
@@ -8,7 +9,7 @@ use std::ptr;
use bn::{BigNum, BigNumRef};
use ec::EcKeyRef;
use error::ErrorStack;
use pkey::{Private, Public};
use pkey::{HasPrivate, HasPublic};
use {cvt_n, cvt_p};

foreign_type_and_impl_send_sync! {
@@ -33,7 +34,10 @@ impl EcdsaSig {
    /// OpenSSL documentation at [`ECDSA_do_sign`]
    ///
    /// [`ECDSA_do_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_do_sign.html
    pub fn sign(data: &[u8], eckey: &EcKeyRef<Private>) -> Result<EcdsaSig, ErrorStack> {
    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(
@@ -60,12 +64,38 @@ impl EcdsaSig {
        }
    }

    from_der! {
        /// Decodes a DER-encoded ECDSA signature.
        ///
        /// This corresponds to [`d2i_ECDSA_SIG`].
        ///
        /// [`d2i_ECDSA_SIG`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_ECDSA_SIG.html
        from_der,
        EcdsaSig,
        ffi::d2i_ECDSA_SIG
    }
}

impl EcdsaSigRef {
    to_der! {
        /// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure.
        ///
        /// This corresponds to [`i2d_ECDSA_SIG`].
        ///
        /// [`i2d_ECDSA_SIG`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_ECDSA_SIG.html
        to_der,
        ffi::i2d_ECDSA_SIG
    }

    /// Verifies if the signature is a valid ECDSA signature using the given public key.
    ///
    /// OpenSSL documentation at [`ECDSA_do_verify`]
    ///
    /// [`ECDSA_do_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_do_verify.html
    pub fn verify(&self, data: &[u8], eckey: &EcKeyRef<Public>) -> Result<bool, ErrorStack> {
    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(
@@ -78,7 +108,7 @@ impl EcdsaSig {
        }
    }

    /// Returns internal component: `r` of a `EcdsaSig`. (See X9.62 or FIPS 186-2)
    /// Returns internal component: `r` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
    ///
    /// OpenSSL documentation at [`ECDSA_SIG_get0`]
    ///
@@ -91,7 +121,7 @@ impl EcdsaSig {
        }
    }

    /// Returns internal components: `s` of a `EcdsaSig`. (See X9.62 or FIPS 186-2)
    /// Returns internal components: `s` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
    ///
    /// OpenSSL documentation at [`ECDSA_SIG_get0`]
    ///
@@ -103,29 +133,6 @@ impl EcdsaSig {
            BigNumRef::from_ptr(s as *mut _)
        }
    }

    from_der! {
        /// Decodes a DER-encoded ECDSA signature.
        ///
        /// This corresponds to [`d2i_ECDSA_SIG`].
        ///
        /// [`d2i_ECDSA_SIG`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_ECDSA_SIG.html
        from_der,
        EcdsaSig,
        ffi::d2i_ECDSA_SIG
    }
}

impl EcdsaSigRef {
    to_der! {
        /// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure.
        ///
        /// This corresponds to [`i2d_ECDSA_SIG`].
        ///
        /// [`i2d_ECDSA_SIG`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_ECDSA_SIG.html
        to_der,
        ffi::i2d_ECDSA_SIG
    }
}

cfg_if! {
@@ -170,6 +177,7 @@ mod test {
    use ec::EcGroup;
    use ec::EcKey;
    use nid::Nid;
    use pkey::{Private, Public};

    fn get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack> {
        let public_key_point = x.public_key();