@@ -67,6 +67,8 @@ let cmac_key = ctx.keygen().unwrap();
67
67
#[ cfg( not( boringssl) ) ]
68
68
use crate :: cipher:: CipherRef ;
69
69
use crate :: error:: ErrorStack ;
70
+ #[ cfg( ossl300) ]
71
+ use crate :: hash:: MessageDigest ;
70
72
use crate :: md:: MdRef ;
71
73
use crate :: pkey:: { HasPrivate , HasPublic , Id , PKey , PKeyRef , Private } ;
72
74
use crate :: rsa:: Padding ;
@@ -75,8 +77,12 @@ use crate::{cvt, cvt_p};
75
77
use foreign_types:: { ForeignType , ForeignTypeRef } ;
76
78
#[ cfg( not( boringssl) ) ]
77
79
use libc:: c_int;
80
+ #[ cfg( ossl320) ]
81
+ use libc:: c_uint;
78
82
use openssl_macros:: corresponds;
79
83
use std:: convert:: TryFrom ;
84
+ #[ cfg( ossl300) ]
85
+ use std:: ffi:: CString ;
80
86
use std:: ptr;
81
87
82
88
/// HKDF modes of operation.
@@ -105,6 +111,21 @@ impl HkdfMode {
105
111
pub const EXPAND_ONLY : Self = HkdfMode ( ffi:: EVP_PKEY_HKDEF_MODE_EXPAND_ONLY ) ;
106
112
}
107
113
114
+ /// Nonce type for ECDSA and DSA.
115
+ #[ cfg( ossl320) ]
116
+ #[ derive( Debug , PartialEq ) ]
117
+ pub struct NonceType ( c_uint ) ;
118
+
119
+ #[ cfg( ossl320) ]
120
+ impl NonceType {
121
+ /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3
122
+ /// “Secret Number Generation”.
123
+ pub const RANDOM_K : Self = NonceType ( 0 ) ;
124
+
125
+ /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”).
126
+ pub const DETERMINISTIC_K : Self = NonceType ( 1 ) ;
127
+ }
128
+
108
129
generic_foreign_type_and_impl_send_sync ! {
109
130
type CType = ffi:: EVP_PKEY_CTX ;
110
131
fn drop = ffi:: EVP_PKEY_CTX_free ;
@@ -714,6 +735,109 @@ impl<T> PkeyCtxRef<T> {
714
735
Ok ( PKey :: from_ptr ( key) )
715
736
}
716
737
}
738
+
739
+ /// Sets the digest algorithm for a private key context.
740
+ ///
741
+ /// Requires OpenSSL 3.0.0 or newer.
742
+ #[ cfg( ossl300) ]
743
+ #[ corresponds( EVP_PKEY_CTX_set_params ) ]
744
+ pub fn set_digest ( & mut self , hash_algorithm : MessageDigest ) -> Result < ( ) , ErrorStack > {
745
+ let digest_name = hash_algorithm. type_ ( ) . short_name ( ) ?;
746
+ let digest = CString :: new ( digest_name) . unwrap ( ) . into_raw ( ) ;
747
+ let digest_field_name = CString :: new ( "digest" ) . unwrap ( ) ;
748
+ unsafe {
749
+ let param_digest = ffi:: OSSL_PARAM_construct_utf8_string (
750
+ digest_field_name. as_ptr ( ) ,
751
+ digest,
752
+ digest_name. len ( ) ,
753
+ ) ;
754
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
755
+
756
+ let params = [ param_digest, param_end] ;
757
+ cvt ( ffi:: EVP_PKEY_CTX_set_params ( self . as_ptr ( ) , params. as_ptr ( ) ) ) ?;
758
+
759
+ // retake pointer to free memory
760
+ let _ = CString :: from_raw ( digest) ;
761
+ }
762
+ Ok ( ( ) )
763
+ }
764
+
765
+ /// Gets the digest algorithm for a private key context.
766
+ ///
767
+ /// Requires OpenSSL 3.0.0 or newer.
768
+ #[ cfg( ossl300) ]
769
+ #[ corresponds( EVP_PKEY_CTX_get_params ) ]
770
+ pub fn digest ( & mut self ) -> Result < Option < MessageDigest > , ErrorStack > {
771
+ use libc:: c_char;
772
+ // From openssl/internal/sizes.h
773
+ let ossl_max_name_size = 50usize ;
774
+ let digest_field_name = CString :: new ( "digest" ) . unwrap ( ) ;
775
+ let digest: * mut c_char = CString :: new ( vec ! [ 1 ; ossl_max_name_size] )
776
+ . unwrap ( )
777
+ . into_raw ( ) ;
778
+ unsafe {
779
+ let param_digest = ffi:: OSSL_PARAM_construct_utf8_string (
780
+ digest_field_name. as_ptr ( ) ,
781
+ digest,
782
+ ossl_max_name_size,
783
+ ) ;
784
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
785
+ let mut params = [ param_digest, param_end] ;
786
+ cvt ( ffi:: EVP_PKEY_CTX_get_params (
787
+ self . as_ptr ( ) ,
788
+ params. as_mut_ptr ( ) ,
789
+ ) ) ?;
790
+ let digest_str = CString :: from_raw ( digest) ;
791
+ Ok ( MessageDigest :: from_name ( digest_str. to_str ( ) . unwrap ( ) ) )
792
+ }
793
+ }
794
+
795
+ /// Sets the nonce type for a private key context.
796
+ ///
797
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
798
+ ///
799
+ /// This is only useful for DSA and ECDSA.
800
+ /// Requires OpenSSL 3.2.0 or newer.
801
+ #[ cfg( ossl320) ]
802
+ #[ corresponds( EVP_PKEY_CTX_set_params ) ]
803
+ pub fn set_nonce_type ( & mut self , nonce_type : NonceType ) -> Result < ( ) , ErrorStack > {
804
+ let nonce_field_name = CString :: new ( "nonce-type" ) . unwrap ( ) ;
805
+ let mut nonce_type = nonce_type. 0 ;
806
+ unsafe {
807
+ let param_nonce =
808
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
809
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
810
+
811
+ let params = [ param_nonce, param_end] ;
812
+ cvt ( ffi:: EVP_PKEY_CTX_set_params ( self . as_ptr ( ) , params. as_ptr ( ) ) ) ?;
813
+ }
814
+ Ok ( ( ) )
815
+ }
816
+
817
+ /// Gets the nonce type for a private key context.
818
+ ///
819
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
820
+ ///
821
+ /// This is only useful for DSA and ECDSA.
822
+ /// Requires OpenSSL 3.2.0 or newer.
823
+ #[ cfg( ossl320) ]
824
+ #[ corresponds( EVP_PKEY_CTX_get_params ) ]
825
+ pub fn nonce_type ( & mut self ) -> Result < NonceType , ErrorStack > {
826
+ let nonce_field_name = CString :: new ( "nonce-type" ) . unwrap ( ) ;
827
+ let mut nonce_type: c_uint = 0 ;
828
+ unsafe {
829
+ let param_nonce =
830
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
831
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
832
+
833
+ let mut params = [ param_nonce, param_end] ;
834
+ cvt ( ffi:: EVP_PKEY_CTX_get_params (
835
+ self . as_ptr ( ) ,
836
+ params. as_mut_ptr ( ) ,
837
+ ) ) ?;
838
+ }
839
+ Ok ( NonceType ( nonce_type) )
840
+ }
717
841
}
718
842
719
843
#[ cfg( test) ]
@@ -999,4 +1123,34 @@ mod test {
999
1123
// The digest is the end of the DigestInfo structure.
1000
1124
assert_eq ! ( result_buf[ length - digest. len( ) ..length] , digest) ;
1001
1125
}
1126
+
1127
+ #[ test]
1128
+ #[ cfg( ossl300) ]
1129
+ fn set_digest ( ) {
1130
+ let key1 =
1131
+ EcKey :: generate ( & EcGroup :: from_curve_name ( Nid :: X9_62_PRIME256V1 ) . unwrap ( ) ) . unwrap ( ) ;
1132
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1133
+
1134
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1135
+ ctx. sign_init ( ) . unwrap ( ) ;
1136
+ ctx. set_digest ( MessageDigest :: sha224 ( ) ) . unwrap ( ) ;
1137
+ let digest_name = ctx. digest ( ) . unwrap ( ) . unwrap ( ) . type_ ( ) ;
1138
+ assert_eq ! ( digest_name, MessageDigest :: sha224( ) . type_( ) ) ;
1139
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1140
+ }
1141
+
1142
+ #[ test]
1143
+ #[ cfg( ossl320) ]
1144
+ fn set_nonce_type ( ) {
1145
+ let key1 =
1146
+ EcKey :: generate ( & EcGroup :: from_curve_name ( Nid :: X9_62_PRIME256V1 ) . unwrap ( ) ) . unwrap ( ) ;
1147
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1148
+
1149
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1150
+ ctx. sign_init ( ) . unwrap ( ) ;
1151
+ ctx. set_nonce_type ( NonceType :: DETERMINISTIC_K ) . unwrap ( ) ;
1152
+ let nonce_type = ctx. nonce_type ( ) . unwrap ( ) ;
1153
+ assert_eq ! ( nonce_type, NonceType :: DETERMINISTIC_K ) ;
1154
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1155
+ }
1002
1156
}
0 commit comments