@@ -36,8 +36,7 @@ VALUE cSSLSocket;
3636static VALUE eSSLErrorWaitReadable ;
3737static VALUE eSSLErrorWaitWritable ;
3838
39- static ID id_call , ID_callback_state , id_tmp_dh_callback ,
40- id_npn_protocols_encoded , id_each ;
39+ static ID id_call , ID_callback_state , id_npn_protocols_encoded , id_each ;
4140static VALUE sym_exception , sym_wait_readable , sym_wait_writable ;
4241
4342static ID id_i_cert_store , id_i_ca_file , id_i_ca_path , id_i_verify_mode ,
@@ -47,7 +46,7 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode,
4746 id_i_session_id_context , id_i_session_get_cb , id_i_session_new_cb ,
4847 id_i_session_remove_cb , id_i_npn_select_cb , id_i_npn_protocols ,
4948 id_i_alpn_select_cb , id_i_alpn_protocols , id_i_servername_cb ,
50- id_i_verify_hostname , id_i_keylog_cb ;
49+ id_i_verify_hostname , id_i_keylog_cb , id_i_tmp_dh_callback ;
5150static ID id_i_io , id_i_context , id_i_hostname ;
5251
5352static int ossl_ssl_ex_ptr_idx ;
@@ -90,6 +89,7 @@ ossl_sslctx_s_alloc(VALUE klass)
9089 ossl_raise (eSSLError , "SSL_CTX_new" );
9190 }
9291 SSL_CTX_set_mode (ctx , mode );
92+ SSL_CTX_set_dh_auto (ctx , 1 );
9393 RTYPEDDATA_DATA (obj ) = ctx ;
9494 SSL_CTX_set_ex_data (ctx , ossl_sslctx_ex_ptr_idx , (void * )obj );
9595
@@ -133,8 +133,6 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
133133#if !defined(OPENSSL_NO_DH )
134134struct tmp_dh_callback_args {
135135 VALUE ssl_obj ;
136- ID id ;
137- int type ;
138136 int is_export ;
139137 int keylength ;
140138};
@@ -143,48 +141,36 @@ static VALUE
143141ossl_call_tmp_dh_callback (VALUE arg )
144142{
145143 struct tmp_dh_callback_args * args = (struct tmp_dh_callback_args * )arg ;
146- VALUE cb , dh ;
147- EVP_PKEY * pkey ;
144+ VALUE ctx_obj , cb , obj ;
145+ const DH * dh ;
148146
149- cb = rb_funcall (args -> ssl_obj , args -> id , 0 );
147+ ctx_obj = rb_attr_get (args -> ssl_obj , id_i_context );
148+ cb = rb_attr_get (ctx_obj , id_i_tmp_dh_callback );
150149 if (NIL_P (cb ))
151- return (VALUE )NULL ;
152- dh = rb_funcall (cb , id_call , 3 , args -> ssl_obj , INT2NUM (args -> is_export ),
153- INT2NUM (args -> keylength ));
154- pkey = GetPKeyPtr (dh );
155- if (EVP_PKEY_base_id (pkey ) != args -> type )
156- return (VALUE )NULL ;
150+ return (VALUE )NULL ;
151+
152+ obj = rb_funcall (cb , id_call , 3 , args -> ssl_obj , INT2NUM (args -> is_export ),
153+ INT2NUM (args -> keylength ));
154+ // TODO: We should riase if obj is not DH
155+ dh = EVP_PKEY_get0_DH (GetPKeyPtr (obj ));
156+ if (!dh )
157+ ossl_clear_error ();
157158
158- return (VALUE )pkey ;
159+ return (VALUE )dh ;
159160}
160- #endif
161161
162- #if !defined(OPENSSL_NO_DH )
163162static DH *
164163ossl_tmp_dh_callback (SSL * ssl , int is_export , int keylength )
165164{
166- VALUE rb_ssl ;
167- EVP_PKEY * pkey ;
168- struct tmp_dh_callback_args args ;
169165 int state ;
170-
171- rb_ssl = (VALUE )SSL_get_ex_data (ssl , ossl_ssl_ex_ptr_idx );
172- args .ssl_obj = rb_ssl ;
173- args .id = id_tmp_dh_callback ;
174- args .is_export = is_export ;
175- args .keylength = keylength ;
176- args .type = EVP_PKEY_DH ;
177-
178- pkey = (EVP_PKEY * )rb_protect (ossl_call_tmp_dh_callback ,
179- (VALUE )& args , & state );
166+ VALUE rb_ssl = (VALUE )SSL_get_ex_data (ssl , ossl_ssl_ex_ptr_idx );
167+ struct tmp_dh_callback_args args = {rb_ssl , is_export , keylength };
168+ VALUE ret = rb_protect (ossl_call_tmp_dh_callback , (VALUE )& args , & state );
180169 if (state ) {
181170 rb_ivar_set (rb_ssl , ID_callback_state , INT2NUM (state ));
182171 return NULL ;
183172 }
184- if (!pkey )
185- return NULL ;
186-
187- return (DH * )EVP_PKEY_get0_DH (pkey );
173+ return (DH * )ret ;
188174}
189175#endif /* OPENSSL_NO_DH */
190176
@@ -703,7 +689,10 @@ ossl_sslctx_setup(VALUE self)
703689 GetSSLCTX (self , ctx );
704690
705691#if !defined(OPENSSL_NO_DH )
706- SSL_CTX_set_tmp_dh_callback (ctx , ossl_tmp_dh_callback );
692+ if (!NIL_P (rb_attr_get (self , id_i_tmp_dh_callback ))) {
693+ SSL_CTX_set_tmp_dh_callback (ctx , ossl_tmp_dh_callback );
694+ SSL_CTX_set_dh_auto (ctx , 0 );
695+ }
707696#endif
708697
709698#if !defined(OPENSSL_IS_AWSLC ) /* AWS-LC has no support for TLS 1.3 PHA. */
@@ -1148,7 +1137,7 @@ ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
11481137 * contained in the key object, if any, are ignored. The server will always
11491138 * generate a new key pair for each handshake.
11501139 *
1151- * Added in version 3.0. See also the man page SSL_set0_tmp_dh_pkey (3).
1140+ * Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey (3).
11521141 *
11531142 * Example:
11541143 * ctx = OpenSSL::SSL::SSLContext.new
@@ -1169,7 +1158,7 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
11691158 if (EVP_PKEY_base_id (pkey ) != EVP_PKEY_DH )
11701159 rb_raise (eSSLError , "invalid pkey type %s (expected DH)" ,
11711160 OBJ_nid2sn (EVP_PKEY_base_id (pkey )));
1172- #ifdef HAVE_SSL_SET0_TMP_DH_PKEY
1161+ #ifdef HAVE_SSL_CTX_SET0_TMP_DH_PKEY
11731162 if (!SSL_CTX_set0_tmp_dh_pkey (ctx , pkey ))
11741163 ossl_raise (eSSLError , "SSL_CTX_set0_tmp_dh_pkey" );
11751164 EVP_PKEY_up_ref (pkey );
@@ -1178,6 +1167,9 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
11781167 ossl_raise (eSSLError , "SSL_CTX_set_tmp_dh" );
11791168#endif
11801169
1170+ // Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc()
1171+ SSL_CTX_set_dh_auto (ctx , 0 );
1172+
11811173 return arg ;
11821174}
11831175#endif
@@ -2865,6 +2857,23 @@ Init_ossl_ssl(void)
28652857 */
28662858 rb_attr (cSSLContext , rb_intern_const ("client_cert_cb" ), 1 , 1 , Qfalse );
28672859
2860+ #ifndef OPENSSL_NO_DH
2861+ /*
2862+ * A callback invoked when DH parameters are required for ephemeral DH key
2863+ * exchange.
2864+ *
2865+ * The callback is invoked with the SSLSocket, a
2866+ * flag indicating the use of an export cipher and the keylength
2867+ * required.
2868+ *
2869+ * The callback must return an OpenSSL::PKey::DH instance of the correct
2870+ * key length.
2871+ *
2872+ * <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
2873+ */
2874+ rb_attr (cSSLContext , rb_intern_const ("tmp_dh_callback" ), 1 , 1 , Qfalse );
2875+ #endif
2876+
28682877 /*
28692878 * Sets the context in which a session can be reused. This allows
28702879 * sessions for multiple applications to be distinguished, for example, by
@@ -3258,7 +3267,6 @@ Init_ossl_ssl(void)
32583267 sym_wait_readable = ID2SYM (rb_intern_const ("wait_readable" ));
32593268 sym_wait_writable = ID2SYM (rb_intern_const ("wait_writable" ));
32603269
3261- id_tmp_dh_callback = rb_intern_const ("tmp_dh_callback" );
32623270 id_npn_protocols_encoded = rb_intern_const ("npn_protocols_encoded" );
32633271 id_each = rb_intern_const ("each" );
32643272
@@ -3289,6 +3297,7 @@ Init_ossl_ssl(void)
32893297 DefIVarID (servername_cb );
32903298 DefIVarID (verify_hostname );
32913299 DefIVarID (keylog_cb );
3300+ DefIVarID (tmp_dh_callback );
32923301
32933302 DefIVarID (io );
32943303 DefIVarID (context );
0 commit comments