]> git.proxmox.com Git - cargo.git/blob - vendor/openssl/src/dsa.rs
New upstream version 0.52.0
[cargo.git] / vendor / openssl / src / dsa.rs
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 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 asymetrical 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> {
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
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`.
107 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`.
141 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
159 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`.
164 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`.
173 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`.
182 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
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`
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.
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> {
291 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]
367 pub fn test_generate() {
368 Dsa::generate(1024).unwrap();
369 }
370
371 #[test]
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]
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]
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]
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)]
456 fn clone() {
457 let key = Dsa::generate(2048).unwrap();
458 drop(key.clone());
459 }
460 }