Add a function to tell if an algorithm is FIPS approved.

Change-Id: I934376ead1bc3e4e8349540c4a3da99cd0b49181
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/51985
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/crypto_test.cc b/crypto/crypto_test.cc
index 7f15a23..228aaf2 100644
--- a/crypto/crypto_test.cc
+++ b/crypto/crypto_test.cc
@@ -138,3 +138,17 @@
 }
 
 #endif  // BORINGSSL_FIPS_COUNTERS
+
+TEST(Crypto, QueryAlgorithmStatus) {
+#if defined(BORINGSSL_FIPS)
+  const bool is_fips_build = true;
+#else
+  const bool is_fips_build = false;
+#endif
+
+  EXPECT_EQ(FIPS_query_algorithm_status("AES-GCM"), is_fips_build);
+  EXPECT_EQ(FIPS_query_algorithm_status("AES-ECB"), is_fips_build);
+
+  EXPECT_FALSE(FIPS_query_algorithm_status("FakeEncrypt"));
+  EXPECT_FALSE(FIPS_query_algorithm_status(""));
+}
diff --git a/crypto/fipsmodule/self_check/fips.c b/crypto/fipsmodule/self_check/fips.c
index d55c493..2b9927f 100644
--- a/crypto/fipsmodule/self_check/fips.c
+++ b/crypto/fipsmodule/self_check/fips.c
@@ -28,6 +28,41 @@
 
 int FIPS_mode_set(int on) { return on == FIPS_mode(); }
 
+int FIPS_query_algorithm_status(const char *algorithm) {
+#if defined(BORINGSSL_FIPS)
+  static const char kApprovedAlgorithms[][13] = {
+    "AES-CBC",
+    "AES-CCM",
+    "AES-CTR",
+    "AES-ECB",
+    "AES-GCM",
+    "AES-KW",
+    "AES-KWP",
+    "ctrDRBG",
+    "ECC-SSC",
+    "ECDSA-sign",
+    "ECDSA-verify",
+    "FFC-SSC",
+    "HMAC",
+    "RSA-sign",
+    "RSA-verify",
+    "SHA-1",
+    "SHA2-224",
+    "SHA2-256",
+    "SHA2-384",
+    "SHA2-512",
+    "SHA2-512/256",
+  };
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kApprovedAlgorithms); i++) {
+    if (strcmp(algorithm, kApprovedAlgorithms[i]) == 0) {
+      return 1;
+    }
+  }
+#endif  // BORINGSSL_FIPS
+
+  return 0;
+}
+
 #if defined(BORINGSSL_FIPS_COUNTERS)
 
 size_t FIPS_read_counter(enum fips_counter_t counter) {
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index 0824b93..ce1e5ce 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -172,6 +172,10 @@
 // |BORINGSSL_FIPS| and zero otherwise.
 OPENSSL_EXPORT int FIPS_mode_set(int on);
 
+// FIPS_query_algorithm_status returns one if |algorithm| is FIPS validated in
+// the current BoringSSL and zero otherwise.
+OPENSSL_EXPORT int FIPS_query_algorithm_status(const char *algorithm);
+
 
 #if defined(__cplusplus)
 }  // extern C