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