@@ -75,8 +75,12 @@ use crate::{cvt, cvt_p};
75
75
use foreign_types:: { ForeignType , ForeignTypeRef } ;
76
76
#[ cfg( not( boringssl) ) ]
77
77
use libc:: c_int;
78
+ #[ cfg( ossl320) ]
79
+ use libc:: c_uint;
78
80
use openssl_macros:: corresponds;
79
81
use std:: convert:: TryFrom ;
82
+ #[ cfg( ossl320) ]
83
+ use std:: ffi:: CStr ;
80
84
use std:: ptr;
81
85
82
86
/// HKDF modes of operation.
@@ -105,6 +109,21 @@ impl HkdfMode {
105
109
pub const EXPAND_ONLY : Self = HkdfMode ( ffi:: EVP_PKEY_HKDEF_MODE_EXPAND_ONLY ) ;
106
110
}
107
111
112
+ /// Nonce type for ECDSA and DSA.
113
+ #[ cfg( ossl320) ]
114
+ #[ derive( Debug , PartialEq ) ]
115
+ pub struct NonceType ( c_uint ) ;
116
+
117
+ #[ cfg( ossl320) ]
118
+ impl NonceType {
119
+ /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3
120
+ /// “Secret Number Generation”.
121
+ pub const RANDOM_K : Self = NonceType ( 0 ) ;
122
+
123
+ /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”).
124
+ pub const DETERMINISTIC_K : Self = NonceType ( 1 ) ;
125
+ }
126
+
108
127
generic_foreign_type_and_impl_send_sync ! {
109
128
type CType = ffi:: EVP_PKEY_CTX ;
110
129
fn drop = ffi:: EVP_PKEY_CTX_free ;
@@ -714,6 +733,53 @@ impl<T> PkeyCtxRef<T> {
714
733
Ok ( PKey :: from_ptr ( key) )
715
734
}
716
735
}
736
+
737
+ /// Sets the nonce type for a private key context.
738
+ ///
739
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
740
+ ///
741
+ /// This is only useful for DSA and ECDSA.
742
+ /// Requires OpenSSL 3.2.0 or newer.
743
+ #[ cfg( ossl320) ]
744
+ #[ corresponds( EVP_PKEY_CTX_set_params ) ]
745
+ pub fn set_nonce_type ( & mut self , nonce_type : NonceType ) -> Result < ( ) , ErrorStack > {
746
+ let nonce_field_name = CStr :: from_bytes_with_nul ( b"nonce-type\0 " ) . unwrap ( ) ;
747
+ let mut nonce_type = nonce_type. 0 ;
748
+ unsafe {
749
+ let param_nonce =
750
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
751
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
752
+
753
+ let params = [ param_nonce, param_end] ;
754
+ cvt ( ffi:: EVP_PKEY_CTX_set_params ( self . as_ptr ( ) , params. as_ptr ( ) ) ) ?;
755
+ }
756
+ Ok ( ( ) )
757
+ }
758
+
759
+ /// Gets the nonce type for a private key context.
760
+ ///
761
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
762
+ ///
763
+ /// This is only useful for DSA and ECDSA.
764
+ /// Requires OpenSSL 3.2.0 or newer.
765
+ #[ cfg( ossl320) ]
766
+ #[ corresponds( EVP_PKEY_CTX_get_params ) ]
767
+ pub fn nonce_type ( & mut self ) -> Result < NonceType , ErrorStack > {
768
+ let nonce_field_name = CStr :: from_bytes_with_nul ( b"nonce-type\0 " ) . unwrap ( ) ;
769
+ let mut nonce_type: c_uint = 0 ;
770
+ unsafe {
771
+ let param_nonce =
772
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
773
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
774
+
775
+ let mut params = [ param_nonce, param_end] ;
776
+ cvt ( ffi:: EVP_PKEY_CTX_get_params (
777
+ self . as_ptr ( ) ,
778
+ params. as_mut_ptr ( ) ,
779
+ ) ) ?;
780
+ }
781
+ Ok ( NonceType ( nonce_type) )
782
+ }
717
783
}
718
784
719
785
#[ cfg( test) ]
@@ -999,4 +1065,46 @@ mod test {
999
1065
// The digest is the end of the DigestInfo structure.
1000
1066
assert_eq ! ( result_buf[ length - digest. len( ) ..length] , digest) ;
1001
1067
}
1068
+
1069
+ #[ test]
1070
+ #[ cfg( ossl320) ]
1071
+ fn set_nonce_type ( ) {
1072
+ let key1 =
1073
+ EcKey :: generate ( & EcGroup :: from_curve_name ( Nid :: X9_62_PRIME256V1 ) . unwrap ( ) ) . unwrap ( ) ;
1074
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1075
+
1076
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1077
+ ctx. sign_init ( ) . unwrap ( ) ;
1078
+ ctx. set_nonce_type ( NonceType :: DETERMINISTIC_K ) . unwrap ( ) ;
1079
+ let nonce_type = ctx. nonce_type ( ) . unwrap ( ) ;
1080
+ assert_eq ! ( nonce_type, NonceType :: DETERMINISTIC_K ) ;
1081
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1082
+ }
1083
+
1084
+ // Test vector from
1085
+ // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt
1086
+ #[ test]
1087
+ #[ cfg( ossl320) ]
1088
+ fn ecdsa_deterministic_signature ( ) {
1089
+ let private_key_pem = "-----BEGIN PRIVATE KEY-----
1090
+ MDkCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEHzAdAgEBBBhvqwNJNOTA/Jrmf1tWWanX0f79GH7g
1091
+ n9Q=
1092
+ -----END PRIVATE KEY-----" ;
1093
+
1094
+ let key1 = EcKey :: private_key_from_pem ( private_key_pem. as_bytes ( ) ) . unwrap ( ) ;
1095
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1096
+ let input = "sample" ;
1097
+ let expected_output = hex:: decode ( "303502190098C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF021857A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64" ) . unwrap ( ) ;
1098
+
1099
+ let hashed_input = hash ( MessageDigest :: sha1 ( ) , input. as_bytes ( ) ) . unwrap ( ) ;
1100
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1101
+ ctx. sign_init ( ) . unwrap ( ) ;
1102
+ ctx. set_signature_md ( Md :: sha1 ( ) ) . unwrap ( ) ;
1103
+ ctx. set_nonce_type ( NonceType :: DETERMINISTIC_K ) . unwrap ( ) ;
1104
+
1105
+ let mut output = vec ! [ ] ;
1106
+ ctx. sign_to_vec ( & hashed_input, & mut output) . unwrap ( ) ;
1107
+ assert_eq ! ( output, expected_output) ;
1108
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1109
+ }
1002
1110
}
0 commit comments