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