Skip to content

ssl: add SSLSocket#sigalg, #peer_sigalg, #group #908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ext/openssl/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,15 @@ def find_openssl_library
have_func("EVP_PKEY_eq(NULL, NULL)", evp_h)
have_func("EVP_PKEY_dup(NULL)", evp_h)

# added in 3.2.0
have_func("SSL_get0_group_name(NULL)", ssl_h)

# added in 3.4.0
have_func("TS_VERIFY_CTX_set0_certs(NULL, NULL)", ts_h)

# added in 3.5.0
have_func("SSL_get0_peer_signature_name(NULL, NULL)", ssl_h)

Logging::message "=== Checking done. ===\n"

# Append flags from environment variables.
Expand Down
69 changes: 69 additions & 0 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2644,6 +2644,68 @@ ossl_ssl_tmp_key(VALUE self)
return Qnil;
return ossl_pkey_new(key);
}

#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
/*
* call-seq:
* ssl.sigalg => String or nil
*
* Returns the signature algorithm name, the IANA name of the signature scheme
* used by the local to sign the TLS handshake.
*/
static VALUE
ossl_ssl_get_sigalg(VALUE self)
{
SSL *ssl;
const char *name;

GetSSL(self, ssl);
if (!SSL_get0_signature_name(ssl, &name))
return Qnil;
return rb_str_new_cstr(name);
}

/*
* call-seq:
* ssl.peer_sigalg => String or nil
*
* Returns the signature algorithm name, the IANA name of the signature scheme
* used by the peer to sign the TLS handshake.
*/
static VALUE
ossl_ssl_get_peer_sigalg(VALUE self)
{
SSL *ssl;
const char *name;

GetSSL(self, ssl);
if (!SSL_get0_peer_signature_name(ssl, &name))
return Qnil;
return rb_str_new_cstr(name);
}
#endif

#ifdef HAVE_SSL_GET0_GROUP_NAME
/*
* call-seq:
* ssl.group => String or nil
*
* Returns the name of the group that was used for the key agreement of the
* current TLS session establishment.
*/
static VALUE
ossl_ssl_get_group(VALUE self)
{
SSL *ssl;
const char *name;

GetSSL(self, ssl);
if (!(name = SSL_get0_group_name(ssl)))
return Qnil;
return rb_str_new_cstr(name);
}
#endif

#endif /* !defined(OPENSSL_NO_SOCK) */

void
Expand Down Expand Up @@ -3067,6 +3129,13 @@ Init_ossl_ssl(void)
# ifdef OSSL_USE_NEXTPROTONEG
rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
# endif
#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
rb_define_method(cSSLSocket, "sigalg", ossl_ssl_get_sigalg, 0);
rb_define_method(cSSLSocket, "peer_sigalg", ossl_ssl_get_peer_sigalg, 0);
#endif
#ifdef HAVE_SSL_GET0_GROUP_NAME
rb_define_method(cSSLSocket, "group", ossl_ssl_get_group, 0);
#endif

rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE));
rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER));
Expand Down
25 changes: 25 additions & 0 deletions test/openssl/test_ssl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2041,6 +2041,27 @@ def test_client_sigalgs
end
end

def test_get_sigalg
# SSL_get0_signature_name() not supported
# SSL_get0_peer_signature_name() not supported
return unless openssl?(3, 5, 0)

server_proc = -> (ctx, ssl) {
assert_equal('rsa_pss_rsae_sha256', ssl.sigalg)
assert_nil(ssl.peer_sigalg)

readwrite_loop(ctx, ssl)
}
start_server(server_proc: server_proc) do |port|
cli_ctx = OpenSSL::SSL::SSLContext.new
server_connect(port, cli_ctx) do |ssl|
assert_nil(ssl.sigalg)
assert_equal('rsa_pss_rsae_sha256', ssl.peer_sigalg)
ssl.puts "abc"; ssl.gets
end
end
end

def test_connect_works_when_setting_dh_callback_to_nil
omit "AWS-LC does not support DHE ciphersuites" if aws_lc?

Expand Down Expand Up @@ -2088,6 +2109,8 @@ def test_set_groups_tls12
server_connect(port, ctx) { |ssl|
cs = ssl.cipher[0]
assert_match (/\AECDH/), cs
# SSL_get0_group_name() is supported on OpenSSL 3.2 or later.
assert_equal "secp384r1", ssl.group if openssl?(3, 2, 0)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
Expand Down Expand Up @@ -2127,6 +2150,8 @@ def test_set_groups_tls13

server_connect(port, ctx) { |ssl|
assert_equal "TLSv1.3", ssl.ssl_version
# SSL_get0_group_name() is supported on OpenSSL 3.2 or later.
assert_equal "secp384r1", ssl.group if openssl?(3, 2, 0)
assert_equal "secp384r1", ssl.tmp_key.group.curve_name
ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
Expand Down
Loading