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