@@ -344,6 +344,159 @@ cfg_if! {
344
344
}
345
345
}
346
346
347
+ foreign_type_and_impl_send_sync ! {
348
+ type CType = ffi:: DSA_SIG ;
349
+ fn drop = ffi:: DSA_SIG_free ;
350
+
351
+ /// Object representing DSA signature.
352
+ ///
353
+ /// DSA signatures consist of two components: `r` and `s`.
354
+ ///
355
+ /// # Examples
356
+ ///
357
+ /// ```
358
+ /// use std::convert::TryInto;
359
+ ///
360
+ /// use openssl::bn::BigNum;
361
+ /// use openssl::dsa::{Dsa, DsaSig};
362
+ /// use openssl::hash::MessageDigest;
363
+ /// use openssl::pkey::PKey;
364
+ /// use openssl::sign::{Signer, Verifier};
365
+ ///
366
+ /// const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
367
+ /// let dsa_ref = Dsa::generate(1024).unwrap();
368
+ ///
369
+ /// let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
370
+ /// let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
371
+ ///
372
+ /// let mut signer = if let Ok(signer) = Signer::new(MessageDigest::sha256(), &priv_key) {
373
+ /// signer
374
+ /// } else {
375
+ /// // DSA signing is not supported (eg. BoringSSL)
376
+ /// return;
377
+ /// };
378
+ ///
379
+ /// signer.update(TEST_DATA).unwrap();
380
+ ///
381
+ /// let signature = signer.sign_to_vec().unwrap();
382
+ /// // Parse DER-encoded DSA signature
383
+ /// let signature = DsaSig::from_der(&signature).unwrap();
384
+ ///
385
+ /// // Extract components `r` and `s`
386
+ /// let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
387
+ /// let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
388
+ ///
389
+ /// // Construct new DSA signature from components
390
+ /// let signature = DsaSig::from_private_components(r, s).unwrap();
391
+ ///
392
+ /// // Serialize DSA signature to DER
393
+ /// let signature = signature.to_der().unwrap();
394
+ ///
395
+ /// let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
396
+ /// verifier.update(TEST_DATA).unwrap();
397
+ /// assert!(verifier.verify(&signature[..]).unwrap());
398
+ /// ```
399
+ pub struct DsaSig ;
400
+
401
+ /// Reference to a [`DsaSig`].
402
+ pub struct DsaSigRef ;
403
+ }
404
+
405
+ impl DsaSig {
406
+ /// Returns a new `DsaSig` by setting the `r` and `s` values associated with an DSA signature.
407
+ #[ corresponds( DSA_SIG_set0 ) ]
408
+ pub fn from_private_components ( r : BigNum , s : BigNum ) -> Result < Self , ErrorStack > {
409
+ unsafe {
410
+ let sig = cvt_p ( ffi:: DSA_SIG_new ( ) ) ?;
411
+ DSA_SIG_set0 ( sig, r. as_ptr ( ) , s. as_ptr ( ) ) ;
412
+ mem:: forget ( ( r, s) ) ;
413
+ Ok ( DsaSig :: from_ptr ( sig) )
414
+ }
415
+ }
416
+
417
+ from_der ! {
418
+ /// Decodes a DER-encoded DSA signature.
419
+ #[ corresponds( d2i_DSA_SIG) ]
420
+ from_der,
421
+ DsaSig ,
422
+ ffi:: d2i_DSA_SIG
423
+ }
424
+ }
425
+
426
+ impl fmt:: Debug for DsaSig {
427
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
428
+ f. debug_struct ( "DsaSig" )
429
+ . field ( "r" , self . r ( ) )
430
+ . field ( "s" , self . s ( ) )
431
+ . finish ( )
432
+ }
433
+ }
434
+
435
+ impl DsaSigRef {
436
+ to_der ! {
437
+ /// Serializes the DSA signature into a DER-encoded `DSASignature` structure.
438
+ #[ corresponds( i2d_DSA_SIG) ]
439
+ to_der,
440
+ ffi:: i2d_DSA_SIG
441
+ }
442
+
443
+ /// Returns internal component `r` of an `DsaSig`.
444
+ #[ corresponds( DSA_SIG_get0 ) ]
445
+ pub fn r ( & self ) -> & BigNumRef {
446
+ unsafe {
447
+ let mut r = ptr:: null ( ) ;
448
+ DSA_SIG_get0 ( self . as_ptr ( ) , & mut r, ptr:: null_mut ( ) ) ;
449
+ BigNumRef :: from_const_ptr ( r)
450
+ }
451
+ }
452
+
453
+ /// Returns internal component `s` of an `DsaSig`.
454
+ #[ corresponds( DSA_SIG_get0 ) ]
455
+ pub fn s ( & self ) -> & BigNumRef {
456
+ unsafe {
457
+ let mut s = ptr:: null ( ) ;
458
+ DSA_SIG_get0 ( self . as_ptr ( ) , ptr:: null_mut ( ) , & mut s) ;
459
+ BigNumRef :: from_const_ptr ( s)
460
+ }
461
+ }
462
+ }
463
+
464
+ cfg_if ! {
465
+ if #[ cfg( any( ossl110, libressl273) ) ] {
466
+ use ffi:: { DSA_SIG_set0 , DSA_SIG_get0 } ;
467
+ } else {
468
+ #[ allow( bad_style) ]
469
+ unsafe fn DSA_SIG_set0 (
470
+ sig: * mut ffi:: DSA_SIG ,
471
+ r: * mut ffi:: BIGNUM ,
472
+ s: * mut ffi:: BIGNUM ,
473
+ ) -> c_int {
474
+ if r. is_null( ) || s. is_null( ) {
475
+ return 0 ;
476
+ }
477
+ ffi:: BN_clear_free ( ( * sig) . r) ;
478
+ ffi:: BN_clear_free ( ( * sig) . s) ;
479
+ ( * sig) . r = r;
480
+ ( * sig) . s = s;
481
+ 1
482
+ }
483
+
484
+ #[ allow( bad_style) ]
485
+ unsafe fn DSA_SIG_get0 (
486
+ sig: * const ffi:: DSA_SIG ,
487
+ pr: * mut * const ffi:: BIGNUM ,
488
+ ps: * mut * const ffi:: BIGNUM )
489
+ {
490
+ if !pr. is_null( ) {
491
+ ( * pr) = ( * sig) . r;
492
+ }
493
+ if !ps. is_null( ) {
494
+ ( * ps) = ( * sig) . s;
495
+ }
496
+ }
497
+ }
498
+ }
499
+
347
500
#[ cfg( test) ]
348
501
mod test {
349
502
use super :: * ;
@@ -444,10 +597,51 @@ mod test {
444
597
assert ! ( verifier. verify( & signature[ ..] ) . unwrap( ) ) ;
445
598
}
446
599
600
+ #[ test]
601
+ #[ cfg( not( boringssl) ) ]
602
+ fn test_signature_der ( ) {
603
+ use std:: convert:: TryInto ;
604
+
605
+ const TEST_DATA : & [ u8 ] = & [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ;
606
+ let dsa_ref = Dsa :: generate ( 1024 ) . unwrap ( ) ;
607
+
608
+ let pub_key: PKey < _ > = dsa_ref. clone ( ) . try_into ( ) . unwrap ( ) ;
609
+ let priv_key: PKey < _ > = dsa_ref. try_into ( ) . unwrap ( ) ;
610
+
611
+ let mut signer = Signer :: new ( MessageDigest :: sha256 ( ) , & priv_key) . unwrap ( ) ;
612
+ signer. update ( TEST_DATA ) . unwrap ( ) ;
613
+
614
+ let signature = signer. sign_to_vec ( ) . unwrap ( ) ;
615
+ eprintln ! ( "{:?}" , signature) ;
616
+ let signature = DsaSig :: from_der ( & signature) . unwrap ( ) ;
617
+
618
+ let r = BigNum :: from_slice ( & signature. r ( ) . to_vec ( ) ) . unwrap ( ) ;
619
+ let s = BigNum :: from_slice ( & signature. s ( ) . to_vec ( ) ) . unwrap ( ) ;
620
+
621
+ let signature = DsaSig :: from_private_components ( r, s) . unwrap ( ) ;
622
+ let signature = signature. to_der ( ) . unwrap ( ) ;
623
+
624
+ let mut verifier = Verifier :: new ( MessageDigest :: sha256 ( ) , & pub_key) . unwrap ( ) ;
625
+ verifier. update ( TEST_DATA ) . unwrap ( ) ;
626
+ assert ! ( verifier. verify( & signature[ ..] ) . unwrap( ) ) ;
627
+ }
628
+
447
629
#[ test]
448
630
#[ allow( clippy:: redundant_clone) ]
449
631
fn clone ( ) {
450
632
let key = Dsa :: generate ( 2048 ) . unwrap ( ) ;
451
633
drop ( key. clone ( ) ) ;
452
634
}
635
+
636
+ #[ test]
637
+ fn dsa_sig_debug ( ) {
638
+ let sig = DsaSig :: from_der ( & [
639
+ 48 , 46 , 2 , 21 , 0 , 135 , 169 , 24 , 58 , 153 , 37 , 175 , 248 , 200 , 45 , 251 , 112 , 238 , 238 , 89 ,
640
+ 172 , 177 , 182 , 166 , 237 , 2 , 21 , 0 , 159 , 146 , 151 , 237 , 187 , 8 , 82 , 115 , 14 , 183 , 103 ,
641
+ 12 , 203 , 46 , 161 , 208 , 251 , 167 , 123 , 131 ,
642
+ ] )
643
+ . unwrap ( ) ;
644
+ let s = format ! ( "{:?}" , sig) ;
645
+ assert_eq ! ( s, "DsaSig { r: 774484690634577222213819810519929266740561094381, s: 910998676210681457251421818099943952372231273347 }" ) ;
646
+ }
453
647
}
0 commit comments