1 //! Digital Signatures
2 //!
3 //! DSA ensures a message originated from a known sender, and was not modified.
4 //! DSA uses asymmetrical keys and an algorithm to output a signature of the message
5 //! using the private key that can be validated with the public key but not be generated
6 //! without the private key.
7 
8 use cfg_if::cfg_if;
9 use foreign_types::{ForeignType, ForeignTypeRef};
10 use libc::c_int;
11 use std::fmt;
12 use std::mem;
13 use std::ptr;
14 
15 use crate::bn::{BigNum, BigNumRef};
16 use crate::error::ErrorStack;
17 use crate::pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
18 use crate::util::ForeignTypeRefExt;
19 use crate::{cvt, cvt_p};
20 
21 generic_foreign_type_and_impl_send_sync! {
22     type CType = ffi::DSA;
23     fn drop = ffi::DSA_free;
24 
25     /// Object representing DSA keys.
26     ///
27     /// A DSA object contains the parameters p, q, and g.  There is a private
28     /// and public key.  The values p, g, and q are:
29     ///
30     /// * `p`: DSA prime parameter
31     /// * `q`: DSA sub-prime parameter
32     /// * `g`: DSA base parameter
33     ///
34     /// These values are used to calculate a pair of asymmetrical keys used for
35     /// signing.
36     ///
37     /// OpenSSL documentation at [`DSA_new`]
38     ///
39     /// [`DSA_new`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_new.html
40     ///
41     /// # Examples
42     ///
43     /// ```
44     /// use openssl::dsa::Dsa;
45     /// use openssl::error::ErrorStack;
46     /// use openssl::pkey::Private;
47     ///
48     /// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
49     ///     let sign = Dsa::generate(2048)?;
50     ///     Ok(sign)
51     /// }
52     /// # fn main() {
53     /// #    create_dsa();
54     /// # }
55     /// ```
56     pub struct Dsa<T>;
57     /// Reference to [`Dsa`].
58     ///
59     /// [`Dsa`]: struct.Dsa.html
60     pub struct DsaRef<T>;
61 }
62 
63 impl<T> Clone for Dsa<T> {
clone(&self) -> Dsa<T>64     fn clone(&self) -> Dsa<T> {
65         (**self).to_owned()
66     }
67 }
68 
69 impl<T> ToOwned for DsaRef<T> {
70     type Owned = Dsa<T>;
71 
to_owned(&self) -> Dsa<T>72     fn to_owned(&self) -> Dsa<T> {
73         unsafe {
74             ffi::DSA_up_ref(self.as_ptr());
75             Dsa::from_ptr(self.as_ptr())
76         }
77     }
78 }
79 
80 impl<T> DsaRef<T>
81 where
82     T: HasPublic,
83 {
84     to_pem! {
85         /// Serialies the public key into a PEM-encoded SubjectPublicKeyInfo structure.
86         ///
87         /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
88         ///
89         /// This corresponds to [`PEM_write_bio_DSA_PUBKEY`].
90         ///
91         /// [`PEM_write_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSA_PUBKEY.html
92         public_key_to_pem,
93         ffi::PEM_write_bio_DSA_PUBKEY
94     }
95 
96     to_der! {
97         /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
98         ///
99         /// This corresponds to [`i2d_DSA_PUBKEY`].
100         ///
101         /// [`i2d_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_DSA_PUBKEY.html
102         public_key_to_der,
103         ffi::i2d_DSA_PUBKEY
104     }
105 
106     /// Returns a reference to the public key component of `self`.
pub_key(&self) -> &BigNumRef107     pub fn pub_key(&self) -> &BigNumRef {
108         unsafe {
109             let mut pub_key = ptr::null();
110             DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
111             BigNumRef::from_const_ptr(pub_key)
112         }
113     }
114 }
115 
116 impl<T> DsaRef<T>
117 where
118     T: HasPrivate,
119 {
120     private_key_to_pem! {
121         /// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
122         ///
123         /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
124         ///
125         /// This corresponds to [`PEM_write_bio_DSAPrivateKey`].
126         ///
127         /// [`PEM_write_bio_DSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSAPrivateKey.html
128         private_key_to_pem,
129         /// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
130         ///
131         /// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
132         ///
133         /// This corresponds to [`PEM_write_bio_DSAPrivateKey`].
134         ///
135         /// [`PEM_write_bio_DSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_DSAPrivateKey.html
136         private_key_to_pem_passphrase,
137         ffi::PEM_write_bio_DSAPrivateKey
138     }
139 
140     /// Returns a reference to the private key component of `self`.
priv_key(&self) -> &BigNumRef141     pub fn priv_key(&self) -> &BigNumRef {
142         unsafe {
143             let mut priv_key = ptr::null();
144             DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
145             BigNumRef::from_const_ptr(priv_key)
146         }
147     }
148 }
149 
150 impl<T> DsaRef<T>
151 where
152     T: HasParams,
153 {
154     /// Returns the maximum size of the signature output by `self` in bytes.
155     ///
156     /// OpenSSL documentation at [`DSA_size`]
157     ///
158     /// [`DSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_size.html
size(&self) -> u32159     pub fn size(&self) -> u32 {
160         unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
161     }
162 
163     /// Returns the DSA prime parameter of `self`.
p(&self) -> &BigNumRef164     pub fn p(&self) -> &BigNumRef {
165         unsafe {
166             let mut p = ptr::null();
167             DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
168             BigNumRef::from_const_ptr(p)
169         }
170     }
171 
172     /// Returns the DSA sub-prime parameter of `self`.
q(&self) -> &BigNumRef173     pub fn q(&self) -> &BigNumRef {
174         unsafe {
175             let mut q = ptr::null();
176             DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
177             BigNumRef::from_const_ptr(q)
178         }
179     }
180 
181     /// Returns the DSA base parameter of `self`.
g(&self) -> &BigNumRef182     pub fn g(&self) -> &BigNumRef {
183         unsafe {
184             let mut g = ptr::null();
185             DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
186             BigNumRef::from_const_ptr(g)
187         }
188     }
189 }
190 
191 impl Dsa<Private> {
192     /// Generate a DSA key pair.
193     ///
194     /// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values.
195     /// These values are used to generate the key pair with [`DSA_generate_key`].
196     ///
197     /// The `bits` parameter corresponds to the length of the prime `p`.
198     ///
199     /// [`DSA_generate_parameters_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_parameters_ex.html
200     /// [`DSA_generate_key`]: https://www.openssl.org/docs/man1.1.0/crypto/DSA_generate_key.html
generate(bits: u32) -> Result<Dsa<Private>, ErrorStack>201     pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
202         ffi::init();
203         unsafe {
204             let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
205             cvt(ffi::DSA_generate_parameters_ex(
206                 dsa.0,
207                 bits as c_int,
208                 ptr::null(),
209                 0,
210                 ptr::null_mut(),
211                 ptr::null_mut(),
212                 ptr::null_mut(),
213             ))?;
214             cvt(ffi::DSA_generate_key(dsa.0))?;
215             Ok(dsa)
216         }
217     }
218 
219     /// Create a DSA key pair with the given parameters
220     ///
221     /// `p`, `q` and `g` are the common parameters.
222     /// `priv_key` is the private component of the key pair.
223     /// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
from_private_components( p: BigNum, q: BigNum, g: BigNum, priv_key: BigNum, pub_key: BigNum, ) -> Result<Dsa<Private>, ErrorStack>224     pub fn from_private_components(
225         p: BigNum,
226         q: BigNum,
227         g: BigNum,
228         priv_key: BigNum,
229         pub_key: BigNum,
230     ) -> Result<Dsa<Private>, ErrorStack> {
231         ffi::init();
232         unsafe {
233             let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
234             cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
235             mem::forget((p, q, g));
236             cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
237             mem::forget((pub_key, priv_key));
238             Ok(dsa)
239         }
240     }
241 }
242 
243 impl Dsa<Public> {
244     from_pem! {
245         /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
246         ///
247         /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
248         ///
249         /// This corresponds to [`PEM_read_bio_DSA_PUBKEY`].
250         ///
251         /// [`PEM_read_bio_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_DSA_PUBKEY.html
252         public_key_from_pem,
253         Dsa<Public>,
254         ffi::PEM_read_bio_DSA_PUBKEY
255     }
256 
257     from_der! {
258         /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
259         ///
260         /// This corresponds to [`d2i_DSA_PUBKEY`].
261         ///
262         /// [`d2i_DSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_DSA_PUBKEY.html
263         public_key_from_der,
264         Dsa<Public>,
265         ffi::d2i_DSA_PUBKEY
266     }
267 
268     /// Create a new DSA key with only public components.
269     ///
270     /// `p`, `q` and `g` are the common parameters.
271     /// `pub_key` is the public component of the key.
from_public_components( p: BigNum, q: BigNum, g: BigNum, pub_key: BigNum, ) -> Result<Dsa<Public>, ErrorStack>272     pub fn from_public_components(
273         p: BigNum,
274         q: BigNum,
275         g: BigNum,
276         pub_key: BigNum,
277     ) -> Result<Dsa<Public>, ErrorStack> {
278         ffi::init();
279         unsafe {
280             let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
281             cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
282             mem::forget((p, q, g));
283             cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?;
284             mem::forget(pub_key);
285             Ok(dsa)
286         }
287     }
288 }
289 
290 impl<T> fmt::Debug for Dsa<T> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result291     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292         write!(f, "DSA")
293     }
294 }
295 
296 cfg_if! {
297     if #[cfg(any(ossl110, libressl273))] {
298         use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
299     } else {
300         #[allow(bad_style)]
301         unsafe fn DSA_get0_pqg(
302             d: *mut ffi::DSA,
303             p: *mut *const ffi::BIGNUM,
304             q: *mut *const ffi::BIGNUM,
305             g: *mut *const ffi::BIGNUM)
306         {
307             if !p.is_null() {
308                 *p = (*d).p;
309             }
310             if !q.is_null() {
311                 *q = (*d).q;
312             }
313             if !g.is_null() {
314                 *g = (*d).g;
315             }
316         }
317 
318         #[allow(bad_style)]
319         unsafe fn DSA_get0_key(
320             d: *mut ffi::DSA,
321             pub_key: *mut *const ffi::BIGNUM,
322             priv_key: *mut *const ffi::BIGNUM)
323         {
324             if !pub_key.is_null() {
325                 *pub_key = (*d).pub_key;
326             }
327             if !priv_key.is_null() {
328                 *priv_key = (*d).priv_key;
329             }
330         }
331 
332         #[allow(bad_style)]
333         unsafe fn DSA_set0_key(
334             d: *mut ffi::DSA,
335             pub_key: *mut ffi::BIGNUM,
336             priv_key: *mut ffi::BIGNUM) -> c_int
337         {
338             (*d).pub_key = pub_key;
339             (*d).priv_key = priv_key;
340             1
341         }
342 
343         #[allow(bad_style)]
344         unsafe fn DSA_set0_pqg(
345             d: *mut ffi::DSA,
346             p: *mut ffi::BIGNUM,
347             q: *mut ffi::BIGNUM,
348             g: *mut ffi::BIGNUM) -> c_int
349         {
350             (*d).p = p;
351             (*d).q = q;
352             (*d).g = g;
353             1
354         }
355     }
356 }
357 
358 #[cfg(test)]
359 mod test {
360     use super::*;
361     use crate::bn::BigNumContext;
362     use crate::hash::MessageDigest;
363     use crate::pkey::PKey;
364     use crate::sign::{Signer, Verifier};
365 
366     #[test]
test_generate()367     pub fn test_generate() {
368         Dsa::generate(1024).unwrap();
369     }
370 
371     #[test]
test_pubkey_generation()372     fn test_pubkey_generation() {
373         let dsa = Dsa::generate(1024).unwrap();
374         let p = dsa.p();
375         let g = dsa.g();
376         let priv_key = dsa.priv_key();
377         let pub_key = dsa.pub_key();
378         let mut ctx = BigNumContext::new().unwrap();
379         let mut calc = BigNum::new().unwrap();
380         calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
381         assert_eq!(&calc, pub_key)
382     }
383 
384     #[test]
test_priv_key_from_parts()385     fn test_priv_key_from_parts() {
386         let p = BigNum::from_u32(283).unwrap();
387         let q = BigNum::from_u32(47).unwrap();
388         let g = BigNum::from_u32(60).unwrap();
389         let priv_key = BigNum::from_u32(15).unwrap();
390         let pub_key = BigNum::from_u32(207).unwrap();
391 
392         let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
393         assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
394         assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
395         assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
396         assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
397         assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
398     }
399 
400     #[test]
test_pub_key_from_parts()401     fn test_pub_key_from_parts() {
402         let p = BigNum::from_u32(283).unwrap();
403         let q = BigNum::from_u32(47).unwrap();
404         let g = BigNum::from_u32(60).unwrap();
405         let pub_key = BigNum::from_u32(207).unwrap();
406 
407         let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
408         assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
409         assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
410         assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
411         assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
412     }
413 
414     #[test]
test_signature()415     fn test_signature() {
416         const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
417         let dsa_ref = Dsa::generate(1024).unwrap();
418 
419         let p = dsa_ref.p();
420         let q = dsa_ref.q();
421         let g = dsa_ref.g();
422 
423         let pub_key = dsa_ref.pub_key();
424         let priv_key = dsa_ref.priv_key();
425 
426         let priv_key = Dsa::from_private_components(
427             BigNumRef::to_owned(p).unwrap(),
428             BigNumRef::to_owned(q).unwrap(),
429             BigNumRef::to_owned(g).unwrap(),
430             BigNumRef::to_owned(priv_key).unwrap(),
431             BigNumRef::to_owned(pub_key).unwrap(),
432         )
433         .unwrap();
434         let priv_key = PKey::from_dsa(priv_key).unwrap();
435 
436         let pub_key = Dsa::from_public_components(
437             BigNumRef::to_owned(p).unwrap(),
438             BigNumRef::to_owned(q).unwrap(),
439             BigNumRef::to_owned(g).unwrap(),
440             BigNumRef::to_owned(pub_key).unwrap(),
441         )
442         .unwrap();
443         let pub_key = PKey::from_dsa(pub_key).unwrap();
444 
445         let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
446         signer.update(TEST_DATA).unwrap();
447 
448         let signature = signer.sign_to_vec().unwrap();
449         let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
450         verifier.update(TEST_DATA).unwrap();
451         assert!(verifier.verify(&signature[..]).unwrap());
452     }
453 
454     #[test]
455     #[allow(clippy::redundant_clone)]
clone()456     fn clone() {
457         let key = Dsa::generate(2048).unwrap();
458         drop(key.clone());
459     }
460 }
461