Add TLS 1.3 1-RTT.

This adds the machinery for doing TLS 1.3 1RTT.

Change-Id: I736921ffe9dc6f6e64a08a836df6bb166d20f504
Reviewed-on: https://boringssl-review.googlesource.com/8720
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Steven Valdez 2016-07-11 13:19:03 -04:00 committed by CQ bot account: commit-bot@chromium.org
parent 4ee027fd05
commit 143e8b3fd9
27 changed files with 3250 additions and 181 deletions

View File

@ -44,6 +44,7 @@ SSL,141,DH_P_TOO_LONG
SSL,142,DIGEST_CHECK_FAILED SSL,142,DIGEST_CHECK_FAILED
SSL,254,DOWNGRADE_DETECTED SSL,254,DOWNGRADE_DETECTED
SSL,143,DTLS_MESSAGE_TOO_BIG SSL,143,DTLS_MESSAGE_TOO_BIG
SSL,257,DUPLICATE_EXTENSION
SSL,144,ECC_CERT_NOT_FOR_SIGNING SSL,144,ECC_CERT_NOT_FOR_SIGNING
SSL,145,EMS_STATE_INCONSISTENT SSL,145,EMS_STATE_INCONSISTENT
SSL,146,ENCRYPTED_LENGTH_TOO_LONG SSL,146,ENCRYPTED_LENGTH_TOO_LONG
@ -59,6 +60,7 @@ SSL,155,HTTPS_PROXY_REQUEST
SSL,156,HTTP_REQUEST SSL,156,HTTP_REQUEST
SSL,157,INAPPROPRIATE_FALLBACK SSL,157,INAPPROPRIATE_FALLBACK
SSL,158,INVALID_COMMAND SSL,158,INVALID_COMMAND
SSL,256,INVALID_COMPRESSION_LIST
SSL,159,INVALID_MESSAGE SSL,159,INVALID_MESSAGE
SSL,251,INVALID_OUTER_RECORD_TYPE SSL,251,INVALID_OUTER_RECORD_TYPE
SSL,160,INVALID_SSL_SESSION SSL,160,INVALID_SSL_SESSION
@ -66,6 +68,7 @@ SSL,161,INVALID_TICKET_KEYS_LENGTH
SSL,162,LENGTH_MISMATCH SSL,162,LENGTH_MISMATCH
SSL,163,LIBRARY_HAS_NO_CIPHERS SSL,163,LIBRARY_HAS_NO_CIPHERS
SSL,164,MISSING_EXTENSION SSL,164,MISSING_EXTENSION
SSL,258,MISSING_KEY_SHARE
SSL,165,MISSING_RSA_CERTIFICATE SSL,165,MISSING_RSA_CERTIFICATE
SSL,166,MISSING_TMP_DH_KEY SSL,166,MISSING_TMP_DH_KEY
SSL,167,MISSING_TMP_ECDH_KEY SSL,167,MISSING_TMP_ECDH_KEY

View File

@ -548,6 +548,8 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define DTLS1_VERSION 0xfeff #define DTLS1_VERSION 0xfeff
#define DTLS1_2_VERSION 0xfefd #define DTLS1_2_VERSION 0xfefd
#define TLS1_3_DRAFT_VERSION 13
/* SSL_CTX_set_min_version sets the minimum protocol version for |ctx| to /* SSL_CTX_set_min_version sets the minimum protocol version for |ctx| to
* |version|. */ * |version|. */
OPENSSL_EXPORT void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version); OPENSSL_EXPORT void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version);
@ -2655,6 +2657,7 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED #define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
#define SSL_AD_MISSING_EXTENSION TLS1_AD_MISSING_EXTENSION
#define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION #define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
#define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME #define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
@ -2919,6 +2922,7 @@ OPENSSL_EXPORT void SSL_CTX_set_dos_protection_cb(
#define SSL_ST_INIT (SSL_ST_CONNECT | SSL_ST_ACCEPT) #define SSL_ST_INIT (SSL_ST_CONNECT | SSL_ST_ACCEPT)
#define SSL_ST_OK 0x03 #define SSL_ST_OK 0x03
#define SSL_ST_RENEGOTIATE (0x04 | SSL_ST_INIT) #define SSL_ST_RENEGOTIATE (0x04 | SSL_ST_INIT)
#define SSL_ST_TLS13 (0x05 | SSL_ST_INIT)
/* SSL_CB_* are possible values for the |type| parameter in the info /* SSL_CB_* are possible values for the |type| parameter in the info
* callback and the bitmasks that make them up. */ * callback and the bitmasks that make them up. */
@ -3538,6 +3542,7 @@ OPENSSL_EXPORT int SSL_set_private_key_digest_prefs(SSL *ssl,
typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD; typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
typedef struct ssl3_enc_method SSL3_ENC_METHOD; typedef struct ssl3_enc_method SSL3_ENC_METHOD;
typedef struct ssl_aead_ctx_st SSL_AEAD_CTX; typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
typedef struct ssl_handshake_st SSL_HANDSHAKE;
struct ssl_cipher_st { struct ssl_cipher_st {
/* name is the OpenSSL name for the cipher. */ /* name is the OpenSSL name for the cipher. */
@ -3578,6 +3583,8 @@ struct ssl_session_st {
* A zero indicates that the value is unknown. */ * A zero indicates that the value is unknown. */
uint32_t key_exchange_info; uint32_t key_exchange_info;
/* master_key, in TLS 1.2 and below, is the master secret associated with the
* session. In TLS 1.3 and up, it is the resumption secret. */
int master_key_length; int master_key_length;
uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH]; uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
@ -4234,11 +4241,21 @@ typedef struct ssl3_state_st {
uint8_t *pending_message; uint8_t *pending_message;
uint32_t pending_message_len; uint32_t pending_message_len;
/* hs is the handshake state for the current handshake or NULL if there isn't
* one. */
SSL_HANDSHAKE *hs;
uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
uint8_t write_traffic_secret_len;
uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
uint8_t read_traffic_secret_len;
uint8_t exporter_secret[EVP_MAX_MD_SIZE];
uint8_t exporter_secret_len;
/* State pertaining to the pending handshake. /* State pertaining to the pending handshake.
* *
* TODO(davidben): State is current spread all over the place. Move * TODO(davidben): Move everything not needed after the handshake completes to
* pending handshake state here so it can be managed separately from * |hs| and remove this. */
* established connection state in case of renegotiations. */
struct { struct {
uint8_t finish_md[EVP_MAX_MD_SIZE]; uint8_t finish_md[EVP_MAX_MD_SIZE];
uint8_t finish_md_len; uint8_t finish_md_len;
@ -4715,6 +4732,9 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
#define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253 #define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253
#define SSL_R_DOWNGRADE_DETECTED 254 #define SSL_R_DOWNGRADE_DETECTED 254
#define SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE 255 #define SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE 255
#define SSL_R_INVALID_COMPRESSION_LIST 256
#define SSL_R_DUPLICATE_EXTENSION 257
#define SSL_R_MISSING_KEY_SHARE 258
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020

View File

@ -392,6 +392,8 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_MT_CLIENT_HELLO 1 #define SSL3_MT_CLIENT_HELLO 1
#define SSL3_MT_SERVER_HELLO 2 #define SSL3_MT_SERVER_HELLO 2
#define SSL3_MT_NEW_SESSION_TICKET 4 #define SSL3_MT_NEW_SESSION_TICKET 4
#define SSL3_MT_HELLO_RETRY_REQUEST 6
#define SSL3_MT_ENCRYPTED_EXTENSIONS 8
#define SSL3_MT_CERTIFICATE 11 #define SSL3_MT_CERTIFICATE 11
#define SSL3_MT_SERVER_KEY_EXCHANGE 12 #define SSL3_MT_SERVER_KEY_EXCHANGE 12
#define SSL3_MT_CERTIFICATE_REQUEST 13 #define SSL3_MT_CERTIFICATE_REQUEST 13
@ -401,6 +403,7 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_MT_FINISHED 20 #define SSL3_MT_FINISHED 20
#define SSL3_MT_CERTIFICATE_STATUS 22 #define SSL3_MT_CERTIFICATE_STATUS 22
#define SSL3_MT_SUPPLEMENTAL_DATA 23 #define SSL3_MT_SUPPLEMENTAL_DATA 23
#define SSL3_MT_KEY_UPDATE 24
#define SSL3_MT_NEXT_PROTO 67 #define SSL3_MT_NEXT_PROTO 67
#define SSL3_MT_CHANNEL_ID 203 #define SSL3_MT_CHANNEL_ID 203
#define DTLS1_MT_HELLO_VERIFY_REQUEST 3 #define DTLS1_MT_HELLO_VERIFY_REQUEST 3

View File

@ -211,6 +211,14 @@ extern "C" {
#define TLSEXT_TYPE_early_data 42 #define TLSEXT_TYPE_early_data 42
#define TLSEXT_TYPE_cookie 44 #define TLSEXT_TYPE_cookie 44
/* TLSEXT_TYPE_draft_version is the extension used to advertise the TLS 1.3
* draft implemented.
*
* See
* https://github.com/tlswg/tls13-spec/wiki/Implementations#version-negotiation
*/
#define TLSEXT_TYPE_draft_version 0xff02
/* ExtensionType value from RFC5746 */ /* ExtensionType value from RFC5746 */
#define TLSEXT_TYPE_renegotiate 0xff01 #define TLSEXT_TYPE_renegotiate 0xff01

View File

@ -31,6 +31,10 @@ add_library(
t1_lib.c t1_lib.c
tls_method.c tls_method.c
tls_record.c tls_record.c
tls13_both.c
tls13_client.c
tls13_enc.c
tls13_server.c
) )
target_link_libraries(ssl crypto) target_link_libraries(ssl crypto)

View File

@ -200,7 +200,9 @@ int ssl3_connect(SSL *ssl) {
case SSL_ST_CONNECT: case SSL_ST_CONNECT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1); ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
if (!ssl->method->begin_handshake(ssl)) { ssl->s3->hs = ssl_handshake_new(tls13_client_handshake);
if (ssl->s3->hs == NULL ||
!ssl->method->begin_handshake(ssl)) {
ret = -1; ret = -1;
goto end; goto end;
} }
@ -244,6 +246,9 @@ int ssl3_connect(SSL *ssl) {
case SSL3_ST_CR_SRVR_HELLO_A: case SSL3_ST_CR_SRVR_HELLO_A:
ret = ssl3_get_server_hello(ssl); ret = ssl3_get_server_hello(ssl);
if (ssl->state == SSL_ST_TLS13) {
break;
}
if (ret <= 0) { if (ret <= 0) {
goto end; goto end;
} }
@ -490,6 +495,14 @@ int ssl3_connect(SSL *ssl) {
} }
break; break;
case SSL_ST_TLS13:
ret = tls13_handshake(ssl);
if (ret <= 0) {
goto end;
}
ssl->state = SSL_ST_OK;
break;
case SSL_ST_OK: case SSL_ST_OK:
/* clean a few things up */ /* clean a few things up */
ssl3_cleanup_key_block(ssl); ssl3_cleanup_key_block(ssl);
@ -499,6 +512,9 @@ int ssl3_connect(SSL *ssl) {
/* Remove write buffering now. */ /* Remove write buffering now. */
ssl_free_wbio_buffer(ssl); ssl_free_wbio_buffer(ssl);
ssl_handshake_free(ssl->s3->hs);
ssl->s3->hs = NULL;
const int is_initial_handshake = !ssl->s3->initial_handshake_complete; const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
ssl->s3->tmp.in_false_start = 0; ssl->s3->tmp.in_false_start = 0;
@ -730,8 +746,7 @@ static int ssl3_get_server_hello(SSL *ssl) {
uint16_t server_wire_version, server_version, cipher_suite; uint16_t server_wire_version, server_version, cipher_suite;
uint8_t compression_method; uint8_t compression_method;
int ret = int ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO, ssl_hash_message);
if (ret <= 0) { if (ret <= 0) {
uint32_t err = ERR_peek_error(); uint32_t err = ERR_peek_error();
if (ERR_GET_LIB(err) == ERR_LIB_SSL && if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
@ -747,14 +762,16 @@ static int ssl3_get_server_hello(SSL *ssl) {
return ret; return ret;
} }
if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO &&
ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return -1;
}
CBS_init(&server_hello, ssl->init_msg, ssl->init_num); CBS_init(&server_hello, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&server_hello, &server_wire_version) || if (!CBS_get_u16(&server_hello, &server_wire_version)) {
!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
!CBS_get_u16(&server_hello, &cipher_suite) ||
!CBS_get_u8(&server_hello, &compression_method)) {
al = SSL_AD_DECODE_ERROR; al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err; goto f_err;
@ -784,6 +801,27 @@ static int ssl3_get_server_hello(SSL *ssl) {
goto f_err; goto f_err;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
ssl->state = SSL_ST_TLS13;
return 1;
}
if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return -1;
}
if (!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
!CBS_get_u16(&server_hello, &cipher_suite) ||
!CBS_get_u8(&server_hello, &compression_method)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
/* Copy over the server random. */ /* Copy over the server random. */
memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);

View File

@ -201,7 +201,9 @@ int ssl3_accept(SSL *ssl) {
case SSL_ST_ACCEPT: case SSL_ST_ACCEPT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1); ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
if (!ssl->method->begin_handshake(ssl)) { ssl->s3->hs = ssl_handshake_new(tls13_server_handshake);
if (ssl->s3->hs == NULL ||
!ssl->method->begin_handshake(ssl)) {
ret = -1; ret = -1;
goto end; goto end;
} }
@ -226,6 +228,9 @@ int ssl3_accept(SSL *ssl) {
case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C: case SSL3_ST_SR_CLNT_HELLO_C:
ret = ssl3_get_client_hello(ssl); ret = ssl3_get_client_hello(ssl);
if (ssl->state == SSL_ST_TLS13) {
break;
}
if (ret <= 0) { if (ret <= 0) {
goto end; goto end;
} }
@ -458,6 +463,14 @@ int ssl3_accept(SSL *ssl) {
} }
break; break;
case SSL_ST_TLS13:
ret = tls13_handshake(ssl);
if (ret <= 0) {
goto end;
}
ssl->state = SSL_ST_OK;
break;
case SSL_ST_OK: case SSL_ST_OK:
/* clean a few things up */ /* clean a few things up */
ssl3_cleanup_key_block(ssl); ssl3_cleanup_key_block(ssl);
@ -467,6 +480,9 @@ int ssl3_accept(SSL *ssl) {
/* remove buffering on output */ /* remove buffering on output */
ssl_free_wbio_buffer(ssl); ssl_free_wbio_buffer(ssl);
ssl_handshake_free(ssl->s3->hs);
ssl->s3->hs = NULL;
/* If we aren't retaining peer certificates then we can discard it /* If we aren't retaining peer certificates then we can discard it
* now. */ * now. */
if (ssl->ctx->retain_only_sha256_of_client_certs) { if (ssl->ctx->retain_only_sha256_of_client_certs) {
@ -569,10 +585,7 @@ static int ssl3_get_client_hello(SSL *ssl) {
} }
CBS_init(&client_hello, ssl->init_msg, ssl->init_num); CBS_init(&client_hello, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&client_hello, &client_wire_version) || if (!CBS_get_u16(&client_hello, &client_wire_version)) {
!CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
al = SSL_AD_DECODE_ERROR; al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err; goto f_err;
@ -584,20 +597,6 @@ static int ssl3_get_client_hello(SSL *ssl) {
* see RFC 2246, Appendix E, second paragraph) */ * see RFC 2246, Appendix E, second paragraph) */
ssl->client_version = client_wire_version; ssl->client_version = client_wire_version;
/* Load the client random. */
memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
if (SSL_IS_DTLS(ssl)) {
CBS cookie;
if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
}
uint16_t min_version, max_version; uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) { if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
al = SSL_AD_PROTOCOL_VERSION; al = SSL_AD_PROTOCOL_VERSION;
@ -632,6 +631,33 @@ static int ssl3_get_client_hello(SSL *ssl) {
goto f_err; goto f_err;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
ssl->state = SSL_ST_TLS13;
return 1;
}
if (!CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
/* Load the client random. */
memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
if (SSL_IS_DTLS(ssl)) {
CBS cookie;
if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
}
}
ssl->hit = 0; ssl->hit = 0;
int send_new_ticket = 0; int send_new_ticket = 0;
switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) { switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) {

View File

@ -615,6 +615,9 @@ void SSL_ECDH_CTX_init_for_cecpq1(SSL_ECDH_CTX *ctx);
* call it in the zero state. */ * call it in the zero state. */
void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx); void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx);
/* SSL_ECDH_CTX_get_id returns the group ID for |ctx|. */
uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx);
/* SSL_ECDH_CTX_get_key calls the |get_key| method of |SSL_ECDH_METHOD|. */ /* SSL_ECDH_CTX_get_key calls the |get_key| method of |SSL_ECDH_METHOD|. */
int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out); int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out);
@ -772,6 +775,141 @@ int ssl_add_client_CA_list(SSL *ssl, CBB *cbb);
int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf); int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf);
/* TLS 1.3 key derivation. */
/* tls13_init_key_schedule initializes the handshake hash and key derivation
* state with the given resumption context. The cipher suite and PRF hash must
* have been selected at this point. It returns one on success and zero on
* error. */
int tls13_init_key_schedule(SSL *ssl, const uint8_t *resumption_ctx,
size_t resumption_ctx_len);
/* tls13_advance_key_schedule incorporates |in| into the key schedule with
* HKDF-Extract. It returns one on success and zero on error. */
int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len);
/* tls13_get_context_hashes writes Hash(Handshake Context) +
* Hash(resumption_context) to |out| which much have room for at least 2 *
* |EVP_MAX_MD_SIZE| bytes. On success, it returns one and sets |*out_len| to
* the number of bytes written. Otherwise, it returns zero. */
int tls13_get_context_hashes(SSL *ssl, uint8_t *out, size_t *out_len);
enum tls_record_type_t {
type_early_handshake,
type_early_data,
type_handshake,
type_data,
};
/* tls13_set_traffic_key sets the read or write traffic keys to |traffic_secret|
* for the given traffic phase |type|. It returns one on success and zero on
* error. */
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
enum evp_aead_direction_t direction,
const uint8_t *traffic_secret,
size_t traffic_secret_len);
/* tls13_set_handshake_traffic derives the handshake traffic secret and
* switches both read and write traffic to it. It returns one on success and
* zero on error. */
int tls13_set_handshake_traffic(SSL *ssl);
/* tls13_derive_traffic_secret_0 derives the initial application data traffic
* secret based on the handshake transcripts and |master_secret|. It returns one
* on success and zero on error. */
int tls13_derive_traffic_secret_0(SSL *ssl);
/* tls13_finalize_keys derives the |exporter_secret| and |resumption_secret|. */
int tls13_finalize_keys(SSL *ssl);
/* tls13_export_keying_material provides and exporter interface to use the
* |exporter_secret|. */
int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
const char *label, size_t label_len,
const uint8_t *context, size_t context_len,
int use_context);
/* tls13_finished_mac calculates the MAC of the handshake transcript to verify
* the integrity of the Finished message, and stores the result in |out| and
* length in |out_len|. |is_server| is 1 if this is for the Server Finished and
* 0 for the Client Finished. */
int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server);
/* Handshake functions. */
enum ssl_hs_wait_t {
ssl_hs_error,
ssl_hs_ok,
ssl_hs_read_message,
ssl_hs_write_message,
ssl_hs_flush,
ssl_hs_x509_lookup,
ssl_hs_private_key_operation,
};
struct ssl_handshake_st {
/* wait contains the operation |do_handshake| is currently blocking on or
* |ssl_hs_ok| if none. */
enum ssl_hs_wait_t wait;
/* do_handshake runs the handshake. On completion, it returns |ssl_hs_ok|.
* Otherwise, it returns a value corresponding to what operation is needed to
* progress. */
enum ssl_hs_wait_t (*do_handshake)(SSL *ssl);
int state;
size_t hash_len;
uint8_t resumption_hash[EVP_MAX_MD_SIZE];
uint8_t secret[EVP_MAX_MD_SIZE];
uint8_t traffic_secret_0[EVP_MAX_MD_SIZE];
SSL_ECDH_CTX *groups;
size_t groups_len;
uint8_t *public_key;
size_t public_key_len;
uint8_t *cert_context;
size_t cert_context_len;
} /* SSL_HANDSHAKE */;
SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl));
/* ssl_handshake_free releases all memory associated with |hs|. */
void ssl_handshake_free(SSL_HANDSHAKE *hs);
/* tls13_handshake runs the TLS 1.3 handshake. It returns one on success and <=
* 0 on error. */
int tls13_handshake(SSL *ssl);
/* The following are implementations of |do_handshake| for the client and
* server. */
enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl);
enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl);
/* tls13_check_message_type checks if the current message has type |type|. If so
* it returns one. Otherwise, it sends an alert and returns zero. */
int tls13_check_message_type(SSL *ssl, int type);
int tls13_process_certificate(SSL *ssl);
int tls13_process_certificate_verify(SSL *ssl);
int tls13_process_finished(SSL *ssl);
int tls13_prepare_certificate(SSL *ssl);
enum ssl_private_key_result_t tls13_prepare_certificate_verify(
SSL *ssl, int is_first_run);
int tls13_prepare_finished(SSL *ssl);
int ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents);
int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents);
int ext_key_share_add_serverhello(SSL *ssl, CBB *out);
/* Underdocumented functions. /* Underdocumented functions.
* *
* Functions below here haven't been touched up and may be underdocumented. */ * Functions below here haven't been touched up and may be underdocumented. */

View File

@ -213,6 +213,7 @@ void ssl3_free(SSL *ssl) {
OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint); OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
ssl3_free_handshake_buffer(ssl); ssl3_free_handshake_buffer(ssl);
ssl3_free_handshake_hash(ssl); ssl3_free_handshake_hash(ssl);
ssl_handshake_free(ssl->s3->hs);
OPENSSL_free(ssl->s3->next_proto_negotiated); OPENSSL_free(ssl->s3->next_proto_negotiated);
OPENSSL_free(ssl->s3->alpn_selected); OPENSSL_free(ssl->s3->alpn_selected);
SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx); SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);

View File

@ -443,6 +443,13 @@ start:
/* Process unexpected records. */ /* Process unexpected records. */
if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) { if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
/* TODO(svaldez): Handle TLS 1.3 post-handshake messages. For now,
* silently drop all handshake records. */
rr->length = 0;
goto start;
}
/* If peer renegotiations are disabled, all out-of-order handshake records /* If peer renegotiations are disabled, all out-of-order handshake records
* are fatal. Renegotiations as a server are never supported. */ * are fatal. Renegotiations as a server are never supported. */
if (ssl->server || !ssl3_can_renegotiate(ssl)) { if (ssl->server || !ssl3_can_renegotiate(ssl)) {

View File

@ -567,6 +567,19 @@ void SSL_ECDH_CTX_init_for_cecpq1(SSL_ECDH_CTX *ctx) {
ctx->method = &kCECPQ1Method; ctx->method = &kCECPQ1Method;
} }
void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
if (ctx->method == NULL) {
return;
}
ctx->method->cleanup(ctx);
ctx->method = NULL;
ctx->data = NULL;
}
uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx) {
return ctx->method->group_id;
}
int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) { int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) {
if (ctx->method == NULL) { if (ctx->method == NULL) {
return 0; return 0;
@ -581,15 +594,6 @@ int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) {
return ctx->method->add_key(cbb, out_contents); return ctx->method->add_key(cbb, out_contents);
} }
void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx) {
if (ctx->method == NULL) {
return;
}
ctx->method->cleanup(ctx);
ctx->method = NULL;
ctx->data = NULL;
}
int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) { int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
return ctx->method->offer(ctx, out_public_key); return ctx->method->offer(ctx, out_public_key);
} }

View File

@ -1122,7 +1122,8 @@ int SSL_get_verify_depth(const SSL *ssl) {
} }
int SSL_get_extms_support(const SSL *ssl) { int SSL_get_extms_support(const SSL *ssl) {
return ssl->s3->tmp.extended_master_secret == 1; return ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
ssl->s3->tmp.extended_master_secret == 1;
} }
int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) { int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {

View File

@ -501,6 +501,11 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
return 0; return 0;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return tls13_export_keying_material(ssl, out, out_len, label, label_len,
context, context_len, use_context);
}
size_t seed_len = 2 * SSL3_RANDOM_SIZE; size_t seed_len = 2 * SSL3_RANDOM_SIZE;
if (use_context) { if (use_context) {
if (context_len >= 1u << 16) { if (context_len >= 1u << 16) {

View File

@ -808,6 +808,10 @@ static int ext_ri_add_clienthello(SSL *ssl, CBB *out) {
static int ext_ri_parse_serverhello(SSL *ssl, uint8_t *out_alert, static int ext_ri_parse_serverhello(SSL *ssl, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
if (contents != NULL && ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
/* Servers may not switch between omitting the extension and supporting it. /* Servers may not switch between omitting the extension and supporting it.
* See RFC 5746, sections 3.5 and 4.2. */ * See RFC 5746, sections 3.5 and 4.2. */
if (ssl->s3->initial_handshake_complete && if (ssl->s3->initial_handshake_complete &&
@ -877,6 +881,10 @@ static int ext_ri_parse_clienthello(SSL *ssl, uint8_t *out_alert,
* called after the initial handshake. */ * called after the initial handshake. */
assert(!ssl->s3->initial_handshake_complete); assert(!ssl->s3->initial_handshake_complete);
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
CBS fake_contents; CBS fake_contents;
static const uint8_t kFakeExtension[] = {0}; static const uint8_t kFakeExtension[] = {0};
@ -917,6 +925,10 @@ static int ext_ri_parse_clienthello(SSL *ssl, uint8_t *out_alert,
} }
static int ext_ri_add_serverhello(SSL *ssl, CBB *out) { static int ext_ri_add_serverhello(SSL *ssl, CBB *out) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
CBB contents, prev_finished; CBB contents, prev_finished;
if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) || if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
!CBB_add_u16_length_prefixed(out, &contents) || !CBB_add_u16_length_prefixed(out, &contents) ||
@ -960,7 +972,12 @@ static int ext_ems_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
if (ssl->version == SSL3_VERSION || CBS_len(contents) != 0) { if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
ssl->version == SSL3_VERSION) {
return 0;
}
if (CBS_len(contents) != 0) {
return 0; return 0;
} }
@ -970,7 +987,12 @@ static int ext_ems_parse_serverhello(SSL *ssl, uint8_t *out_alert,
static int ext_ems_parse_clienthello(SSL *ssl, uint8_t *out_alert, static int ext_ems_parse_clienthello(SSL *ssl, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
if (ssl->version == SSL3_VERSION || contents == NULL) { if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
ssl->version == SSL3_VERSION) {
return 1;
}
if (contents == NULL) {
return 1; return 1;
} }
@ -1038,6 +1060,10 @@ static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
/* If |SSL_OP_NO_TICKET| is set then no extension will have been sent and /* If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
* this function should never be called, even if the server tries to send the * this function should never be called, even if the server tries to send the
* extension. */ * extension. */
@ -1185,6 +1211,10 @@ static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
} }
static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) { static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
/* The extension shouldn't be sent when resuming sessions. */ /* The extension shouldn't be sent when resuming sessions. */
if (ssl->hit || if (ssl->hit ||
!ssl->s3->tmp.ocsp_stapling_requested || !ssl->s3->tmp.ocsp_stapling_requested ||
@ -1229,6 +1259,10 @@ static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
/* If any of these are false then we should never have sent the NPN /* If any of these are false then we should never have sent the NPN
* extension in the ClientHello and thus this function should never have been * extension in the ClientHello and thus this function should never have been
* called. */ * called. */
@ -1279,6 +1313,10 @@ static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
static int ext_npn_parse_clienthello(SSL *ssl, uint8_t *out_alert, static int ext_npn_parse_clienthello(SSL *ssl, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
if (contents != NULL && CBS_len(contents) != 0) { if (contents != NULL && CBS_len(contents) != 0) {
return 0; return 0;
} }
@ -1555,6 +1593,10 @@ static int ext_channel_id_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
assert(!SSL_IS_DTLS(ssl)); assert(!SSL_IS_DTLS(ssl));
assert(ssl->tlsext_channel_id_enabled); assert(ssl->tlsext_channel_id_enabled);
@ -1583,6 +1625,10 @@ static int ext_channel_id_parse_clienthello(SSL *ssl, uint8_t *out_alert,
} }
static int ext_channel_id_add_serverhello(SSL *ssl, CBB *out) { static int ext_channel_id_add_serverhello(SSL *ssl, CBB *out) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
if (!ssl->s3->tlsext_channel_id_valid) { if (!ssl->s3->tlsext_channel_id_valid) {
return 1; return 1;
} }
@ -1801,6 +1847,10 @@ static int ext_ec_point_parse_serverhello(SSL *ssl, uint8_t *out_alert,
return 1; return 1;
} }
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
CBS ec_point_format_list; CBS ec_point_format_list;
if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) || if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
CBS_len(contents) != 0) { CBS_len(contents) != 0) {
@ -1820,10 +1870,18 @@ static int ext_ec_point_parse_serverhello(SSL *ssl, uint8_t *out_alert,
static int ext_ec_point_parse_clienthello(SSL *ssl, uint8_t *out_alert, static int ext_ec_point_parse_clienthello(SSL *ssl, uint8_t *out_alert,
CBS *contents) { CBS *contents) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
return ext_ec_point_parse_serverhello(ssl, out_alert, contents); return ext_ec_point_parse_serverhello(ssl, out_alert, contents);
} }
static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) { static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) {
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
const uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey; const uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
const uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth; const uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
const int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA); const int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
@ -1836,6 +1894,182 @@ static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) {
} }
/* Draft Version Extension */
static int ext_draft_version_add_clienthello(SSL *ssl, CBB *out) {
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version) ||
max_version >= TLS1_3_VERSION) {
return 1;
}
CBB contents;
if (!CBB_add_u16(out, TLSEXT_TYPE_draft_version) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16(&contents, TLS1_3_DRAFT_VERSION)) {
return 0;
}
return CBB_flush(out);
}
/* Key Share
*
* https://tools.ietf.org/html/draft-ietf-tls-tls13-12 */
static int ext_key_share_add_clienthello(SSL *ssl, CBB *out) {
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
}
if (max_version < TLS1_3_VERSION || !ssl_any_ec_cipher_suites_enabled(ssl)) {
return 1;
}
CBB contents, kse_bytes;
if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
return 0;
}
const uint16_t *groups;
size_t groups_len;
tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
ssl->s3->hs->groups = OPENSSL_malloc(groups_len * sizeof(SSL_ECDH_CTX));
if (ssl->s3->hs->groups == NULL) {
return 0;
}
memset(ssl->s3->hs->groups, 0, groups_len * sizeof(SSL_ECDH_CTX));
ssl->s3->hs->groups_len = groups_len;
for (size_t i = 0; i < groups_len; i++) {
if (!CBB_add_u16(&kse_bytes, groups[i])) {
return 0;
}
CBB key_exchange;
if (!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
!SSL_ECDH_CTX_init(&ssl->s3->hs->groups[i], groups[i]) ||
!SSL_ECDH_CTX_offer(&ssl->s3->hs->groups[i], &key_exchange) ||
!CBB_flush(&kse_bytes)) {
return 0;
}
}
return CBB_flush(out);
}
int ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents) {
CBS peer_key;
uint16_t group;
if (!CBS_get_u16(contents, &group) ||
!CBS_get_u16_length_prefixed(contents, &peer_key)) {
*out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
SSL_ECDH_CTX *group_ctx = NULL;
for (size_t i = 0; i < ssl->s3->hs->groups_len; i++) {
if (SSL_ECDH_CTX_get_id(&ssl->s3->hs->groups[i]) == group) {
group_ctx = &ssl->s3->hs->groups[i];
break;
}
}
if (group_ctx == NULL) {
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return 0;
}
if (!SSL_ECDH_CTX_finish(group_ctx, out_secret, out_secret_len, out_alert,
CBS_data(&peer_key), CBS_len(&peer_key))) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
for (size_t i = 0; i < ssl->s3->hs->groups_len; i++) {
SSL_ECDH_CTX_cleanup(&ssl->s3->hs->groups[i]);
}
OPENSSL_free(ssl->s3->hs->groups);
ssl->s3->hs->groups = NULL;
return 1;
}
int ext_key_share_parse_clienthello(SSL *ssl, uint8_t **out_secret,
size_t *out_secret_len, uint8_t *out_alert,
CBS *contents) {
uint16_t group_id;
CBS key_shares;
if (!tls1_get_shared_group(ssl, &group_id) ||
!CBS_get_u16_length_prefixed(contents, &key_shares)) {
return 0;
}
int found = 0;
while (CBS_len(&key_shares) > 0) {
uint16_t id;
CBS peer_key;
if (!CBS_get_u16(&key_shares, &id) ||
!CBS_get_u16_length_prefixed(&key_shares, &peer_key)) {
return 0;
}
if (id != group_id || found) {
continue;
}
SSL_ECDH_CTX group;
memset(&group, 0, sizeof(SSL_ECDH_CTX));
CBB public_key;
if (!CBB_init(&public_key, 0) ||
!SSL_ECDH_CTX_init(&group, group_id) ||
!SSL_ECDH_CTX_accept(&group, &public_key, out_secret, out_secret_len,
out_alert, CBS_data(&peer_key),
CBS_len(&peer_key)) ||
!CBB_finish(&public_key, &ssl->s3->hs->public_key,
&ssl->s3->hs->public_key_len)) {
SSL_ECDH_CTX_cleanup(&group);
CBB_cleanup(&public_key);
return 0;
}
SSL_ECDH_CTX_cleanup(&group);
found = 1;
}
return found;
}
int ext_key_share_add_serverhello(SSL *ssl, CBB *out) {
if (ssl->s3->tmp.new_cipher->algorithm_mkey != SSL_kECDHE) {
return 1;
}
uint16_t group_id;
CBB kse_bytes, public_key;
if (!tls1_get_shared_group(ssl, &group_id) ||
!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
!CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
!CBB_add_bytes(&public_key, ssl->s3->hs->public_key,
ssl->s3->hs->public_key_len) ||
!CBB_flush(out)) {
return 0;
}
return 1;
}
/* Negotiated Groups /* Negotiated Groups
* *
* https://tools.ietf.org/html/rfc4492#section-5.1.2 * https://tools.ietf.org/html/rfc4492#section-5.1.2
@ -2029,6 +2263,22 @@ static const struct tls_extension kExtensions[] = {
ext_ec_point_parse_clienthello, ext_ec_point_parse_clienthello,
ext_ec_point_add_serverhello, ext_ec_point_add_serverhello,
}, },
{
TLSEXT_TYPE_draft_version,
NULL,
ext_draft_version_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
{
TLSEXT_TYPE_key_share,
NULL,
ext_key_share_add_clienthello,
forbid_parse_serverhello,
ignore_parse_clienthello,
dont_add_serverhello,
},
/* The final extension must be non-empty. WebSphere Application Server 7.0 is /* The final extension must be non-empty. WebSphere Application Server 7.0 is
* intolerant to the last extension being zero-length. See * intolerant to the last extension being zero-length. See
* https://crbug.com/363583. */ * https://crbug.com/363583. */
@ -2175,8 +2425,9 @@ int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out) {
goto err; goto err;
} }
/* Discard empty extensions blocks. */ /* Discard empty extensions blocks before TLS 1.3. */
if (CBB_len(&extensions) == 0) { if (ssl3_protocol_version(ssl) < TLS1_3_VERSION &&
CBB_len(&extensions) == 0) {
CBB_discard_child(out); CBB_discard_child(out);
} }
@ -2287,57 +2538,58 @@ int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs) {
OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits); OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits);
static int ssl_scan_serverhello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) { static int ssl_scan_serverhello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) {
uint32_t received = 0; /* Before TLS 1.3, ServerHello extensions blocks may be omitted if empty. */
if (CBS_len(cbs) == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
return 1;
}
if (CBS_len(cbs) != 0) { /* Decode the extensions block and check it is valid. */
/* Decode the extensions block and check it is valid. */ CBS extensions;
CBS extensions; if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
if (!CBS_get_u16_length_prefixed(cbs, &extensions) || !tls1_check_duplicate_extensions(&extensions)) {
!tls1_check_duplicate_extensions(&extensions)) { *out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
uint32_t received = 0;
while (CBS_len(&extensions) != 0) {
uint16_t type;
CBS extension;
/* Decode the next extension. */
if (!CBS_get_u16(&extensions, &type) ||
!CBS_get_u16_length_prefixed(&extensions, &extension)) {
*out_alert = SSL_AD_DECODE_ERROR; *out_alert = SSL_AD_DECODE_ERROR;
return 0; return 0;
} }
unsigned ext_index;
const struct tls_extension *const ext =
tls_extension_find(&ext_index, type);
while (CBS_len(&extensions) != 0) { if (ext == NULL) {
uint16_t type; if (!custom_ext_parse_serverhello(ssl, out_alert, type, &extension)) {
CBS extension;
/* Decode the next extension. */
if (!CBS_get_u16(&extensions, &type) ||
!CBS_get_u16_length_prefixed(&extensions, &extension)) {
*out_alert = SSL_AD_DECODE_ERROR;
return 0; return 0;
} }
continue;
}
unsigned ext_index; if (!(ssl->s3->tmp.extensions.sent & (1u << ext_index))) {
const struct tls_extension *const ext = /* If the extension was never sent then it is illegal. */
tls_extension_find(&ext_index, type); OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ERR_add_error_dataf("extension :%u", (unsigned)type);
*out_alert = SSL_AD_DECODE_ERROR;
return 0;
}
if (ext == NULL) { received |= (1u << ext_index);
if (!custom_ext_parse_serverhello(ssl, out_alert, type, &extension)) {
return 0;
}
continue;
}
if (!(ssl->s3->tmp.extensions.sent & (1u << ext_index))) { uint8_t alert = SSL_AD_DECODE_ERROR;
/* If the extension was never sent then it is illegal. */ if (!ext->parse_serverhello(ssl, &alert, &extension)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
ERR_add_error_dataf("extension :%u", (unsigned)type); ERR_add_error_dataf("extension: %u", (unsigned)type);
*out_alert = SSL_AD_DECODE_ERROR; *out_alert = alert;
return 0; return 0;
}
received |= (1u << ext_index);
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ext->parse_serverhello(ssl, &alert, &extension)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
ERR_add_error_dataf("extension: %u", (unsigned)type);
*out_alert = alert;
return 0;
}
} }
} }

View File

@ -1045,7 +1045,9 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
if (expect_handshake_done && !config->is_server) { if (expect_handshake_done && !config->is_server) {
bool expect_new_session = bool expect_new_session =
!config->expect_no_session && !config->expect_no_session &&
(!SSL_session_reused(ssl) || config->expect_ticket_renewal); (!SSL_session_reused(ssl) || config->expect_ticket_renewal) &&
/* TODO(svaldez): Implement Session Resumption. */
SSL_version(ssl) != TLS1_3_VERSION;
if (expect_new_session != GetTestState(ssl)->got_new_session) { if (expect_new_session != GetTestState(ssl)->got_new_session) {
fprintf(stderr, fprintf(stderr,
"new session was%s cached, but we expected the opposite\n", "new session was%s cached, but we expected the opposite\n",
@ -1264,7 +1266,8 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
if (config->no_ssl3) { if (config->no_ssl3) {
SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3); SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3);
} }
if (!config->expected_channel_id.empty()) { if (!config->expected_channel_id.empty() ||
config->enable_channel_id) {
SSL_enable_tls_channel_id(ssl.get()); SSL_enable_tls_channel_id(ssl.get());
} }
if (!config->send_channel_id.empty()) { if (!config->send_channel_id.empty()) {

View File

@ -18,8 +18,7 @@ import (
"time" "time"
) )
// TODO(davidben): Flip this to true when the C code lands. const enableTLS13Handshake = true
const enableTLS13Handshake = false
const ( const (
VersionSSL30 = 0x0300 VersionSSL30 = 0x0300
@ -919,6 +918,43 @@ type ProtocolBugs struct {
// IgnoreSignatureVersionChecks, if true, causes all signature // IgnoreSignatureVersionChecks, if true, causes all signature
// algorithms to be enabled at all TLS versions. // algorithms to be enabled at all TLS versions.
IgnoreSignatureVersionChecks bool IgnoreSignatureVersionChecks bool
// NegotiateRenegotiationInfoAtAllVersions, if true, causes
// Renegotiation Info to be negotiated at all versions.
NegotiateRenegotiationInfoAtAllVersions bool
// NegotiateChannelIDAtAllVersions, if true, causes Channel ID to be
// negotiated at all versions.
NegotiateChannelIDAtAllVersions bool
// NegotiateNPNAtAllVersions, if true, causes NPN to be negotiated at
// all versions.
NegotiateNPNAtAllVersions bool
// NegotiateEMSAtAllVersions, if true, causes EMS to be negotiated at
// all versions.
NegotiateEMSAtAllVersions bool
// AdvertiseTicketExtension, if true, causes the ticket extension to be
// advertised in server extensions
AdvertiseTicketExtension bool
// MissingKeyShare, if true, causes the TLS 1.3 implementation to skip
// sending a key_share extension and use the zero ECDHE secret
// instead.
MissingKeyShare bool
// DuplicateKeyShares, if true, causes the TLS 1.3 client to send two
// copies of each KeyShareEntry.
DuplicateKeyShares bool
// EmptyEncryptedExtensions, if true, causes the TLS 1.3 server to
// emit an empty EncryptedExtensions block.
EmptyEncryptedExtensions bool
// EncryptedExtensionsWithKeyShare, if true, causes the TLS 1.3 server to
// include the KeyShare extension in the EncryptedExtensions block.
EncryptedExtensionsWithKeyShare bool
} }
func (c *Config) serverInit() { func (c *Config) serverInit() {

View File

@ -133,6 +133,14 @@ func (c *Conn) clientHandshake() error {
keyExchange: publicKey, keyExchange: publicKey,
}) })
keyShares[curveID] = curve keyShares[curveID] = curve
if c.config.Bugs.DuplicateKeyShares {
hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
}
}
if c.config.Bugs.MissingKeyShare {
hello.keyShares = nil
} }
} }
@ -477,7 +485,7 @@ func (hs *clientHandshakeState) doTLS13Handshake() error {
// Resolve ECDHE and compute the handshake secret. // Resolve ECDHE and compute the handshake secret.
var ecdheSecret []byte var ecdheSecret []byte
if hs.suite.flags&suiteECDHE != 0 { if hs.suite.flags&suiteECDHE != 0 && !c.config.Bugs.MissingKeyShare {
if !hs.serverHello.hasKeyShare { if !hs.serverHello.hasKeyShare {
c.sendAlert(alertMissingExtension) c.sendAlert(alertMissingExtension)
return errors.New("tls: server omitted the key share extension") return errors.New("tls: server omitted the key share extension")
@ -1014,6 +1022,10 @@ func (hs *clientHandshakeState) processServerExtensions(serverExtensions *server
return errors.New("tls: server advertised extended master secret over TLS 1.3") return errors.New("tls: server advertised extended master secret over TLS 1.3")
} }
if serverExtensions.ticketSupported && c.vers >= VersionTLS13 && enableTLS13Handshake {
return errors.New("tls: server advertised ticket extension over TLS 1.3")
}
if serverExtensions.srtpProtectionProfile != 0 { if serverExtensions.srtpProtectionProfile != 0 {
if serverExtensions.srtpMasterKeyIdentifier != "" { if serverExtensions.srtpMasterKeyIdentifier != "" {
return errors.New("tls: server selected SRTP MKI value") return errors.New("tls: server selected SRTP MKI value")

View File

@ -847,6 +847,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
type encryptedExtensionsMsg struct { type encryptedExtensionsMsg struct {
raw []byte raw []byte
extensions serverExtensions extensions serverExtensions
empty bool
} }
func (m *encryptedExtensionsMsg) marshal() []byte { func (m *encryptedExtensionsMsg) marshal() []byte {
@ -857,8 +858,10 @@ func (m *encryptedExtensionsMsg) marshal() []byte {
encryptedExtensionsMsg := newByteBuilder() encryptedExtensionsMsg := newByteBuilder()
encryptedExtensionsMsg.addU8(typeEncryptedExtensions) encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed() encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
extensions := encryptedExtensions.addU16LengthPrefixed() if !m.empty {
m.extensions.marshal(extensions, VersionTLS13) extensions := encryptedExtensions.addU16LengthPrefixed()
m.extensions.marshal(extensions, VersionTLS13)
}
m.raw = encryptedExtensionsMsg.finish() m.raw = encryptedExtensionsMsg.finish()
return m.raw return m.raw
@ -902,6 +905,8 @@ type serverExtensions struct {
sctList []byte sctList []byte
customExtension string customExtension string
npnLast bool npnLast bool
hasKeyShare bool
keyShare keyShareEntry
} }
func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) { func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) {
@ -999,6 +1004,13 @@ func (m *serverExtensions) marshal(extensions *byteBuilder, version uint16) {
npn.addBytes([]byte(v)) npn.addBytes([]byte(v))
} }
} }
if m.hasKeyShare {
extensions.addU16(extensionKeyShare)
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
keyExchange.addBytes(m.keyShare.keyExchange)
}
} }
func (m *serverExtensions) unmarshal(data []byte, version uint16) bool { func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {

View File

@ -279,6 +279,7 @@ func (hs *serverHandshakeState) doTLS13Handshake() error {
// Prepare an EncryptedExtensions message, but do not send it yet. // Prepare an EncryptedExtensions message, but do not send it yet.
encryptedExtensions := new(encryptedExtensionsMsg) encryptedExtensions := new(encryptedExtensionsMsg)
encryptedExtensions.empty = config.Bugs.EmptyEncryptedExtensions
if err := hs.processClientExtensions(&encryptedExtensions.extensions); err != nil { if err := hs.processClientExtensions(&encryptedExtensions.extensions); err != nil {
return err return err
} }
@ -341,7 +342,7 @@ Curves:
// Resolve ECDHE and compute the handshake secret. // Resolve ECDHE and compute the handshake secret.
var ecdheSecret []byte var ecdheSecret []byte
if hs.suite.flags&suiteECDHE != 0 { if hs.suite.flags&suiteECDHE != 0 && !config.Bugs.MissingKeyShare {
// Look for the key share corresponding to our selected curve. // Look for the key share corresponding to our selected curve.
var selectedKeyShare *keyShareEntry var selectedKeyShare *keyShareEntry
for i := range hs.clientHello.keyShares { for i := range hs.clientHello.keyShares {
@ -384,6 +385,14 @@ Curves:
group: curveID, group: curveID,
keyExchange: publicKey, keyExchange: publicKey,
} }
if config.Bugs.EncryptedExtensionsWithKeyShare {
encryptedExtensions.extensions.hasKeyShare = true
encryptedExtensions.extensions.keyShare = keyShareEntry{
group: curveID,
keyExchange: publicKey,
}
}
} else { } else {
ecdheSecret = hs.finishedHash.zeroSecret() ecdheSecret = hs.finishedHash.zeroSecret()
} }
@ -700,7 +709,7 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
config := hs.c.config config := hs.c.config
c := hs.c c := hs.c
if c.vers < VersionTLS13 || !enableTLS13Handshake { if c.vers < VersionTLS13 || config.Bugs.NegotiateRenegotiationInfoAtAllVersions || !enableTLS13Handshake {
if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) { if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
c.sendAlert(alertHandshakeFailure) c.sendAlert(alertHandshakeFailure)
return errors.New("tls: renegotiation mismatch") return errors.New("tls: renegotiation mismatch")
@ -751,7 +760,7 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
} }
} }
if c.vers < VersionTLS13 || !enableTLS13Handshake { if c.vers < VersionTLS13 || config.Bugs.NegotiateNPNAtAllVersions || !enableTLS13Handshake {
if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN { if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
// Although sending an empty NPN extension is reasonable, Firefox has // Although sending an empty NPN extension is reasonable, Firefox has
// had a bug around this. Best to send nothing at all if // had a bug around this. Best to send nothing at all if
@ -763,9 +772,13 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
serverExtensions.npnLast = config.Bugs.SwapNPNAndALPN serverExtensions.npnLast = config.Bugs.SwapNPNAndALPN
} }
} }
}
if c.vers < VersionTLS13 || config.Bugs.NegotiateEMSAtAllVersions || !enableTLS13Handshake {
serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
}
if c.vers < VersionTLS13 || config.Bugs.NegotiateChannelIDAtAllVersions || !enableTLS13Handshake {
if hs.clientHello.channelIDSupported && config.RequestChannelID { if hs.clientHello.channelIDSupported && config.RequestChannelID {
serverExtensions.channelIDRequested = true serverExtensions.channelIDRequested = true
} }
@ -795,6 +808,10 @@ func (hs *serverHandshakeState) processClientExtensions(serverExtensions *server
} }
serverExtensions.customExtension = config.Bugs.CustomExtension serverExtensions.customExtension = config.Bugs.CustomExtension
if c.config.Bugs.AdvertiseTicketExtension {
serverExtensions.ticketSupported = true
}
return nil return nil
} }

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ const Flag<bool> kBoolFlags[] = {
{ "-no-tls11", &TestConfig::no_tls11 }, { "-no-tls11", &TestConfig::no_tls11 },
{ "-no-tls1", &TestConfig::no_tls1 }, { "-no-tls1", &TestConfig::no_tls1 },
{ "-no-ssl3", &TestConfig::no_ssl3 }, { "-no-ssl3", &TestConfig::no_ssl3 },
{ "-enable-channel-id", &TestConfig::enable_channel_id },
{ "-shim-writes-first", &TestConfig::shim_writes_first }, { "-shim-writes-first", &TestConfig::shim_writes_first },
{ "-expect-session-miss", &TestConfig::expect_session_miss }, { "-expect-session-miss", &TestConfig::expect_session_miss },
{ "-decline-alpn", &TestConfig::decline_alpn }, { "-decline-alpn", &TestConfig::decline_alpn },

View File

@ -46,6 +46,7 @@ struct TestConfig {
bool no_tls1 = false; bool no_tls1 = false;
bool no_ssl3 = false; bool no_ssl3 = false;
std::string expected_channel_id; std::string expected_channel_id;
bool enable_channel_id = false;
std::string send_channel_id; std::string send_channel_id;
bool shim_writes_first = false; bool shim_writes_first = false;
std::string host_name; std::string host_name;

437
ssl/tls13_both.c Normal file
View File

@ -0,0 +1,437 @@
/* Copyright (c) 2016, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/ssl.h>
#include <assert.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/hkdf.h>
#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "internal.h"
SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl)) {
SSL_HANDSHAKE *hs = OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
if (hs == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(hs, 0, sizeof(SSL_HANDSHAKE));
hs->do_handshake = do_handshake;
hs->wait = ssl_hs_ok;
return hs;
}
void ssl_handshake_free(SSL_HANDSHAKE *hs) {
if (hs == NULL) {
return;
}
OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
OPENSSL_cleanse(hs->traffic_secret_0, sizeof(hs->traffic_secret_0));
if (hs->groups != NULL) {
for (size_t i = 0; i < hs->groups_len; i++) {
SSL_ECDH_CTX_cleanup(&hs->groups[i]);
}
OPENSSL_free(hs->groups);
}
OPENSSL_free(hs->public_key);
OPENSSL_free(hs->cert_context);
OPENSSL_free(hs);
}
int tls13_handshake(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
for (;;) {
/* Resolve the operation the handshake was waiting on. */
switch (hs->wait) {
case ssl_hs_error:
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
return -1;
case ssl_hs_read_message: {
int ret = ssl->method->ssl_get_message(ssl, -1, ssl_dont_hash_message);
if (ret <= 0) {
return ret;
}
break;
}
case ssl_hs_write_message: {
int ret = ssl->method->write_message(ssl);
if (ret <= 0) {
return ret;
}
break;
}
case ssl_hs_flush: {
int ret = BIO_flush(ssl->wbio);
if (ret <= 0) {
ssl->rwstate = SSL_WRITING;
return ret;
}
break;
}
case ssl_hs_x509_lookup:
ssl->rwstate = SSL_X509_LOOKUP;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_private_key_operation:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_ok:
break;
}
/* Run the state machine again. */
hs->wait = hs->do_handshake(ssl);
if (hs->wait == ssl_hs_error) {
/* Don't loop around to avoid a stray |SSL_R_SSL_HANDSHAKE_FAILURE| the
* first time around. */
return -1;
}
if (hs->wait == ssl_hs_ok) {
/* The handshake has completed. */
return 1;
}
/* Otherwise, loop to the beginning and resolve what was blocking the
* handshake. */
}
}
static int tls13_get_cert_verify_signature_input(SSL *ssl, uint8_t **out,
size_t *out_len, int server) {
CBB cbb;
if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
goto err;
}
for (size_t i = 0; i < 64; i++) {
if (!CBB_add_u8(&cbb, 0x20)) {
goto err;
}
}
if (server) {
/* Include the NUL byte. */
static const char kContext[] = "TLS 1.3, server CertificateVerify";
if (!CBB_add_bytes(&cbb, (const uint8_t *)kContext, sizeof(kContext))) {
goto err;
}
} else {
static const char kContext[] = "TLS 1.3, client CertificateVerify";
if (!CBB_add_bytes(&cbb, (const uint8_t *)kContext, sizeof(kContext))) {
goto err;
}
}
uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
size_t context_hashes_len;
if (!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len) ||
!CBB_add_bytes(&cbb, context_hashes, context_hashes_len) ||
!CBB_finish(&cbb, out, out_len)) {
goto err;
}
return 1;
err:
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
CBB_cleanup(&cbb);
return 0;
}
int tls13_process_certificate(SSL *ssl) {
CBS cbs, context;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
CBS_len(&context) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return 0;
}
int ret = 0;
uint8_t alert;
STACK_OF(X509) *chain = ssl_parse_cert_chain(
ssl, &alert,
ssl->ctx->retain_only_sha256_of_client_certs ? ssl->session->peer_sha256
: NULL,
&cbs);
if (chain == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
if (CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
}
if (sk_X509_num(chain) == 0) {
/* Clients must receive a certificate from the server. */
if (!ssl->server) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
}
/* Servers may be configured to accept anonymous clients. */
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);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
}
/* No certificate, so nothing more to do. */
ret = 1;
goto err;
}
if (ssl->server && ssl->ctx->retain_only_sha256_of_client_certs) {
/* The hash was filled in by |ssl_parse_cert_chain|. */
ssl->session->peer_sha256_valid = 1;
}
X509 *leaf = sk_X509_value(chain, 0);
if (!ssl->server && !ssl_check_leaf_certificate(ssl, leaf)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
goto err;
}
int verify_ret = ssl_verify_cert_chain(ssl, chain);
/* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
if (ssl->verify_mode != SSL_VERIFY_NONE && verify_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);
goto err;
}
ERR_clear_error();
ssl->session->verify_result = ssl->verify_result;
X509_free(ssl->session->peer);
/* For historical reasons, the client and server differ on whether the chain
* includes the leaf. */
if (ssl->server) {
ssl->session->peer = sk_X509_shift(chain);
} else {
ssl->session->peer = X509_up_ref(leaf);
}
sk_X509_pop_free(ssl->session->cert_chain, X509_free);
ssl->session->cert_chain = chain;
chain = NULL;
ret = 1;
err:
sk_X509_pop_free(chain, X509_free);
return ret;
}
int tls13_process_certificate_verify(SSL *ssl) {
int ret = 0;
X509 *peer = ssl->session->peer;
EVP_PKEY *pkey = NULL;
uint8_t *msg = NULL;
size_t msg_len;
/* Filter out unsupported certificate types. */
pkey = X509_get_pubkey(peer);
if (pkey == NULL) {
goto err;
}
CBS cbs, signature;
uint16_t signature_algorithm;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&cbs, &signature_algorithm) ||
!CBS_get_u16_length_prefixed(&cbs, &signature) ||
CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
}
int al;
if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
goto err;
}
ssl->s3->tmp.peer_signature_algorithm = signature_algorithm;
if (!tls13_get_cert_verify_signature_input(ssl, &msg, &msg_len,
!ssl->server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
int sig_ok =
ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature),
signature_algorithm, pkey, msg, msg_len);
if (!sig_ok) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
goto err;
}
ret = 1;
err:
EVP_PKEY_free(pkey);
OPENSSL_free(msg);
return ret;
}
int tls13_check_message_type(SSL *ssl, int type) {
if (ssl->s3->tmp.message_type != type) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
return 1;
}
int tls13_process_finished(SSL *ssl) {
uint8_t verify_data[EVP_MAX_MD_SIZE];
size_t verify_data_len;
if (!tls13_finished_mac(ssl, verify_data, &verify_data_len, !ssl->server)) {
return 0;
}
if (ssl->init_num != verify_data_len ||
CRYPTO_memcmp(verify_data, ssl->init_msg, verify_data_len) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
return 0;
}
return 1;
}
int tls13_prepare_certificate(SSL *ssl) {
CBB cbb, body, context;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
!CBB_add_u8_length_prefixed(&body, &context) ||
!CBB_add_bytes(&context, ssl->s3->hs->cert_context,
ssl->s3->hs->cert_context_len) ||
!ssl_add_cert_chain(ssl, &body) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return 0;
}
return 1;
}
enum ssl_private_key_result_t tls13_prepare_certificate_verify(
SSL *ssl, int is_first_run) {
enum ssl_private_key_result_t ret = ssl_private_key_failure;
uint8_t *msg = NULL;
size_t msg_len;
CBB cbb, body;
CBB_zero(&cbb);
uint16_t signature_algorithm;
if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) {
goto err;
}
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_VERIFY) ||
!CBB_add_u16(&body, signature_algorithm)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Sign the digest. */
CBB child;
const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
uint8_t *sig;
size_t sig_len;
if (!CBB_add_u16_length_prefixed(&body, &child) ||
!CBB_reserve(&child, &sig, max_sig_len)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
enum ssl_private_key_result_t sign_result;
if (is_first_run) {
if (!tls13_get_cert_verify_signature_input(ssl, &msg, &msg_len,
ssl->server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len,
signature_algorithm, msg, msg_len);
} else {
sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len);
}
if (sign_result != ssl_private_key_success) {
ret = sign_result;
goto err;
}
if (!CBB_did_write(&child, sig_len) ||
!ssl->method->finish_message(ssl, &cbb)) {
goto err;
}
ret = ssl_private_key_success;
err:
CBB_cleanup(&cbb);
OPENSSL_free(msg);
return ret;
}
int tls13_prepare_finished(SSL *ssl) {
size_t verify_data_len;
uint8_t verify_data[EVP_MAX_MD_SIZE];
if (!tls13_finished_mac(ssl, verify_data, &verify_data_len, ssl->server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
return 0;
}
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
!CBB_add_bytes(&body, verify_data, verify_data_len) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return 0;
}
return 1;
}

462
ssl/tls13_client.c Normal file
View File

@ -0,0 +1,462 @@
/* Copyright (c) 2016, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/ssl.h>
#include <assert.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/x509.h>
#include "internal.h"
enum client_hs_state_t {
state_process_server_hello = 0,
state_process_encrypted_extensions,
state_process_certificate_request,
state_process_server_certificate,
state_process_server_certificate_verify,
state_process_server_finished,
state_certificate_callback,
state_send_client_certificate,
state_send_client_certificate_verify,
state_complete_client_certificate_verify,
state_send_client_finished,
state_flush,
state_done,
};
static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
return ssl_hs_error;
}
CBS cbs, server_random, extensions;
uint16_t server_wire_version;
uint16_t cipher_suite;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&cbs, &server_wire_version) ||
!CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u16(&cbs, &cipher_suite) ||
!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
/* Parse out the extensions. */
int have_key_share = 0;
CBS key_share;
while (CBS_len(&extensions) != 0) {
uint16_t type;
CBS extension;
if (!CBS_get_u16(&extensions, &type) ||
!CBS_get_u16_length_prefixed(&extensions, &extension)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
switch (type) {
case TLSEXT_TYPE_key_share:
if (have_key_share) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
key_share = extension;
have_key_share = 1;
break;
default:
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return ssl_hs_error;
}
}
assert(ssl->s3->have_version);
memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
ssl->hit = 0;
if (!ssl_get_new_session(ssl, 0)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
if (cipher == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
/* Check if the cipher is disabled. */
if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
(cipher->algorithm_auth & ssl->cert->mask_a) ||
SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) ||
SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) ||
!sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(ssl), NULL, cipher)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
ssl->session->cipher = cipher;
ssl->s3->tmp.new_cipher = cipher;
/* The PRF hash is now known. Set up the key schedule. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
/* Resolve PSK and incorporate it into the secret. */
if (cipher->algorithm_auth == SSL_aPSK) {
/* TODO(davidben): Support PSK. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
} else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
/* Resolve ECDHE and incorporate it into the secret. */
if (cipher->algorithm_mkey == SSL_kECDHE) {
if (!have_key_share) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return ssl_hs_error;
}
uint8_t *dhe_secret;
size_t dhe_secret_len;
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len,
&alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
OPENSSL_free(dhe_secret);
if (!ok) {
return ssl_hs_error;
}
} else {
if (have_key_share) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return ssl_hs_error;
}
if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
return ssl_hs_error;
}
if (!tls13_set_handshake_traffic(ssl)) {
return ssl_hs_error;
}
hs->state = state_process_encrypted_extensions;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
return ssl_hs_error;
}
CBS cbs;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!ssl_parse_serverhello_tlsext(ssl, &cbs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
if (CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
if (!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}
hs->state = state_process_certificate_request;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_certificate_request(SSL *ssl,
SSL_HANDSHAKE *hs) {
ssl->s3->tmp.cert_request = 0;
/* CertificateRequest may only be sent in certificate-based ciphers. */
if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
hs->state = state_process_server_finished;
return ssl_hs_ok;
}
/* CertificateRequest is optional. */
if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
hs->state = state_process_server_certificate;
return ssl_hs_ok;
}
CBS cbs, context, supported_signature_algorithms;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
!CBS_stow(&context, &ssl->s3->hs->cert_context,
&ssl->s3->hs->cert_context_len) ||
!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
!tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
}
uint8_t alert;
STACK_OF(X509_NAME) *ca_sk = ssl_parse_client_CA_list(ssl, &alert, &cbs);
if (ca_sk == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
/* Ignore extensions. */
CBS extensions;
if (!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
}
ssl->s3->tmp.cert_request = 1;
sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
ssl->s3->tmp.ca_names = ca_sk;
if (!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}
hs->state = state_process_server_certificate;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_server_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
!tls13_process_certificate(ssl) ||
!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}
hs->state = state_process_server_certificate_verify;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_server_certificate_verify(
SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(ssl) ||
!ssl->method->hash_current_message(ssl)) {
return 0;
}
hs->state = state_process_server_finished;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_server_finished(SSL *ssl,
SSL_HANDSHAKE *hs) {
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
!tls13_process_finished(ssl) ||
!ssl->method->hash_current_message(ssl) ||
/* Update the secret to the master secret and derive traffic keys. */
!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
!tls13_derive_traffic_secret_0(ssl)) {
return ssl_hs_error;
}
hs->state = state_certificate_callback;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
/* The peer didn't request a certificate. */
if (!ssl->s3->tmp.cert_request) {
hs->state = state_send_client_finished;
return ssl_hs_ok;
}
/* Call cert_cb to update the certificate. */
if (ssl->cert->cert_cb != NULL) {
int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
if (rv == 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
return ssl_hs_error;
}
if (rv < 0) {
hs->state = state_certificate_callback;
return ssl_hs_x509_lookup;
}
}
hs->state = state_send_client_certificate;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_client_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!ssl_has_certificate(ssl) && ssl->ctx->client_cert_cb != NULL) {
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int rv = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
if (rv < 0) {
hs->state = state_send_client_certificate;
return ssl_hs_x509_lookup;
}
int setup_error = rv == 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 ssl_hs_error;
}
}
if (!tls13_prepare_certificate(ssl)) {
return ssl_hs_error;
}
hs->state = state_send_client_certificate_verify;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL *ssl,
SSL_HANDSHAKE *hs,
int is_first_run) {
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
hs->state = state_send_client_finished;
return ssl_hs_ok;
}
switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
case ssl_private_key_success:
hs->state = state_send_client_finished;
return ssl_hs_write_message;
case ssl_private_key_retry:
hs->state = state_complete_client_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
return ssl_hs_error;
}
assert(0);
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_client_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_prepare_finished(ssl)) {
return ssl_hs_error;
}
hs->state = state_flush;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_set_traffic_key(ssl, type_data, evp_aead_open,
hs->traffic_secret_0, hs->hash_len) ||
!tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
hs->traffic_secret_0, hs->hash_len) ||
!tls13_finalize_keys(ssl)) {
return ssl_hs_error;
}
hs->state = state_done;
return ssl_hs_flush;
}
enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
while (hs->state != state_done) {
enum ssl_hs_wait_t ret = ssl_hs_error;
enum client_hs_state_t state = hs->state;
switch (state) {
case state_process_server_hello:
ret = do_process_server_hello(ssl, hs);
break;
case state_process_encrypted_extensions:
ret = do_process_encrypted_extensions(ssl, hs);
break;
case state_process_certificate_request:
ret = do_process_certificate_request(ssl, hs);
break;
case state_process_server_certificate:
ret = do_process_server_certificate(ssl, hs);
break;
case state_process_server_certificate_verify:
ret = do_process_server_certificate_verify(ssl, hs);
break;
case state_process_server_finished:
ret = do_process_server_finished(ssl, hs);
break;
case state_certificate_callback:
ret = do_certificate_callback(ssl, hs);
break;
case state_send_client_certificate:
ret = do_send_client_certificate(ssl, hs);
break;
case state_send_client_certificate_verify:
ret = do_send_client_certificate_verify(ssl, hs, 1 /* first run */);
break;
case state_complete_client_certificate_verify:
ret = do_send_client_certificate_verify(ssl, hs, 0 /* complete */);
break;
case state_send_client_finished:
ret = do_send_client_finished(ssl, hs);
break;
case state_flush:
ret = do_flush(ssl, hs);
break;
case state_done:
ret = ssl_hs_ok;
break;
}
if (ret != ssl_hs_ok) {
return ret;
}
}
return ssl_hs_ok;
}

344
ssl/tls13_enc.c Normal file
View File

@ -0,0 +1,344 @@
/* Copyright (c) 2016, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/ssl.h>
#include <assert.h>
#include <string.h>
#include <openssl/aead.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <openssl/hkdf.h>
#include <openssl/mem.h>
#include "internal.h"
int tls13_init_key_schedule(SSL *ssl, const uint8_t *resumption_ctx,
size_t resumption_ctx_len) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
hs->hash_len = EVP_MD_size(digest);
/* Save the hash of the resumption context. */
unsigned resumption_hash_len;
if (!EVP_Digest(resumption_ctx, resumption_ctx_len, hs->resumption_hash,
&resumption_hash_len, digest, NULL)) {
return 0;
}
/* Initialize the secret to the zero key. */
memset(hs->secret, 0, hs->hash_len);
/* Initialize the rolling hashes and release the handshake buffer. */
if (!ssl3_init_handshake_hash(ssl)) {
return 0;
}
ssl3_free_handshake_buffer(ssl);
return 1;
}
int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
return HKDF_extract(hs->secret, &hs->hash_len, digest, in, len, hs->secret,
hs->hash_len);
}
static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
const uint8_t *secret, size_t secret_len,
const uint8_t *label, size_t label_len,
const uint8_t *hash, size_t hash_len, size_t len) {
static const char kTLS13LabelVersion[] = "TLS 1.3, ";
CBB cbb, child;
uint8_t *hkdf_label;
size_t hkdf_label_len;
if (!CBB_init(&cbb, 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 +
hash_len) ||
!CBB_add_u16(&cbb, len) ||
!CBB_add_u8_length_prefixed(&cbb, &child) ||
!CBB_add_bytes(&child, (const uint8_t *)kTLS13LabelVersion,
strlen(kTLS13LabelVersion)) ||
!CBB_add_bytes(&child, label, label_len) ||
!CBB_add_u8_length_prefixed(&cbb, &child) ||
!CBB_add_bytes(&child, hash, hash_len) ||
!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) {
CBB_cleanup(&cbb);
return 0;
}
int ret = HKDF_expand(out, len, digest, secret, secret_len, hkdf_label,
hkdf_label_len);
OPENSSL_free(hkdf_label);
return ret;
}
int tls13_get_context_hashes(SSL *ssl, uint8_t *out, size_t *out_len) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
EVP_MD_CTX ctx;
EVP_MD_CTX_init(&ctx);
unsigned handshake_len = 0;
int ok = EVP_MD_CTX_copy_ex(&ctx, &ssl->s3->handshake_hash) &&
EVP_DigestFinal_ex(&ctx, out, &handshake_len);
EVP_MD_CTX_cleanup(&ctx);
if (!ok) {
return 0;
}
memcpy(out + handshake_len, hs->resumption_hash, hs->hash_len);
*out_len = handshake_len + hs->hash_len;
return 1;
}
/* derive_secret derives a secret of length |len| and writes the result in |out|
* with the given label and the current base secret and most recently-saved
* handshake context. It returns one on success and zero on error. */
static int derive_secret(SSL *ssl, uint8_t *out, size_t len,
const uint8_t *label, size_t label_len) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
size_t context_hashes_len;
if (!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len)) {
return 0;
}
return hkdf_expand_label(out, digest, hs->secret, hs->hash_len, label,
label_len, context_hashes, context_hashes_len, len);
}
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
enum evp_aead_direction_t direction,
const uint8_t *traffic_secret,
size_t traffic_secret_len) {
if (traffic_secret_len > 0xff) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
}
const char *phase;
switch (type) {
case type_early_handshake:
phase = "early handshake key expansion, ";
break;
case type_early_data:
phase = "early application data key expansion, ";
break;
case type_handshake:
phase = "handshake key expansion, ";
break;
case type_data:
phase = "application data key expansion, ";
break;
default:
return 0;
}
size_t phase_len = strlen(phase);
const char *purpose = "client write key";
if ((ssl->server && direction == evp_aead_seal) ||
(!ssl->server && direction == evp_aead_open)) {
purpose = "server write key";
}
size_t purpose_len = strlen(purpose);
/* The longest label has length 38 (type_early_data) + 16 (either purpose
* value). */
uint8_t label[38 + 16];
size_t label_len = phase_len + purpose_len;
if (label_len > sizeof(label)) {
assert(0);
return 0;
}
memcpy(label, phase, phase_len);
memcpy(label + phase_len, purpose, purpose_len);
/* Look up cipher suite properties. */
const EVP_AEAD *aead;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
size_t mac_secret_len, fixed_iv_len;
if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
ssl->session->cipher,
ssl3_protocol_version(ssl))) {
return 0;
}
/* Derive the key. */
size_t key_len = EVP_AEAD_key_length(aead);
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label,
label_len, NULL, 0, key_len)) {
return 0;
}
/* The IV's label ends in "iv" instead of "key". */
if (label_len < 3) {
assert(0);
return 0;
}
label_len--;
label[label_len - 2] = 'i';
label[label_len - 1] = 'v';
/* Derive the IV. */
size_t iv_len = EVP_AEAD_nonce_length(aead);
uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label,
label_len, NULL, 0, iv_len)) {
return 0;
}
SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction,
ssl3_protocol_version(ssl),
ssl->session->cipher,
key, key_len, NULL, 0,
iv, iv_len);
if (traffic_aead == NULL) {
return 0;
}
if (direction == evp_aead_open) {
if (!ssl->method->set_read_state(ssl, traffic_aead)) {
return 0;
}
} else {
if (!ssl->method->set_write_state(ssl, traffic_aead)) {
return 0;
}
}
/* Save the traffic secret. */
if (direction == evp_aead_open) {
memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
ssl->s3->read_traffic_secret_len = traffic_secret_len;
} else {
memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
ssl->s3->write_traffic_secret_len = traffic_secret_len;
}
return 1;
}
static const char kTLS13LabelHandshakeTraffic[] = "handshake traffic secret";
static const char kTLS13LabelApplicationTraffic[] =
"application traffic secret";
int tls13_set_handshake_traffic(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
uint8_t traffic_secret[EVP_MAX_MD_SIZE];
if (!derive_secret(ssl, traffic_secret, hs->hash_len,
(const uint8_t *)kTLS13LabelHandshakeTraffic,
strlen(kTLS13LabelHandshakeTraffic)) ||
!tls13_set_traffic_key(ssl, type_handshake, evp_aead_open, traffic_secret,
hs->hash_len) ||
!tls13_set_traffic_key(ssl, type_handshake, evp_aead_seal, traffic_secret,
hs->hash_len)) {
return 0;
}
return 1;
}
int tls13_derive_traffic_secret_0(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
return derive_secret(ssl, hs->traffic_secret_0, hs->hash_len,
(const uint8_t *)kTLS13LabelApplicationTraffic,
strlen(kTLS13LabelApplicationTraffic));
}
static const char kTLS13LabelExporter[] = "exporter master secret";
static const char kTLS13LabelResumption[] = "resumption master secret";
int tls13_finalize_keys(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
ssl->s3->exporter_secret_len = hs->hash_len;
ssl->session->master_key_length = hs->hash_len;
if (!derive_secret(
ssl, ssl->s3->exporter_secret, ssl->s3->exporter_secret_len,
(const uint8_t *)kTLS13LabelExporter, strlen(kTLS13LabelExporter)) ||
!derive_secret(ssl, ssl->session->master_key,
ssl->session->master_key_length,
(const uint8_t *)kTLS13LabelResumption,
strlen(kTLS13LabelResumption))) {
return 0;
}
return 1;
}
int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
uint8_t key[EVP_MAX_MD_SIZE];
size_t key_len = EVP_MD_size(digest);
uint8_t *traffic_secret;
const char *label;
if (is_server) {
label = "server finished";
if (ssl->server) {
traffic_secret = ssl->s3->write_traffic_secret;
} else {
traffic_secret = ssl->s3->read_traffic_secret;
}
} else {
label = "client finished";
if (!ssl->server) {
traffic_secret = ssl->s3->write_traffic_secret;
} else {
traffic_secret = ssl->s3->read_traffic_secret;
}
}
uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
size_t context_hashes_len;
unsigned len;
if (!hkdf_expand_label(key, digest, traffic_secret, hs->hash_len,
(const uint8_t *)label, strlen(label), NULL, 0,
hs->hash_len) ||
!tls13_get_context_hashes(ssl, context_hashes, &context_hashes_len) ||
HMAC(digest, key, key_len, context_hashes, context_hashes_len, out,
&len) == NULL) {
return 0;
}
*out_len = len;
return 1;
}
int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
const char *label, size_t label_len,
const uint8_t *context, size_t context_len,
int use_context) {
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
const uint8_t *hash = NULL;
size_t hash_len = 0;
if (use_context) {
hash = context;
hash_len = context_len;
}
return hkdf_expand_label(out, digest, ssl->s3->exporter_secret,
ssl->s3->exporter_secret_len, (const uint8_t *)label,
label_len, hash, hash_len, out_len);
}

483
ssl/tls13_server.c Normal file
View File

@ -0,0 +1,483 @@
/* Copyright (c) 2016, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <openssl/ssl.h>
#include <assert.h>
#include <string.h>
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
#include <openssl/stack.h>
#include "internal.h"
enum server_hs_state_t {
state_process_client_hello = 0,
state_send_server_hello,
state_send_encrypted_extensions,
state_send_certificate_request,
state_send_server_certificate,
state_send_server_certificate_verify,
state_complete_server_certificate_verify,
state_send_server_finished,
state_flush,
state_read_client_second_flight,
state_process_client_certificate,
state_process_client_certificate_verify,
state_process_client_finished,
state_done,
};
static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
}
struct ssl_early_callback_ctx early_ctx;
uint16_t client_wire_version;
CBS client_random, session_id, cipher_suites, compression_methods;
memset(&early_ctx, 0, sizeof(early_ctx));
early_ctx.ssl = ssl;
early_ctx.client_hello = ssl->init_msg;
early_ctx.client_hello_len = ssl->init_num;
if (!ssl_early_callback_init(&early_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
CBS cbs;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&cbs, &client_wire_version) ||
!CBS_get_bytes(&cbs, &client_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&cbs, &session_id) ||
CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
assert(ssl->s3->have_version);
/* Load the client random. */
memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
ssl->hit = 0;
if (!ssl_get_new_session(ssl, 1 /* server */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
if (ssl->ctx->dos_protection_cb != NULL &&
ssl->ctx->dos_protection_cb(&early_ctx) == 0) {
/* Connection rejected for DOS reasons. */
OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ACCESS_DENIED);
return ssl_hs_error;
}
if (!CBS_get_u16_length_prefixed(&cbs, &cipher_suites) ||
CBS_len(&cipher_suites) == 0 ||
CBS_len(&cipher_suites) % 2 != 0 ||
!CBS_get_u8_length_prefixed(&cbs, &compression_methods) ||
CBS_len(&compression_methods) == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
/* TLS 1.3 requires the peer only advertise the null compression. */
if (CBS_len(&compression_methods) != 1 ||
CBS_data(&compression_methods)[0] != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
/* TLS extensions. */
if (!ssl_parse_clienthello_tlsext(ssl, &cbs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
/* There should be nothing left over in the message. */
if (CBS_len(&cbs) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
/* Let cert callback update server certificates if required.
*
* TODO(davidben): Can this get run earlier? */
if (ssl->cert->cert_cb != NULL) {
int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
if (rv == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
if (rv < 0) {
hs->state = state_process_client_hello;
return ssl_hs_x509_lookup;
}
}
STACK_OF(SSL_CIPHER) *ciphers =
ssl_bytes_to_cipher_list(ssl, &cipher_suites, max_version);
if (ciphers == NULL) {
return ssl_hs_error;
}
const SSL_CIPHER *cipher =
ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl));
sk_SSL_CIPHER_free(ciphers);
if (cipher == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return ssl_hs_error;
}
ssl->session->cipher = cipher;
ssl->s3->tmp.new_cipher = cipher;
/* The PRF hash is now known. Set up the key schedule and hash the
* ClientHello. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
if (!tls13_init_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
/* Resolve PSK and incorporate it into the secret. */
if (cipher->algorithm_auth == SSL_aPSK) {
/* TODO(davidben): Support PSK. */
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
} else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
/* Resolve ECDHE and incorporate it into the secret. */
if (cipher->algorithm_mkey == SSL_kECDHE) {
const uint8_t *key_share_buf = NULL;
size_t key_share_len = 0;
CBS key_share;
if (!SSL_early_callback_ctx_extension_get(&early_ctx, TLSEXT_TYPE_key_share,
&key_share_buf, &key_share_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return ssl_hs_error;
}
CBS_init(&key_share, key_share_buf, key_share_len);
uint8_t *dhe_secret;
size_t dhe_secret_len;
uint8_t alert;
if (!ext_key_share_parse_clienthello(ssl, &dhe_secret, &dhe_secret_len,
&alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
OPENSSL_free(dhe_secret);
if (!ok) {
return ssl_hs_error;
}
} else if (!tls13_advance_key_schedule(ssl, kZeroes, hash_len)) {
return ssl_hs_error;
}
hs->state = state_send_server_hello;
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
CBB cbb, body, extensions;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, ssl->version) ||
!RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ext_key_share_add_serverhello(ssl, &extensions) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}
hs->state = state_send_encrypted_extensions;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!tls13_set_handshake_traffic(ssl)) {
return ssl_hs_error;
}
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_ENCRYPTED_EXTENSIONS) ||
!ssl_add_serverhello_tlsext(ssl, &body) ||
!ssl->method->finish_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
}
hs->state = state_send_certificate_request;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
SSL_HANDSHAKE *hs) {
/* Determine whether to request a client certificate. */
ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
/* CertificateRequest may only be sent in certificate-based ciphers. */
if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
ssl->s3->tmp.cert_request = 0;
}
if (!ssl->s3->tmp.cert_request) {
/* Skip this state. */
hs->state = state_send_server_certificate;
return ssl_hs_ok;
}
CBB cbb, body, sigalgs_cbb;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_REQUEST) ||
!CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
goto err;
}
const uint16_t *sigalgs;
size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs);
if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
goto err;
}
for (size_t i = 0; i < sigalgs_len; i++) {
if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
goto err;
}
}
if (!ssl_add_client_CA_list(ssl, &body) ||
!CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
!ssl->method->finish_message(ssl, &cbb)) {
goto err;
}
hs->state = state_send_server_certificate;
return ssl_hs_write_message;
err:
CBB_cleanup(&cbb);
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
hs->state = state_send_server_finished;
return ssl_hs_ok;
}
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return ssl_hs_error;
}
if (!tls13_prepare_certificate(ssl)) {
return ssl_hs_error;
}
hs->state = state_send_server_certificate_verify;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
SSL_HANDSHAKE *hs,
int is_first_run) {
switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
case ssl_private_key_success:
hs->state = state_send_server_finished;
return ssl_hs_write_message;
case ssl_private_key_retry:
hs->state = state_complete_server_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
return ssl_hs_error;
}
assert(0);
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
if (!tls13_prepare_finished(ssl)) {
return ssl_hs_error;
}
hs->state = state_flush;
return ssl_hs_write_message;
}
static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
hs->state = state_read_client_second_flight;
return ssl_hs_flush;
}
static enum ssl_hs_wait_t do_read_client_second_flight(SSL *ssl,
SSL_HANDSHAKE *hs) {
/* Update the secret to the master secret and derive traffic keys. */
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
!tls13_derive_traffic_secret_0(ssl) ||
!tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
hs->traffic_secret_0, hs->hash_len)) {
return ssl_hs_error;
}
hs->state = state_process_client_certificate;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!ssl->s3->tmp.cert_request) {
/* Skip this state. */
hs->state = state_process_client_certificate_verify;
return ssl_hs_ok;
}
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
!tls13_process_certificate(ssl) ||
!ssl->method->hash_current_message(ssl)) {
return ssl_hs_error;
}
hs->state = state_process_client_certificate_verify;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_client_certificate_verify(
SSL *ssl, SSL_HANDSHAKE *hs) {
if (ssl->session->peer == NULL) {
/* Skip this state. */
hs->state = state_process_client_finished;
return ssl_hs_ok;
}
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(ssl) ||
!ssl->method->hash_current_message(ssl)) {
return 0;
}
hs->state = state_process_client_finished;
return ssl_hs_read_message;
}
static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
SSL_HANDSHAKE *hs) {
if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
!tls13_process_finished(ssl) ||
!ssl->method->hash_current_message(ssl) ||
/* evp_aead_seal keys have already been switched. */
!tls13_set_traffic_key(ssl, type_data, evp_aead_open,
hs->traffic_secret_0, hs->hash_len) ||
!tls13_finalize_keys(ssl)) {
return ssl_hs_error;
}
hs->state = state_done;
return ssl_hs_ok;
}
enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
SSL_HANDSHAKE *hs = ssl->s3->hs;
while (hs->state != state_done) {
enum ssl_hs_wait_t ret = ssl_hs_error;
enum server_hs_state_t state = hs->state;
switch (state) {
case state_process_client_hello:
ret = do_process_client_hello(ssl, hs);
break;
case state_send_server_hello:
ret = do_send_server_hello(ssl, hs);
break;
case state_send_encrypted_extensions:
ret = do_send_encrypted_extensions(ssl, hs);
break;
case state_send_certificate_request:
ret = do_send_certificate_request(ssl, hs);
break;
case state_send_server_certificate:
ret = do_send_server_certificate(ssl, hs);
break;
case state_send_server_certificate_verify:
ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
break;
case state_complete_server_certificate_verify:
ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
break;
case state_send_server_finished:
ret = do_send_server_finished(ssl, hs);
break;
case state_flush:
ret = do_flush(ssl, hs);
break;
case state_read_client_second_flight:
ret = do_read_client_second_flight(ssl, hs);
break;
case state_process_client_certificate:
ret = do_process_client_certificate(ssl, hs);
break;
case state_process_client_certificate_verify:
ret = do_process_client_certificate_verify(ssl, hs);
break;
case state_process_client_finished:
ret = do_process_client_finished(ssl, hs);
break;
case state_done:
ret = ssl_hs_ok;
break;
}
if (ret != ssl_hs_ok) {
return ret;
}
}
return ssl_hs_ok;
}

View File

@ -56,7 +56,6 @@
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <assert.h>
#include <string.h> #include <string.h>
#include <openssl/buf.h> #include <openssl/buf.h>
@ -93,9 +92,13 @@ static void ssl3_finish_handshake(SSL *ssl) {
} }
static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) { static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
/* TODO(davidben): In TLS 1.3, cipher changes are not always preceeded by a if (ssl->s3->rrec.length != 0) {
* ChangeCipherSpec, so this must become a runtime check. */ /* There may not be unprocessed record data at a cipher change. */
assert(ssl->s3->rrec.length == 0); OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
SSL_AEAD_CTX_free(aead_ctx);
return 0;
}
memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence)); memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));