Browse Source

Add async certificate verification callback.

This also serves as a certificate verification callback for
CRYPTO_BUFFER-based consumers. Remove the silly
SSL_CTX_i_promise_to_verify_certs_after_the_handshake placeholder.

Bug: 54, chromium:347402
Change-Id: I4c6b445cb9cd7204218acb2e5d1625e6f37aff6f
Reviewed-on: https://boringssl-review.googlesource.com/17964
Reviewed-by: David Benjamin <davidben@google.com>
kris/onging/CECPQ3_patch15
David Benjamin 7 years ago
parent
commit
3a1dd46e4e
17 changed files with 259 additions and 112 deletions
  1. +44
    -13
      include/openssl/ssl.h
  2. +1
    -0
      include/openssl/ssl3.h
  3. +10
    -13
      ssl/handshake_client.cc
  4. +17
    -4
      ssl/handshake_server.cc
  5. +9
    -1
      ssl/internal.h
  6. +31
    -0
      ssl/s3_both.cc
  7. +18
    -4
      ssl/ssl_lib.cc
  8. +5
    -1
      ssl/ssl_test.cc
  9. +4
    -3
      ssl/ssl_x509.cc
  10. +49
    -19
      ssl/test/bssl_shim.cc
  11. +41
    -39
      ssl/test/runner/runner.go
  12. +1
    -0
      ssl/test/test_config.cc
  13. +1
    -0
      ssl/test/test_config.h
  14. +5
    -6
      ssl/tls13_both.cc
  15. +10
    -0
      ssl/tls13_client.cc
  16. +10
    -0
      ssl/tls13_server.cc
  17. +3
    -9
      ssl/tls_method.cc

+ 44
- 13
include/openssl/ssl.h View File

@@ -517,6 +517,13 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* used to reuse the underlying connection for the retry. */
#define SSL_ERROR_EARLY_DATA_REJECTED 15

/* SSL_ERROR_WANT_CERTIFICATE_VERIFY indicates the operation failed because
* certificate verification was incomplete. The caller may retry the operation
* when certificate verification is complete.
*
* See also |SSL_CTX_set_custom_verify|. */
#define SSL_ERROR_WANT_CERTIFICATE_VERIFY 16

/* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
* and zero on failure. */
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
@@ -2201,6 +2208,39 @@ OPENSSL_EXPORT void SSL_set_verify(SSL *ssl, int mode,
int (*callback)(int ok,
X509_STORE_CTX *store_ctx));

enum ssl_verify_result_t {
ssl_verify_ok,
ssl_verify_invalid,
ssl_verify_retry,
};

/* SSL_CTX_set_custom_verify configures certificate verification. |mode| is one
* of the |SSL_VERIFY_*| values defined above. |callback| performs the
* certificate verification.
*
* The callback may call |SSL_get0_peer_certificates| for the certificate chain
* to validate. The callback should return |ssl_verify_ok| if the certificate is
* valid. If the certificate is invalid, the callback should return
* |ssl_verify_invalid| and optionally set |*out_alert| to an alert to send to
* the peer. Some useful alerts include |SSL_AD_CERTIFICATE_EXPIRED|,
* |SSL_AD_CERTIFICATE_REVOKED|, |SSL_AD_UNKNOWN_CA|, |SSL_AD_BAD_CERTIFICATE|,
* |SSL_AD_CERTIFICATE_UNKNOWN|, and |SSL_AD_INTERNAL_ERROR|. See RFC 5246
* section 7.2.2 for their precise meanings. If unspecified,
* |SSL_AD_CERTIFICATE_UNKNOWN| will be sent by default.
*
* To verify a certificate asynchronously, the callback may return
* |ssl_verify_retry|. The handshake will then pause with |SSL_get_error|
* returning |SSL_ERROR_WANT_CERTIFICATE_VERIFY|. */
OPENSSL_EXPORT void SSL_CTX_set_custom_verify(
SSL_CTX *ctx, int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert));

/* SSL_set_custom_verify behaves like |SSL_CTX_set_custom_verify| but configures
* an individual |SSL|. */
OPENSSL_EXPORT void SSL_set_custom_verify(
SSL *ssl, int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert));

/* SSL_CTX_get_verify_mode returns |ctx|'s verify mode, set by
* |SSL_CTX_set_verify|. */
OPENSSL_EXPORT int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
@@ -2320,13 +2360,6 @@ OPENSSL_EXPORT void SSL_CTX_set_cert_verify_callback(
SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *store_ctx, void *arg),
void *arg);

/* SSL_CTX_i_promise_to_verify_certs_after_the_handshake indicates that the
* caller understands that the |CRYPTO_BUFFER|-based methods currently require
* post-handshake verification of certificates and thus it's ok to accept any
* certificates during the handshake. */
OPENSSL_EXPORT void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(
SSL_CTX *ctx);

/* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
* of a connection) to request SCTs from the server. See
* https://tools.ietf.org/html/rfc6962.
@@ -3748,6 +3781,7 @@ OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
#define SSL_PRIVATE_KEY_OPERATION 9
#define SSL_PENDING_TICKET 10
#define SSL_EARLY_DATA_REJECTED 11
#define SSL_CERTIFICATE_VERIFY 12

/* SSL_want returns one of the above values to determine what the most recent
* operation on |ssl| was blocked on. Use |SSL_get_error| instead. */
@@ -4194,6 +4228,9 @@ struct ssl_ctx_st {
int (*app_verify_callback)(X509_STORE_CTX *store_ctx, void *arg);
void *app_verify_arg;

enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
uint8_t *out_alert);

/* Default password callback. */
pem_password_cb *default_passwd_callback;

@@ -4374,12 +4411,6 @@ struct ssl_ctx_st {
* otherwise. */
unsigned grease_enabled:1;

/* i_promise_to_verify_certs_after_the_handshake indicates that the
* application is using the |CRYPTO_BUFFER|-based methods and understands
* that this currently requires post-handshake verification of
* certificates. */
unsigned i_promise_to_verify_certs_after_the_handshake:1;

/* allow_unknown_alpn_protos is one if the client allows unsolicited ALPN
* protocols from the peer. */
unsigned allow_unknown_alpn_protos:1;


+ 1
- 0
include/openssl/ssl3.h View File

@@ -334,6 +334,7 @@ OPENSSL_COMPILE_ASSERT(
/* server */
/* extra state */
#define SSL3_ST_SW_FLUSH (0x100 | SSL_ST_ACCEPT)
#define SSL3_ST_VERIFY_CLIENT_CERT (0x101 | SSL_ST_ACCEPT)
/* read from client */
#define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT)


+ 10
- 13
ssl/handshake_client.cc View File

@@ -173,7 +173,6 @@ static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs);
static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs);
static int ssl3_get_cert_status(SSL_HANDSHAKE *hs);
static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs);
static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs);
static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs);
static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs);
@@ -292,9 +291,16 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {

case SSL3_ST_VERIFY_SERVER_CERT:
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
ret = ssl3_verify_server_cert(hs);
if (ret <= 0) {
goto end;
switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
ret = -1;
goto end;
case ssl_verify_retry:
ssl->rwstate = SSL_CERTIFICATE_VERIFY;
ret = -1;
goto end;
}
}
hs->state = SSL3_ST_CR_KEY_EXCH_A;
@@ -1185,15 +1191,6 @@ static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
return 1;
}

static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
return -1;
}

return 1;
}

static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
EC_KEY *ecdh = NULL;


+ 17
- 4
ssl/handshake_server.cc View File

@@ -282,6 +282,23 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
goto end;
}
}
hs->state = SSL3_ST_VERIFY_CLIENT_CERT;
break;

case SSL3_ST_VERIFY_CLIENT_CERT:
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) > 0) {
switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
ret = -1;
goto end;
case ssl_verify_retry:
ssl->rwstate = SSL_CERTIFICATE_VERIFY;
ret = -1;
goto end;
}
}
hs->state = SSL3_ST_SR_KEY_EXCH_A;
break;

@@ -1264,10 +1281,6 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
hs->new_session->peer_sha256_valid = 1;
}

if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
return -1;
}

return 1;
}



+ 9
- 1
ssl/internal.h View File

@@ -1007,6 +1007,7 @@ enum ssl_hs_wait_t {
ssl_hs_early_data_rejected,
ssl_hs_read_end_of_early_data,
ssl_hs_read_change_cipher_spec,
ssl_hs_certificate_verify,
};

struct ssl_handshake_st {
@@ -1341,6 +1342,9 @@ int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
const SSL_EXTENSION_TYPE *ext_types,
size_t num_ext_types, int ignore_unknown);

/* ssl_verify_peer_cert verifies the peer certificate for |hs|. */
enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs);


/* SSLKEYLOGFILE functions. */

@@ -1597,7 +1601,8 @@ struct ssl_x509_method_st {
/* session_verify_cert_chain verifies the certificate chain in |session|,
* sets |session->verify_result| and returns one on success or zero on
* error. */
int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl);
int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl,
uint8_t *out_alert);

/* hs_flush_cached_ca_names drops any cached |X509_NAME|s from |hs|. */
void (*hs_flush_cached_ca_names)(SSL_HANDSHAKE *hs);
@@ -1990,6 +1995,9 @@ struct ssl_st {
int (*verify_callback)(int ok,
X509_STORE_CTX *ctx); /* fail if callback returns 0 */

enum ssl_verify_result_t (*custom_verify_callback)(SSL *ssl,
uint8_t *out_alert);

void (*info_callback)(const SSL *ssl, int type, int value);

/* Server-only: psk_identity_hint is the identity hint to send in


+ 31
- 0
ssl/s3_both.cc View File

@@ -830,3 +830,34 @@ int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,

return 1;
}

enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
uint8_t alert = SSL_AD_CERTIFICATE_UNKNOWN;
enum ssl_verify_result_t ret;
if (ssl->custom_verify_callback != nullptr) {
ret = ssl->custom_verify_callback(ssl, &alert);
switch (ret) {
case ssl_verify_ok:
hs->new_session->verify_result = X509_V_OK;
break;
case ssl_verify_invalid:
hs->new_session->verify_result = X509_V_ERR_APPLICATION_VERIFICATION;
break;
case ssl_verify_retry:
break;
}
} else {
ret = ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl,
&alert)
? ssl_verify_ok
: ssl_verify_invalid;
}

if (ret == ssl_verify_invalid) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
}

return ret;
}

+ 18
- 4
ssl/ssl_lib.cc View File

@@ -392,6 +392,7 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->msg_callback_arg = ctx->msg_callback_arg;
ssl->verify_mode = ctx->verify_mode;
ssl->verify_callback = ctx->default_verify_callback;
ssl->custom_verify_callback = ctx->custom_verify_callback;
ssl->retain_only_sha256_of_client_certs =
ctx->retain_only_sha256_of_client_certs;

@@ -984,6 +985,9 @@ int SSL_get_error(const SSL *ssl, int ret_code) {

case SSL_EARLY_DATA_REJECTED:
return SSL_ERROR_EARLY_DATA_REJECTED;

case SSL_CERTIFICATE_VERIFY:
return SSL_ERROR_WANT_CERTIFICATE_VERIFY;
}

return SSL_ERROR_SYSCALL;
@@ -1554,12 +1558,22 @@ int SSL_get_servername_type(const SSL *ssl) {
return TLSEXT_NAMETYPE_host_name;
}

void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
ctx->signed_cert_timestamps_enabled = 1;
void SSL_CTX_set_custom_verify(
SSL_CTX *ctx, int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)) {
ctx->verify_mode = mode;
ctx->custom_verify_callback = callback;
}

void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(SSL_CTX *ctx) {
ctx->i_promise_to_verify_certs_after_the_handshake = 1;
void SSL_set_custom_verify(
SSL *ssl, int mode,
enum ssl_verify_result_t (*callback)(SSL *ssl, uint8_t *out_alert)) {
ssl->verify_mode = mode;
ssl->custom_verify_callback = callback;
}

void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
ctx->signed_cert_timestamps_enabled = 1;
}

void SSL_enable_signed_cert_timestamps(SSL *ssl) {


+ 5
- 1
ssl/ssl_test.cc View File

@@ -3276,7 +3276,11 @@ TEST(SSLTest, SetChainAndKey) {
ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
chain.size(), key.get(), nullptr));

SSL_CTX_i_promise_to_verify_certs_after_the_handshake(client_ctx.get());
SSL_CTX_set_custom_verify(
client_ctx.get(), SSL_VERIFY_PEER,
[](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {
return ssl_verify_ok;
});

bssl::UniquePtr<SSL> client, server;
ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),


+ 4
- 3
ssl/ssl_x509.cc View File

@@ -620,7 +620,9 @@ static int ssl_verify_alarm_type(long type) {
}

static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
SSL *ssl) {
SSL *ssl,
uint8_t *out_alert) {
*out_alert = SSL_AD_INTERNAL_ERROR;
STACK_OF(X509) *const cert_chain = session->x509_chain;
if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
return 0;
@@ -666,8 +668,7 @@ static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,

/* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, ssl_verify_alarm_type(ctx.error));
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
*out_alert = ssl_verify_alarm_type(ctx.error);
goto err;
}



+ 49
- 19
ssl/test/bssl_shim.cc View File

@@ -112,6 +112,7 @@ struct TestState {
bool alpn_select_done = false;
bool is_resume = false;
bool early_callback_ready = false;
bool custom_verify_ready = false;
};

static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
@@ -684,27 +685,52 @@ static int CertCallback(SSL *ssl, void *arg) {
return 1;
}

static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
static bool CheckVerifyCallback(SSL *ssl) {
const TestConfig *config = GetTestConfig(ssl);

if (!config->expected_ocsp_response.empty()) {
const uint8_t *data;
size_t len;
SSL_get0_ocsp_response(ssl, &data, &len);
if (len == 0) {
fprintf(stderr, "OCSP response not available in verify callback\n");
return 0;
return false;
}
}

return true;
}

static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) {
SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
SSL_get_ex_data_X509_STORE_CTX_idx());
const TestConfig *config = GetTestConfig(ssl);
if (!CheckVerifyCallback(ssl)) {
return 0;
}

if (config->verify_fail) {
store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
return 0;
}

return 1;
}

static int VerifyFail(X509_STORE_CTX *store_ctx, void *arg) {
store_ctx->error = X509_V_ERR_APPLICATION_VERIFICATION;
return 0;
static ssl_verify_result_t CustomVerifyCallback(SSL *ssl, uint8_t *out_alert) {
const TestConfig *config = GetTestConfig(ssl);
if (!CheckVerifyCallback(ssl)) {
return ssl_verify_invalid;
}

if (config->async && !GetTestState(ssl)->custom_verify_ready) {
return ssl_verify_retry;
}

if (config->verify_fail) {
return ssl_verify_invalid;
}

return ssl_verify_ok;
}

static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
@@ -1139,10 +1165,8 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx,
return nullptr;
}

if (config->verify_fail) {
SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifyFail, NULL);
} else {
SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), VerifySucceed, NULL);
if (!config->use_custom_verify_callback) {
SSL_CTX_set_cert_verify_callback(ssl_ctx.get(), CertVerifyCallback, NULL);
}

if (!config->signed_cert_timestamps.empty() &&
@@ -1270,6 +1294,9 @@ static bool RetryAsync(SSL *ssl, int ret) {
case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION:
test_state->private_key_retries++;
return true;
case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
test_state->custom_verify_ready = true;
return true;
default:
return false;
}
@@ -1763,20 +1790,23 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
if (!config->use_old_client_cert_callback) {
SSL_set_cert_cb(ssl.get(), CertCallback, nullptr);
}
int mode = SSL_VERIFY_NONE;
if (config->require_any_client_certificate) {
SSL_set_verify(ssl.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
NULL);
mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
if (config->verify_peer) {
SSL_set_verify(ssl.get(), SSL_VERIFY_PEER, NULL);
mode = SSL_VERIFY_PEER;
}
if (config->verify_peer_if_no_obc) {
// Set SSL_VERIFY_FAIL_IF_NO_PEER_CERT so testing whether client
// certificates were requested is easy.
SSL_set_verify(ssl.get(),
SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
NULL);
mode = SSL_VERIFY_PEER | SSL_VERIFY_PEER_IF_NO_OBC |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
if (config->use_custom_verify_callback) {
SSL_set_custom_verify(ssl.get(), mode, CustomVerifyCallback);
} else if (mode != SSL_VERIFY_NONE) {
SSL_set_verify(ssl.get(), mode, NULL);
}
if (config->false_start) {
SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_FALSE_START);


+ 41
- 39
ssl/test/runner/runner.go View File

@@ -4553,47 +4553,49 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
if config.protocol == dtls && !vers.hasDTLS {
continue
}
for _, testType := range []testType{clientTest, serverTest} {
suffix := "-Client"
if testType == serverTest {
suffix = "-Server"
}
suffix += "-" + vers.name
for _, useCustomCallback := range []bool{false, true} {
for _, testType := range []testType{clientTest, serverTest} {
suffix := "-Client"
if testType == serverTest {
suffix = "-Server"
}
suffix += "-" + vers.name
if useCustomCallback {
suffix += "-CustomCallback"
}

flag := "-verify-peer"
if testType == serverTest {
flag = "-require-any-client-certificate"
}
flags := []string{"-verify-peer"}
if testType == serverTest {
flags = append(flags, "-require-any-client-certificate")
}
if useCustomCallback {
flags = append(flags, "-use-custom-verify-callback")
}

tests = append(tests, testCase{
testType: testType,
name: "CertificateVerificationSucceed" + suffix,
config: Config{
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
tls13Variant: vers.tls13Variant,
flags: []string{
flag,
"-expect-verify-result",
},
resumeSession: true,
})
tests = append(tests, testCase{
testType: testType,
name: "CertificateVerificationFail" + suffix,
config: Config{
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
tls13Variant: vers.tls13Variant,
flags: []string{
flag,
"-verify-fail",
},
shouldFail: true,
expectedError: ":CERTIFICATE_VERIFY_FAILED:",
})
tests = append(tests, testCase{
testType: testType,
name: "CertificateVerificationSucceed" + suffix,
config: Config{
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
tls13Variant: vers.tls13Variant,
flags: append([]string{"-expect-verify-result"}, flags...),
resumeSession: true,
})
tests = append(tests, testCase{
testType: testType,
name: "CertificateVerificationFail" + suffix,
config: Config{
MaxVersion: vers.version,
Certificates: []Certificate{rsaCertificate},
},
tls13Variant: vers.tls13Variant,
flags: append([]string{"-verify-fail"}, flags...),
shouldFail: true,
expectedError: ":CERTIFICATE_VERIFY_FAILED:",
})
}
}

// By default, the client is in a soft fail mode where the peer


+ 1
- 0
ssl/test/test_config.cc View File

@@ -129,6 +129,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-handshake-twice", &TestConfig::handshake_twice },
{ "-allow-unknown-alpn-protos", &TestConfig::allow_unknown_alpn_protos },
{ "-enable-ed25519", &TestConfig::enable_ed25519 },
{ "-use-custom-verify-callback", &TestConfig::use_custom_verify_callback },
};

const Flag<std::string> kStringFlags[] = {


+ 1
- 0
ssl/test/test_config.h View File

@@ -144,6 +144,7 @@ struct TestConfig {
bool handshake_twice = false;
bool allow_unknown_alpn_protos = false;
bool enable_ed25519 = false;
bool use_custom_verify_callback = false;
};

bool ParseConfig(int argc, char **argv, TestConfig *out_initial,


+ 5
- 6
ssl/tls13_both.cc View File

@@ -102,6 +102,11 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
hs->wait = ssl_hs_ok;
return -1;

case ssl_hs_certificate_verify:
ssl->rwstate = SSL_CERTIFICATE_VERIFY;
hs->wait = ssl_hs_ok;
return -1;

case ssl_hs_early_data_rejected:
ssl->rwstate = SSL_EARLY_DATA_REJECTED;
/* Cause |SSL_write| to start failing immediately. */
@@ -357,12 +362,6 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
}

hs->new_session->peer_sha256_valid = retain_sha256;

if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session,
ssl)) {
goto err;
}

ret = 1;

err:


+ 10
- 0
ssl/tls13_client.cc View File

@@ -494,6 +494,16 @@ static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_process_server_certificate_verify(
SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
return ssl_hs_error;
case ssl_verify_retry:
hs->tls13_state = state_process_server_certificate_verify;
return ssl_hs_certificate_verify;
}

if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
!ssl_hash_current_message(hs)) {


+ 10
- 0
ssl/tls13_server.cc View File

@@ -766,6 +766,16 @@ static enum ssl_hs_wait_t do_process_client_certificate_verify(
return ssl_hs_ok;
}

switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
return ssl_hs_error;
case ssl_verify_retry:
hs->tls13_state = state_process_client_certificate_verify;
return ssl_hs_certificate_verify;
}

if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(hs) ||
!ssl_hash_current_message(hs)) {


+ 3
- 9
ssl/tls_method.cc View File

@@ -240,15 +240,9 @@ static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
}
static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
SSL *ssl) {
if (!ssl->ctx->i_promise_to_verify_certs_after_the_handshake) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_CA);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
return 0;
}

session->verify_result = X509_V_OK;
return 1;
SSL *ssl,
uint8_t *out_alert) {
return 0;
}

static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}


Loading…
Cancel
Save