76c5f5cc8a
In the GN build, libchromiumcontent is no longer a distinct library, but merely a container for a set of scripts and patches. Maintaining those patches in a separate repository is tedious and error-prone, so merge them into the main repo. Once this is merged and GN is the default way to build Electron, the libchromiumcontent repository can be archived.
741 lines
28 KiB
Diff
741 lines
28 KiB
Diff
From 81d4909d00c3628453a8712bc331304bd01d8eaf Mon Sep 17 00:00:00 2001
|
|
From: David Benjamin <davidben@google.com>
|
|
Date: Thu, 10 May 2018 19:55:02 -0400
|
|
Subject: [PATCH] Implement legacy OCSP APIs for libssl.
|
|
|
|
Previously, we'd omitted OpenSSL's OCSP APIs because they depend on a
|
|
complex OCSP mechanism and encourage the the unreliable server behavior
|
|
that hampers using OCSP stapling to fix revocation today. (OCSP
|
|
responses should not be fetched on-demand on a callback. They should be
|
|
managed like other server credentials and refreshed eagerly, so
|
|
temporary CA outage does not translate to loss of OCSP.)
|
|
|
|
But most of the APIs are byte-oriented anyway, so they're easy to
|
|
support. Intentionally omit the one that takes a bunch of OCSP_RESPIDs.
|
|
|
|
The callback is benign on the client (an artifact of OpenSSL reading
|
|
OCSP and verifying certificates in the wrong order). On the server, it
|
|
encourages unreliability, but pyOpenSSL/cryptography.io depends on this.
|
|
Dcument that this is only for compatibility with legacy software.
|
|
|
|
Also tweak a few things for compatilibility. cryptography.io expects
|
|
SSL_CTX_set_read_ahead to return something, SSL_get_server_tmp_key's
|
|
signature was wrong, and cryptography.io tries to redefine
|
|
SSL_get_server_tmp_key if SSL_CTRL_GET_SERVER_TMP_KEY is missing.
|
|
|
|
Change-Id: I2f99711783456bfb7324e9ad972510be8a95e845
|
|
Reviewed-on: https://boringssl-review.googlesource.com/28404
|
|
Commit-Queue: David Benjamin <davidben@google.com>
|
|
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
|
|
Reviewed-by: Adam Langley <agl@google.com>
|
|
---
|
|
crypto/err/ssl.errordata | 1 +
|
|
include/openssl/ssl.h | 64 +++++++++++++--
|
|
include/openssl/tls1.h | 1 +
|
|
ssl/handshake.cc | 16 ++++
|
|
ssl/handshake_server.cc | 16 ++++
|
|
ssl/internal.h | 5 ++
|
|
ssl/ssl_lib.cc | 39 ++++++++-
|
|
ssl/test/bssl_shim.cc | 26 ++++++
|
|
ssl/test/runner/alert.go | 122 +++++++++++++--------------
|
|
ssl/test/runner/runner.go | 205 ++++++++++++++++++++++++++++++++++------------
|
|
ssl/test/test_config.cc | 4 +
|
|
ssl/test/test_config.h | 4 +
|
|
12 files changed, 381 insertions(+), 122 deletions(-)
|
|
|
|
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
|
|
index 7b63bc8..375df9a 100644
|
|
--- a/crypto/err/ssl.errordata
|
|
+++ b/crypto/err/ssl.errordata
|
|
@@ -108,6 +108,7 @@ SSL,266,NO_SHARED_GROUP
|
|
SSL,280,NO_SUPPORTED_VERSIONS_ENABLED
|
|
SSL,185,NULL_SSL_CTX
|
|
SSL,186,NULL_SSL_METHOD_PASSED
|
|
+SSL,289,OCSP_CB_ERROR
|
|
SSL,187,OLD_SESSION_CIPHER_NOT_RETURNED
|
|
SSL,268,OLD_SESSION_PRF_HASH_MISMATCH
|
|
SSL,188,OLD_SESSION_VERSION_NOT_RETURNED
|
|
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
|
|
index 35506f7..d46a5af 100644
|
|
--- a/include/openssl/ssl.h
|
|
+++ b/include/openssl/ssl.h
|
|
@@ -3715,14 +3715,14 @@ OPENSSL_EXPORT int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa);
|
|
// SSL_CTX_get_read_ahead returns zero.
|
|
OPENSSL_EXPORT int SSL_CTX_get_read_ahead(const SSL_CTX *ctx);
|
|
|
|
-// SSL_CTX_set_read_ahead does nothing.
|
|
-OPENSSL_EXPORT void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
|
|
+// SSL_CTX_set_read_ahead returns one.
|
|
+OPENSSL_EXPORT int SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
|
|
|
|
// SSL_get_read_ahead returns zero.
|
|
OPENSSL_EXPORT int SSL_get_read_ahead(const SSL *ssl);
|
|
|
|
-// SSL_set_read_ahead does nothing.
|
|
-OPENSSL_EXPORT void SSL_set_read_ahead(SSL *ssl, int yes);
|
|
+// SSL_set_read_ahead returns one.
|
|
+OPENSSL_EXPORT int SSL_set_read_ahead(SSL *ssl, int yes);
|
|
|
|
// SSL_renegotiate put an error on the error queue and returns zero.
|
|
OPENSSL_EXPORT int SSL_renegotiate(SSL *ssl);
|
|
@@ -3793,7 +3793,7 @@ OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_compression(SSL *ssl);
|
|
OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *ssl);
|
|
|
|
// SSL_get_server_tmp_key returns zero.
|
|
-OPENSSL_EXPORT int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
|
|
+OPENSSL_EXPORT int SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
|
|
|
|
// SSL_CTX_set_tmp_dh returns 1.
|
|
OPENSSL_EXPORT int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh);
|
|
@@ -4108,6 +4108,58 @@ extern "C++" OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
|
|
int id_len, int *out_copy));
|
|
#endif
|
|
|
|
+// SSL_set_tlsext_status_type configures a client to request OCSP stapling if
|
|
+// |type| is |TLSEXT_STATUSTYPE_ocsp| and disables it otherwise. It returns one
|
|
+// on success and zero if handshake configuration has already been shed.
|
|
+//
|
|
+// Use |SSL_enable_ocsp_stapling| instead.
|
|
+OPENSSL_EXPORT int SSL_set_tlsext_status_type(SSL *ssl, int type);
|
|
+
|
|
+// SSL_set_tlsext_status_ocsp_resp sets the OCSP response. It returns one on
|
|
+// success and zero on error. On success, |ssl| takes ownership of |resp|, which
|
|
+// must have been allocated by |OPENSSL_malloc|.
|
|
+//
|
|
+// Use |SSL_set_ocsp_response| instead.
|
|
+OPENSSL_EXPORT int SSL_set_tlsext_status_ocsp_resp(SSL *ssl, uint8_t *resp,
|
|
+ size_t resp_len);
|
|
+
|
|
+// SSL_get_tlsext_status_ocsp_resp sets |*out| to point to the OCSP response
|
|
+// from the server. It returns the length of the response. If there was no
|
|
+// response, it sets |*out| to NULL and returns zero.
|
|
+//
|
|
+// Use |SSL_get0_ocsp_response| instead.
|
|
+//
|
|
+// WARNING: the returned data is not guaranteed to be well formed.
|
|
+OPENSSL_EXPORT size_t SSL_get_tlsext_status_ocsp_resp(const SSL *ssl,
|
|
+ const uint8_t **out);
|
|
+
|
|
+// SSL_CTX_set_tlsext_status_cb configures the legacy OpenSSL OCSP callback and
|
|
+// returns one. Though the type signature is the same, this callback has
|
|
+// different behavior for client and server connections:
|
|
+//
|
|
+// For clients, the callback is called after certificate verification. It should
|
|
+// return one for success, zero for a bad OCSP response, and a negative number
|
|
+// for internal error. Instead, handle this as part of certificate verification.
|
|
+// (Historically, OpenSSL verified certificates just before parsing stapled OCSP
|
|
+// responses, but BoringSSL fixes this ordering. All server credentials are
|
|
+// available during verification.)
|
|
+//
|
|
+// Do not use this callback as a server. It is provided for compatibility
|
|
+// purposes only. For servers, it is called to configure server credentials. It
|
|
+// should return |SSL_TLSEXT_ERR_OK| on success, |SSL_TLSEXT_ERR_NOACK| to
|
|
+// ignore OCSP requests, or |SSL_TLSEXT_ERR_ALERT_FATAL| on error. It is usually
|
|
+// used to fetch OCSP responses on demand, which is not ideal. Instead, treat
|
|
+// OCSP responses like other server credentials, such as certificates or SCT
|
|
+// lists. Configure, store, and refresh them eagerly. This avoids downtime if
|
|
+// the CA's OCSP responder is briefly offline.
|
|
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
|
|
+ int (*callback)(SSL *ssl,
|
|
+ void *arg));
|
|
+
|
|
+// SSL_CTX_set_tlsext_status_arg sets additional data for
|
|
+// |SSL_CTX_set_tlsext_status_cb|'s callback and returns one.
|
|
+OPENSSL_EXPORT int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
|
|
+
|
|
|
|
// Private structures.
|
|
//
|
|
@@ -4285,6 +4337,7 @@ struct ssl_session_st {
|
|
#define SSL_CTRL_GET_NUM_RENEGOTIATIONS doesnt_exist
|
|
#define SSL_CTRL_GET_READ_AHEAD doesnt_exist
|
|
#define SSL_CTRL_GET_RI_SUPPORT doesnt_exist
|
|
+#define SSL_CTRL_GET_SERVER_TMP_KEY doesnt_exist
|
|
#define SSL_CTRL_GET_SESSION_REUSED doesnt_exist
|
|
#define SSL_CTRL_GET_SESS_CACHE_MODE doesnt_exist
|
|
#define SSL_CTRL_GET_SESS_CACHE_SIZE doesnt_exist
|
|
@@ -4698,6 +4751,7 @@ OPENSSL_EXPORT bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback);
|
|
#define SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI 285
|
|
#define SSL_R_SERVER_ECHOED_INVALID_SESSION_ID 286
|
|
#define SSL_R_PRIVATE_KEY_OPERATION_FAILED 287
|
|
+#define SSL_R_OCSP_CB_ERROR 289
|
|
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
|
|
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
|
|
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
|
|
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
|
|
index 3424f3d..7a05969 100644
|
|
--- a/include/openssl/tls1.h
|
|
+++ b/include/openssl/tls1.h
|
|
@@ -237,6 +237,7 @@ extern "C" {
|
|
#define TLSEXT_TYPE_dummy_pq_padding 54537
|
|
|
|
// status request value from RFC 3546
|
|
+#define TLSEXT_STATUSTYPE_nothing (-1)
|
|
#define TLSEXT_STATUSTYPE_ocsp 1
|
|
|
|
// ECPointFormat values from RFC 4492
|
|
diff --git a/ssl/handshake.cc b/ssl/handshake.cc
|
|
index 6432424..0a90b9f 100644
|
|
--- a/ssl/handshake.cc
|
|
+++ b/ssl/handshake.cc
|
|
@@ -356,6 +356,22 @@ enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) {
|
|
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
|
|
}
|
|
|
|
+ // Emulate OpenSSL's client OCSP callback. OpenSSL verifies certificates
|
|
+ // before it receives the OCSP, so it needs a second callback for OCSP.
|
|
+ if (ret == ssl_verify_ok && !ssl->server &&
|
|
+ hs->new_session->ocsp_response != nullptr &&
|
|
+ ssl->ctx->legacy_ocsp_callback != nullptr) {
|
|
+ int cb_ret =
|
|
+ ssl->ctx->legacy_ocsp_callback(ssl, ssl->ctx->legacy_ocsp_callback_arg);
|
|
+ if (cb_ret <= 0) {
|
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OCSP_CB_ERROR);
|
|
+ ssl_send_alert(ssl, SSL3_AL_FATAL,
|
|
+ cb_ret == 0 ? SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE
|
|
+ : SSL_AD_INTERNAL_ERROR);
|
|
+ ret = ssl_verify_invalid;
|
|
+ }
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/ssl/handshake_server.cc b/ssl/handshake_server.cc
|
|
index fa8a241..7a96767 100644
|
|
--- a/ssl/handshake_server.cc
|
|
+++ b/ssl/handshake_server.cc
|
|
@@ -534,6 +534,22 @@ static enum ssl_hs_wait_t do_select_certificate(SSL_HANDSHAKE *hs) {
|
|
return ssl_hs_error;
|
|
}
|
|
|
|
+ if (hs->ocsp_stapling_requested &&
|
|
+ ssl->ctx->legacy_ocsp_callback != nullptr) {
|
|
+ switch (ssl->ctx->legacy_ocsp_callback(
|
|
+ ssl, ssl->ctx->legacy_ocsp_callback_arg)) {
|
|
+ case SSL_TLSEXT_ERR_OK:
|
|
+ break;
|
|
+ case SSL_TLSEXT_ERR_NOACK:
|
|
+ hs->ocsp_stapling_requested = false;
|
|
+ break;
|
|
+ default:
|
|
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OCSP_CB_ERROR);
|
|
+ ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
|
+ return ssl_hs_error;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) {
|
|
// Jump to the TLS 1.3 state machine.
|
|
hs->state = state_tls13;
|
|
diff --git a/ssl/internal.h b/ssl/internal.h
|
|
index d13d5f2..1cdfb8e 100644
|
|
--- a/ssl/internal.h
|
|
+++ b/ssl/internal.h
|
|
@@ -2140,6 +2140,11 @@ struct SSLContext {
|
|
// session tickets.
|
|
const SSL_TICKET_AEAD_METHOD *ticket_aead_method;
|
|
|
|
+ // legacy_ocsp_callback implements an OCSP-related callback for OpenSSL
|
|
+ // compatibility.
|
|
+ int (*legacy_ocsp_callback)(SSL *ssl, void *arg);
|
|
+ void *legacy_ocsp_callback_arg;
|
|
+
|
|
// verify_sigalgs, if not empty, is the set of signature algorithms
|
|
// accepted from the peer in decreasing order of preference.
|
|
uint16_t *verify_sigalgs;
|
|
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc
|
|
index 9f56d54..50608e9 100644
|
|
--- a/ssl/ssl_lib.cc
|
|
+++ b/ssl/ssl_lib.cc
|
|
@@ -1591,9 +1591,9 @@ int SSL_CTX_get_read_ahead(const SSL_CTX *ctx) { return 0; }
|
|
|
|
int SSL_get_read_ahead(const SSL *ssl) { return 0; }
|
|
|
|
-void SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes) { }
|
|
+int SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes) { return 1; }
|
|
|
|
-void SSL_set_read_ahead(SSL *ssl, int yes) { }
|
|
+int SSL_set_read_ahead(SSL *ssl, int yes) { return 1; }
|
|
|
|
int SSL_pending(const SSL *ssl) {
|
|
return static_cast<int>(ssl->s3->pending_app_data.size());
|
|
@@ -2205,7 +2205,7 @@ const COMP_METHOD *SSL_get_current_compression(SSL *ssl) { return NULL; }
|
|
|
|
const COMP_METHOD *SSL_get_current_expansion(SSL *ssl) { return NULL; }
|
|
|
|
-int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key) { return 0; }
|
|
+int SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key) { return 0; }
|
|
|
|
void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) {
|
|
ctx->quiet_shutdown = (mode != 0);
|
|
@@ -2717,3 +2717,33 @@ void SSL_CTX_set_ticket_aead_method(SSL_CTX *ctx,
|
|
const SSL_TICKET_AEAD_METHOD *aead_method) {
|
|
ctx->ticket_aead_method = aead_method;
|
|
}
|
|
+
|
|
+int SSL_set_tlsext_status_type(SSL *ssl, int type) {
|
|
+ ssl->ocsp_stapling_enabled = type == TLSEXT_STATUSTYPE_ocsp;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int SSL_set_tlsext_status_ocsp_resp(SSL *ssl, uint8_t *resp, size_t resp_len) {
|
|
+ if (SSL_set_ocsp_response(ssl, resp, resp_len)) {
|
|
+ OPENSSL_free(resp);
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+size_t SSL_get_tlsext_status_ocsp_resp(const SSL *ssl, const uint8_t **out) {
|
|
+ size_t ret;
|
|
+ SSL_get0_ocsp_response(ssl, out, &ret);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
|
|
+ int (*callback)(SSL *ssl, void *arg)) {
|
|
+ ctx->legacy_ocsp_callback = callback;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+int SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg) {
|
|
+ ctx->legacy_ocsp_callback_arg = arg;
|
|
+ return 1;
|
|
+}
|
|
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
|
|
index ae26ded..3a33d60 100644
|
|
--- a/ssl/test/bssl_shim.cc
|
|
+++ b/ssl/test/bssl_shim.cc
|
|
@@ -495,6 +495,7 @@ static bool GetCertificate(SSL *ssl, bssl::UniquePtr<X509> *out_x509,
|
|
return false;
|
|
}
|
|
if (!config->ocsp_response.empty() &&
|
|
+ !config->set_ocsp_in_callback &&
|
|
!SSL_set_ocsp_response(ssl, (const uint8_t *)config->ocsp_response.data(),
|
|
config->ocsp_response.size())) {
|
|
return false;
|
|
@@ -1100,6 +1101,27 @@ static void MessageCallback(int is_write, int version, int content_type,
|
|
}
|
|
}
|
|
|
|
+static int LegacyOCSPCallback(SSL *ssl, void *arg) {
|
|
+ const TestConfig *config = GetTestConfig(ssl);
|
|
+ if (!SSL_is_server(ssl)) {
|
|
+ return !config->fail_ocsp_callback;
|
|
+ }
|
|
+
|
|
+ if (!config->ocsp_response.empty() &&
|
|
+ config->set_ocsp_in_callback &&
|
|
+ !SSL_set_ocsp_response(ssl, (const uint8_t *)config->ocsp_response.data(),
|
|
+ config->ocsp_response.size())) {
|
|
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
+ }
|
|
+ if (config->fail_ocsp_callback) {
|
|
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
|
|
+ }
|
|
+ if (config->decline_ocsp_callback) {
|
|
+ return SSL_TLSEXT_ERR_NOACK;
|
|
+ }
|
|
+ return SSL_TLSEXT_ERR_OK;
|
|
+}
|
|
+
|
|
// Connect returns a new socket connected to localhost on |port| or -1 on
|
|
// error.
|
|
static int Connect(uint16_t port) {
|
|
@@ -1334,6 +1356,10 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
|
|
SSL_CTX_set_false_start_allowed_without_alpn(ssl_ctx.get(), 1);
|
|
}
|
|
|
|
+ if (config->use_ocsp_callback) {
|
|
+ SSL_CTX_set_tlsext_status_cb(ssl_ctx.get(), LegacyOCSPCallback);
|
|
+ }
|
|
+
|
|
if (old_ctx) {
|
|
uint8_t keys[48];
|
|
if (!SSL_CTX_get_tlsext_ticket_keys(old_ctx, &keys, sizeof(keys)) ||
|
|
diff --git a/ssl/test/runner/alert.go b/ssl/test/runner/alert.go
|
|
index 652e9ee..c79725e 100644
|
|
--- a/ssl/test/runner/alert.go
|
|
+++ b/ssl/test/runner/alert.go
|
|
@@ -15,69 +15,71 @@ const (
|
|
)
|
|
|
|
const (
|
|
- alertCloseNotify alert = 0
|
|
- alertEndOfEarlyData alert = 1
|
|
- alertUnexpectedMessage alert = 10
|
|
- alertBadRecordMAC alert = 20
|
|
- alertDecryptionFailed alert = 21
|
|
- alertRecordOverflow alert = 22
|
|
- alertDecompressionFailure alert = 30
|
|
- alertHandshakeFailure alert = 40
|
|
- alertNoCertificate alert = 41
|
|
- alertBadCertificate alert = 42
|
|
- alertUnsupportedCertificate alert = 43
|
|
- alertCertificateRevoked alert = 44
|
|
- alertCertificateExpired alert = 45
|
|
- alertCertificateUnknown alert = 46
|
|
- alertIllegalParameter alert = 47
|
|
- alertUnknownCA alert = 48
|
|
- alertAccessDenied alert = 49
|
|
- alertDecodeError alert = 50
|
|
- alertDecryptError alert = 51
|
|
- alertProtocolVersion alert = 70
|
|
- alertInsufficientSecurity alert = 71
|
|
- alertInternalError alert = 80
|
|
- alertInappropriateFallback alert = 86
|
|
- alertUserCanceled alert = 90
|
|
- alertNoRenegotiation alert = 100
|
|
- alertMissingExtension alert = 109
|
|
- alertUnsupportedExtension alert = 110
|
|
- alertUnrecognizedName alert = 112
|
|
- alertUnknownPSKIdentity alert = 115
|
|
- alertCertificateRequired alert = 116
|
|
+ alertCloseNotify alert = 0
|
|
+ alertEndOfEarlyData alert = 1
|
|
+ alertUnexpectedMessage alert = 10
|
|
+ alertBadRecordMAC alert = 20
|
|
+ alertDecryptionFailed alert = 21
|
|
+ alertRecordOverflow alert = 22
|
|
+ alertDecompressionFailure alert = 30
|
|
+ alertHandshakeFailure alert = 40
|
|
+ alertNoCertificate alert = 41
|
|
+ alertBadCertificate alert = 42
|
|
+ alertUnsupportedCertificate alert = 43
|
|
+ alertCertificateRevoked alert = 44
|
|
+ alertCertificateExpired alert = 45
|
|
+ alertCertificateUnknown alert = 46
|
|
+ alertIllegalParameter alert = 47
|
|
+ alertUnknownCA alert = 48
|
|
+ alertAccessDenied alert = 49
|
|
+ alertDecodeError alert = 50
|
|
+ alertDecryptError alert = 51
|
|
+ alertProtocolVersion alert = 70
|
|
+ alertInsufficientSecurity alert = 71
|
|
+ alertInternalError alert = 80
|
|
+ alertInappropriateFallback alert = 86
|
|
+ alertUserCanceled alert = 90
|
|
+ alertNoRenegotiation alert = 100
|
|
+ alertMissingExtension alert = 109
|
|
+ alertUnsupportedExtension alert = 110
|
|
+ alertUnrecognizedName alert = 112
|
|
+ alertBadCertificateStatusResponse alert = 113
|
|
+ alertUnknownPSKIdentity alert = 115
|
|
+ alertCertificateRequired alert = 116
|
|
)
|
|
|
|
var alertText = map[alert]string{
|
|
- alertCloseNotify: "close notify",
|
|
- alertEndOfEarlyData: "end of early data",
|
|
- alertUnexpectedMessage: "unexpected message",
|
|
- alertBadRecordMAC: "bad record MAC",
|
|
- alertDecryptionFailed: "decryption failed",
|
|
- alertRecordOverflow: "record overflow",
|
|
- alertDecompressionFailure: "decompression failure",
|
|
- alertHandshakeFailure: "handshake failure",
|
|
- alertNoCertificate: "no certificate",
|
|
- alertBadCertificate: "bad certificate",
|
|
- alertUnsupportedCertificate: "unsupported certificate",
|
|
- alertCertificateRevoked: "revoked certificate",
|
|
- alertCertificateExpired: "expired certificate",
|
|
- alertCertificateUnknown: "unknown certificate",
|
|
- alertIllegalParameter: "illegal parameter",
|
|
- alertUnknownCA: "unknown certificate authority",
|
|
- alertAccessDenied: "access denied",
|
|
- alertDecodeError: "error decoding message",
|
|
- alertDecryptError: "error decrypting message",
|
|
- alertProtocolVersion: "protocol version not supported",
|
|
- alertInsufficientSecurity: "insufficient security level",
|
|
- alertInternalError: "internal error",
|
|
- alertInappropriateFallback: "inappropriate fallback",
|
|
- alertUserCanceled: "user canceled",
|
|
- alertNoRenegotiation: "no renegotiation",
|
|
- alertMissingExtension: "missing extension",
|
|
- alertUnsupportedExtension: "unsupported extension",
|
|
- alertUnrecognizedName: "unrecognized name",
|
|
- alertUnknownPSKIdentity: "unknown PSK identity",
|
|
- alertCertificateRequired: "certificate required",
|
|
+ alertCloseNotify: "close notify",
|
|
+ alertEndOfEarlyData: "end of early data",
|
|
+ alertUnexpectedMessage: "unexpected message",
|
|
+ alertBadRecordMAC: "bad record MAC",
|
|
+ alertDecryptionFailed: "decryption failed",
|
|
+ alertRecordOverflow: "record overflow",
|
|
+ alertDecompressionFailure: "decompression failure",
|
|
+ alertHandshakeFailure: "handshake failure",
|
|
+ alertNoCertificate: "no certificate",
|
|
+ alertBadCertificate: "bad certificate",
|
|
+ alertUnsupportedCertificate: "unsupported certificate",
|
|
+ alertCertificateRevoked: "revoked certificate",
|
|
+ alertCertificateExpired: "expired certificate",
|
|
+ alertCertificateUnknown: "unknown certificate",
|
|
+ alertIllegalParameter: "illegal parameter",
|
|
+ alertUnknownCA: "unknown certificate authority",
|
|
+ alertAccessDenied: "access denied",
|
|
+ alertDecodeError: "error decoding message",
|
|
+ alertDecryptError: "error decrypting message",
|
|
+ alertProtocolVersion: "protocol version not supported",
|
|
+ alertInsufficientSecurity: "insufficient security level",
|
|
+ alertInternalError: "internal error",
|
|
+ alertInappropriateFallback: "inappropriate fallback",
|
|
+ alertUserCanceled: "user canceled",
|
|
+ alertNoRenegotiation: "no renegotiation",
|
|
+ alertMissingExtension: "missing extension",
|
|
+ alertUnsupportedExtension: "unsupported extension",
|
|
+ alertBadCertificateStatusResponse: "bad certificate status response",
|
|
+ alertUnrecognizedName: "unrecognized name",
|
|
+ alertUnknownPSKIdentity: "unknown PSK identity",
|
|
+ alertCertificateRequired: "certificate required",
|
|
}
|
|
|
|
func (e alert) String() string {
|
|
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
|
|
index 510a48b..1a6d0f9 100644
|
|
--- a/ssl/test/runner/runner.go
|
|
+++ b/ssl/test/runner/runner.go
|
|
@@ -4744,60 +4744,157 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
|
|
})
|
|
|
|
// OCSP stapling tests.
|
|
- tests = append(tests, testCase{
|
|
- testType: clientTest,
|
|
- name: "OCSPStapling-Client",
|
|
- config: Config{
|
|
- MaxVersion: VersionTLS12,
|
|
- },
|
|
- flags: []string{
|
|
- "-enable-ocsp-stapling",
|
|
- "-expect-ocsp-response",
|
|
- base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
- "-verify-peer",
|
|
- },
|
|
- resumeSession: true,
|
|
- })
|
|
- tests = append(tests, testCase{
|
|
- testType: serverTest,
|
|
- name: "OCSPStapling-Server",
|
|
- config: Config{
|
|
- MaxVersion: VersionTLS12,
|
|
- },
|
|
- expectedOCSPResponse: testOCSPResponse,
|
|
- flags: []string{
|
|
- "-ocsp-response",
|
|
- base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
- },
|
|
- resumeSession: true,
|
|
- })
|
|
- tests = append(tests, testCase{
|
|
- testType: clientTest,
|
|
- name: "OCSPStapling-Client-TLS13",
|
|
- config: Config{
|
|
- MaxVersion: VersionTLS13,
|
|
- },
|
|
- flags: []string{
|
|
- "-enable-ocsp-stapling",
|
|
- "-expect-ocsp-response",
|
|
- base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
- "-verify-peer",
|
|
- },
|
|
- resumeSession: true,
|
|
- })
|
|
- tests = append(tests, testCase{
|
|
- testType: serverTest,
|
|
- name: "OCSPStapling-Server-TLS13",
|
|
- config: Config{
|
|
- MaxVersion: VersionTLS13,
|
|
- },
|
|
- expectedOCSPResponse: testOCSPResponse,
|
|
- flags: []string{
|
|
- "-ocsp-response",
|
|
- base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
- },
|
|
- resumeSession: true,
|
|
- })
|
|
+ for _, vers := range tlsVersions {
|
|
+ if config.protocol == dtls && !vers.hasDTLS {
|
|
+ continue
|
|
+ }
|
|
+ if vers.version == VersionSSL30 {
|
|
+ continue
|
|
+ }
|
|
+ tests = append(tests, testCase{
|
|
+ testType: clientTest,
|
|
+ name: "OCSPStapling-Client-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ flags: []string{
|
|
+ "-enable-ocsp-stapling",
|
|
+ "-expect-ocsp-response",
|
|
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
+ "-verify-peer",
|
|
+ },
|
|
+ resumeSession: true,
|
|
+ })
|
|
+ tests = append(tests, testCase{
|
|
+ testType: serverTest,
|
|
+ name: "OCSPStapling-Server-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ expectedOCSPResponse: testOCSPResponse,
|
|
+ flags: []string{
|
|
+ "-ocsp-response",
|
|
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
+ },
|
|
+ resumeSession: true,
|
|
+ })
|
|
+
|
|
+ // The client OCSP callback is an alternate certificate
|
|
+ // verification callback.
|
|
+ tests = append(tests, testCase{
|
|
+ testType: clientTest,
|
|
+ name: "ClientOCSPCallback-Pass-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ Certificates: []Certificate{rsaCertificate},
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ flags: []string{
|
|
+ "-enable-ocsp-stapling",
|
|
+ "-use-ocsp-callback",
|
|
+ },
|
|
+ })
|
|
+ var expectedLocalError string
|
|
+ if !config.async {
|
|
+ // TODO(davidben): Asynchronous fatal alerts are never
|
|
+ // sent. https://crbug.com/boringssl/130.
|
|
+ expectedLocalError = "remote error: bad certificate status response"
|
|
+ }
|
|
+ tests = append(tests, testCase{
|
|
+ testType: clientTest,
|
|
+ name: "ClientOCSPCallback-Fail-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ Certificates: []Certificate{rsaCertificate},
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ flags: []string{
|
|
+ "-enable-ocsp-stapling",
|
|
+ "-use-ocsp-callback",
|
|
+ "-fail-ocsp-callback",
|
|
+ },
|
|
+ shouldFail: true,
|
|
+ expectedLocalError: expectedLocalError,
|
|
+ expectedError: ":OCSP_CB_ERROR:",
|
|
+ })
|
|
+ // The callback does not run if the server does not send an
|
|
+ // OCSP response.
|
|
+ certNoStaple := rsaCertificate
|
|
+ certNoStaple.OCSPStaple = nil
|
|
+ tests = append(tests, testCase{
|
|
+ testType: clientTest,
|
|
+ name: "ClientOCSPCallback-FailNoStaple-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ Certificates: []Certificate{certNoStaple},
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ flags: []string{
|
|
+ "-enable-ocsp-stapling",
|
|
+ "-use-ocsp-callback",
|
|
+ "-fail-ocsp-callback",
|
|
+ },
|
|
+ })
|
|
+
|
|
+ // The server OCSP callback is a legacy mechanism for
|
|
+ // configuring OCSP, used by unreliable server software.
|
|
+ tests = append(tests, testCase{
|
|
+ testType: serverTest,
|
|
+ name: "ServerOCSPCallback-SetInCallback-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ expectedOCSPResponse: testOCSPResponse,
|
|
+ flags: []string{
|
|
+ "-use-ocsp-callback",
|
|
+ "-set-ocsp-in-callback",
|
|
+ "-ocsp-response",
|
|
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
+ },
|
|
+ resumeSession: true,
|
|
+ })
|
|
+
|
|
+ // The callback may decline OCSP, in which case we act as if
|
|
+ // the client did not support it, even if a response was
|
|
+ // configured.
|
|
+ tests = append(tests, testCase{
|
|
+ testType: serverTest,
|
|
+ name: "ServerOCSPCallback-Decline-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ expectedOCSPResponse: []byte{},
|
|
+ flags: []string{
|
|
+ "-use-ocsp-callback",
|
|
+ "-decline-ocsp-callback",
|
|
+ "-ocsp-response",
|
|
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
+ },
|
|
+ resumeSession: true,
|
|
+ })
|
|
+
|
|
+ // The callback may also signal an internal error.
|
|
+ tests = append(tests, testCase{
|
|
+ testType: serverTest,
|
|
+ name: "ServerOCSPCallback-Fail-" + vers.name,
|
|
+ config: Config{
|
|
+ MaxVersion: vers.version,
|
|
+ },
|
|
+ tls13Variant: vers.tls13Variant,
|
|
+ flags: []string{
|
|
+ "-use-ocsp-callback",
|
|
+ "-fail-ocsp-callback",
|
|
+ "-ocsp-response",
|
|
+ base64.StdEncoding.EncodeToString(testOCSPResponse),
|
|
+ },
|
|
+ shouldFail: true,
|
|
+ expectedError: ":OCSP_CB_ERROR:",
|
|
+ })
|
|
+ }
|
|
|
|
// Certificate verification tests.
|
|
for _, vers := range tlsVersions {
|
|
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
|
|
index f50251d..3afb01b 100644
|
|
--- a/ssl/test/test_config.cc
|
|
+++ b/ssl/test/test_config.cc
|
|
@@ -133,6 +133,10 @@ const Flag<bool> kBoolFlags[] = {
|
|
{ "-expect-draft-downgrade", &TestConfig::expect_draft_downgrade },
|
|
{ "-handoff", &TestConfig::handoff },
|
|
{ "-expect-dummy-pq-padding", &TestConfig::expect_dummy_pq_padding },
|
|
+ { "-use-ocsp-callback", &TestConfig::use_ocsp_callback },
|
|
+ { "-set-ocsp-in-callback", &TestConfig::set_ocsp_in_callback },
|
|
+ { "-decline-ocsp-callback", &TestConfig::decline_ocsp_callback },
|
|
+ { "-fail-ocsp-callback", &TestConfig::fail_ocsp_callback },
|
|
};
|
|
|
|
const Flag<std::string> kStringFlags[] = {
|
|
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
|
|
index fb479d1..a9eec62 100644
|
|
--- a/ssl/test/test_config.h
|
|
+++ b/ssl/test/test_config.h
|
|
@@ -154,6 +154,10 @@ struct TestConfig {
|
|
int dummy_pq_padding_len = 0;
|
|
bool handoff = false;
|
|
bool expect_dummy_pq_padding = false;
|
|
+ bool use_ocsp_callback = false;
|
|
+ bool set_ocsp_in_callback = false;
|
|
+ bool decline_ocsp_callback = false;
|
|
+ bool fail_ocsp_callback = false;
|
|
};
|
|
|
|
bool ParseConfig(int argc, char **argv, TestConfig *out_initial,
|
|
--
|
|
2.7.4
|
|
|