Bläddra i källkod

A bit of cleanup post state machine merging.

Reorder states and functions by where they appear in the handshake. Remove
unnecessary hooks on SSL_PROTOCOL_METHOD.

Change-Id: I78dae9cf70792170abed6f38510ce870707e82ff
Reviewed-on: https://boringssl-review.googlesource.com/8184
Reviewed-by: David Benjamin <davidben@google.com>
kris/onging/CECPQ3_patch15
David Benjamin 8 år sedan
förälder
incheckning
9f1dc8254e
6 ändrade filer med 540 tillägg och 552 borttagningar
  1. +0
    -2
      ssl/d1_meth.c
  2. +0
    -2
      ssl/internal.h
  3. +235
    -237
      ssl/s3_clnt.c
  4. +0
    -2
      ssl/s3_meth.c
  5. +303
    -303
      ssl/s3_srvr.c
  6. +2
    -6
      ssl/ssl_lib.c

+ 0
- 2
ssl/d1_meth.c Visa fil

@@ -63,8 +63,6 @@ static const SSL_PROTOCOL_METHOD DTLS_protocol_method = {
1 /* is_dtls */,
dtls1_new,
dtls1_free,
ssl3_accept,
ssl3_connect,
dtls1_get_message,
dtls1_read_app_data,
dtls1_read_change_cipher_spec,


+ 0
- 2
ssl/internal.h Visa fil

@@ -806,8 +806,6 @@ struct ssl_protocol_method_st {
char is_dtls;
int (*ssl_new)(SSL *ssl);
void (*ssl_free)(SSL *ssl);
int (*ssl_accept)(SSL *ssl);
int (*ssl_connect)(SSL *ssl);
long (*ssl_get_message)(SSL *ssl, int msg_type,
enum ssl_hash_message_t hash_message, int *ok);
int (*ssl_read_app_data)(SSL *ssl, uint8_t *buf, int len, int peek);


+ 235
- 237
ssl/s3_clnt.c Visa fil

@@ -173,20 +173,18 @@
static int ssl3_send_client_hello(SSL *ssl);
static int dtls1_get_hello_verify(SSL *ssl);
static int ssl3_get_server_hello(SSL *ssl);
static int ssl3_get_certificate_request(SSL *ssl);
static int ssl3_get_new_session_ticket(SSL *ssl);
static int ssl3_get_server_certificate(SSL *ssl);
static int ssl3_get_cert_status(SSL *ssl);
static int ssl3_verify_server_cert(SSL *ssl);
static int ssl3_get_server_key_exchange(SSL *ssl);
static int ssl3_get_certificate_request(SSL *ssl);
static int ssl3_get_server_done(SSL *ssl);
static int ssl3_send_cert_verify(SSL *ssl);
static int ssl3_send_client_certificate(SSL *ssl);
static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509,
EVP_PKEY **out_pkey);
static int ssl3_send_client_key_exchange(SSL *ssl);
static int ssl3_get_server_key_exchange(SSL *ssl);
static int ssl3_get_server_certificate(SSL *ssl);
static int ssl3_send_cert_verify(SSL *ssl);
static int ssl3_send_next_proto(SSL *ssl);
static int ssl3_send_channel_id(SSL *ssl);
static int ssl3_verify_server_cert(SSL *ssl);
static int ssl3_get_new_session_ticket(SSL *ssl);

int ssl3_connect(SSL *ssl) {
BUF_MEM *buf = NULL;
@@ -287,6 +285,14 @@ int ssl3_connect(SSL *ssl) {
}
break;

case SSL3_ST_CR_CERT_STATUS_A:
ret = ssl3_get_cert_status(ssl);
if (ret <= 0) {
goto end;
}
ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
break;

case SSL3_ST_VERIFY_SERVER_CERT:
ret = ssl3_verify_server_cert(ssl);
if (ret <= 0) {
@@ -448,6 +454,19 @@ int ssl3_connect(SSL *ssl) {
}
break;

case SSL3_ST_FALSE_START:
/* Allow NewSessionTicket if ticket expected */
if (ssl->tlsext_ticket_expected) {
ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
} else {
ssl->state = SSL3_ST_CR_CHANGE;
}
ssl->s3->tmp.in_false_start = 1;

ssl_free_wbio_buffer(ssl);
ret = 1;
goto end;

case SSL3_ST_CR_SESSION_TICKET_A:
ret = ssl3_get_new_session_ticket(ssl);
if (ret <= 0) {
@@ -456,14 +475,6 @@ int ssl3_connect(SSL *ssl) {
ssl->state = SSL3_ST_CR_CHANGE;
break;

case SSL3_ST_CR_CERT_STATUS_A:
ret = ssl3_get_cert_status(ssl);
if (ret <= 0) {
goto end;
}
ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
break;

case SSL3_ST_CR_CHANGE:
ret = ssl->method->ssl_read_change_cipher_spec(ssl);
if (ret <= 0) {
@@ -503,19 +514,6 @@ int ssl3_connect(SSL *ssl) {
}
break;

case SSL3_ST_FALSE_START:
/* Allow NewSessionTicket if ticket expected */
if (ssl->tlsext_ticket_expected) {
ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
} else {
ssl->state = SSL3_ST_CR_CHANGE;
}
ssl->s3->tmp.in_false_start = 1;

ssl_free_wbio_buffer(ssl);
ret = 1;
goto end;

case SSL_ST_OK:
/* clean a few things up */
ssl3_cleanup_key_block(ssl);
@@ -1083,6 +1081,63 @@ err:
return ret;
}

static int ssl3_get_cert_status(SSL *ssl) {
int ok, al;
long n;
CBS certificate_status, ocsp_response;
uint8_t status_type;

n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);

if (!ok) {
return n;
}

if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
/* A server may send status_request in ServerHello and then change
* its mind about sending CertificateStatus. */
ssl->s3->tmp.reuse_message = 1;
return 1;
}

CBS_init(&certificate_status, ssl->init_msg, n);
if (!CBS_get_u8(&certificate_status, &status_type) ||
status_type != TLSEXT_STATUSTYPE_ocsp ||
!CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
CBS_len(&ocsp_response) == 0 ||
CBS_len(&certificate_status) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}

if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
&ssl->session->ocsp_response_length)) {
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto f_err;
}
return 1;

f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
return -1;
}

static int ssl3_verify_server_cert(SSL *ssl) {
int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain);
if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
int al = ssl_verify_alarm_type(ssl->verify_result);
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
} else {
ret = 1;
ERR_clear_error(); /* but we keep ssl->verify_result */
}

return ret;
}

static int ssl3_get_server_key_exchange(SSL *ssl) {
EVP_MD_CTX md_ctx;
int al, ok;
@@ -1460,141 +1515,120 @@ err:
return ret;
}

static int ssl3_get_new_session_ticket(SSL *ssl) {
int ok, al;
long n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET,
ssl_hash_message, &ok);
static int ssl3_get_server_done(SSL *ssl) {
int ok;
long n;

n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_DONE, ssl_hash_message,
&ok);

if (!ok) {
return n;
}

CBS new_session_ticket, ticket;
uint32_t ticket_lifetime_hint;
CBS_init(&new_session_ticket, ssl->init_msg, n);
if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) ||
!CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
CBS_len(&new_session_ticket) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}

if (CBS_len(&ticket) == 0) {
/* RFC 5077 allows a server to change its mind and send no ticket after
* negotiating the extension. The value of |tlsext_ticket_expected| is
* checked in |ssl_update_cache| so is cleared here to avoid an unnecessary
* update. */
ssl->tlsext_ticket_expected = 0;
return 1;
if (n > 0) {
/* should contain no data */
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
return -1;
}

if (ssl->hit) {
/* The server is sending a new ticket for an existing session. Sessions are
* immutable once established, so duplicate all but the ticket of the
* existing session. */
uint8_t *bytes;
size_t bytes_len;
if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) {
goto err;
}
SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
OPENSSL_free(bytes);
if (new_session == NULL) {
/* This should never happen. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
}

SSL_SESSION_free(ssl->session);
ssl->session = new_session;
}
/* ssl3_has_client_certificate returns true if a client certificate is
* configured. */
static int ssl3_has_client_certificate(SSL *ssl) {
return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl);
}

if (!CBS_stow(&ticket, &ssl->session->tlsext_tick,
&ssl->session->tlsext_ticklen)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509,
EVP_PKEY **out_pkey) {
if (ssl->ctx->client_cert_cb == NULL) {
return 0;
}
ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;

/* Generate a session ID for this session based on the session ticket. We use
* the session ID mechanism for detecting ticket resumption. This also fits in
* with assumptions elsewhere in OpenSSL.*/
if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id,
&ssl->session->session_id_length, EVP_sha256(), NULL)) {
goto err;
int ret = ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
if (ret <= 0) {
return ret;
}

assert(*out_x509 != NULL);
assert(*out_pkey != NULL);
return 1;

f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
err:
return -1;
}

static int ssl3_get_cert_status(SSL *ssl) {
int ok, al;
long n;
CBS certificate_status, ocsp_response;
uint8_t status_type;

n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
static int ssl3_send_client_certificate(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_CERT_A) {
/* Call cert_cb to update the certificate. */
if (ssl->cert->cert_cb) {
int ret = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
if (ret < 0) {
ssl->rwstate = SSL_X509_LOOKUP;
return -1;
}
if (ret == 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
}

if (!ok) {
return n;
if (ssl3_has_client_certificate(ssl)) {
ssl->state = SSL3_ST_CW_CERT_C;
} else {
ssl->state = SSL3_ST_CW_CERT_B;
}
}

if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
/* A server may send status_request in ServerHello and then change
* its mind about sending CertificateStatus. */
ssl->s3->tmp.reuse_message = 1;
return 1;
}
if (ssl->state == SSL3_ST_CW_CERT_B) {
/* Call client_cert_cb to update the certificate. */
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int ret = ssl_do_client_cert_cb(ssl, &x509, &pkey);
if (ret < 0) {
ssl->rwstate = SSL_X509_LOOKUP;
return -1;
}

CBS_init(&certificate_status, ssl->init_msg, n);
if (!CBS_get_u8(&certificate_status, &status_type) ||
status_type != TLSEXT_STATUSTYPE_ocsp ||
!CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
CBS_len(&ocsp_response) == 0 ||
CBS_len(&certificate_status) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
int setup_error = ret == 1 && (!SSL_use_certificate(ssl, x509) ||
!SSL_use_PrivateKey(ssl, pkey));
X509_free(x509);
EVP_PKEY_free(pkey);
if (setup_error) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}

if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
&ssl->session->ocsp_response_length)) {
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto f_err;
ssl->state = SSL3_ST_CW_CERT_C;
}
return 1;

f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
return -1;
}

static int ssl3_get_server_done(SSL *ssl) {
int ok;
long n;

n = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_DONE, ssl_hash_message,
&ok);
if (ssl->state == SSL3_ST_CW_CERT_C) {
if (!ssl3_has_client_certificate(ssl)) {
/* Without a client certificate, the handshake buffer may be released. */
ssl3_free_handshake_buffer(ssl);

if (!ok) {
return n;
}
if (ssl->version == SSL3_VERSION) {
/* In SSL 3.0, send no certificate by skipping both messages. */
ssl->s3->tmp.cert_req = 0;
ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
return 1;
}

if (n > 0) {
/* should contain no data */
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
return -1;
/* In TLS, send an empty Certificate message. */
ssl->s3->tmp.cert_req = 2;
uint8_t *p = ssl_handshake_start(ssl);
l2n3(0, p);
if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) {
return -1;
}
} else if (!ssl3_output_cert_chain(ssl)) {
return -1;
}
ssl->state = SSL3_ST_CW_CERT_D;
}

return 1;
assert(ssl->state == SSL3_ST_CW_CERT_D);
return ssl_do_write(ssl);
}

OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
@@ -1887,85 +1921,6 @@ err:
return -1;
}

/* ssl3_has_client_certificate returns true if a client certificate is
* configured. */
static int ssl3_has_client_certificate(SSL *ssl) {
return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl);
}

static int ssl3_send_client_certificate(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_CERT_A) {
/* Call cert_cb to update the certificate. */
if (ssl->cert->cert_cb) {
int ret = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
if (ret < 0) {
ssl->rwstate = SSL_X509_LOOKUP;
return -1;
}
if (ret == 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
}

if (ssl3_has_client_certificate(ssl)) {
ssl->state = SSL3_ST_CW_CERT_C;
} else {
ssl->state = SSL3_ST_CW_CERT_B;
}
}

if (ssl->state == SSL3_ST_CW_CERT_B) {
/* Call client_cert_cb to update the certificate. */
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int ret = ssl_do_client_cert_cb(ssl, &x509, &pkey);
if (ret < 0) {
ssl->rwstate = SSL_X509_LOOKUP;
return -1;
}

int setup_error = ret == 1 && (!SSL_use_certificate(ssl, x509) ||
!SSL_use_PrivateKey(ssl, pkey));
X509_free(x509);
EVP_PKEY_free(pkey);
if (setup_error) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}

ssl->state = SSL3_ST_CW_CERT_C;
}

if (ssl->state == SSL3_ST_CW_CERT_C) {
if (!ssl3_has_client_certificate(ssl)) {
/* Without a client certificate, the handshake buffer may be released. */
ssl3_free_handshake_buffer(ssl);

if (ssl->version == SSL3_VERSION) {
/* In SSL 3.0, send no certificate by skipping both messages. */
ssl->s3->tmp.cert_req = 0;
ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
return 1;
}

/* In TLS, send an empty Certificate message. */
ssl->s3->tmp.cert_req = 2;
uint8_t *p = ssl_handshake_start(ssl);
l2n3(0, p);
if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) {
return -1;
}
} else if (!ssl3_output_cert_chain(ssl)) {
return -1;
}
ssl->state = SSL3_ST_CW_CERT_D;
}

assert(ssl->state == SSL3_ST_CW_CERT_D);
return ssl_do_write(ssl);
}

static int ssl3_send_next_proto(SSL *ssl) {
if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
return ssl_do_write(ssl);
@@ -2078,32 +2033,75 @@ err:
return ret;
}

static int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509,
EVP_PKEY **out_pkey) {
if (ssl->ctx->client_cert_cb == NULL) {
return 0;
static int ssl3_get_new_session_ticket(SSL *ssl) {
int ok, al;
long n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET,
ssl_hash_message, &ok);

if (!ok) {
return n;
}

int ret = ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
if (ret <= 0) {
return ret;
CBS new_session_ticket, ticket;
uint32_t ticket_lifetime_hint;
CBS_init(&new_session_ticket, ssl->init_msg, n);
if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) ||
!CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
CBS_len(&new_session_ticket) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}

assert(*out_x509 != NULL);
assert(*out_pkey != NULL);
return 1;
}
if (CBS_len(&ticket) == 0) {
/* RFC 5077 allows a server to change its mind and send no ticket after
* negotiating the extension. The value of |tlsext_ticket_expected| is
* checked in |ssl_update_cache| so is cleared here to avoid an unnecessary
* update. */
ssl->tlsext_ticket_expected = 0;
return 1;
}

static int ssl3_verify_server_cert(SSL *ssl) {
int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain);
if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
int al = ssl_verify_alarm_type(ssl->verify_result);
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
} else {
ret = 1;
ERR_clear_error(); /* but we keep ssl->verify_result */
if (ssl->hit) {
/* The server is sending a new ticket for an existing session. Sessions are
* immutable once established, so duplicate all but the ticket of the
* existing session. */
uint8_t *bytes;
size_t bytes_len;
if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) {
goto err;
}
SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
OPENSSL_free(bytes);
if (new_session == NULL) {
/* This should never happen. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}

SSL_SESSION_free(ssl->session);
ssl->session = new_session;
}

return ret;
if (!CBS_stow(&ticket, &ssl->session->tlsext_tick,
&ssl->session->tlsext_ticklen)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;

/* Generate a session ID for this session based on the session ticket. We use
* the session ID mechanism for detecting ticket resumption. This also fits in
* with assumptions elsewhere in OpenSSL.*/
if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id,
&ssl->session->session_id_length, EVP_sha256(), NULL)) {
goto err;
}

return 1;

f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
err:
return -1;
}

+ 0
- 2
ssl/s3_meth.c Visa fil

@@ -63,8 +63,6 @@ static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
0 /* is_dtls */,
ssl3_new,
ssl3_free,
ssl3_accept,
ssl3_connect,
ssl3_get_message,
ssl3_read_app_data,
ssl3_read_change_cipher_spec,


+ 303
- 303
ssl/s3_srvr.c Visa fil

@@ -177,17 +177,17 @@ static int ssl3_get_initial_bytes(SSL *ssl);
static int ssl3_get_v2_client_hello(SSL *ssl);
static int ssl3_get_client_hello(SSL *ssl);
static int ssl3_send_server_hello(SSL *ssl);
static int ssl3_send_server_certificate(SSL *ssl);
static int ssl3_send_certificate_status(SSL *ssl);
static int ssl3_send_server_done(SSL *ssl);
static int ssl3_send_server_key_exchange(SSL *ssl);
static int ssl3_send_certificate_request(SSL *ssl);
static int ssl3_send_server_done(SSL *ssl);
static int ssl3_get_client_certificate(SSL *ssl);
static int ssl3_get_client_key_exchange(SSL *ssl);
static int ssl3_get_cert_verify(SSL *ssl);
static int ssl3_get_client_certificate(SSL *ssl);
static int ssl3_send_server_certificate(SSL *ssl);
static int ssl3_send_new_session_ticket(SSL *ssl);
static int ssl3_get_next_proto(SSL *ssl);
static int ssl3_get_channel_id(SSL *ssl);
static int ssl3_send_new_session_ticket(SSL *ssl);

int ssl3_accept(SSL *ssl) {
BUF_MEM *buf = NULL;
@@ -352,19 +352,6 @@ int ssl3_accept(SSL *ssl) {
ssl->state = SSL3_ST_SW_FLUSH;
break;

case SSL3_ST_SW_FLUSH:
if (BIO_flush(ssl->wbio) <= 0) {
ssl->rwstate = SSL_WRITING;
ret = -1;
goto end;
}

ssl->state = ssl->s3->tmp.next_state;
if (ssl->state != SSL_ST_OK) {
ssl->method->expect_flight(ssl);
}
break;

case SSL3_ST_SR_CERT_A:
if (ssl->s3->tmp.cert_request) {
ret = ssl3_get_client_certificate(ssl);
@@ -498,6 +485,19 @@ int ssl3_accept(SSL *ssl) {
}
break;

case SSL3_ST_SW_FLUSH:
if (BIO_flush(ssl->wbio) <= 0) {
ssl->rwstate = SSL_WRITING;
ret = -1;
goto end;
}

ssl->state = ssl->s3->tmp.next_state;
if (ssl->state != SSL_ST_OK) {
ssl->method->expect_flight(ssl);
}
break;

case SSL_ST_OK:
/* clean a few things up */
ssl3_cleanup_key_block(ssl);
@@ -1121,6 +1121,18 @@ static int ssl3_send_server_hello(SSL *ssl) {
return ssl_do_write(ssl);
}

static int ssl3_send_server_certificate(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_CERT_A) {
if (!ssl3_output_cert_chain(ssl)) {
return 0;
}
ssl->state = SSL3_ST_SW_CERT_B;
}

/* SSL3_ST_SW_CERT_B */
return ssl_do_write(ssl);
}

static int ssl3_send_certificate_status(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_CERT_STATUS_A) {
CBB out, ocsp_response;
@@ -1147,18 +1159,6 @@ static int ssl3_send_certificate_status(SSL *ssl) {
return ssl_do_write(ssl);
}

static int ssl3_send_server_done(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) {
if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_DONE, 0)) {
return -1;
}
ssl->state = SSL3_ST_SW_SRVR_DONE_B;
}

/* SSL3_ST_SW_SRVR_DONE_B */
return ssl_do_write(ssl);
}

static int ssl3_send_server_key_exchange(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
return ssl_do_write(ssl);
@@ -1415,6 +1415,157 @@ err:
return -1;
}

static int ssl3_send_server_done(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) {
if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_DONE, 0)) {
return -1;
}
ssl->state = SSL3_ST_SW_SRVR_DONE_B;
}

/* SSL3_ST_SW_SRVR_DONE_B */
return ssl_do_write(ssl);
}

static int ssl3_get_client_certificate(SSL *ssl) {
int ok, al, ret = -1;
X509 *x = NULL;
unsigned long n;
STACK_OF(X509) *sk = NULL;
SHA256_CTX sha256;
CBS certificate_msg, certificate_list;
int is_first_certificate = 1;

assert(ssl->s3->tmp.cert_request);
n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);

if (!ok) {
return n;
}

if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
if (ssl->version == SSL3_VERSION &&
ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
/* In SSL 3.0, the Certificate message is omitted to signal no certificate. */
if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
(ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}

ssl->s3->tmp.reuse_message = 1;
return 1;
}

al = SSL_AD_UNEXPECTED_MESSAGE;
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
}

CBS_init(&certificate_msg, ssl->init_msg, n);

sk = sk_X509_new_null();
if (sk == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}

if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
CBS_len(&certificate_msg) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}

while (CBS_len(&certificate_list) > 0) {
CBS certificate;
const uint8_t *data;

if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}

if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) {
/* If this is the first certificate, and we don't want to keep peer
* certificates in memory, then we hash it right away. */
SHA256_Init(&sha256);
SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
SHA256_Final(ssl->session->peer_sha256, &sha256);
ssl->session->peer_sha256_valid = 1;
}
is_first_certificate = 0;

/* A u24 length cannot overflow a long. */
data = CBS_data(&certificate);
x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
if (x == NULL) {
al = SSL_AD_BAD_CERTIFICATE;
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
goto f_err;
}
if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
if (!sk_X509_push(sk, x)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
}

if (sk_X509_num(sk) <= 0) {
/* No client certificate so the handshake buffer may be discarded. */
ssl3_free_handshake_buffer(ssl);

/* TLS does not mind 0 certs returned */
if (ssl->version == SSL3_VERSION) {
al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
goto f_err;
} else if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
(ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
/* Fail for TLS only if we required a certificate */
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
} else {
if (ssl_verify_cert_chain(ssl, sk) <= 0) {
al = ssl_verify_alarm_type(ssl->verify_result);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
goto f_err;
}
}

X509_free(ssl->session->peer);
ssl->session->peer = sk_X509_shift(sk);
ssl->session->verify_result = ssl->verify_result;

sk_X509_pop_free(ssl->session->cert_chain, X509_free);
ssl->session->cert_chain = sk;
/* Inconsistency alert: cert_chain does *not* include the peer's own
* certificate, while we do include it in s3_clnt.c */

sk = NULL;

ret = 1;

if (0) {
f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
}

err:
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return ret;
}

static int ssl3_get_client_key_exchange(SSL *ssl) {
int al;
CBS client_key_exchange;
@@ -1790,155 +1941,155 @@ err:
return ret;
}

static int ssl3_get_client_certificate(SSL *ssl) {
int ok, al, ret = -1;
X509 *x = NULL;
unsigned long n;
STACK_OF(X509) *sk = NULL;
SHA256_CTX sha256;
CBS certificate_msg, certificate_list;
int is_first_certificate = 1;

assert(ssl->s3->tmp.cert_request);
n = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message, &ok);
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
static int ssl3_get_next_proto(SSL *ssl) {
int ok;
long n;
CBS next_protocol, selected_protocol, padding;

if (!ok) {
return n;
/* Clients cannot send a NextProtocol message if we didn't see the extension
* in their ClientHello */
if (!ssl->s3->next_proto_neg_seen) {
OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
return -1;
}

if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
if (ssl->version == SSL3_VERSION &&
ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
/* In SSL 3.0, the Certificate message is omitted to signal no certificate. */
if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
(ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}

ssl->s3->tmp.reuse_message = 1;
return 1;
}
n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message,
&ok);

al = SSL_AD_UNEXPECTED_MESSAGE;
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
goto f_err;
if (!ok) {
return n;
}

CBS_init(&certificate_msg, ssl->init_msg, n);
CBS_init(&next_protocol, ssl->init_msg, n);

sk = sk_X509_new_null();
if (sk == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
CBS_len(&certificate_msg) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
/* The payload looks like:
* uint8 proto_len;
* uint8 proto[proto_len];
* uint8 padding_len;
* uint8 padding[padding_len]; */
if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
!CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
CBS_len(&next_protocol) != 0 ||
!CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
&ssl->s3->next_proto_negotiated_len)) {
return 0;
}

while (CBS_len(&certificate_list) > 0) {
CBS certificate;
const uint8_t *data;
return 1;
}

if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
static int ssl3_get_channel_id(SSL *ssl) {
int ret = -1, ok;
long n;
uint8_t channel_id_hash[EVP_MAX_MD_SIZE];
size_t channel_id_hash_len;
const uint8_t *p;
uint16_t extension_type;
EC_GROUP *p256 = NULL;
EC_KEY *key = NULL;
EC_POINT *point = NULL;
ECDSA_SIG sig;
BIGNUM x, y;
CBS encrypted_extensions, extension;

if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) {
/* If this is the first certificate, and we don't want to keep peer
* certificates in memory, then we hash it right away. */
SHA256_Init(&sha256);
SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
SHA256_Final(ssl->session->peer_sha256, &sha256);
ssl->session->peer_sha256_valid = 1;
}
is_first_certificate = 0;
n = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS,
ssl_dont_hash_message, &ok);

/* A u24 length cannot overflow a long. */
data = CBS_data(&certificate);
x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
if (x == NULL) {
al = SSL_AD_BAD_CERTIFICATE;
OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
goto f_err;
}
if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
goto f_err;
}
if (!sk_X509_push(sk, x)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
if (!ok) {
return n;
}

if (sk_X509_num(sk) <= 0) {
/* No client certificate so the handshake buffer may be discarded. */
ssl3_free_handshake_buffer(ssl);
/* Before incorporating the EncryptedExtensions message to the handshake
* hash, compute the hash that should have been signed. */
if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) {
return -1;
}
assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);

/* TLS does not mind 0 certs returned */
if (ssl->version == SSL3_VERSION) {
al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
goto f_err;
} else if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
(ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
/* Fail for TLS only if we required a certificate */
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
al = SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
} else {
if (ssl_verify_cert_chain(ssl, sk) <= 0) {
al = ssl_verify_alarm_type(ssl->verify_result);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
goto f_err;
}
if (!ssl3_hash_current_message(ssl)) {
return -1;
}

X509_free(ssl->session->peer);
ssl->session->peer = sk_X509_shift(sk);
ssl->session->verify_result = ssl->verify_result;
CBS_init(&encrypted_extensions, ssl->init_msg, n);

sk_X509_pop_free(ssl->session->cert_chain, X509_free);
ssl->session->cert_chain = sk;
/* Inconsistency alert: cert_chain does *not* include the peer's own
* certificate, while we do include it in s3_clnt.c */
/* EncryptedExtensions could include multiple extensions, but the only
* extension that could be negotiated is ChannelID, so there can only be one
* entry.
*
* The payload looks like:
* uint16 extension_type
* uint16 extension_len;
* uint8 x[32];
* uint8 y[32];
* uint8 r[32];
* uint8 s[32]; */

sk = NULL;
if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
!CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
CBS_len(&encrypted_extensions) != 0 ||
extension_type != TLSEXT_TYPE_channel_id ||
CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE);
return -1;
}

ret = 1;
p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
if (!p256) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
return -1;
}

if (0) {
f_err:
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
BN_init(&x);
BN_init(&y);
sig.r = BN_new();
sig.s = BN_new();
if (sig.r == NULL || sig.s == NULL) {
goto err;
}

err:
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return ret;
}
p = CBS_data(&extension);
if (BN_bin2bn(p + 0, 32, &x) == NULL ||
BN_bin2bn(p + 32, 32, &y) == NULL ||
BN_bin2bn(p + 64, 32, sig.r) == NULL ||
BN_bin2bn(p + 96, 32, sig.s) == NULL) {
goto err;
}

static int ssl3_send_server_certificate(SSL *ssl) {
if (ssl->state == SSL3_ST_SW_CERT_A) {
if (!ssl3_output_cert_chain(ssl)) {
return 0;
}
ssl->state = SSL3_ST_SW_CERT_B;
point = EC_POINT_new(p256);
if (!point ||
!EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
goto err;
}

/* SSL3_ST_SW_CERT_B */
return ssl_do_write(ssl);
key = EC_KEY_new();
if (!key || !EC_KEY_set_group(key, p256) ||
!EC_KEY_set_public_key(key, point)) {
goto err;
}

/* We stored the handshake hash in |tlsext_channel_id| the first time that we
* were called. */
if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
ssl->s3->tlsext_channel_id_valid = 0;
goto err;
}

memcpy(ssl->s3->tlsext_channel_id, p, 64);
ret = 1;

err:
BN_free(&x);
BN_free(&y);
BN_free(sig.r);
BN_free(sig.s);
EC_KEY_free(key);
EC_POINT_free(point);
EC_GROUP_free(p256);
return ret;
}

/* send a new session ticket (not necessarily for a new session) */
@@ -2072,154 +2223,3 @@ err:
HMAC_CTX_cleanup(&hctx);
return ret;
}

/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
static int ssl3_get_next_proto(SSL *ssl) {
int ok;
long n;
CBS next_protocol, selected_protocol, padding;

/* Clients cannot send a NextProtocol message if we didn't see the extension
* in their ClientHello */
if (!ssl->s3->next_proto_neg_seen) {
OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
return -1;
}

n = ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message,
&ok);

if (!ok) {
return n;
}

CBS_init(&next_protocol, ssl->init_msg, n);

/* The payload looks like:
* uint8 proto_len;
* uint8 proto[proto_len];
* uint8 padding_len;
* uint8 padding[padding_len]; */
if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
!CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
CBS_len(&next_protocol) != 0 ||
!CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
&ssl->s3->next_proto_negotiated_len)) {
return 0;
}

return 1;
}

/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
static int ssl3_get_channel_id(SSL *ssl) {
int ret = -1, ok;
long n;
uint8_t channel_id_hash[EVP_MAX_MD_SIZE];
size_t channel_id_hash_len;
const uint8_t *p;
uint16_t extension_type;
EC_GROUP *p256 = NULL;
EC_KEY *key = NULL;
EC_POINT *point = NULL;
ECDSA_SIG sig;
BIGNUM x, y;
CBS encrypted_extensions, extension;

n = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID_ENCRYPTED_EXTENSIONS,
ssl_dont_hash_message, &ok);

if (!ok) {
return n;
}

/* Before incorporating the EncryptedExtensions message to the handshake
* hash, compute the hash that should have been signed. */
if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) {
return -1;
}
assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);

if (!ssl3_hash_current_message(ssl)) {
return -1;
}

CBS_init(&encrypted_extensions, ssl->init_msg, n);

/* EncryptedExtensions could include multiple extensions, but the only
* extension that could be negotiated is ChannelID, so there can only be one
* entry.
*
* The payload looks like:
* uint16 extension_type
* uint16 extension_len;
* uint8 x[32];
* uint8 y[32];
* uint8 r[32];
* uint8 s[32]; */

if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
!CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
CBS_len(&encrypted_extensions) != 0 ||
extension_type != TLSEXT_TYPE_channel_id ||
CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE);
return -1;
}

p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
if (!p256) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
return -1;
}

BN_init(&x);
BN_init(&y);
sig.r = BN_new();
sig.s = BN_new();
if (sig.r == NULL || sig.s == NULL) {
goto err;
}

p = CBS_data(&extension);
if (BN_bin2bn(p + 0, 32, &x) == NULL ||
BN_bin2bn(p + 32, 32, &y) == NULL ||
BN_bin2bn(p + 64, 32, sig.r) == NULL ||
BN_bin2bn(p + 96, 32, sig.s) == NULL) {
goto err;
}

point = EC_POINT_new(p256);
if (!point ||
!EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
goto err;
}

key = EC_KEY_new();
if (!key || !EC_KEY_set_group(key, p256) ||
!EC_KEY_set_public_key(key, point)) {
goto err;
}

/* We stored the handshake hash in |tlsext_channel_id| the first time that we
* were called. */
if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
ssl->s3->tlsext_channel_id_valid = 0;
goto err;
}

memcpy(ssl->s3->tlsext_channel_id, p, 64);
ret = 1;

err:
BN_free(&x);
BN_free(&y);
BN_free(sig.r);
BN_free(sig.s);
EC_KEY_free(key);
EC_POINT_free(point);
EC_GROUP_free(p256);
return ret;
}

+ 2
- 6
ssl/ssl_lib.c Visa fil

@@ -514,13 +514,13 @@ void SSL_free(SSL *ssl) {
void SSL_set_connect_state(SSL *ssl) {
ssl->server = 0;
ssl->state = SSL_ST_CONNECT;
ssl->handshake_func = ssl->method->ssl_connect;
ssl->handshake_func = ssl3_connect;
}

void SSL_set_accept_state(SSL *ssl) {
ssl->server = 1;
ssl->state = SSL_ST_ACCEPT;
ssl->handshake_func = ssl->method->ssl_accept;
ssl->handshake_func = ssl3_accept;
}

void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio) {
@@ -579,8 +579,6 @@ int SSL_connect(SSL *ssl) {
SSL_set_connect_state(ssl);
}

assert(ssl->handshake_func == ssl->method->ssl_connect);

return SSL_do_handshake(ssl);
}

@@ -590,8 +588,6 @@ int SSL_accept(SSL *ssl) {
SSL_set_accept_state(ssl);
}

assert(ssl->handshake_func == ssl->method->ssl_accept);

return SSL_do_handshake(ssl);
}



Laddar…
Avbryt
Spara