@@ -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 ;
@@ -115,6 +136,8 @@ generic_foreign_type_and_impl_send_sync! {
115
136
pub struct PkeyCtxRef <T >;
116
137
}
117
138
139
+ pub const OSSL_MAX_NAME_SIZE : c_int = 50 ;
140
+
118
141
impl < T > PkeyCtx < T > {
119
142
/// Creates a new pkey context using the provided key.
120
143
#[ corresponds( EVP_PKEY_CTX_new ) ]
@@ -714,6 +737,109 @@ impl<T> PkeyCtxRef<T> {
714
737
Ok ( PKey :: from_ptr ( key) )
715
738
}
716
739
}
740
+
741
+ /// Sets the digest algorithm for a private key context.
742
+ ///
743
+ /// Requires OpenSSL 3.0.0 or newer.
744
+ #[ cfg( ossl300) ]
745
+ #[ corresponds( EVP_PKEY_CTX_set_params ) ]
746
+ pub fn set_digest ( & mut self , hash_algorithm : MessageDigest ) -> Result < ( ) , ErrorStack > {
747
+ let digest_name = hash_algorithm. type_ ( ) . short_name ( ) ?;
748
+ let digest = CString :: new ( digest_name) . unwrap ( ) . into_raw ( ) ;
749
+ let digest_field_name = CString :: new ( "digest" ) . unwrap ( ) ;
750
+ unsafe {
751
+ let param_digest = ffi:: OSSL_PARAM_construct_utf8_string (
752
+ digest_field_name. as_ptr ( ) ,
753
+ digest,
754
+ digest_name. len ( ) ,
755
+ ) ;
756
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
757
+
758
+ let params = [ param_digest, param_end] ;
759
+ cvt ( ffi:: EVP_PKEY_CTX_set_params ( self . as_ptr ( ) , params. as_ptr ( ) ) ) ?;
760
+
761
+ // retake pointer to free memory
762
+ let _ = CString :: from_raw ( digest) ;
763
+ }
764
+ Ok ( ( ) )
765
+ }
766
+
767
+ /// Gets the digest algorithm for a private key context.
768
+ ///
769
+ /// Requires OpenSSL 3.0.0 or newer.
770
+ #[ cfg( ossl300) ]
771
+ #[ corresponds( EVP_PKEY_CTX_get_params ) ]
772
+ pub fn digest ( & mut self ) -> Result < Option < MessageDigest > , ErrorStack > {
773
+ use libc:: c_char;
774
+ // From openssl/internal/sizes.h
775
+ let ossl_max_name_size = 50usize ;
776
+ let digest_field_name = CString :: new ( "digest" ) . unwrap ( ) ;
777
+ let digest: * mut c_char = CString :: new ( vec ! [ 1 ; ossl_max_name_size] )
778
+ . unwrap ( )
779
+ . into_raw ( ) ;
780
+ unsafe {
781
+ let param_digest = ffi:: OSSL_PARAM_construct_utf8_string (
782
+ digest_field_name. as_ptr ( ) ,
783
+ digest,
784
+ ossl_max_name_size,
785
+ ) ;
786
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
787
+ let mut params = [ param_digest, param_end] ;
788
+ cvt ( ffi:: EVP_PKEY_CTX_get_params (
789
+ self . as_ptr ( ) ,
790
+ params. as_mut_ptr ( ) ,
791
+ ) ) ?;
792
+ let digest_str = CString :: from_raw ( digest) ;
793
+ Ok ( MessageDigest :: from_name ( digest_str. to_str ( ) . unwrap ( ) ) )
794
+ }
795
+ }
796
+
797
+ /// Sets the nonce type for a private key context.
798
+ ///
799
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
800
+ ///
801
+ /// This is only useful for DSA and ECDSA.
802
+ /// Requires OpenSSL 3.2.0 or newer.
803
+ #[ cfg( ossl320) ]
804
+ #[ corresponds( EVP_PKEY_CTX_set_params ) ]
805
+ pub fn set_nonce_type ( & mut self , nonce_type : NonceType ) -> Result < ( ) , ErrorStack > {
806
+ let nonce_field_name = CString :: new ( "nonce-type" ) . unwrap ( ) ;
807
+ let mut nonce_type = nonce_type. 0 ;
808
+ unsafe {
809
+ let param_nonce =
810
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
811
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
812
+
813
+ let params = [ param_nonce, param_end] ;
814
+ cvt ( ffi:: EVP_PKEY_CTX_set_params ( self . as_ptr ( ) , params. as_ptr ( ) ) ) ?;
815
+ }
816
+ Ok ( ( ) )
817
+ }
818
+
819
+ /// Gets the nonce type for a private key context.
820
+ ///
821
+ /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979).
822
+ ///
823
+ /// This is only useful for DSA and ECDSA.
824
+ /// Requires OpenSSL 3.2.0 or newer.
825
+ #[ cfg( ossl320) ]
826
+ #[ corresponds( EVP_PKEY_CTX_get_params ) ]
827
+ pub fn nonce_type ( & mut self ) -> Result < NonceType , ErrorStack > {
828
+ let nonce_field_name = CString :: new ( "nonce-type" ) . unwrap ( ) ;
829
+ let mut nonce_type: c_uint = 0 ;
830
+ unsafe {
831
+ let param_nonce =
832
+ ffi:: OSSL_PARAM_construct_uint ( nonce_field_name. as_ptr ( ) , & mut nonce_type) ;
833
+ let param_end = ffi:: OSSL_PARAM_construct_end ( ) ;
834
+
835
+ let mut params = [ param_nonce, param_end] ;
836
+ cvt ( ffi:: EVP_PKEY_CTX_get_params (
837
+ self . as_ptr ( ) ,
838
+ params. as_mut_ptr ( ) ,
839
+ ) ) ?;
840
+ }
841
+ Ok ( NonceType ( nonce_type) )
842
+ }
717
843
}
718
844
719
845
#[ cfg( test) ]
@@ -999,4 +1125,34 @@ mod test {
999
1125
// The digest is the end of the DigestInfo structure.
1000
1126
assert_eq ! ( result_buf[ length - digest. len( ) ..length] , digest) ;
1001
1127
}
1128
+
1129
+ #[ test]
1130
+ #[ cfg( ossl300) ]
1131
+ fn set_digest ( ) {
1132
+ let key1 =
1133
+ EcKey :: generate ( & EcGroup :: from_curve_name ( Nid :: X9_62_PRIME256V1 ) . unwrap ( ) ) . unwrap ( ) ;
1134
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1135
+
1136
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1137
+ ctx. sign_init ( ) . unwrap ( ) ;
1138
+ ctx. set_digest ( MessageDigest :: sha224 ( ) ) . unwrap ( ) ;
1139
+ let digest_name = ctx. digest ( ) . unwrap ( ) . unwrap ( ) . type_ ( ) ;
1140
+ assert_eq ! ( digest_name, MessageDigest :: sha224( ) . type_( ) ) ;
1141
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1142
+ }
1143
+
1144
+ #[ test]
1145
+ #[ cfg( ossl320) ]
1146
+ fn set_nonce_type ( ) {
1147
+ let key1 =
1148
+ EcKey :: generate ( & EcGroup :: from_curve_name ( Nid :: X9_62_PRIME256V1 ) . unwrap ( ) ) . unwrap ( ) ;
1149
+ let key1 = PKey :: from_ec_key ( key1) . unwrap ( ) ;
1150
+
1151
+ let mut ctx = PkeyCtx :: new ( & key1) . unwrap ( ) ;
1152
+ ctx. sign_init ( ) . unwrap ( ) ;
1153
+ ctx. set_nonce_type ( NonceType :: DETERMINISTIC_K ) . unwrap ( ) ;
1154
+ let nonce_type = ctx. nonce_type ( ) . unwrap ( ) ;
1155
+ assert_eq ! ( nonce_type, NonceType :: DETERMINISTIC_K ) ;
1156
+ assert ! ( ErrorStack :: get( ) . errors( ) . is_empty( ) ) ;
1157
+ }
1002
1158
}
0 commit comments