Introduce SSL_get_signature_algorithm_used. Change-Id: Ifed5f5ef022a8c0d6bd57d196f9b4c308ca4f213 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/95087 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: David Benjamin <davidben@google.com> Commit-Queue: James Buckland <jbuckland@google.com>
diff --git a/include/openssl/prefix_symbols.h b/include/openssl/prefix_symbols.h index 23a98ae..c25242d 100644 --- a/include/openssl/prefix_symbols.h +++ b/include/openssl/prefix_symbols.h
@@ -2254,6 +2254,7 @@ #pragma redefine_extname SSL_get_signature_algorithm_digest BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_signature_algorithm_digest) #pragma redefine_extname SSL_get_signature_algorithm_key_type BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_signature_algorithm_key_type) #pragma redefine_extname SSL_get_signature_algorithm_name BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_signature_algorithm_name) +#pragma redefine_extname SSL_get_signature_algorithm_used BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_signature_algorithm_used) #pragma redefine_extname SSL_get_srtp_profiles BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_srtp_profiles) #pragma redefine_extname SSL_get_ticket_age_skew BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_ticket_age_skew) #pragma redefine_extname SSL_get_tls_channel_id BORINGSSL_ADD_USER_LABEL_AND_PREFIX(SSL_get_tls_channel_id) @@ -5367,6 +5368,7 @@ #define SSL_get_signature_algorithm_digest BORINGSSL_ADD_PREFIX(SSL_get_signature_algorithm_digest) #define SSL_get_signature_algorithm_key_type BORINGSSL_ADD_PREFIX(SSL_get_signature_algorithm_key_type) #define SSL_get_signature_algorithm_name BORINGSSL_ADD_PREFIX(SSL_get_signature_algorithm_name) +#define SSL_get_signature_algorithm_used BORINGSSL_ADD_PREFIX(SSL_get_signature_algorithm_used) #define SSL_get_srtp_profiles BORINGSSL_ADD_PREFIX(SSL_get_srtp_profiles) #define SSL_get_ticket_age_skew BORINGSSL_ADD_PREFIX(SSL_get_ticket_age_skew) #define SSL_get_tls_channel_id BORINGSSL_ADD_PREFIX(SSL_get_tls_channel_id)
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 1a2ac58..055b3e0 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -5467,6 +5467,17 @@ OPENSSL_EXPORT size_t SSL_get_server_random(const SSL *ssl, uint8_t *out, size_t max_out); +// SSL_get_signature_algorithm_used returns the signature algorithm that |ssl| +// used, or will use, to generate a signature in the current handshake. If not +// applicable (e.g. if |ssl| did not authenticate itself with a certificate), it +// returns zero. +// +// This function only returns a value during the handshake. After the handshake +// is complete, the value is discarded. If needed after the handshake, callers +// may save the value at |SSL_CB_HANDSHAKE_DONE| with +// |SSL_CTX_set_info_callback|. +OPENSSL_EXPORT uint16_t SSL_get_signature_algorithm_used(const SSL *ssl); + // SSL_get_pending_cipher returns the cipher suite for the current handshake or // NULL if one has not been negotiated yet or there is no pending handshake. OPENSSL_EXPORT const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl);
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index a878c9c..89702ea 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc
@@ -3121,6 +3121,14 @@ return max_out; } +uint16_t SSL_get_signature_algorithm_used(const SSL *ssl) { + SSL_HANDSHAKE *hs = ssl->s3->hs.get(); + if (hs == nullptr) { + return 0; + } + return hs->signature_algorithm; +} + const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl) { SSL_HANDSHAKE *hs = ssl->s3->hs.get(); if (hs == nullptr) {
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 7a6da95..a876718 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc
@@ -11646,5 +11646,59 @@ } #endif // OPENSSL_THREADS +static uint16_t g_client_sigalg_used = 0; +static uint16_t g_server_sigalg_used = 0; + +static void SignatureAlgorithmUsedInfoCallback(const SSL *ssl, int type, + int value) { + if (type == SSL_CB_HANDSHAKE_DONE) { + if (SSL_is_server(ssl)) { + g_server_sigalg_used = SSL_get_signature_algorithm_used(ssl); + } else { + g_client_sigalg_used = SSL_get_signature_algorithm_used(ssl); + } + } +} + +TEST(SSLTest, SignatureAlgorithmUsed) { + g_client_sigalg_used = 0; + g_server_sigalg_used = 0; + + bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method())); + bssl::UniquePtr<SSL_CTX> server_ctx( + CreateContextWithTestCertificate(TLS_method())); + ASSERT_TRUE(client_ctx); + ASSERT_TRUE(server_ctx); + + // By setting a single signature algorithm, we force the handshake to use + // that algorithm, and we can check that it is reported as the signature + // algorithm used. + const uint16_t kPref = SSL_SIGN_RSA_PSS_RSAE_SHA384; + static const uint16_t kPrefs[] = {kPref}; + ASSERT_TRUE(SSL_CTX_set_signing_algorithm_prefs( + server_ctx.get(), kPrefs, std::size(kPrefs))); + ASSERT_TRUE(SSL_CTX_set_signing_algorithm_prefs( + client_ctx.get(), kPrefs, std::size(kPrefs))); + + SSL_CTX_set_info_callback(client_ctx.get(), + SignatureAlgorithmUsedInfoCallback); + SSL_CTX_set_info_callback(server_ctx.get(), + SignatureAlgorithmUsedInfoCallback); + + bssl::UniquePtr<SSL> client, server; + ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(), + server_ctx.get())); + + EXPECT_EQ(g_server_sigalg_used, kPref); + // There is no client signature algorithm. + EXPECT_EQ(g_client_sigalg_used, 0u); + + // After the handshake completes, the handshake object is reset, so the API + // returns 0. + EXPECT_EQ(SSL_get_signature_algorithm_used(client.get()), 0u); + EXPECT_EQ(SSL_get_signature_algorithm_used(server.get()), 0u); +} + } // namespace BSSL_NAMESPACE_END +