192f3ab15Sopenharmony_ci//! Digital Signatures
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! DSA ensures a message originated from a known sender, and was not modified.
492f3ab15Sopenharmony_ci//! DSA uses asymmetrical keys and an algorithm to output a signature of the message
592f3ab15Sopenharmony_ci//! using the private key that can be validated with the public key but not be generated
692f3ab15Sopenharmony_ci//! without the private key.
792f3ab15Sopenharmony_ci
892f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
992f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef};
1092f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
1192f3ab15Sopenharmony_ciuse libc::c_int;
1292f3ab15Sopenharmony_ciuse std::fmt;
1392f3ab15Sopenharmony_ciuse std::mem;
1492f3ab15Sopenharmony_ciuse std::ptr;
1592f3ab15Sopenharmony_ci
1692f3ab15Sopenharmony_ciuse crate::bn::{BigNum, BigNumRef};
1792f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
1892f3ab15Sopenharmony_ciuse crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
1992f3ab15Sopenharmony_ciuse crate::util::ForeignTypeRefExt;
2092f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p};
2192f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
2292f3ab15Sopenharmony_ci
2392f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! {
2492f3ab15Sopenharmony_ci    type CType = ffi::DSA;
2592f3ab15Sopenharmony_ci    fn drop = ffi::DSA_free;
2692f3ab15Sopenharmony_ci
2792f3ab15Sopenharmony_ci    /// Object representing DSA keys.
2892f3ab15Sopenharmony_ci    ///
2992f3ab15Sopenharmony_ci    /// A DSA object contains the parameters p, q, and g.  There is a private
3092f3ab15Sopenharmony_ci    /// and public key.  The values p, g, and q are:
3192f3ab15Sopenharmony_ci    ///
3292f3ab15Sopenharmony_ci    /// * `p`: DSA prime parameter
3392f3ab15Sopenharmony_ci    /// * `q`: DSA sub-prime parameter
3492f3ab15Sopenharmony_ci    /// * `g`: DSA base parameter
3592f3ab15Sopenharmony_ci    ///
3692f3ab15Sopenharmony_ci    /// These values are used to calculate a pair of asymmetrical keys used for
3792f3ab15Sopenharmony_ci    /// signing.
3892f3ab15Sopenharmony_ci    ///
3992f3ab15Sopenharmony_ci    /// OpenSSL documentation at [`DSA_new`]
4092f3ab15Sopenharmony_ci    ///
4192f3ab15Sopenharmony_ci    /// [`DSA_new`]: https://www.openssl.org/docs/manmaster/crypto/DSA_new.html
4292f3ab15Sopenharmony_ci    ///
4392f3ab15Sopenharmony_ci    /// # Examples
4492f3ab15Sopenharmony_ci    ///
4592f3ab15Sopenharmony_ci    /// ```
4692f3ab15Sopenharmony_ci    /// use openssl::dsa::Dsa;
4792f3ab15Sopenharmony_ci    /// use openssl::error::ErrorStack;
4892f3ab15Sopenharmony_ci    /// use openssl::pkey::Private;
4992f3ab15Sopenharmony_ci    ///
5092f3ab15Sopenharmony_ci    /// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
5192f3ab15Sopenharmony_ci    ///     let sign = Dsa::generate(2048)?;
5292f3ab15Sopenharmony_ci    ///     Ok(sign)
5392f3ab15Sopenharmony_ci    /// }
5492f3ab15Sopenharmony_ci    /// # fn main() {
5592f3ab15Sopenharmony_ci    /// #    create_dsa();
5692f3ab15Sopenharmony_ci    /// # }
5792f3ab15Sopenharmony_ci    /// ```
5892f3ab15Sopenharmony_ci    pub struct Dsa<T>;
5992f3ab15Sopenharmony_ci    /// Reference to [`Dsa`].
6092f3ab15Sopenharmony_ci    ///
6192f3ab15Sopenharmony_ci    /// [`Dsa`]: struct.Dsa.html
6292f3ab15Sopenharmony_ci    pub struct DsaRef<T>;
6392f3ab15Sopenharmony_ci}
6492f3ab15Sopenharmony_ci
6592f3ab15Sopenharmony_ciimpl<T> Clone for Dsa<T> {
6692f3ab15Sopenharmony_ci    fn clone(&self) -> Dsa<T> {
6792f3ab15Sopenharmony_ci        (**self).to_owned()
6892f3ab15Sopenharmony_ci    }
6992f3ab15Sopenharmony_ci}
7092f3ab15Sopenharmony_ci
7192f3ab15Sopenharmony_ciimpl<T> ToOwned for DsaRef<T> {
7292f3ab15Sopenharmony_ci    type Owned = Dsa<T>;
7392f3ab15Sopenharmony_ci
7492f3ab15Sopenharmony_ci    fn to_owned(&self) -> Dsa<T> {
7592f3ab15Sopenharmony_ci        unsafe {
7692f3ab15Sopenharmony_ci            ffi::DSA_up_ref(self.as_ptr());
7792f3ab15Sopenharmony_ci            Dsa::from_ptr(self.as_ptr())
7892f3ab15Sopenharmony_ci        }
7992f3ab15Sopenharmony_ci    }
8092f3ab15Sopenharmony_ci}
8192f3ab15Sopenharmony_ci
8292f3ab15Sopenharmony_ciimpl<T> DsaRef<T>
8392f3ab15Sopenharmony_ciwhere
8492f3ab15Sopenharmony_ci    T: HasPublic,
8592f3ab15Sopenharmony_ci{
8692f3ab15Sopenharmony_ci    to_pem! {
8792f3ab15Sopenharmony_ci        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
8892f3ab15Sopenharmony_ci        ///
8992f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
9092f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_DSA_PUBKEY)]
9192f3ab15Sopenharmony_ci        public_key_to_pem,
9292f3ab15Sopenharmony_ci        ffi::PEM_write_bio_DSA_PUBKEY
9392f3ab15Sopenharmony_ci    }
9492f3ab15Sopenharmony_ci
9592f3ab15Sopenharmony_ci    to_der! {
9692f3ab15Sopenharmony_ci        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
9792f3ab15Sopenharmony_ci        #[corresponds(i2d_DSA_PUBKEY)]
9892f3ab15Sopenharmony_ci        public_key_to_der,
9992f3ab15Sopenharmony_ci        ffi::i2d_DSA_PUBKEY
10092f3ab15Sopenharmony_ci    }
10192f3ab15Sopenharmony_ci
10292f3ab15Sopenharmony_ci    /// Returns a reference to the public key component of `self`.
10392f3ab15Sopenharmony_ci    #[corresponds(DSA_get0_key)]
10492f3ab15Sopenharmony_ci    pub fn pub_key(&self) -> &BigNumRef {
10592f3ab15Sopenharmony_ci        unsafe {
10692f3ab15Sopenharmony_ci            let mut pub_key = ptr::null();
10792f3ab15Sopenharmony_ci            DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
10892f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(pub_key)
10992f3ab15Sopenharmony_ci        }
11092f3ab15Sopenharmony_ci    }
11192f3ab15Sopenharmony_ci}
11292f3ab15Sopenharmony_ci
11392f3ab15Sopenharmony_ciimpl<T> DsaRef<T>
11492f3ab15Sopenharmony_ciwhere
11592f3ab15Sopenharmony_ci    T: HasPrivate,
11692f3ab15Sopenharmony_ci{
11792f3ab15Sopenharmony_ci    private_key_to_pem! {
11892f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
11992f3ab15Sopenharmony_ci        ///
12092f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
12192f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_DSAPrivateKey)]
12292f3ab15Sopenharmony_ci        private_key_to_pem,
12392f3ab15Sopenharmony_ci        /// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
12492f3ab15Sopenharmony_ci        ///
12592f3ab15Sopenharmony_ci        /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
12692f3ab15Sopenharmony_ci        #[corresponds(PEM_write_bio_DSAPrivateKey)]
12792f3ab15Sopenharmony_ci        private_key_to_pem_passphrase,
12892f3ab15Sopenharmony_ci        ffi::PEM_write_bio_DSAPrivateKey
12992f3ab15Sopenharmony_ci    }
13092f3ab15Sopenharmony_ci
13192f3ab15Sopenharmony_ci    to_der! {
13292f3ab15Sopenharmony_ci        /// Serializes the private_key to a DER-encoded `DSAPrivateKey` structure.
13392f3ab15Sopenharmony_ci        #[corresponds(i2d_DSAPrivateKey)]
13492f3ab15Sopenharmony_ci        private_key_to_der,
13592f3ab15Sopenharmony_ci        ffi::i2d_DSAPrivateKey
13692f3ab15Sopenharmony_ci    }
13792f3ab15Sopenharmony_ci
13892f3ab15Sopenharmony_ci    /// Returns a reference to the private key component of `self`.
13992f3ab15Sopenharmony_ci    #[corresponds(DSA_get0_key)]
14092f3ab15Sopenharmony_ci    pub fn priv_key(&self) -> &BigNumRef {
14192f3ab15Sopenharmony_ci        unsafe {
14292f3ab15Sopenharmony_ci            let mut priv_key = ptr::null();
14392f3ab15Sopenharmony_ci            DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
14492f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(priv_key)
14592f3ab15Sopenharmony_ci        }
14692f3ab15Sopenharmony_ci    }
14792f3ab15Sopenharmony_ci}
14892f3ab15Sopenharmony_ci
14992f3ab15Sopenharmony_ciimpl<T> DsaRef<T>
15092f3ab15Sopenharmony_ciwhere
15192f3ab15Sopenharmony_ci    T: HasParams,
15292f3ab15Sopenharmony_ci{
15392f3ab15Sopenharmony_ci    /// Returns the maximum size of the signature output by `self` in bytes.
15492f3ab15Sopenharmony_ci    #[corresponds(DSA_size)]
15592f3ab15Sopenharmony_ci    pub fn size(&self) -> u32 {
15692f3ab15Sopenharmony_ci        unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
15792f3ab15Sopenharmony_ci    }
15892f3ab15Sopenharmony_ci
15992f3ab15Sopenharmony_ci    /// Returns the DSA prime parameter of `self`.
16092f3ab15Sopenharmony_ci    #[corresponds(DSA_get0_pqg)]
16192f3ab15Sopenharmony_ci    pub fn p(&self) -> &BigNumRef {
16292f3ab15Sopenharmony_ci        unsafe {
16392f3ab15Sopenharmony_ci            let mut p = ptr::null();
16492f3ab15Sopenharmony_ci            DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
16592f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(p)
16692f3ab15Sopenharmony_ci        }
16792f3ab15Sopenharmony_ci    }
16892f3ab15Sopenharmony_ci
16992f3ab15Sopenharmony_ci    /// Returns the DSA sub-prime parameter of `self`.
17092f3ab15Sopenharmony_ci    #[corresponds(DSA_get0_pqg)]
17192f3ab15Sopenharmony_ci    pub fn q(&self) -> &BigNumRef {
17292f3ab15Sopenharmony_ci        unsafe {
17392f3ab15Sopenharmony_ci            let mut q = ptr::null();
17492f3ab15Sopenharmony_ci            DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
17592f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(q)
17692f3ab15Sopenharmony_ci        }
17792f3ab15Sopenharmony_ci    }
17892f3ab15Sopenharmony_ci
17992f3ab15Sopenharmony_ci    /// Returns the DSA base parameter of `self`.
18092f3ab15Sopenharmony_ci    #[corresponds(DSA_get0_pqg)]
18192f3ab15Sopenharmony_ci    pub fn g(&self) -> &BigNumRef {
18292f3ab15Sopenharmony_ci        unsafe {
18392f3ab15Sopenharmony_ci            let mut g = ptr::null();
18492f3ab15Sopenharmony_ci            DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
18592f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(g)
18692f3ab15Sopenharmony_ci        }
18792f3ab15Sopenharmony_ci    }
18892f3ab15Sopenharmony_ci}
18992f3ab15Sopenharmony_ci#[cfg(boringssl)]
19092f3ab15Sopenharmony_citype BitType = libc::c_uint;
19192f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
19292f3ab15Sopenharmony_citype BitType = c_int;
19392f3ab15Sopenharmony_ci
19492f3ab15Sopenharmony_ciimpl Dsa<Params> {
19592f3ab15Sopenharmony_ci    /// Creates a DSA params based upon the given parameters.
19692f3ab15Sopenharmony_ci    #[corresponds(DSA_set0_pqg)]
19792f3ab15Sopenharmony_ci    pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result<Dsa<Params>, ErrorStack> {
19892f3ab15Sopenharmony_ci        unsafe {
19992f3ab15Sopenharmony_ci            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
20092f3ab15Sopenharmony_ci            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
20192f3ab15Sopenharmony_ci            mem::forget((p, q, g));
20292f3ab15Sopenharmony_ci            Ok(dsa)
20392f3ab15Sopenharmony_ci        }
20492f3ab15Sopenharmony_ci    }
20592f3ab15Sopenharmony_ci
20692f3ab15Sopenharmony_ci    /// Generates DSA params based on the given number of bits.
20792f3ab15Sopenharmony_ci    #[corresponds(DSA_generate_parameters_ex)]
20892f3ab15Sopenharmony_ci    pub fn generate_params(bits: u32) -> Result<Dsa<Params>, ErrorStack> {
20992f3ab15Sopenharmony_ci        ffi::init();
21092f3ab15Sopenharmony_ci        unsafe {
21192f3ab15Sopenharmony_ci            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
21292f3ab15Sopenharmony_ci            cvt(ffi::DSA_generate_parameters_ex(
21392f3ab15Sopenharmony_ci                dsa.0,
21492f3ab15Sopenharmony_ci                bits as BitType,
21592f3ab15Sopenharmony_ci                ptr::null(),
21692f3ab15Sopenharmony_ci                0,
21792f3ab15Sopenharmony_ci                ptr::null_mut(),
21892f3ab15Sopenharmony_ci                ptr::null_mut(),
21992f3ab15Sopenharmony_ci                ptr::null_mut(),
22092f3ab15Sopenharmony_ci            ))?;
22192f3ab15Sopenharmony_ci            Ok(dsa)
22292f3ab15Sopenharmony_ci        }
22392f3ab15Sopenharmony_ci    }
22492f3ab15Sopenharmony_ci
22592f3ab15Sopenharmony_ci    /// Generates a private key based on the DSA params.
22692f3ab15Sopenharmony_ci    #[corresponds(DSA_generate_key)]
22792f3ab15Sopenharmony_ci    pub fn generate_key(self) -> Result<Dsa<Private>, ErrorStack> {
22892f3ab15Sopenharmony_ci        unsafe {
22992f3ab15Sopenharmony_ci            let dsa_ptr = self.0;
23092f3ab15Sopenharmony_ci            cvt(ffi::DSA_generate_key(dsa_ptr))?;
23192f3ab15Sopenharmony_ci            mem::forget(self);
23292f3ab15Sopenharmony_ci            Ok(Dsa::from_ptr(dsa_ptr))
23392f3ab15Sopenharmony_ci        }
23492f3ab15Sopenharmony_ci    }
23592f3ab15Sopenharmony_ci}
23692f3ab15Sopenharmony_ci
23792f3ab15Sopenharmony_ciimpl Dsa<Private> {
23892f3ab15Sopenharmony_ci    /// Generate a DSA key pair.
23992f3ab15Sopenharmony_ci    ///
24092f3ab15Sopenharmony_ci    /// The `bits` parameter corresponds to the length of the prime `p`.
24192f3ab15Sopenharmony_ci    pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
24292f3ab15Sopenharmony_ci        let params = Dsa::generate_params(bits)?;
24392f3ab15Sopenharmony_ci        params.generate_key()
24492f3ab15Sopenharmony_ci    }
24592f3ab15Sopenharmony_ci
24692f3ab15Sopenharmony_ci    /// Create a DSA key pair with the given parameters
24792f3ab15Sopenharmony_ci    ///
24892f3ab15Sopenharmony_ci    /// `p`, `q` and `g` are the common parameters.
24992f3ab15Sopenharmony_ci    /// `priv_key` is the private component of the key pair.
25092f3ab15Sopenharmony_ci    /// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
25192f3ab15Sopenharmony_ci    pub fn from_private_components(
25292f3ab15Sopenharmony_ci        p: BigNum,
25392f3ab15Sopenharmony_ci        q: BigNum,
25492f3ab15Sopenharmony_ci        g: BigNum,
25592f3ab15Sopenharmony_ci        priv_key: BigNum,
25692f3ab15Sopenharmony_ci        pub_key: BigNum,
25792f3ab15Sopenharmony_ci    ) -> Result<Dsa<Private>, ErrorStack> {
25892f3ab15Sopenharmony_ci        ffi::init();
25992f3ab15Sopenharmony_ci        unsafe {
26092f3ab15Sopenharmony_ci            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
26192f3ab15Sopenharmony_ci            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
26292f3ab15Sopenharmony_ci            mem::forget((p, q, g));
26392f3ab15Sopenharmony_ci            cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
26492f3ab15Sopenharmony_ci            mem::forget((pub_key, priv_key));
26592f3ab15Sopenharmony_ci            Ok(dsa)
26692f3ab15Sopenharmony_ci        }
26792f3ab15Sopenharmony_ci    }
26892f3ab15Sopenharmony_ci}
26992f3ab15Sopenharmony_ci
27092f3ab15Sopenharmony_ciimpl Dsa<Public> {
27192f3ab15Sopenharmony_ci    from_pem! {
27292f3ab15Sopenharmony_ci        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
27392f3ab15Sopenharmony_ci        ///
27492f3ab15Sopenharmony_ci        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
27592f3ab15Sopenharmony_ci        #[corresponds(PEM_read_bio_DSA_PUBKEY)]
27692f3ab15Sopenharmony_ci        public_key_from_pem,
27792f3ab15Sopenharmony_ci        Dsa<Public>,
27892f3ab15Sopenharmony_ci        ffi::PEM_read_bio_DSA_PUBKEY
27992f3ab15Sopenharmony_ci    }
28092f3ab15Sopenharmony_ci
28192f3ab15Sopenharmony_ci    from_der! {
28292f3ab15Sopenharmony_ci        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
28392f3ab15Sopenharmony_ci        #[corresponds(d2i_DSA_PUBKEY)]
28492f3ab15Sopenharmony_ci        public_key_from_der,
28592f3ab15Sopenharmony_ci        Dsa<Public>,
28692f3ab15Sopenharmony_ci        ffi::d2i_DSA_PUBKEY
28792f3ab15Sopenharmony_ci    }
28892f3ab15Sopenharmony_ci
28992f3ab15Sopenharmony_ci    /// Create a new DSA key with only public components.
29092f3ab15Sopenharmony_ci    ///
29192f3ab15Sopenharmony_ci    /// `p`, `q` and `g` are the common parameters.
29292f3ab15Sopenharmony_ci    /// `pub_key` is the public component of the key.
29392f3ab15Sopenharmony_ci    pub fn from_public_components(
29492f3ab15Sopenharmony_ci        p: BigNum,
29592f3ab15Sopenharmony_ci        q: BigNum,
29692f3ab15Sopenharmony_ci        g: BigNum,
29792f3ab15Sopenharmony_ci        pub_key: BigNum,
29892f3ab15Sopenharmony_ci    ) -> Result<Dsa<Public>, ErrorStack> {
29992f3ab15Sopenharmony_ci        ffi::init();
30092f3ab15Sopenharmony_ci        unsafe {
30192f3ab15Sopenharmony_ci            let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
30292f3ab15Sopenharmony_ci            cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
30392f3ab15Sopenharmony_ci            mem::forget((p, q, g));
30492f3ab15Sopenharmony_ci            cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?;
30592f3ab15Sopenharmony_ci            mem::forget(pub_key);
30692f3ab15Sopenharmony_ci            Ok(dsa)
30792f3ab15Sopenharmony_ci        }
30892f3ab15Sopenharmony_ci    }
30992f3ab15Sopenharmony_ci}
31092f3ab15Sopenharmony_ci
31192f3ab15Sopenharmony_ciimpl<T> fmt::Debug for Dsa<T> {
31292f3ab15Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31392f3ab15Sopenharmony_ci        write!(f, "DSA")
31492f3ab15Sopenharmony_ci    }
31592f3ab15Sopenharmony_ci}
31692f3ab15Sopenharmony_ci
31792f3ab15Sopenharmony_cicfg_if! {
31892f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, libressl273, boringssl))] {
31992f3ab15Sopenharmony_ci        use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
32092f3ab15Sopenharmony_ci    } else {
32192f3ab15Sopenharmony_ci        #[allow(bad_style)]
32292f3ab15Sopenharmony_ci        unsafe fn DSA_get0_pqg(
32392f3ab15Sopenharmony_ci            d: *mut ffi::DSA,
32492f3ab15Sopenharmony_ci            p: *mut *const ffi::BIGNUM,
32592f3ab15Sopenharmony_ci            q: *mut *const ffi::BIGNUM,
32692f3ab15Sopenharmony_ci            g: *mut *const ffi::BIGNUM)
32792f3ab15Sopenharmony_ci        {
32892f3ab15Sopenharmony_ci            if !p.is_null() {
32992f3ab15Sopenharmony_ci                *p = (*d).p;
33092f3ab15Sopenharmony_ci            }
33192f3ab15Sopenharmony_ci            if !q.is_null() {
33292f3ab15Sopenharmony_ci                *q = (*d).q;
33392f3ab15Sopenharmony_ci            }
33492f3ab15Sopenharmony_ci            if !g.is_null() {
33592f3ab15Sopenharmony_ci                *g = (*d).g;
33692f3ab15Sopenharmony_ci            }
33792f3ab15Sopenharmony_ci        }
33892f3ab15Sopenharmony_ci
33992f3ab15Sopenharmony_ci        #[allow(bad_style)]
34092f3ab15Sopenharmony_ci        unsafe fn DSA_get0_key(
34192f3ab15Sopenharmony_ci            d: *mut ffi::DSA,
34292f3ab15Sopenharmony_ci            pub_key: *mut *const ffi::BIGNUM,
34392f3ab15Sopenharmony_ci            priv_key: *mut *const ffi::BIGNUM)
34492f3ab15Sopenharmony_ci        {
34592f3ab15Sopenharmony_ci            if !pub_key.is_null() {
34692f3ab15Sopenharmony_ci                *pub_key = (*d).pub_key;
34792f3ab15Sopenharmony_ci            }
34892f3ab15Sopenharmony_ci            if !priv_key.is_null() {
34992f3ab15Sopenharmony_ci                *priv_key = (*d).priv_key;
35092f3ab15Sopenharmony_ci            }
35192f3ab15Sopenharmony_ci        }
35292f3ab15Sopenharmony_ci
35392f3ab15Sopenharmony_ci        #[allow(bad_style)]
35492f3ab15Sopenharmony_ci        unsafe fn DSA_set0_key(
35592f3ab15Sopenharmony_ci            d: *mut ffi::DSA,
35692f3ab15Sopenharmony_ci            pub_key: *mut ffi::BIGNUM,
35792f3ab15Sopenharmony_ci            priv_key: *mut ffi::BIGNUM) -> c_int
35892f3ab15Sopenharmony_ci        {
35992f3ab15Sopenharmony_ci            (*d).pub_key = pub_key;
36092f3ab15Sopenharmony_ci            (*d).priv_key = priv_key;
36192f3ab15Sopenharmony_ci            1
36292f3ab15Sopenharmony_ci        }
36392f3ab15Sopenharmony_ci
36492f3ab15Sopenharmony_ci        #[allow(bad_style)]
36592f3ab15Sopenharmony_ci        unsafe fn DSA_set0_pqg(
36692f3ab15Sopenharmony_ci            d: *mut ffi::DSA,
36792f3ab15Sopenharmony_ci            p: *mut ffi::BIGNUM,
36892f3ab15Sopenharmony_ci            q: *mut ffi::BIGNUM,
36992f3ab15Sopenharmony_ci            g: *mut ffi::BIGNUM) -> c_int
37092f3ab15Sopenharmony_ci        {
37192f3ab15Sopenharmony_ci            (*d).p = p;
37292f3ab15Sopenharmony_ci            (*d).q = q;
37392f3ab15Sopenharmony_ci            (*d).g = g;
37492f3ab15Sopenharmony_ci            1
37592f3ab15Sopenharmony_ci        }
37692f3ab15Sopenharmony_ci    }
37792f3ab15Sopenharmony_ci}
37892f3ab15Sopenharmony_ci
37992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! {
38092f3ab15Sopenharmony_ci    type CType = ffi::DSA_SIG;
38192f3ab15Sopenharmony_ci    fn drop = ffi::DSA_SIG_free;
38292f3ab15Sopenharmony_ci
38392f3ab15Sopenharmony_ci    /// Object representing DSA signature.
38492f3ab15Sopenharmony_ci    ///
38592f3ab15Sopenharmony_ci    /// DSA signatures consist of two components: `r` and `s`.
38692f3ab15Sopenharmony_ci    ///
38792f3ab15Sopenharmony_ci    /// # Examples
38892f3ab15Sopenharmony_ci    ///
38992f3ab15Sopenharmony_ci    /// ```
39092f3ab15Sopenharmony_ci    /// use std::convert::TryInto;
39192f3ab15Sopenharmony_ci    ///
39292f3ab15Sopenharmony_ci    /// use openssl::bn::BigNum;
39392f3ab15Sopenharmony_ci    /// use openssl::dsa::{Dsa, DsaSig};
39492f3ab15Sopenharmony_ci    /// use openssl::hash::MessageDigest;
39592f3ab15Sopenharmony_ci    /// use openssl::pkey::PKey;
39692f3ab15Sopenharmony_ci    /// use openssl::sign::{Signer, Verifier};
39792f3ab15Sopenharmony_ci    ///
39892f3ab15Sopenharmony_ci    /// const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
39992f3ab15Sopenharmony_ci    /// let dsa_ref = Dsa::generate(1024).unwrap();
40092f3ab15Sopenharmony_ci    ///
40192f3ab15Sopenharmony_ci    /// let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
40292f3ab15Sopenharmony_ci    /// let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
40392f3ab15Sopenharmony_ci    ///
40492f3ab15Sopenharmony_ci    /// let mut signer = if let Ok(signer) = Signer::new(MessageDigest::sha256(), &priv_key) {
40592f3ab15Sopenharmony_ci    ///     signer
40692f3ab15Sopenharmony_ci    /// } else {
40792f3ab15Sopenharmony_ci    ///     // DSA signing is not supported (eg. BoringSSL)
40892f3ab15Sopenharmony_ci    ///     return;
40992f3ab15Sopenharmony_ci    /// };
41092f3ab15Sopenharmony_ci    ///
41192f3ab15Sopenharmony_ci    /// signer.update(TEST_DATA).unwrap();
41292f3ab15Sopenharmony_ci    ///
41392f3ab15Sopenharmony_ci    /// let signature = signer.sign_to_vec().unwrap();
41492f3ab15Sopenharmony_ci    /// // Parse DER-encoded DSA signature
41592f3ab15Sopenharmony_ci    /// let signature = DsaSig::from_der(&signature).unwrap();
41692f3ab15Sopenharmony_ci    ///
41792f3ab15Sopenharmony_ci    /// // Extract components `r` and `s`
41892f3ab15Sopenharmony_ci    /// let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
41992f3ab15Sopenharmony_ci    /// let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
42092f3ab15Sopenharmony_ci    ///
42192f3ab15Sopenharmony_ci    /// // Construct new DSA signature from components
42292f3ab15Sopenharmony_ci    /// let signature = DsaSig::from_private_components(r, s).unwrap();
42392f3ab15Sopenharmony_ci    ///
42492f3ab15Sopenharmony_ci    /// // Serialize DSA signature to DER
42592f3ab15Sopenharmony_ci    /// let signature = signature.to_der().unwrap();
42692f3ab15Sopenharmony_ci    ///
42792f3ab15Sopenharmony_ci    /// let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
42892f3ab15Sopenharmony_ci    /// verifier.update(TEST_DATA).unwrap();
42992f3ab15Sopenharmony_ci    /// assert!(verifier.verify(&signature[..]).unwrap());
43092f3ab15Sopenharmony_ci    /// ```
43192f3ab15Sopenharmony_ci    pub struct DsaSig;
43292f3ab15Sopenharmony_ci
43392f3ab15Sopenharmony_ci    /// Reference to a [`DsaSig`].
43492f3ab15Sopenharmony_ci    pub struct DsaSigRef;
43592f3ab15Sopenharmony_ci}
43692f3ab15Sopenharmony_ci
43792f3ab15Sopenharmony_ciimpl DsaSig {
43892f3ab15Sopenharmony_ci    /// Returns a new `DsaSig` by setting the `r` and `s` values associated with an DSA signature.
43992f3ab15Sopenharmony_ci    #[corresponds(DSA_SIG_set0)]
44092f3ab15Sopenharmony_ci    pub fn from_private_components(r: BigNum, s: BigNum) -> Result<Self, ErrorStack> {
44192f3ab15Sopenharmony_ci        unsafe {
44292f3ab15Sopenharmony_ci            let sig = cvt_p(ffi::DSA_SIG_new())?;
44392f3ab15Sopenharmony_ci            DSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
44492f3ab15Sopenharmony_ci            mem::forget((r, s));
44592f3ab15Sopenharmony_ci            Ok(DsaSig::from_ptr(sig))
44692f3ab15Sopenharmony_ci        }
44792f3ab15Sopenharmony_ci    }
44892f3ab15Sopenharmony_ci
44992f3ab15Sopenharmony_ci    from_der! {
45092f3ab15Sopenharmony_ci        /// Decodes a DER-encoded DSA signature.
45192f3ab15Sopenharmony_ci        #[corresponds(d2i_DSA_SIG)]
45292f3ab15Sopenharmony_ci        from_der,
45392f3ab15Sopenharmony_ci        DsaSig,
45492f3ab15Sopenharmony_ci        ffi::d2i_DSA_SIG
45592f3ab15Sopenharmony_ci    }
45692f3ab15Sopenharmony_ci}
45792f3ab15Sopenharmony_ci
45892f3ab15Sopenharmony_ciimpl fmt::Debug for DsaSig {
45992f3ab15Sopenharmony_ci    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46092f3ab15Sopenharmony_ci        f.debug_struct("DsaSig")
46192f3ab15Sopenharmony_ci            .field("r", self.r())
46292f3ab15Sopenharmony_ci            .field("s", self.s())
46392f3ab15Sopenharmony_ci            .finish()
46492f3ab15Sopenharmony_ci    }
46592f3ab15Sopenharmony_ci}
46692f3ab15Sopenharmony_ci
46792f3ab15Sopenharmony_ciimpl DsaSigRef {
46892f3ab15Sopenharmony_ci    to_der! {
46992f3ab15Sopenharmony_ci        /// Serializes the DSA signature into a DER-encoded `DSASignature` structure.
47092f3ab15Sopenharmony_ci        #[corresponds(i2d_DSA_SIG)]
47192f3ab15Sopenharmony_ci        to_der,
47292f3ab15Sopenharmony_ci        ffi::i2d_DSA_SIG
47392f3ab15Sopenharmony_ci    }
47492f3ab15Sopenharmony_ci
47592f3ab15Sopenharmony_ci    /// Returns internal component `r` of an `DsaSig`.
47692f3ab15Sopenharmony_ci    #[corresponds(DSA_SIG_get0)]
47792f3ab15Sopenharmony_ci    pub fn r(&self) -> &BigNumRef {
47892f3ab15Sopenharmony_ci        unsafe {
47992f3ab15Sopenharmony_ci            let mut r = ptr::null();
48092f3ab15Sopenharmony_ci            DSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
48192f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(r)
48292f3ab15Sopenharmony_ci        }
48392f3ab15Sopenharmony_ci    }
48492f3ab15Sopenharmony_ci
48592f3ab15Sopenharmony_ci    /// Returns internal component `s` of an `DsaSig`.
48692f3ab15Sopenharmony_ci    #[corresponds(DSA_SIG_get0)]
48792f3ab15Sopenharmony_ci    pub fn s(&self) -> &BigNumRef {
48892f3ab15Sopenharmony_ci        unsafe {
48992f3ab15Sopenharmony_ci            let mut s = ptr::null();
49092f3ab15Sopenharmony_ci            DSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
49192f3ab15Sopenharmony_ci            BigNumRef::from_const_ptr(s)
49292f3ab15Sopenharmony_ci        }
49392f3ab15Sopenharmony_ci    }
49492f3ab15Sopenharmony_ci}
49592f3ab15Sopenharmony_ci
49692f3ab15Sopenharmony_cicfg_if! {
49792f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, libressl273, boringssl))] {
49892f3ab15Sopenharmony_ci        use ffi::{DSA_SIG_set0, DSA_SIG_get0};
49992f3ab15Sopenharmony_ci    } else {
50092f3ab15Sopenharmony_ci        #[allow(bad_style)]
50192f3ab15Sopenharmony_ci        unsafe fn DSA_SIG_set0(
50292f3ab15Sopenharmony_ci            sig: *mut ffi::DSA_SIG,
50392f3ab15Sopenharmony_ci            r: *mut ffi::BIGNUM,
50492f3ab15Sopenharmony_ci            s: *mut ffi::BIGNUM,
50592f3ab15Sopenharmony_ci        ) -> c_int {
50692f3ab15Sopenharmony_ci            if r.is_null() || s.is_null() {
50792f3ab15Sopenharmony_ci                return 0;
50892f3ab15Sopenharmony_ci            }
50992f3ab15Sopenharmony_ci            ffi::BN_clear_free((*sig).r);
51092f3ab15Sopenharmony_ci            ffi::BN_clear_free((*sig).s);
51192f3ab15Sopenharmony_ci            (*sig).r = r;
51292f3ab15Sopenharmony_ci            (*sig).s = s;
51392f3ab15Sopenharmony_ci            1
51492f3ab15Sopenharmony_ci        }
51592f3ab15Sopenharmony_ci
51692f3ab15Sopenharmony_ci        #[allow(bad_style)]
51792f3ab15Sopenharmony_ci        unsafe fn DSA_SIG_get0(
51892f3ab15Sopenharmony_ci            sig: *const ffi::DSA_SIG,
51992f3ab15Sopenharmony_ci            pr: *mut *const ffi::BIGNUM,
52092f3ab15Sopenharmony_ci            ps: *mut *const ffi::BIGNUM)
52192f3ab15Sopenharmony_ci        {
52292f3ab15Sopenharmony_ci            if !pr.is_null() {
52392f3ab15Sopenharmony_ci                (*pr) = (*sig).r;
52492f3ab15Sopenharmony_ci            }
52592f3ab15Sopenharmony_ci            if !ps.is_null() {
52692f3ab15Sopenharmony_ci                (*ps) = (*sig).s;
52792f3ab15Sopenharmony_ci            }
52892f3ab15Sopenharmony_ci        }
52992f3ab15Sopenharmony_ci    }
53092f3ab15Sopenharmony_ci}
53192f3ab15Sopenharmony_ci
53292f3ab15Sopenharmony_ci#[cfg(test)]
53392f3ab15Sopenharmony_cimod test {
53492f3ab15Sopenharmony_ci    use super::*;
53592f3ab15Sopenharmony_ci    use crate::bn::BigNumContext;
53692f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
53792f3ab15Sopenharmony_ci    use crate::hash::MessageDigest;
53892f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
53992f3ab15Sopenharmony_ci    use crate::pkey::PKey;
54092f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
54192f3ab15Sopenharmony_ci    use crate::sign::{Signer, Verifier};
54292f3ab15Sopenharmony_ci
54392f3ab15Sopenharmony_ci    #[test]
54492f3ab15Sopenharmony_ci    pub fn test_generate() {
54592f3ab15Sopenharmony_ci        Dsa::generate(1024).unwrap();
54692f3ab15Sopenharmony_ci    }
54792f3ab15Sopenharmony_ci
54892f3ab15Sopenharmony_ci    #[test]
54992f3ab15Sopenharmony_ci    fn test_pubkey_generation() {
55092f3ab15Sopenharmony_ci        let dsa = Dsa::generate(1024).unwrap();
55192f3ab15Sopenharmony_ci        let p = dsa.p();
55292f3ab15Sopenharmony_ci        let g = dsa.g();
55392f3ab15Sopenharmony_ci        let priv_key = dsa.priv_key();
55492f3ab15Sopenharmony_ci        let pub_key = dsa.pub_key();
55592f3ab15Sopenharmony_ci        let mut ctx = BigNumContext::new().unwrap();
55692f3ab15Sopenharmony_ci        let mut calc = BigNum::new().unwrap();
55792f3ab15Sopenharmony_ci        calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
55892f3ab15Sopenharmony_ci        assert_eq!(&calc, pub_key)
55992f3ab15Sopenharmony_ci    }
56092f3ab15Sopenharmony_ci
56192f3ab15Sopenharmony_ci    #[test]
56292f3ab15Sopenharmony_ci    fn test_priv_key_from_parts() {
56392f3ab15Sopenharmony_ci        let p = BigNum::from_u32(283).unwrap();
56492f3ab15Sopenharmony_ci        let q = BigNum::from_u32(47).unwrap();
56592f3ab15Sopenharmony_ci        let g = BigNum::from_u32(60).unwrap();
56692f3ab15Sopenharmony_ci        let priv_key = BigNum::from_u32(15).unwrap();
56792f3ab15Sopenharmony_ci        let pub_key = BigNum::from_u32(207).unwrap();
56892f3ab15Sopenharmony_ci
56992f3ab15Sopenharmony_ci        let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
57092f3ab15Sopenharmony_ci        assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
57192f3ab15Sopenharmony_ci        assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
57292f3ab15Sopenharmony_ci        assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
57392f3ab15Sopenharmony_ci        assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
57492f3ab15Sopenharmony_ci        assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
57592f3ab15Sopenharmony_ci    }
57692f3ab15Sopenharmony_ci
57792f3ab15Sopenharmony_ci    #[test]
57892f3ab15Sopenharmony_ci    fn test_pub_key_from_parts() {
57992f3ab15Sopenharmony_ci        let p = BigNum::from_u32(283).unwrap();
58092f3ab15Sopenharmony_ci        let q = BigNum::from_u32(47).unwrap();
58192f3ab15Sopenharmony_ci        let g = BigNum::from_u32(60).unwrap();
58292f3ab15Sopenharmony_ci        let pub_key = BigNum::from_u32(207).unwrap();
58392f3ab15Sopenharmony_ci
58492f3ab15Sopenharmony_ci        let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
58592f3ab15Sopenharmony_ci        assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
58692f3ab15Sopenharmony_ci        assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
58792f3ab15Sopenharmony_ci        assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
58892f3ab15Sopenharmony_ci        assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
58992f3ab15Sopenharmony_ci    }
59092f3ab15Sopenharmony_ci
59192f3ab15Sopenharmony_ci    #[test]
59292f3ab15Sopenharmony_ci    fn test_params() {
59392f3ab15Sopenharmony_ci        let params = Dsa::generate_params(1024).unwrap();
59492f3ab15Sopenharmony_ci        let p = params.p().to_owned().unwrap();
59592f3ab15Sopenharmony_ci        let q = params.q().to_owned().unwrap();
59692f3ab15Sopenharmony_ci        let g = params.g().to_owned().unwrap();
59792f3ab15Sopenharmony_ci        let key = params.generate_key().unwrap();
59892f3ab15Sopenharmony_ci        let params2 = Dsa::from_pqg(
59992f3ab15Sopenharmony_ci            key.p().to_owned().unwrap(),
60092f3ab15Sopenharmony_ci            key.q().to_owned().unwrap(),
60192f3ab15Sopenharmony_ci            key.g().to_owned().unwrap(),
60292f3ab15Sopenharmony_ci        )
60392f3ab15Sopenharmony_ci        .unwrap();
60492f3ab15Sopenharmony_ci        assert_eq!(p, *params2.p());
60592f3ab15Sopenharmony_ci        assert_eq!(q, *params2.q());
60692f3ab15Sopenharmony_ci        assert_eq!(g, *params2.g());
60792f3ab15Sopenharmony_ci    }
60892f3ab15Sopenharmony_ci
60992f3ab15Sopenharmony_ci    #[test]
61092f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
61192f3ab15Sopenharmony_ci    fn test_signature() {
61292f3ab15Sopenharmony_ci        const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
61392f3ab15Sopenharmony_ci        let dsa_ref = Dsa::generate(1024).unwrap();
61492f3ab15Sopenharmony_ci
61592f3ab15Sopenharmony_ci        let p = dsa_ref.p();
61692f3ab15Sopenharmony_ci        let q = dsa_ref.q();
61792f3ab15Sopenharmony_ci        let g = dsa_ref.g();
61892f3ab15Sopenharmony_ci
61992f3ab15Sopenharmony_ci        let pub_key = dsa_ref.pub_key();
62092f3ab15Sopenharmony_ci        let priv_key = dsa_ref.priv_key();
62192f3ab15Sopenharmony_ci
62292f3ab15Sopenharmony_ci        let priv_key = Dsa::from_private_components(
62392f3ab15Sopenharmony_ci            BigNumRef::to_owned(p).unwrap(),
62492f3ab15Sopenharmony_ci            BigNumRef::to_owned(q).unwrap(),
62592f3ab15Sopenharmony_ci            BigNumRef::to_owned(g).unwrap(),
62692f3ab15Sopenharmony_ci            BigNumRef::to_owned(priv_key).unwrap(),
62792f3ab15Sopenharmony_ci            BigNumRef::to_owned(pub_key).unwrap(),
62892f3ab15Sopenharmony_ci        )
62992f3ab15Sopenharmony_ci        .unwrap();
63092f3ab15Sopenharmony_ci        let priv_key = PKey::from_dsa(priv_key).unwrap();
63192f3ab15Sopenharmony_ci
63292f3ab15Sopenharmony_ci        let pub_key = Dsa::from_public_components(
63392f3ab15Sopenharmony_ci            BigNumRef::to_owned(p).unwrap(),
63492f3ab15Sopenharmony_ci            BigNumRef::to_owned(q).unwrap(),
63592f3ab15Sopenharmony_ci            BigNumRef::to_owned(g).unwrap(),
63692f3ab15Sopenharmony_ci            BigNumRef::to_owned(pub_key).unwrap(),
63792f3ab15Sopenharmony_ci        )
63892f3ab15Sopenharmony_ci        .unwrap();
63992f3ab15Sopenharmony_ci        let pub_key = PKey::from_dsa(pub_key).unwrap();
64092f3ab15Sopenharmony_ci
64192f3ab15Sopenharmony_ci        let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
64292f3ab15Sopenharmony_ci        signer.update(TEST_DATA).unwrap();
64392f3ab15Sopenharmony_ci
64492f3ab15Sopenharmony_ci        let signature = signer.sign_to_vec().unwrap();
64592f3ab15Sopenharmony_ci        let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
64692f3ab15Sopenharmony_ci        verifier.update(TEST_DATA).unwrap();
64792f3ab15Sopenharmony_ci        assert!(verifier.verify(&signature[..]).unwrap());
64892f3ab15Sopenharmony_ci    }
64992f3ab15Sopenharmony_ci
65092f3ab15Sopenharmony_ci    #[test]
65192f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
65292f3ab15Sopenharmony_ci    fn test_signature_der() {
65392f3ab15Sopenharmony_ci        use std::convert::TryInto;
65492f3ab15Sopenharmony_ci
65592f3ab15Sopenharmony_ci        const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
65692f3ab15Sopenharmony_ci        let dsa_ref = Dsa::generate(1024).unwrap();
65792f3ab15Sopenharmony_ci
65892f3ab15Sopenharmony_ci        let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
65992f3ab15Sopenharmony_ci        let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
66092f3ab15Sopenharmony_ci
66192f3ab15Sopenharmony_ci        let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
66292f3ab15Sopenharmony_ci        signer.update(TEST_DATA).unwrap();
66392f3ab15Sopenharmony_ci
66492f3ab15Sopenharmony_ci        let signature = signer.sign_to_vec().unwrap();
66592f3ab15Sopenharmony_ci        eprintln!("{:?}", signature);
66692f3ab15Sopenharmony_ci        let signature = DsaSig::from_der(&signature).unwrap();
66792f3ab15Sopenharmony_ci
66892f3ab15Sopenharmony_ci        let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
66992f3ab15Sopenharmony_ci        let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
67092f3ab15Sopenharmony_ci
67192f3ab15Sopenharmony_ci        let signature = DsaSig::from_private_components(r, s).unwrap();
67292f3ab15Sopenharmony_ci        let signature = signature.to_der().unwrap();
67392f3ab15Sopenharmony_ci
67492f3ab15Sopenharmony_ci        let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
67592f3ab15Sopenharmony_ci        verifier.update(TEST_DATA).unwrap();
67692f3ab15Sopenharmony_ci        assert!(verifier.verify(&signature[..]).unwrap());
67792f3ab15Sopenharmony_ci    }
67892f3ab15Sopenharmony_ci
67992f3ab15Sopenharmony_ci    #[test]
68092f3ab15Sopenharmony_ci    #[allow(clippy::redundant_clone)]
68192f3ab15Sopenharmony_ci    fn clone() {
68292f3ab15Sopenharmony_ci        let key = Dsa::generate(2048).unwrap();
68392f3ab15Sopenharmony_ci        drop(key.clone());
68492f3ab15Sopenharmony_ci    }
68592f3ab15Sopenharmony_ci
68692f3ab15Sopenharmony_ci    #[test]
68792f3ab15Sopenharmony_ci    fn dsa_sig_debug() {
68892f3ab15Sopenharmony_ci        let sig = DsaSig::from_der(&[
68992f3ab15Sopenharmony_ci            48, 46, 2, 21, 0, 135, 169, 24, 58, 153, 37, 175, 248, 200, 45, 251, 112, 238, 238, 89,
69092f3ab15Sopenharmony_ci            172, 177, 182, 166, 237, 2, 21, 0, 159, 146, 151, 237, 187, 8, 82, 115, 14, 183, 103,
69192f3ab15Sopenharmony_ci            12, 203, 46, 161, 208, 251, 167, 123, 131,
69292f3ab15Sopenharmony_ci        ])
69392f3ab15Sopenharmony_ci        .unwrap();
69492f3ab15Sopenharmony_ci        let s = format!("{:?}", sig);
69592f3ab15Sopenharmony_ci        assert_eq!(s, "DsaSig { r: 774484690634577222213819810519929266740561094381, s: 910998676210681457251421818099943952372231273347 }");
69692f3ab15Sopenharmony_ci    }
69792f3ab15Sopenharmony_ci}
698