SSL_alert_from_verify_result: expose.
This function maps |X509_V_ERR_*| to SSL alarm codes. It's used
internally when certs are verified with X509_verify_cert(), and is
helpful to callers who want to call that function, but who also want
to report its errors in a less implementation-dependent way.
Change-Id: I2900cce2eb631489f0947c317beafafd3ea57a75
Reviewed-on: https://boringssl-review.googlesource.com/24564
Commit-Queue: Matt Braithwaite <mab@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 1a65e2b..6ab1682 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2380,6 +2380,11 @@
// either |X509_V_OK| or a |X509_V_ERR_*| value.
OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl);
+// SSL_alert_from_verify_result returns the SSL alert code, such as
+// |SSL_AD_CERTIFICATE_EXPIRED|, that corresponds to an |X509_V_ERR_*| value.
+// The return value is always an alert, even when |result| is |X509_V_OK|.
+OPENSSL_EXPORT int SSL_alert_from_verify_result(long result);
+
// SSL_get_ex_data_X509_STORE_CTX_idx returns the ex_data index used to look up
// the |SSL| associated with an |X509_STORE_CTX| in the verify callback.
OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void);
diff --git a/ssl/ssl_x509.cc b/ssl/ssl_x509.cc
index 2b7ba83..5c0365f 100644
--- a/ssl/ssl_x509.cc
+++ b/ssl/ssl_x509.cc
@@ -354,66 +354,6 @@
session->x509_chain_without_leaf = NULL;
}
-static int ssl_verify_alarm_type(long type) {
- switch (type) {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- case X509_V_ERR_UNABLE_TO_GET_CRL:
- case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
- return SSL_AD_UNKNOWN_CA;
-
- case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
- case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
- case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
- case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_CRL_NOT_YET_VALID:
- case X509_V_ERR_CERT_UNTRUSTED:
- case X509_V_ERR_CERT_REJECTED:
- case X509_V_ERR_HOSTNAME_MISMATCH:
- case X509_V_ERR_EMAIL_MISMATCH:
- case X509_V_ERR_IP_ADDRESS_MISMATCH:
- return SSL_AD_BAD_CERTIFICATE;
-
- case X509_V_ERR_CERT_SIGNATURE_FAILURE:
- case X509_V_ERR_CRL_SIGNATURE_FAILURE:
- return SSL_AD_DECRYPT_ERROR;
-
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_CRL_HAS_EXPIRED:
- return SSL_AD_CERTIFICATE_EXPIRED;
-
- case X509_V_ERR_CERT_REVOKED:
- return SSL_AD_CERTIFICATE_REVOKED;
-
- case X509_V_ERR_UNSPECIFIED:
- case X509_V_ERR_OUT_OF_MEM:
- case X509_V_ERR_INVALID_CALL:
- case X509_V_ERR_STORE_LOOKUP:
- return SSL_AD_INTERNAL_ERROR;
-
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
- case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
- case X509_V_ERR_CERT_CHAIN_TOO_LONG:
- case X509_V_ERR_PATH_LENGTH_EXCEEDED:
- case X509_V_ERR_INVALID_CA:
- return SSL_AD_UNKNOWN_CA;
-
- case X509_V_ERR_APPLICATION_VERIFICATION:
- return SSL_AD_HANDSHAKE_FAILURE;
-
- case X509_V_ERR_INVALID_PURPOSE:
- return SSL_AD_UNSUPPORTED_CERTIFICATE;
-
- default:
- return SSL_AD_CERTIFICATE_UNKNOWN;
- }
-}
-
static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
SSL *ssl,
uint8_t *out_alert) {
@@ -464,7 +404,7 @@
// If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result.
if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
- *out_alert = ssl_verify_alarm_type(ctx->error);
+ *out_alert = SSL_alert_from_verify_result(ctx->error);
return 0;
}
@@ -1297,3 +1237,63 @@
check_ssl_x509_method(ssl);
return set_cert_store(&ssl->cert->verify_store, store, 1);
}
+
+int SSL_alert_from_verify_result(long result) {
+ switch (result) {
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+ return SSL_AD_UNKNOWN_CA;
+
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ case X509_V_ERR_CERT_UNTRUSTED:
+ case X509_V_ERR_CERT_REJECTED:
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ case X509_V_ERR_EMAIL_MISMATCH:
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ return SSL_AD_BAD_CERTIFICATE;
+
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ return SSL_AD_DECRYPT_ERROR;
+
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ return SSL_AD_CERTIFICATE_EXPIRED;
+
+ case X509_V_ERR_CERT_REVOKED:
+ return SSL_AD_CERTIFICATE_REVOKED;
+
+ case X509_V_ERR_UNSPECIFIED:
+ case X509_V_ERR_OUT_OF_MEM:
+ case X509_V_ERR_INVALID_CALL:
+ case X509_V_ERR_STORE_LOOKUP:
+ return SSL_AD_INTERNAL_ERROR;
+
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ case X509_V_ERR_INVALID_CA:
+ return SSL_AD_UNKNOWN_CA;
+
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ return SSL_AD_HANDSHAKE_FAILURE;
+
+ case X509_V_ERR_INVALID_PURPOSE:
+ return SSL_AD_UNSUPPORTED_CERTIFICATE;
+
+ default:
+ return SSL_AD_CERTIFICATE_UNKNOWN;
+ }
+}