diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 2dd278c2..3540a25e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -978,6 +978,25 @@ OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl, // before TLS 1.2. #define SSL_SIGN_RSA_PKCS1_MD5_SHA1 0xff01 +// SSL_get_signature_algorithm_name returns a human-readable name for |sigalg|, +// or NULL if unknown. If |include_curve| is one, the curve for ECDSA algorithms +// is included as in TLS 1.3. Otherwise, it is excluded as in TLS 1.2. +OPENSSL_EXPORT const char *SSL_get_signature_algorithm_name(uint16_t sigalg, + int include_curve); + +// SSL_get_signature_algorithm_key_type returns the key type associated with +// |sigalg| as an |EVP_PKEY_*| constant or |EVP_PKEY_NONE| if unknown. +OPENSSL_EXPORT int SSL_get_signature_algorithm_key_type(uint16_t sigalg); + +// SSL_get_signature_algorithm_digest returns the digest function associated +// with |sigalg| or |NULL| if |sigalg| has no prehash (Ed25519) or is unknown. +OPENSSL_EXPORT const EVP_MD *SSL_get_signature_algorithm_digest( + uint16_t sigalg); + +// SSL_is_signature_algorithm_rsa_pss returns one if |sigalg| is an RSA-PSS +// signature algorithm and zero otherwise. +OPENSSL_EXPORT int SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg); + // SSL_CTX_set_signing_algorithm_prefs configures |ctx| to use |prefs| as the // preference list when signing with |ctx|'s private key. It returns one on // success and zero on error. |prefs| should not include the internal-only value diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc index b00613d0..da037d73 100644 --- a/ssl/ssl_privkey.cc +++ b/ssl/ssl_privkey.cc @@ -438,6 +438,56 @@ void SSL_CTX_set_private_key_method(SSL_CTX *ctx, ctx->cert->key_method = key_method; } +const char *SSL_get_signature_algorithm_name(uint16_t sigalg, + int include_curve) { + switch (sigalg) { + case SSL_SIGN_RSA_PKCS1_SHA1: + return "rsa_pkcs1_sha1"; + case SSL_SIGN_RSA_PKCS1_SHA256: + return "rsa_pkcs1_sha256"; + case SSL_SIGN_RSA_PKCS1_SHA384: + return "rsa_pkcs1_sha384"; + case SSL_SIGN_RSA_PKCS1_SHA512: + return "rsa_pkcs1_sha512"; + case SSL_SIGN_ECDSA_SHA1: + return "ecdsa_sha1"; + case SSL_SIGN_ECDSA_SECP256R1_SHA256: + return include_curve ? "ecdsa_secp256r1_sha256" : "ecdsa_sha256"; + case SSL_SIGN_ECDSA_SECP384R1_SHA384: + return include_curve ? "ecdsa_secp384r1_sha384" : "ecdsa_sha384"; + case SSL_SIGN_ECDSA_SECP521R1_SHA512: + return include_curve ? "ecdsa_secp521r1_sha512" : "ecdsa_sha512"; + case SSL_SIGN_RSA_PSS_SHA256: + return "rsa_pss_sha256"; + case SSL_SIGN_RSA_PSS_SHA384: + return "rsa_pss_sha384"; + case SSL_SIGN_RSA_PSS_SHA512: + return "rsa_pss_sha512"; + case SSL_SIGN_ED25519: + return "ed25519"; + default: + return NULL; + } +} + +int SSL_get_signature_algorithm_key_type(uint16_t sigalg) { + const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg); + return alg != nullptr ? alg->pkey_type : EVP_PKEY_NONE; +} + +const EVP_MD *SSL_get_signature_algorithm_digest(uint16_t sigalg) { + const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg); + if (alg == nullptr || alg->digest_func == nullptr) { + return nullptr; + } + return alg->digest_func(); +} + +int SSL_is_signature_algorithm_rsa_pss(uint16_t sigalg) { + const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg); + return alg != nullptr && alg->is_rsa_pss; +} + static int set_algorithm_prefs(uint16_t **out_prefs, size_t *out_num_prefs, const uint16_t *prefs, size_t num_prefs) { OPENSSL_free(*out_prefs); diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 1600b57c..82888780 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc @@ -3822,6 +3822,31 @@ TEST(SSLTest, ShutdownIgnoresTickets) { EXPECT_EQ(1, SSL_shutdown(client.get())); } +TEST(SSLTest, SignatureAlgorithmProperties) { + EXPECT_EQ(EVP_PKEY_NONE, SSL_get_signature_algorithm_key_type(0x1234)); + EXPECT_EQ(nullptr, SSL_get_signature_algorithm_digest(0x1234)); + EXPECT_FALSE(SSL_is_signature_algorithm_rsa_pss(0x1234)); + + EXPECT_EQ(EVP_PKEY_RSA, + SSL_get_signature_algorithm_key_type(SSL_SIGN_RSA_PKCS1_MD5_SHA1)); + EXPECT_EQ(EVP_md5_sha1(), + SSL_get_signature_algorithm_digest(SSL_SIGN_RSA_PKCS1_MD5_SHA1)); + EXPECT_FALSE(SSL_is_signature_algorithm_rsa_pss(SSL_SIGN_RSA_PKCS1_MD5_SHA1)); + + EXPECT_EQ(EVP_PKEY_EC, SSL_get_signature_algorithm_key_type( + SSL_SIGN_ECDSA_SECP256R1_SHA256)); + EXPECT_EQ(EVP_sha256(), SSL_get_signature_algorithm_digest( + SSL_SIGN_ECDSA_SECP256R1_SHA256)); + EXPECT_FALSE( + SSL_is_signature_algorithm_rsa_pss(SSL_SIGN_ECDSA_SECP256R1_SHA256)); + + EXPECT_EQ(EVP_PKEY_RSA, + SSL_get_signature_algorithm_key_type(SSL_SIGN_RSA_PSS_SHA384)); + EXPECT_EQ(EVP_sha384(), + SSL_get_signature_algorithm_digest(SSL_SIGN_RSA_PSS_SHA384)); + EXPECT_TRUE(SSL_is_signature_algorithm_rsa_pss(SSL_SIGN_RSA_PSS_SHA384)); +} + // TODO(davidben): Convert this file to GTest properly. TEST(SSLTest, AllTests) { if (!TestSSL_SESSIONEncoding(kOpenSSLSession) || diff --git a/tool/transport_common.cc b/tool/transport_common.cc index a7c2b36a..1a806784 100644 --- a/tool/transport_common.cc +++ b/tool/transport_common.cc @@ -234,38 +234,6 @@ bool VersionFromString(uint16_t *out_version, const std::string &version) { return false; } -static const char *SignatureAlgorithmToString(uint16_t version, uint16_t sigalg) { - const bool is_tls12 = version == TLS1_2_VERSION || version == DTLS1_2_VERSION; - switch (sigalg) { - case SSL_SIGN_RSA_PKCS1_SHA1: - return "rsa_pkcs1_sha1"; - case SSL_SIGN_RSA_PKCS1_SHA256: - return "rsa_pkcs1_sha256"; - case SSL_SIGN_RSA_PKCS1_SHA384: - return "rsa_pkcs1_sha384"; - case SSL_SIGN_RSA_PKCS1_SHA512: - return "rsa_pkcs1_sha512"; - case SSL_SIGN_ECDSA_SHA1: - return "ecdsa_sha1"; - case SSL_SIGN_ECDSA_SECP256R1_SHA256: - return is_tls12 ? "ecdsa_sha256" : "ecdsa_secp256r1_sha256"; - case SSL_SIGN_ECDSA_SECP384R1_SHA384: - return is_tls12 ? "ecdsa_sha384" : "ecdsa_secp384r1_sha384"; - case SSL_SIGN_ECDSA_SECP521R1_SHA512: - return is_tls12 ? "ecdsa_sha512" : "ecdsa_secp521r1_sha512"; - case SSL_SIGN_RSA_PSS_SHA256: - return "rsa_pss_sha256"; - case SSL_SIGN_RSA_PSS_SHA384: - return "rsa_pss_sha384"; - case SSL_SIGN_RSA_PSS_SHA512: - return "rsa_pss_sha512"; - case SSL_SIGN_ED25519: - return "ed25519"; - default: - return "(unknown)"; - } -} - void PrintConnectionInfo(BIO *bio, const SSL *ssl) { const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); @@ -280,7 +248,8 @@ void PrintConnectionInfo(BIO *bio, const SSL *ssl) { uint16_t sigalg = SSL_get_peer_signature_algorithm(ssl); if (sigalg != 0) { BIO_printf(bio, " Signature algorithm: %s\n", - SignatureAlgorithmToString(SSL_version(ssl), sigalg)); + SSL_get_signature_algorithm_name( + sigalg, SSL_version(ssl) != TLS1_2_VERSION)); } BIO_printf(bio, " Secure renegotiation: %s\n", SSL_get_secure_renegotiation_support(ssl) ? "yes" : "no");