Add helper functions for SSL_SIGN_*.
We end up writing these switch cases everywhere. Let consumers decompose
these a bit. The original thought was folks should write switch-cases so
they handle everything they support, but that's a pain. As long as
algorithm preferences are always configured, we can still add new
dimensions because folks won't be asked to sign algorithms that depend
on dimensions they don't understand.
Change-Id: I3dd7f067f2c55212f0201876546bc70fee032bcf
Reviewed-on: https://boringssl-review.googlesource.com/22524
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
Reviewed-by: Steven Valdez <svaldez@google.com>
diff --git a/ssl/ssl_privkey.cc b/ssl/ssl_privkey.cc
index b00613d..da037d7 100644
--- a/ssl/ssl_privkey.cc
+++ b/ssl/ssl_privkey.cc
@@ -438,6 +438,56 @@
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 1600b57..8288878 100644
--- a/ssl/ssl_test.cc
+++ b/ssl/ssl_test.cc
@@ -3822,6 +3822,31 @@
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) ||