fix: backport legacy OCSP APIs in boringssl (#628)
One of Electron's tests exposed the fact that boringssl didn't support the OCSP stapling APIs that nodejs was calling. This backports a patch from boringssl that adds the APIs that nodejs expects, and causes the test to pass.
This commit is contained in:
Родитель
ede7e31980
Коммит
714d2ea890
|
@ -0,0 +1,6 @@
|
|||
repo: src/third_party/boringssl/src
|
||||
patches:
|
||||
-
|
||||
owners: nornagon
|
||||
file: 0001-Implement-legacy-OCSP-APIs-for-libssl.patch
|
||||
description: see patch header
|
|
@ -0,0 +1,741 @@
|
|||
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
|
||||
|
Загрузка…
Ссылка в новой задаче