external/boringssl: Sync to 9c33ae85621ef8e00a42309b5101e0bedd02b816.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/629db8cd0c84628e37aa81242b5b07fec7602f55..9c33ae85621ef8e00a42309b5101e0bedd02b816
Bug: 33622440
Test: BoringSSL tests
Change-Id: I20da15ad995a620b6b2f08db20c77ebd0f05ca10
diff --git a/src/ssl/d1_both.c b/src/ssl/d1_both.c
index f9bb8f4..d3e4a92 100644
--- a/src/ssl/d1_both.c
+++ b/src/ssl/d1_both.c
@@ -124,6 +124,7 @@
#include <openssl/rand.h>
#include <openssl/x509.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -157,7 +158,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- memset(frag, 0, sizeof(hm_fragment));
+ OPENSSL_memset(frag, 0, sizeof(hm_fragment));
frag->type = msg_hdr->type;
frag->seq = msg_hdr->seq;
frag->msg_len = msg_hdr->msg_len;
@@ -195,7 +196,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- memset(frag->reassembly, 0, bitmask_len);
+ OPENSSL_memset(frag->reassembly, 0, bitmask_len);
}
return frag;
@@ -383,7 +384,7 @@
assert(msg_len > 0);
/* Copy the body into the fragment. */
- memcpy(frag->data + DTLS1_HM_HEADER_LENGTH + frag_off, CBS_data(&body),
+ OPENSSL_memcpy(frag->data + DTLS1_HM_HEADER_LENGTH + frag_off, CBS_data(&body),
CBS_len(&body));
dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len);
}
@@ -489,7 +490,7 @@
int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr,
CBS *out_body) {
- memset(out_hdr, 0x00, sizeof(struct hm_header_st));
+ OPENSSL_memset(out_hdr, 0x00, sizeof(struct hm_header_st));
if (!CBS_get_u8(cbs, &out_hdr->type) ||
!CBS_get_u24(cbs, &out_hdr->msg_len) ||
@@ -747,7 +748,7 @@
/* Fix up the header. Copy the fragment length into the total message
* length. */
- memcpy(*out_msg + 1, *out_msg + DTLS1_HM_HEADER_LENGTH - 3, 3);
+ OPENSSL_memcpy(*out_msg + 1, *out_msg + DTLS1_HM_HEADER_LENGTH - 3, 3);
return 1;
}
diff --git a/src/ssl/d1_lib.c b/src/ssl/d1_lib.c
index cafb4c2..258e9ab 100644
--- a/src/ssl/d1_lib.c
+++ b/src/ssl/d1_lib.c
@@ -64,9 +64,11 @@
#include <openssl/mem.h>
#include <openssl/nid.h>
+#include "../crypto/internal.h"
#include "internal.h"
+
/* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
* before starting to decrease the MTU. */
#define DTLS1_MTU_TIMEOUTS 2
@@ -86,7 +88,7 @@
ssl3_free(ssl);
return 0;
}
- memset(d1, 0, sizeof *d1);
+ OPENSSL_memset(d1, 0, sizeof *d1);
ssl->d1 = d1;
@@ -154,12 +156,12 @@
if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
(ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
- memset(out, 0, sizeof(struct timeval));
+ OPENSSL_memset(out, 0, sizeof(struct timeval));
return 1;
}
/* Calculate time left until timer expires */
- memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval));
+ OPENSSL_memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval));
out->tv_sec -= timenow.tv_sec;
out->tv_usec -= timenow.tv_usec;
if (out->tv_usec < 0) {
@@ -170,7 +172,7 @@
/* If remaining time is less than 15 ms, set it to 0 to prevent issues
* because of small devergences with socket timeouts. */
if (out->tv_sec == 0 && out->tv_usec < 15000) {
- memset(out, 0, sizeof(struct timeval));
+ OPENSSL_memset(out, 0, sizeof(struct timeval));
}
return 1;
@@ -204,7 +206,7 @@
void dtls1_stop_timer(SSL *ssl) {
/* Reset everything */
ssl->d1->num_timeouts = 0;
- memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
+ OPENSSL_memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
BIO_ctrl(ssl->rbio, BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&ssl->d1->next_timeout);
@@ -234,9 +236,7 @@
}
int DTLSv1_handle_timeout(SSL *ssl) {
- ssl->rwstate = SSL_NOTHING;
- /* Functions which use SSL_get_error must clear the error queue on entry. */
- ERR_clear_error();
+ ssl_reset_error_state(ssl);
if (!SSL_is_dtls(ssl)) {
return -1;
diff --git a/src/ssl/d1_pkt.c b/src/ssl/d1_pkt.c
index 155359c..c6950d5 100644
--- a/src/ssl/d1_pkt.c
+++ b/src/ssl/d1_pkt.c
@@ -122,6 +122,7 @@
#include <openssl/err.h>
#include <openssl/rand.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -265,7 +266,7 @@
len = rr->length;
}
- memcpy(buf, rr->data, len);
+ OPENSSL_memcpy(buf, rr->data, len);
if (!peek) {
/* TODO(davidben): Should the record be truncated instead? This is a
* datagram transport. See https://crbug.com/boringssl/65. */
diff --git a/src/ssl/dtls_method.c b/src/ssl/dtls_method.c
index 89b5491..6576686 100644
--- a/src/ssl/dtls_method.c
+++ b/src/ssl/dtls_method.c
@@ -62,6 +62,7 @@
#include <openssl/buf.h>
#include <openssl/err.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -112,8 +113,8 @@
}
ssl->d1->r_epoch++;
- memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
- memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
+ OPENSSL_memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
+ OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
ssl->s3->aead_read_ctx = aead_ctx;
@@ -122,9 +123,9 @@
static int dtls1_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
ssl->d1->w_epoch++;
- memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
- sizeof(ssl->s3->write_sequence));
- memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
+ OPENSSL_memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
+ sizeof(ssl->s3->write_sequence));
+ OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
ssl->s3->aead_write_ctx = aead_ctx;
diff --git a/src/ssl/dtls_record.c b/src/ssl/dtls_record.c
index ffe4053..e507f5c 100644
--- a/src/ssl/dtls_record.c
+++ b/src/ssl/dtls_record.c
@@ -283,7 +283,7 @@
out[3] = epoch >> 8;
out[4] = epoch & 0xff;
- memcpy(&out[5], &seq[2], 6);
+ OPENSSL_memcpy(&out[5], &seq[2], 6);
size_t ciphertext_len;
if (!SSL_AEAD_CTX_seal(aead, out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
index 8c21818..720c215 100644
--- a/src/ssl/handshake_client.c
+++ b/src/ssl/handshake_client.c
@@ -167,6 +167,7 @@
#include <openssl/x509.h>
#include <openssl/x509v3.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -349,7 +350,7 @@
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
case SSL3_ST_CW_CERT_VRFY_C:
- if (hs->cert_request) {
+ if (hs->cert_request && ssl_has_certificate(ssl)) {
ret = ssl3_send_cert_verify(hs);
if (ret <= 0) {
goto end;
@@ -815,7 +816,7 @@
goto f_err;
}
- memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
+ OPENSSL_memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
ssl->d1->cookie_len = CBS_len(&cookie);
ssl->d1->send_cookie = 1;
@@ -913,7 +914,7 @@
}
/* Copy over the server random. */
- memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+ OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
/* TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS
* 1.3 is finalized and we are not implementing a draft version. */
@@ -932,7 +933,7 @@
}
/* Note: session_id could be empty. */
ssl->s3->new_session->session_id_length = CBS_len(&session_id);
- memcpy(ssl->s3->new_session->session_id, CBS_data(&session_id),
+ OPENSSL_memcpy(ssl->s3->new_session->session_id, CBS_data(&session_id),
CBS_len(&session_id));
}
@@ -1466,7 +1467,6 @@
}
if (!ssl_has_certificate(ssl)) {
- hs->cert_request = 0;
/* Without a client certificate, the handshake buffer may be released. */
ssl3_free_handshake_buffer(ssl);
@@ -1477,7 +1477,8 @@
}
}
- if (!ssl3_output_cert_chain(ssl)) {
+ if (!ssl_auto_chain_if_needed(ssl) ||
+ !ssl3_output_cert_chain(ssl)) {
return -1;
}
hs->state = SSL3_ST_CW_CERT_B;
@@ -1515,7 +1516,7 @@
}
char identity[PSK_MAX_IDENTITY_LEN + 1];
- memset(identity, 0, sizeof(identity));
+ OPENSSL_memset(identity, 0, sizeof(identity));
psk_len =
ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint, identity,
sizeof(identity), psk, sizeof(psk));
@@ -1616,7 +1617,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- memset(pms, 0, pms_len);
+ OPENSSL_memset(pms, 0, pms_len);
} else {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index d41685e..6ce49f5 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -881,12 +881,12 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
- memcpy(ssl->s3->client_random, client_hello.random,
- client_hello.random_len);
+ OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
+ client_hello.random_len);
/* Only null compression is supported. */
- if (memchr(client_hello.compression_methods, 0,
- client_hello.compression_methods_len) == NULL) {
+ if (OPENSSL_memchr(client_hello.compression_methods, 0,
+ client_hello.compression_methods_len) == NULL) {
al = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED);
goto f_err;
@@ -916,6 +916,10 @@
}
}
+ if (!ssl_auto_chain_if_needed(ssl)) {
+ goto err;
+ }
+
/* Negotiate the cipher suite. This must be done after |cert_cb| so the
* certificate is finalized. */
ssl->s3->tmp.new_cipher =
@@ -1736,7 +1740,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
- memset(premaster_secret, 0, premaster_secret_len);
+ OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
} else {
al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 2688bc7..919f5aa 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -779,6 +779,11 @@
* empty certificate list. It returns one on success and zero on error. */
int ssl_add_cert_chain(SSL *ssl, CBB *cbb);
+/* ssl_auto_chain_if_needed runs the deprecated auto-chaining logic if
+ * necessary. On success, it updates |ssl|'s certificate configuration as needed
+ * and returns one. Otherwise, it returns zero. */
+int ssl_auto_chain_if_needed(SSL *ssl);
+
/* ssl_cert_check_digital_signature_key_usage parses the DER-encoded, X.509
* certificate in |in| and returns one if doesn't specify a key usage or, if it
* does, if it includes digitalSignature. Otherwise it pushes to the error
@@ -833,10 +838,9 @@
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_HANDSHAKE *hs);
+/* tls13_derive_handshake_secrets derives the handshake traffic secret. It
+ * returns one on success and zero on error. */
+int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs);
/* tls13_rotate_traffic_key derives the next read or write traffic secret. It
* returns one on success and zero on error. */
@@ -914,6 +918,8 @@
size_t hash_len;
uint8_t secret[EVP_MAX_MD_SIZE];
+ uint8_t client_handshake_secret[EVP_MAX_MD_SIZE];
+ uint8_t server_handshake_secret[EVP_MAX_MD_SIZE];
uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE];
uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE];
@@ -1142,10 +1148,10 @@
* it. It writes the parsed extensions to pointers denoted by |ext_types|. On
* success, it fills in the |out_present| and |out_data| fields and returns one.
* Otherwise, it sets |*out_alert| to an alert to send and returns zero. Unknown
- * extensions are rejected. */
+ * extensions are rejected unless |ignore_unknown| is 1. */
int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
const SSL_EXTENSION_TYPE *ext_types,
- size_t num_ext_types);
+ size_t num_ext_types, int ignore_unknown);
/* SSLKEYLOGFILE functions. */
@@ -1482,6 +1488,10 @@
* handshake. */
unsigned tlsext_channel_id_valid:1;
+ /* short_header is one if https://github.com/tlswg/tls13-spec/pull/762 has
+ * been negotiated. */
+ unsigned short_header:1;
+
uint8_t send_alert[2];
/* pending_message is the current outgoing handshake message. */
@@ -1936,6 +1946,9 @@
void ssl_get_current_time(const SSL *ssl, struct timeval *out_clock);
+/* ssl_reset_error_state resets state for |SSL_get_error|. */
+void ssl_reset_error_state(SSL *ssl);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index 4800f92..492884f 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -127,6 +127,7 @@
#include <openssl/sha.h>
#include <openssl/x509.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -136,7 +137,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- memset(hs, 0, sizeof(SSL_HANDSHAKE));
+ OPENSSL_memset(hs, 0, sizeof(SSL_HANDSHAKE));
hs->ssl = ssl;
hs->wait = ssl_hs_ok;
hs->state = SSL_ST_INIT;
@@ -149,6 +150,10 @@
}
OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
+ OPENSSL_cleanse(hs->client_handshake_secret,
+ sizeof(hs->client_handshake_secret));
+ OPENSSL_cleanse(hs->server_handshake_secret,
+ sizeof(hs->server_handshake_secret));
OPENSSL_cleanse(hs->client_traffic_secret_0,
sizeof(hs->client_traffic_secret_0));
OPENSSL_cleanse(hs->server_traffic_secret_0,
@@ -291,10 +296,10 @@
}
if (ssl->server) {
- memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+ OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len);
ssl->s3->previous_server_finished_len = finished_len;
} else {
- memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+ OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len);
ssl->s3->previous_client_finished_len = finished_len;
}
}
@@ -349,10 +354,10 @@
}
if (ssl->server) {
- memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+ OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len);
ssl->s3->previous_client_finished_len = finished_len;
} else {
- memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+ OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len);
ssl->s3->previous_server_finished_len = finished_len;
}
}
@@ -517,9 +522,9 @@
rand_len = SSL3_RANDOM_SIZE;
}
uint8_t random[SSL3_RANDOM_SIZE];
- memset(random, 0, SSL3_RANDOM_SIZE);
- memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
- rand_len);
+ OPENSSL_memset(random, 0, SSL3_RANDOM_SIZE);
+ OPENSSL_memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
+ rand_len);
/* Write out an equivalent SSLv3 ClientHello. */
size_t max_v3_client_hello = SSL3_HM_HEADER_LENGTH + 2 /* version */ +
@@ -775,7 +780,7 @@
int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
const SSL_EXTENSION_TYPE *ext_types,
- size_t num_ext_types) {
+ size_t num_ext_types, int ignore_unknown) {
/* Reset everything. */
for (size_t i = 0; i < num_ext_types; i++) {
*ext_types[i].out_present = 0;
@@ -802,6 +807,9 @@
}
if (ext_type == NULL) {
+ if (ignore_unknown) {
+ continue;
+ }
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
*out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
return 0;
diff --git a/src/ssl/s3_enc.c b/src/ssl/s3_enc.c
index 7cdc294..bf82e08 100644
--- a/src/ssl/s3_enc.c
+++ b/src/ssl/s3_enc.c
@@ -144,8 +144,10 @@
#include <openssl/md5.h>
#include <openssl/nid.h>
+#include "../crypto/internal.h"
#include "internal.h"
+
static int ssl3_prf(const SSL *ssl, uint8_t *out, size_t out_len,
const uint8_t *secret, size_t secret_len, const char *label,
size_t label_len, const uint8_t *seed1, size_t seed1_len,
@@ -194,7 +196,7 @@
EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
if (i + MD5_DIGEST_LENGTH > out_len) {
EVP_DigestFinal_ex(&md5, smd, NULL);
- memcpy(out, smd, out_len - i);
+ OPENSSL_memcpy(out, smd, out_len - i);
} else {
EVP_DigestFinal_ex(&md5, out, NULL);
}
@@ -269,7 +271,8 @@
if (!BUF_MEM_grow(ssl->s3->handshake_buffer, new_len)) {
return 0;
}
- memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in, in_len);
+ OPENSSL_memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in,
+ in_len);
}
if (EVP_MD_CTX_md(&ssl->s3->handshake_hash) != NULL) {
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
index 859cb9b..7039418 100644
--- a/src/ssl/s3_lib.c
+++ b/src/ssl/s3_lib.c
@@ -159,6 +159,7 @@
#include <openssl/mem.h>
#include <openssl/nid.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -169,7 +170,7 @@
if (s3 == NULL) {
return 0;
}
- memset(s3, 0, sizeof *s3);
+ OPENSSL_memset(s3, 0, sizeof *s3);
s3->hs = ssl_handshake_new(ssl);
if (s3->hs == NULL) {
@@ -221,19 +222,7 @@
return ssl->cipher_list;
}
- if (ssl->version >= TLS1_1_VERSION && ssl->ctx->cipher_list_tls11 != NULL) {
- return ssl->ctx->cipher_list_tls11;
- }
-
- if (ssl->version >= TLS1_VERSION && ssl->ctx->cipher_list_tls10 != NULL) {
- return ssl->ctx->cipher_list_tls10;
- }
-
- if (ssl->ctx->cipher_list != NULL) {
- return ssl->ctx->cipher_list;
- }
-
- return NULL;
+ return ssl->ctx->cipher_list;
}
/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
index e4116fb..9bd9f1f 100644
--- a/src/ssl/s3_pkt.c
+++ b/src/ssl/s3_pkt.c
@@ -118,6 +118,7 @@
#include <openssl/mem.h>
#include <openssl/rand.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -319,7 +320,7 @@
len = (int)rr->length;
}
- memcpy(out, rr->data, len);
+ OPENSSL_memcpy(out, rr->data, len);
if (!peek) {
rr->length -= len;
rr->data += len;
diff --git a/src/ssl/ssl_aead_ctx.c b/src/ssl/ssl_aead_ctx.c
index b05df0b..1b95150 100644
--- a/src/ssl/ssl_aead_ctx.c
+++ b/src/ssl/ssl_aead_ctx.c
@@ -22,6 +22,7 @@
#include <openssl/rand.h>
#include <openssl/type_check.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -52,9 +53,10 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- memcpy(merged_key, mac_key, mac_key_len);
- memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
- memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len);
+ OPENSSL_memcpy(merged_key, mac_key, mac_key_len);
+ OPENSSL_memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
+ OPENSSL_memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv,
+ fixed_iv_len);
enc_key = merged_key;
enc_key_len += mac_key_len;
enc_key_len += fixed_iv_len;
@@ -65,7 +67,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
+ OPENSSL_memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
aead_ctx->cipher = cipher;
if (!EVP_AEAD_CTX_init_with_direction(
@@ -79,7 +81,7 @@
aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
if (mac_key_len == 0) {
assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce));
- memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
+ OPENSSL_memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
aead_ctx->fixed_nonce_len = fixed_iv_len;
if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
@@ -158,7 +160,7 @@
return 0;
}
- memcpy(out, seqnum, 8);
+ OPENSSL_memcpy(out, seqnum, 8);
size_t len = 8;
out[len++] = type;
if (!aead->omit_version_in_ad) {
@@ -208,9 +210,9 @@
/* Prepend the fixed nonce, or left-pad with zeros if XORing. */
if (aead->xor_fixed_nonce) {
nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
- memset(nonce, 0, nonce_len);
+ OPENSSL_memset(nonce, 0, nonce_len);
} else {
- memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+ OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
nonce_len += aead->fixed_nonce_len;
}
@@ -221,12 +223,12 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
return 0;
}
- memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
+ OPENSSL_memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
in += aead->variable_nonce_len;
in_len -= aead->variable_nonce_len;
} else {
assert(aead->variable_nonce_len == 8);
- memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+ OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
}
nonce_len += aead->variable_nonce_len;
@@ -262,7 +264,7 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return 0;
}
- memmove(out, in, in_len);
+ OPENSSL_memmove(out, in, in_len);
*out_len = in_len;
return 1;
}
@@ -278,9 +280,9 @@
/* Prepend the fixed nonce, or left-pad with zeros if XORing. */
if (aead->xor_fixed_nonce) {
nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
- memset(nonce, 0, nonce_len);
+ OPENSSL_memset(nonce, 0, nonce_len);
} else {
- memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+ OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
nonce_len += aead->fixed_nonce_len;
}
@@ -294,7 +296,7 @@
/* When sending we use the sequence number as the variable part of the
* nonce. */
assert(aead->variable_nonce_len == 8);
- memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+ OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
}
nonce_len += aead->variable_nonce_len;
@@ -310,7 +312,8 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
return 0;
}
- memcpy(out, nonce + aead->fixed_nonce_len, aead->variable_nonce_len);
+ OPENSSL_memcpy(out, nonce + aead->fixed_nonce_len,
+ aead->variable_nonce_len);
extra_len = aead->variable_nonce_len;
out += aead->variable_nonce_len;
max_out -= aead->variable_nonce_len;
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
index 902b580..c9dfdcc 100644
--- a/src/ssl/ssl_asn1.c
+++ b/src/ssl/ssl_asn1.c
@@ -91,6 +91,7 @@
#include <openssl/mem.h>
#include <openssl/x509.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -127,6 +128,7 @@
* ticketAgeAdd [21] OCTET STRING OPTIONAL,
* isServer [22] BOOLEAN DEFAULT TRUE,
* peerSignatureAlgorithm [23] INTEGER OPTIONAL,
+ * ticketMaxEarlyData [24] INTEGER OPTIONAL,
* }
*
* Note: historically this serialization has included other optional
@@ -179,6 +181,8 @@
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 22;
static const int kPeerSignatureAlgorithmTag =
CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 23;
+static const int kTicketMaxEarlyDataTag =
+ CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24;
static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
size_t *out_len, int for_ticket) {
@@ -391,6 +395,13 @@
goto err;
}
+ if (in->ticket_max_early_data != 0 &&
+ (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) ||
+ !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
if (!CBB_finish(&cbb, out_data, out_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
@@ -443,7 +454,7 @@
}
if (pp) {
- memcpy(*pp, out, len);
+ OPENSSL_memcpy(*pp, out, len);
*pp += len;
}
OPENSSL_free(out);
@@ -510,7 +521,7 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
return 0;
}
- memcpy(out, CBS_data(&value), CBS_len(&value));
+ OPENSSL_memcpy(out, CBS_data(&value), CBS_len(&value));
*out_len = (uint8_t)CBS_len(&value);
return 1;
}
@@ -593,9 +604,9 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
- memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
+ OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
ret->session_id_length = CBS_len(&session_id);
- memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
+ OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
ret->master_key_length = CBS_len(&master_key);
CBS child;
@@ -647,7 +658,8 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
}
- memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256));
+ OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
+ sizeof(ret->peer_sha256));
ret->peer_sha256_valid = 1;
} else {
ret->peer_sha256_valid = 0;
@@ -773,6 +785,8 @@
if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
kPeerSignatureAlgorithmTag, 0) ||
+ !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
+ kTicketMaxEarlyDataTag, 0) ||
CBS_len(&session) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
goto err;
diff --git a/src/ssl/ssl_buffer.c b/src/ssl/ssl_buffer.c
index 7feb161..c27db8b 100644
--- a/src/ssl/ssl_buffer.c
+++ b/src/ssl/ssl_buffer.c
@@ -24,6 +24,7 @@
#include <openssl/mem.h>
#include <openssl/type_check.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -67,7 +68,7 @@
static void clear_buffer(SSL3_BUFFER *buf) {
OPENSSL_free(buf->buf);
- memset(buf, 0, sizeof(SSL3_BUFFER));
+ OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
}
OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <=
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
index 277ee4d..397fbf0 100644
--- a/src/ssl/ssl_cert.c
+++ b/src/ssl/ssl_cert.c
@@ -147,7 +147,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- memset(ret, 0, sizeof(CERT));
+ OPENSSL_memset(ret, 0, sizeof(CERT));
return ret;
}
@@ -158,7 +158,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
- memset(ret, 0, sizeof(CERT));
+ OPENSSL_memset(ret, 0, sizeof(CERT));
if (cert->x509_leaf != NULL) {
X509_up_ref(cert->x509_leaf);
@@ -557,56 +557,55 @@
return CBB_add_u24(cbb, 0);
}
- CERT *cert = ssl->cert;
- X509 *x = cert->x509_leaf;
-
CBB child;
- if (!CBB_add_u24_length_prefixed(cbb, &child)) {
+ if (!CBB_add_u24_length_prefixed(cbb, &child) ||
+ !ssl_add_cert_with_length(&child, ssl->cert->x509_leaf)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- int no_chain = 0;
- STACK_OF(X509) *chain = cert->x509_chain;
- if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) || chain != NULL) {
- no_chain = 1;
- }
-
- if (no_chain) {
- if (!ssl_add_cert_with_length(&child, x)) {
+ STACK_OF(X509) *chain = ssl->cert->x509_chain;
+ for (size_t i = 0; i < sk_X509_num(chain); i++) {
+ if (!ssl_add_cert_with_length(&child, sk_X509_value(chain, i))) {
return 0;
}
-
- for (size_t i = 0; i < sk_X509_num(chain); i++) {
- x = sk_X509_value(chain, i);
- if (!ssl_add_cert_with_length(&child, x)) {
- return 0;
- }
- }
- } else {
- X509_STORE_CTX xs_ctx;
-
- if (!X509_STORE_CTX_init(&xs_ctx, ssl->ctx->cert_store, x, NULL)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
- return 0;
- }
- X509_verify_cert(&xs_ctx);
- /* Don't leave errors in the queue */
- ERR_clear_error();
-
- for (size_t i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
- x = sk_X509_value(xs_ctx.chain, i);
- if (!ssl_add_cert_with_length(&child, x)) {
- X509_STORE_CTX_cleanup(&xs_ctx);
- return 0;
- }
- }
- X509_STORE_CTX_cleanup(&xs_ctx);
}
return CBB_flush(cbb);
}
+int ssl_auto_chain_if_needed(SSL *ssl) {
+ /* Only build a chain if there are no intermediates configured and the feature
+ * isn't disabled. */
+ if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
+ !ssl_has_certificate(ssl) ||
+ ssl->cert->x509_chain != NULL) {
+ return 1;
+ }
+
+ X509_STORE_CTX ctx;
+ if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, ssl->cert->x509_leaf,
+ NULL)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+ return 0;
+ }
+
+ /* Attempt to build a chain, ignoring the result. */
+ X509_verify_cert(&ctx);
+ ERR_clear_error();
+
+ /* Configure the intermediates from any partial chain we managed to build. */
+ for (size_t i = 1; i < sk_X509_num(ctx.chain); i++) {
+ if (!SSL_add1_chain_cert(ssl, sk_X509_value(ctx.chain, i))) {
+ X509_STORE_CTX_cleanup(&ctx);
+ return 0;
+ }
+ }
+
+ X509_STORE_CTX_cleanup(&ctx);
+ return 1;
+}
+
/* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and
* positions |*out_tbs_cert| to cover the TBSCertificate, starting at the
* subjectPublicKeyInfo. */
@@ -707,7 +706,8 @@
static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f};
if (CBS_len(&oid) != sizeof(kKeyUsageOID) ||
- memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) != 0) {
+ OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) !=
+ 0) {
continue;
}
diff --git a/src/ssl/ssl_cipher.c b/src/ssl/ssl_cipher.c
index 5223721..20b075e 100644
--- a/src/ssl/ssl_cipher.c
+++ b/src/ssl/ssl_cipher.c
@@ -1073,7 +1073,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
+ OPENSSL_memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
/* Now find the strength_bits values actually used. */
curr = *head_p;
@@ -1437,7 +1437,7 @@
if (!pref_list->in_group_flags) {
goto err;
}
- memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
+ OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
OPENSSL_free(in_group_flags);
in_group_flags = NULL;
if (*out_cipher_list != NULL) {
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index 77e86a8..a60bf81 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -196,8 +196,8 @@
uint8_t tmp_storage[sizeof(uint32_t)];
if (sess->session_id_length < sizeof(tmp_storage)) {
- memset(tmp_storage, 0, sizeof(tmp_storage));
- memcpy(tmp_storage, sess->session_id, sess->session_id_length);
+ OPENSSL_memset(tmp_storage, 0, sizeof(tmp_storage));
+ OPENSSL_memcpy(tmp_storage, sess->session_id, sess->session_id_length);
session_id = tmp_storage;
}
@@ -224,7 +224,7 @@
return 1;
}
- return memcmp(a->session_id, b->session_id, a->session_id_length);
+ return OPENSSL_memcmp(a->session_id, b->session_id, a->session_id_length);
}
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
@@ -245,7 +245,7 @@
goto err;
}
- memset(ret, 0, sizeof(SSL_CTX));
+ OPENSSL_memset(ret, 0, sizeof(SSL_CTX));
ret->method = method->method;
@@ -352,8 +352,6 @@
lh_SSL_SESSION_free(ctx->sessions);
X509_STORE_free(ctx->cert_store);
ssl_cipher_preference_list_free(ctx->cipher_list);
- ssl_cipher_preference_list_free(ctx->cipher_list_tls10);
- ssl_cipher_preference_list_free(ctx->cipher_list_tls11);
ssl_cert_free(ctx->cert);
sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->client_custom_extensions,
SSL_CUSTOM_EXTENSION_free);
@@ -385,7 +383,7 @@
if (ssl == NULL) {
goto err;
}
- memset(ssl, 0, sizeof(SSL));
+ OPENSSL_memset(ssl, 0, sizeof(SSL));
ssl->min_version = ctx->min_version;
ssl->max_version = ctx->max_version;
@@ -408,7 +406,7 @@
ssl->verify_mode = ctx->verify_mode;
ssl->sid_ctx_length = ctx->sid_ctx_length;
assert(ssl->sid_ctx_length <= sizeof ssl->sid_ctx);
- memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx));
+ OPENSSL_memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx));
ssl->verify_callback = ctx->default_verify_callback;
ssl->retain_only_sha256_of_client_certs =
ctx->retain_only_sha256_of_client_certs;
@@ -421,9 +419,9 @@
ssl->quiet_shutdown = ctx->quiet_shutdown;
ssl->max_send_fragment = ctx->max_send_fragment;
- CRYPTO_refcount_inc(&ctx->references);
+ SSL_CTX_up_ref(ctx);
ssl->ctx = ctx;
- CRYPTO_refcount_inc(&ctx->references);
+ SSL_CTX_up_ref(ctx);
ssl->initial_ctx = ctx;
if (ctx->supported_group_list) {
@@ -614,11 +612,16 @@
return ssl->wbio;
}
-int SSL_do_handshake(SSL *ssl) {
+void ssl_reset_error_state(SSL *ssl) {
+ /* Functions which use |SSL_get_error| must reset I/O and error state on
+ * entry. */
ssl->rwstate = SSL_NOTHING;
- /* Functions which use SSL_get_error must clear the error queue on entry. */
ERR_clear_error();
ERR_clear_system_error();
+}
+
+int SSL_do_handshake(SSL *ssl) {
+ ssl_reset_error_state(ssl);
if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_TYPE_NOT_SET);
@@ -737,10 +740,7 @@
}
static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) {
- ssl->rwstate = SSL_NOTHING;
- /* Functions which use SSL_get_error must clear the error queue on entry. */
- ERR_clear_error();
- ERR_clear_system_error();
+ ssl_reset_error_state(ssl);
if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
@@ -786,10 +786,7 @@
}
int SSL_write(SSL *ssl, const void *buf, int num) {
- ssl->rwstate = SSL_NOTHING;
- /* Functions which use SSL_get_error must clear the error queue on entry. */
- ERR_clear_error();
- ERR_clear_system_error();
+ ssl_reset_error_state(ssl);
if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
@@ -817,10 +814,7 @@
}
int SSL_shutdown(SSL *ssl) {
- ssl->rwstate = SSL_NOTHING;
- /* Functions which use SSL_get_error must clear the error queue on entry. */
- ERR_clear_error();
- ERR_clear_system_error();
+ ssl_reset_error_state(ssl);
if (ssl->handshake_func == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
@@ -880,6 +874,10 @@
return ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
}
+void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
+ ctx->enable_early_data = !!enabled;
+}
+
static int bio_retry_reason_to_error(int reason) {
switch (reason) {
case BIO_RR_CONNECT:
@@ -1159,12 +1157,12 @@
*out_len = max_out;
}
- memcpy(out, finished, *out_len);
+ OPENSSL_memcpy(out, finished, *out_len);
return 1;
err:
*out_len = 0;
- memset(out, 0, max_out);
+ OPENSSL_memset(out, 0, max_out);
return 0;
}
@@ -1177,7 +1175,7 @@
assert(sizeof(ctx->sid_ctx) < 256);
ctx->sid_ctx_length = (uint8_t)sid_ctx_len;
- memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
+ OPENSSL_memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
@@ -1191,7 +1189,7 @@
assert(sizeof(ssl->sid_ctx) < 256);
ssl->sid_ctx_length = (uint8_t)sid_ctx_len;
- memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
+ OPENSSL_memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
@@ -1311,7 +1309,7 @@
if (out_len > in_len) {
out_len = in_len;
}
- memcpy(out, in, out_len);
+ OPENSSL_memcpy(out, in, out_len);
return in_len;
}
@@ -1547,9 +1545,9 @@
return 0;
}
uint8_t *out_bytes = out;
- memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
- memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
- memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
+ OPENSSL_memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
+ OPENSSL_memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
+ OPENSSL_memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
return 1;
}
@@ -1562,9 +1560,9 @@
return 0;
}
const uint8_t *in_bytes = in;
- memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
- memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
- memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
+ OPENSSL_memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
+ OPENSSL_memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
+ OPENSSL_memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
return 1;
}
@@ -1680,38 +1678,6 @@
return 1;
}
-int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str) {
- STACK_OF(SSL_CIPHER) *cipher_list =
- ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls10, str);
- if (cipher_list == NULL) {
- return 0;
- }
-
- /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
- if (sk_SSL_CIPHER_num(cipher_list) == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
- return 0;
- }
-
- return 1;
-}
-
-int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) {
- STACK_OF(SSL_CIPHER) *cipher_list =
- ssl_create_cipher_list(ctx->method, &ctx->cipher_list_tls11, str);
- if (cipher_list == NULL) {
- return 0;
- }
-
- /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
- if (sk_SSL_CIPHER_num(cipher_list) == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
- return 0;
- }
-
- return 1;
-}
-
int SSL_set_cipher_list(SSL *ssl, const char *str) {
STACK_OF(SSL_CIPHER) *cipher_list =
ssl_create_cipher_list(ssl->ctx->method, &ssl->cipher_list, str);
@@ -1878,7 +1844,7 @@
for (i = 0; i < server_len;) {
for (j = 0; j < client_len;) {
if (server[i] == client[j] &&
- memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
+ OPENSSL_memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
/* We found a match */
result = &server[i];
status = OPENSSL_NPN_NEGOTIATED;
@@ -2030,7 +1996,8 @@
if (!ssl->s3->tlsext_channel_id_valid) {
return 0;
}
- memcpy(out, ssl->s3->tlsext_channel_id, (max_out < 64) ? max_out : 64);
+ OPENSSL_memcpy(out, ssl->s3->tlsext_channel_id,
+ (max_out < 64) ? max_out : 64);
return 64;
}
@@ -2299,13 +2266,13 @@
ssl_cert_free(ssl->cert);
ssl->cert = ssl_cert_dup(ctx->cert);
- CRYPTO_refcount_inc(&ctx->references);
- SSL_CTX_free(ssl->ctx); /* decrement reference count */
+ SSL_CTX_up_ref(ctx);
+ SSL_CTX_free(ssl->ctx);
ssl->ctx = ctx;
ssl->sid_ctx_length = ctx->sid_ctx_length;
assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx));
- memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx));
+ OPENSSL_memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx));
return ssl->ctx;
}
@@ -2869,7 +2836,7 @@
if (max_out > sizeof(ssl->s3->client_random)) {
max_out = sizeof(ssl->s3->client_random);
}
- memcpy(out, ssl->s3->client_random, max_out);
+ OPENSSL_memcpy(out, ssl->s3->client_random, max_out);
return max_out;
}
@@ -2880,7 +2847,7 @@
if (max_out > sizeof(ssl->s3->server_random)) {
max_out = sizeof(ssl->s3->server_random);
}
- memcpy(out, ssl->s3->server_random, max_out);
+ OPENSSL_memcpy(out, ssl->s3->server_random, max_out);
return max_out;
}
@@ -2903,6 +2870,10 @@
ctx->grease_enabled = !!enabled;
}
+void SSL_CTX_set_short_header_enabled(SSL_CTX *ctx, int enabled) {
+ ctx->short_header_enabled = !!enabled;
+}
+
int SSL_clear(SSL *ssl) {
/* In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously
* established session to be offered the next time around. wpa_supplicant
diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.c
index d6d7dab..7adef1a 100644
--- a/src/ssl/ssl_session.c
+++ b/src/ssl/ssl_session.c
@@ -166,7 +166,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- memset(session, 0, sizeof(SSL_SESSION));
+ OPENSSL_memset(session, 0, sizeof(SSL_SESSION));
session->verify_result = X509_V_ERR_INVALID_CALL;
session->references = 1;
@@ -185,11 +185,11 @@
new_session->is_server = session->is_server;
new_session->ssl_version = session->ssl_version;
new_session->sid_ctx_length = session->sid_ctx_length;
- memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
+ OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
/* Copy the key material. */
new_session->master_key_length = session->master_key_length;
- memcpy(new_session->master_key, session->master_key,
+ OPENSSL_memcpy(new_session->master_key, session->master_key,
session->master_key_length);
new_session->cipher = session->cipher;
@@ -245,7 +245,8 @@
}
}
- memcpy(new_session->peer_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH);
+ OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
+ SHA256_DIGEST_LENGTH);
new_session->peer_sha256_valid = session->peer_sha256_valid;
if (session->tlsext_hostname != NULL) {
@@ -263,18 +264,19 @@
/* Copy non-authentication connection properties. */
if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
new_session->session_id_length = session->session_id_length;
- memcpy(new_session->session_id, session->session_id,
- session->session_id_length);
+ OPENSSL_memcpy(new_session->session_id, session->session_id,
+ session->session_id_length);
new_session->group_id = session->group_id;
- memcpy(new_session->original_handshake_hash,
- session->original_handshake_hash,
- session->original_handshake_hash_len);
+ OPENSSL_memcpy(new_session->original_handshake_hash,
+ session->original_handshake_hash,
+ session->original_handshake_hash_len);
new_session->original_handshake_hash_len =
session->original_handshake_hash_len;
new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
new_session->ticket_age_add = session->ticket_age_add;
+ new_session->ticket_max_early_data = session->ticket_max_early_data;
new_session->extended_master_secret = session->extended_master_secret;
}
@@ -387,7 +389,7 @@
if (max_out > (size_t)session->master_key_length) {
max_out = (size_t)session->master_key_length;
}
- memcpy(out, session->master_key, max_out);
+ OPENSSL_memcpy(out, session->master_key, max_out);
return max_out;
}
@@ -418,7 +420,7 @@
assert(sizeof(session->sid_ctx) < 256);
session->sid_ctx_length = (uint8_t)sid_ctx_len;
- memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
+ OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
@@ -517,7 +519,7 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
- memcpy(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length);
+ OPENSSL_memcpy(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length);
session->sid_ctx_length = ssl->sid_ctx_length;
/* The session is marked not resumable until it is completely filled in. */
@@ -627,7 +629,7 @@
NULL)) {
goto err;
}
- memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+ OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16);
}
uint8_t *ptr;
@@ -639,7 +641,7 @@
size_t total = 0;
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- memcpy(ptr, session_buf, session_len);
+ OPENSSL_memcpy(ptr, session_buf, session_len);
total = session_len;
#else
int len;
@@ -679,7 +681,8 @@
}
return session->sid_ctx_length == ssl->sid_ctx_length &&
- memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) == 0;
+ OPENSSL_memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) ==
+ 0;
}
int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
@@ -737,7 +740,7 @@
SSL_SESSION data;
data.ssl_version = ssl->version;
data.session_id_length = session_id_len;
- memcpy(data.session_id, session_id, session_id_len);
+ OPENSSL_memcpy(data.session_id, session_id, session_id_len);
CRYPTO_MUTEX_lock_read(&ssl->initial_ctx->lock);
session = lh_SSL_SESSION_retrieve(ssl->initial_ctx->sessions, &data);
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index b74e51e..952ac11 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -673,7 +673,7 @@
}
encoded.reset(encoded_raw);
if (encoded_len != input.size() ||
- memcmp(input.data(), encoded.get(), input.size()) != 0) {
+ OPENSSL_memcmp(input.data(), encoded.get(), input.size()) != 0) {
fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
hexdump(stderr, "Before: ", input.data(), input.size());
hexdump(stderr, "After: ", encoded_raw, encoded_len);
@@ -711,7 +711,7 @@
fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
return false;
}
- if (memcmp(input.data(), encoded.get(), input.size()) != 0) {
+ if (OPENSSL_memcmp(input.data(), encoded.get(), input.size()) != 0) {
fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
return false;
}
@@ -838,7 +838,7 @@
if (session->tlsext_tick == nullptr) {
return nullptr;
}
- memset(session->tlsext_tick, 'a', ticket_len);
+ OPENSSL_memset(session->tlsext_tick, 'a', ticket_len);
session->tlsext_ticklen = ticket_len;
// Fix up the timeout.
@@ -1030,8 +1030,8 @@
}
ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
- memset(ret->session_id, 0, ret->session_id_length);
- memcpy(ret->session_id, &number, sizeof(number));
+ OPENSSL_memset(ret->session_id, 0, ret->session_id_length);
+ OPENSSL_memcpy(ret->session_id, &number, sizeof(number));
return ret;
}
@@ -1142,7 +1142,8 @@
"j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
"-----END CERTIFICATE-----\n";
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
- return bssl::UniquePtr<X509>(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+ return bssl::UniquePtr<X509>(
+ PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
}
static bssl::UniquePtr<EVP_PKEY> GetTestKey() {
@@ -1197,6 +1198,90 @@
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
}
+static bssl::UniquePtr<X509> GetChainTestCertificate() {
+ static const char kCertPEM[] =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD\n"
+ "QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs\n"
+ "aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRvaz8\n"
+ "CC/cshpCafJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/\n"
+ "kLRcH89M/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3\n"
+ "tHb+xs2PSs8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+c\n"
+ "IDs2rQ+lP7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1\n"
+ "z7C8jU50Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9V\n"
+ "iLeXANgZi+Xx9KgfAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI\n"
+ "KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBFEVbmYl+2RtNw\n"
+ "rDftRDF1v2QUbcN2ouSnQDHxeDQdSgasLzT3ui8iYu0Rw2WWcZ0DV5e0ztGPhWq7\n"
+ "AO0B120aFRMOY+4+bzu9Q2FFkQqc7/fKTvTDzIJI5wrMnFvUfzzvxh3OHWMYSs/w\n"
+ "giq33hTKeHEq6Jyk3btCny0Ycecyc3yGXH10sizUfiHlhviCkDuESk8mFDwDDzqW\n"
+ "ZF0IipzFbEDHoIxLlm3GQxpiLoEV4k8KYJp3R5KBLFyxM6UGPz8h72mIPCJp2RuK\n"
+ "MYgF91UDvVzvnYm6TfseM2+ewKirC00GOrZ7rEcFvtxnKSqYf4ckqfNdSU1Y+RRC\n"
+ "1ngWZ7Ih\n"
+ "-----END CERTIFICATE-----\n";
+ bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
+ return bssl::UniquePtr<X509>(
+ PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<X509> GetChainTestIntermediate() {
+ static const char kCertPEM[] =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS\n"
+ "b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE\n"
+ "AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsSCYmDip2D\n"
+ "GkjFxw7ykz26JSjELkl6ArlYjFJ3aT/SCh8qbS4gln7RH8CPBd78oFdfhIKQrwtZ\n"
+ "3/q21ykD9BAS3qHe2YdcJfm8/kWAy5DvXk6NXU4qX334KofBAEpgdA/igEFq1P1l\n"
+ "HAuIfZCpMRfT+i5WohVsGi8f/NgpRvVaMONLNfgw57mz1lbtFeBEISmX0kbsuJxF\n"
+ "Qj/Bwhi5/0HAEXG8e7zN4cEx0yPRvmOATRdVb/8dW2pwOHRJq9R5M0NUkIsTSnL7\n"
+ "6N/z8hRAHMsV3IudC5Yd7GXW1AGu9a+iKU+Q4xcZCoj0DC99tL4VKujrV1kAeqsM\n"
+ "cz5/dKzi6+cCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
+ "AQYwDQYJKoZIhvcNAQELBQADggEBAIIeZiEeNhWWQ8Y4D+AGDwqUUeG8NjCbKrXQ\n"
+ "BlHg5wZ8xftFaiP1Dp/UAezmx2LNazdmuwrYB8lm3FVTyaPDTKEGIPS4wJKHgqH1\n"
+ "QPDhqNm85ey7TEtI9oYjsNim/Rb+iGkIAMXaxt58SzxbjvP0kMr1JfJIZbic9vye\n"
+ "NwIspMFIpP3FB8ywyu0T0hWtCQgL4J47nigCHpOu58deP88fS/Nyz/fyGVWOZ76b\n"
+ "WhWwgM3P3X95fQ3d7oFPR/bVh0YV+Cf861INwplokXgXQ3/TCQ+HNXeAMWn3JLWv\n"
+ "XFwk8owk9dq/kQGdndGgy3KTEW4ctPX5GNhf3LJ9Q7dLji4ReQ4=\n"
+ "-----END CERTIFICATE-----\n";
+ bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
+ return bssl::UniquePtr<X509>(
+ PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<EVP_PKEY> GetChainTestKey() {
+ static const char kKeyPEM[] =
+ "-----BEGIN PRIVATE KEY-----\n"
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRvaz8CC/cshpC\n"
+ "afJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/kLRcH89M\n"
+ "/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3tHb+xs2P\n"
+ "Ss8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+cIDs2rQ+l\n"
+ "P7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1z7C8jU50\n"
+ "Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9ViLeXANgZ\n"
+ "i+Xx9KgfAgMBAAECggEBAK0VjSJzkyPaamcyTVSWjo7GdaBGcK60lk657RjR+lK0\n"
+ "YJ7pkej4oM2hdsVZFsP8Cs4E33nXLa/0pDsRov/qrp0WQm2skwqGMC1I/bZ0WRPk\n"
+ "wHaDrBBfESWnJDX/AGpVtlyOjPmgmK6J2usMPihQUDkKdAYrVWJePrMIxt1q6BMe\n"
+ "iczs3qriMmtY3bUc4UyUwJ5fhDLjshHvfuIpYQyI6EXZM6dZksn9LylXJnigY6QJ\n"
+ "HxOYO0BDwOsZ8yQ8J8afLk88i0GizEkgE1z3REtQUwgWfxr1WV/ud+T6/ZhSAgH9\n"
+ "042mQvSFZnIUSEsmCvjhWuAunfxHKCTcAoYISWfzWpkCgYEA7gpf3HHU5Tn+CgUn\n"
+ "1X5uGpG3DmcMgfeGgs2r2f/IIg/5Ac1dfYILiybL1tN9zbyLCJfcbFpWBc9hJL6f\n"
+ "CPc5hUiwWFJqBJewxQkC1Ae/HakHbip+IZ+Jr0842O4BAArvixk4Lb7/N2Ct9sTE\n"
+ "NJO6RtK9lbEZ5uK61DglHy8CS2UCgYEA4ZC1o36kPAMQBggajgnucb2yuUEelk0f\n"
+ "AEr+GI32MGE+93xMr7rAhBoqLg4AITyIfEnOSQ5HwagnIHonBbv1LV/Gf9ursx8Z\n"
+ "YOGbvT8zzzC+SU1bkDzdjAYnFQVGIjMtKOBJ3K07++ypwX1fr4QsQ8uKL8WSOWwt\n"
+ "Z3Bym6XiZzMCgYADnhy+2OwHX85AkLt+PyGlPbmuelpyTzS4IDAQbBa6jcuW/2wA\n"
+ "UE2km75VUXmD+u2R/9zVuLm99NzhFhSMqlUxdV1YukfqMfP5yp1EY6m/5aW7QuIP\n"
+ "2MDa7TVL9rIFMiVZ09RKvbBbQxjhuzPQKL6X/PPspnhiTefQ+dl2k9xREQKBgHDS\n"
+ "fMfGNEeAEKezrfSVqxphE9/tXms3L+ZpnCaT+yu/uEr5dTIAawKoQ6i9f/sf1/Sy\n"
+ "xedsqR+IB+oKrzIDDWMgoJybN4pkZ8E5lzhVQIjFjKgFdWLzzqyW9z1gYfABQPlN\n"
+ "FiS20WX0vgP1vcKAjdNrHzc9zyHBpgQzDmAj3NZZAoGBAI8vKCKdH7w3aL5CNkZQ\n"
+ "2buIeWNA2HZazVwAGG5F2TU/LmXfRKnG6dX5bkU+AkBZh56jNZy//hfFSewJB4Kk\n"
+ "buB7ERSdaNbO21zXt9FEA3+z0RfMd/Zv2vlIWOSB5nzl/7UKti3sribK6s9ZVLfi\n"
+ "SxpiPQ8d/hmSGwn4ksrWUsJD\n"
+ "-----END PRIVATE KEY-----\n";
+ bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
+ return bssl::UniquePtr<EVP_PKEY>(
+ PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
static bool CompleteHandshakes(SSL *client, SSL *server) {
// Drive both their handshakes to completion.
for (;;) {
@@ -1442,7 +1527,7 @@
}
bssl::UniquePtr<uint8_t> free_s1(s1_bytes);
- return s0_len == s1_len && memcmp(s0_bytes, s1_bytes, s0_len) == 0;
+ return s0_len == s1_len && OPENSSL_memcmp(s0_bytes, s1_bytes, s0_len) == 0;
}
static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
@@ -1711,7 +1796,8 @@
return false;
}
- if (memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) != 0) {
+ if (OPENSSL_memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) !=
+ 0) {
fprintf(stderr, "peer_sha256 did not match.\n");
return false;
}
@@ -1747,10 +1833,10 @@
fprintf(stderr, "ClientHello for version %04x too short.\n", version);
return false;
}
- memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
+ OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
if (client_hello.size() != expected_len ||
- memcmp(client_hello.data(), expected, expected_len) != 0) {
+ OPENSSL_memcmp(client_hello.data(), expected, expected_len) != 0) {
fprintf(stderr, "ClientHello for version %04x did not match:\n", version);
fprintf(stderr, "Got:\n\t");
for (size_t i = 0; i < client_hello.size(); i++) {
@@ -2097,9 +2183,9 @@
static const uint8_t kZeros[16] = {0};
if (encrypt) {
- memcpy(key_name, kZeros, sizeof(kZeros));
+ OPENSSL_memcpy(key_name, kZeros, sizeof(kZeros));
RAND_bytes(iv, 16);
- } else if (memcmp(key_name, kZeros, 16) != 0) {
+ } else if (OPENSSL_memcmp(key_name, kZeros, 16) != 0) {
return 0;
}
@@ -2124,7 +2210,7 @@
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
// Fuzzer-mode tickets are unencrypted.
- memcpy(plaintext.get(), ciphertext, len);
+ OPENSSL_memcpy(plaintext.get(), ciphertext, len);
#else
static const uint8_t kZeros[16] = {0};
const uint8_t *iv = session->tlsext_tick + 16;
@@ -2588,6 +2674,27 @@
return true;
}
+static const char *GetVersionName(uint16_t version) {
+ switch (version) {
+ case SSL3_VERSION:
+ return "SSLv3";
+ case TLS1_VERSION:
+ return "TLSv1";
+ case TLS1_1_VERSION:
+ return "TLSv1.1";
+ case TLS1_2_VERSION:
+ return "TLSv1.2";
+ case TLS1_3_VERSION:
+ return "TLSv1.3";
+ case DTLS1_VERSION:
+ return "DTLSv1";
+ case DTLS1_2_VERSION:
+ return "DTLSv1.2";
+ default:
+ return "???";
+ }
+}
+
static bool TestVersion(bool is_dtls, const SSL_METHOD *method,
uint16_t version) {
bssl::UniquePtr<X509> cert = GetTestCertificate();
@@ -2619,6 +2726,29 @@
return false;
}
+ // Test the version name is reported as expected.
+ const char *version_name = GetVersionName(version);
+ if (strcmp(version_name, SSL_get_version(client.get())) != 0 ||
+ strcmp(version_name, SSL_get_version(server.get())) != 0) {
+ fprintf(stderr, "Version name mismatch. Got '%s' and '%s', wanted '%s'.\n",
+ SSL_get_version(client.get()), SSL_get_version(server.get()),
+ version_name);
+ return false;
+ }
+
+ // Test SSL_SESSION reports the same name.
+ const char *client_name =
+ SSL_SESSION_get_version(SSL_get_session(client.get()));
+ const char *server_name =
+ SSL_SESSION_get_version(SSL_get_session(server.get()));
+ if (strcmp(version_name, client_name) != 0 ||
+ strcmp(version_name, server_name) != 0) {
+ fprintf(stderr,
+ "Session version name mismatch. Got '%s' and '%s', wanted '%s'.\n",
+ client_name, server_name, version_name);
+ return false;
+ }
+
return true;
}
@@ -2738,6 +2868,268 @@
return true;
}
+static bool ChainsEqual(STACK_OF(X509) *chain,
+ const std::vector<X509 *> &expected) {
+ if (sk_X509_num(chain) != expected.size()) {
+ return false;
+ }
+
+ for (size_t i = 0; i < expected.size(); i++) {
+ if (X509_cmp(sk_X509_value(chain, i), expected[i]) != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool TestAutoChain(bool is_dtls, const SSL_METHOD *method,
+ uint16_t version) {
+ bssl::UniquePtr<X509> cert = GetChainTestCertificate();
+ bssl::UniquePtr<X509> intermediate = GetChainTestIntermediate();
+ bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
+ if (!cert || !intermediate || !key) {
+ return false;
+ }
+
+ // Configure both client and server to accept any certificate. Add
+ // |intermediate| to the cert store.
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+ if (!ctx ||
+ !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+ !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+ !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+ !X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx.get()),
+ intermediate.get())) {
+ return false;
+ }
+ SSL_CTX_set_verify(
+ ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
+ SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
+
+ // By default, the client and server should each only send the leaf.
+ bssl::UniquePtr<SSL> client, server;
+ if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+ nullptr /* no session */)) {
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()), {cert.get()})) {
+ fprintf(stderr, "Client-received chain did not match.\n");
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()), {cert.get()})) {
+ fprintf(stderr, "Server-received chain did not match.\n");
+ return false;
+ }
+
+ // If auto-chaining is enabled, then the intermediate is sent.
+ SSL_CTX_clear_mode(ctx.get(), SSL_MODE_NO_AUTO_CHAIN);
+ if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+ nullptr /* no session */)) {
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()),
+ {cert.get(), intermediate.get()})) {
+ fprintf(stderr, "Client-received chain did not match (auto-chaining).\n");
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()),
+ {cert.get(), intermediate.get()})) {
+ fprintf(stderr, "Server-received chain did not match (auto-chaining).\n");
+ return false;
+ }
+
+ // Auto-chaining does not override explicitly-configured intermediates.
+ if (!SSL_CTX_add1_chain_cert(ctx.get(), cert.get()) ||
+ !ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+ nullptr /* no session */)) {
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()),
+ {cert.get(), cert.get()})) {
+ fprintf(stderr,
+ "Client-received chain did not match (auto-chaining, explicit "
+ "intermediate).\n");
+ return false;
+ }
+
+ if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()),
+ {cert.get(), cert.get()})) {
+ fprintf(stderr,
+ "Server-received chain did not match (auto-chaining, explicit "
+ "intermediate).\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool ExpectBadWriteRetry() {
+ int err = ERR_get_error();
+ if (ERR_GET_LIB(err) != ERR_LIB_SSL ||
+ ERR_GET_REASON(err) != SSL_R_BAD_WRITE_RETRY) {
+ char buf[ERR_ERROR_STRING_BUF_LEN];
+ ERR_error_string_n(err, buf, sizeof(buf));
+ fprintf(stderr, "Wanted SSL_R_BAD_WRITE_RETRY, got: %s.\n", buf);
+ return false;
+ }
+
+ if (ERR_peek_error() != 0) {
+ fprintf(stderr, "Unexpected error following SSL_R_BAD_WRITE_RETRY.\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool TestSSLWriteRetry(bool is_dtls, const SSL_METHOD *method,
+ uint16_t version) {
+ if (is_dtls) {
+ return true;
+ }
+
+ for (bool enable_partial_write : std::vector<bool>{false, true}) {
+ // Connect a client and server.
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+ bssl::UniquePtr<SSL> client, server;
+ if (!cert || !key || !ctx ||
+ !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+ !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+ !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+ !ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+ nullptr /* no session */)) {
+ return false;
+ }
+
+ if (enable_partial_write) {
+ SSL_set_mode(client.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
+ }
+
+ // Write without reading until the buffer is full and we have an unfinished
+ // write. Keep a count so we may reread it again later. "hello!" will be
+ // written in two chunks, "hello" and "!".
+ char data[] = "hello!";
+ static const int kChunkLen = 5; // The length of "hello".
+ unsigned count = 0;
+ for (;;) {
+ int ret = SSL_write(client.get(), data, kChunkLen);
+ if (ret <= 0) {
+ int err = SSL_get_error(client.get(), ret);
+ if (SSL_get_error(client.get(), ret) == SSL_ERROR_WANT_WRITE) {
+ break;
+ }
+ fprintf(stderr, "SSL_write failed in unexpected way: %d\n", err);
+ return false;
+ }
+
+ if (ret != 5) {
+ fprintf(stderr, "SSL_write wrote %d bytes, expected 5.\n", ret);
+ return false;
+ }
+
+ count++;
+ }
+
+ // Retrying with the same parameters is legal.
+ if (SSL_get_error(client.get(), SSL_write(client.get(), data, kChunkLen)) !=
+ SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+ return false;
+ }
+
+ // Retrying with the same buffer but shorter length is not legal.
+ if (SSL_get_error(client.get(),
+ SSL_write(client.get(), data, kChunkLen - 1)) !=
+ SSL_ERROR_SSL ||
+ !ExpectBadWriteRetry()) {
+ fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+ return false;
+ }
+
+ // Retrying with a different buffer pointer is not legal.
+ char data2[] = "hello";
+ if (SSL_get_error(client.get(), SSL_write(client.get(), data2,
+ kChunkLen)) != SSL_ERROR_SSL ||
+ !ExpectBadWriteRetry()) {
+ fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+ return false;
+ }
+
+ // With |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|, the buffer may move.
+ SSL_set_mode(client.get(), SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ if (SSL_get_error(client.get(),
+ SSL_write(client.get(), data2, kChunkLen)) !=
+ SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+ return false;
+ }
+
+ // |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER| does not disable length checks.
+ if (SSL_get_error(client.get(),
+ SSL_write(client.get(), data2, kChunkLen - 1)) !=
+ SSL_ERROR_SSL ||
+ !ExpectBadWriteRetry()) {
+ fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+ return false;
+ }
+
+ // Retrying with a larger buffer is legal.
+ if (SSL_get_error(client.get(),
+ SSL_write(client.get(), data, kChunkLen + 1)) !=
+ SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+ return false;
+ }
+
+ // Drain the buffer.
+ char buf[20];
+ for (unsigned i = 0; i < count; i++) {
+ if (SSL_read(server.get(), buf, sizeof(buf)) != kChunkLen ||
+ OPENSSL_memcmp(buf, "hello", kChunkLen) != 0) {
+ fprintf(stderr, "Failed to read initial records.\n");
+ return false;
+ }
+ }
+
+ // Now that there is space, a retry with a larger buffer should flush the
+ // pending record, skip over that many bytes of input (on assumption they
+ // are the same), and write the remainder. If SSL_MODE_ENABLE_PARTIAL_WRITE
+ // is set, this will complete in two steps.
+ char data3[] = "_____!";
+ if (enable_partial_write) {
+ if (SSL_write(client.get(), data3, kChunkLen + 1) != kChunkLen ||
+ SSL_write(client.get(), data3 + kChunkLen, 1) != 1) {
+ fprintf(stderr, "SSL_write retry failed.\n");
+ return false;
+ }
+ } else if (SSL_write(client.get(), data3, kChunkLen + 1) != kChunkLen + 1) {
+ fprintf(stderr, "SSL_write retry failed.\n");
+ return false;
+ }
+
+ // Check the last write was correct. The data will be spread over two
+ // records, so SSL_read returns twice.
+ if (SSL_read(server.get(), buf, sizeof(buf)) != kChunkLen ||
+ OPENSSL_memcmp(buf, "hello", kChunkLen) != 0 ||
+ SSL_read(server.get(), buf, sizeof(buf)) != 1 ||
+ buf[0] != '!') {
+ fprintf(stderr, "Failed to read write retry.\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool ForEachVersion(bool (*test_func)(bool is_dtls,
const SSL_METHOD *method,
uint16_t version)) {
@@ -2814,7 +3206,9 @@
!TestSetVersion() ||
!ForEachVersion(TestVersion) ||
!ForEachVersion(TestALPNCipherAvailable) ||
- !ForEachVersion(TestSSLClearSessionResumption)) {
+ !ForEachVersion(TestSSLClearSessionResumption) ||
+ !ForEachVersion(TestAutoChain) ||
+ !ForEachVersion(TestSSLWriteRetry)) {
ERR_print_errors_fp(stderr);
return 1;
}
diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.c
index 70907e1..5e5c348 100644
--- a/src/ssl/t1_enc.c
+++ b/src/ssl/t1_enc.c
@@ -146,6 +146,7 @@
#include <openssl/nid.h>
#include <openssl/rand.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -231,7 +232,7 @@
return 1;
}
- memset(out, 0, out_len);
+ OPENSSL_memset(out, 0, out_len);
uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) {
@@ -528,12 +529,13 @@
return 0;
}
- memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
- memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+ OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE);
if (use_context) {
seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8);
seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len;
- memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
+ OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
}
int ret =
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 4549fe2..0681919 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -205,7 +205,7 @@
int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
size_t in_len) {
- memset(out, 0, sizeof(*out));
+ OPENSSL_memset(out, 0, sizeof(*out));
out->ssl = ssl;
out->client_hello = in;
out->client_hello_len = in_len;
@@ -308,9 +308,6 @@
SSL_CURVE_X25519,
SSL_CURVE_SECP256R1,
SSL_CURVE_SECP384R1,
-#if defined(BORINGSSL_ANDROID_SYSTEM)
- SSL_CURVE_SECP521R1,
-#endif
};
void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
@@ -464,8 +461,7 @@
#endif
SSL_SIGN_RSA_PKCS1_SHA384,
- /* TODO(davidben): Remove this entry and SSL_CURVE_SECP521R1 from
- * kDefaultGroups. */
+ /* TODO(davidben): Remove this. */
#if defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_ECDSA_SECP521R1_SHA512,
#endif
@@ -1510,8 +1506,9 @@
}
if (CBS_len(&client_protocol_name) == CBS_len(&protocol_name) &&
- memcmp(CBS_data(&client_protocol_name), CBS_data(&protocol_name),
- CBS_len(&protocol_name)) == 0) {
+ OPENSSL_memcmp(CBS_data(&client_protocol_name),
+ CBS_data(&protocol_name),
+ CBS_len(&protocol_name)) == 0) {
protocol_ok = 1;
break;
}
@@ -1885,8 +1882,9 @@
/* Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
* point format. */
- if (memchr(CBS_data(&ec_point_format_list), TLSEXT_ECPOINTFORMAT_uncompressed,
- CBS_len(&ec_point_format_list)) == NULL) {
+ if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
+ TLSEXT_ECPOINTFORMAT_uncompressed,
+ CBS_len(&ec_point_format_list)) == NULL) {
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
@@ -2145,8 +2143,8 @@
}
/* We only support tickets with PSK_DHE_KE. */
- hs->accept_psk_mode =
- memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE, CBS_len(&ke_modes)) != NULL;
+ hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
+ CBS_len(&ke_modes)) != NULL;
return 1;
}
@@ -2347,7 +2345,7 @@
uint8_t *secret = NULL;
size_t secret_len;
SSL_ECDH_CTX group;
- memset(&group, 0, sizeof(SSL_ECDH_CTX));
+ OPENSSL_memset(&group, 0, sizeof(SSL_ECDH_CTX));
CBB public_key;
if (!CBB_init(&public_key, 32) ||
!SSL_ECDH_CTX_init(&group, group_id) ||
@@ -2460,6 +2458,46 @@
}
+/* Short record headers
+ *
+ * This is a non-standard extension which negotiates
+ * https://github.com/tlswg/tls13-spec/pull/762 for experimenting. */
+
+static int ext_short_header_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
+ 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->ctx->short_header_enabled) {
+ return 1;
+ }
+
+ return CBB_add_u16(out, TLSEXT_TYPE_short_header) &&
+ CBB_add_u16(out, 0 /* empty extension */);
+}
+
+static int ext_short_header_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
+ CBS *contents) {
+ SSL *const ssl = hs->ssl;
+ if (contents == NULL ||
+ !ssl->ctx->short_header_enabled ||
+ ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+ return 1;
+ }
+
+ if (CBS_len(contents) != 0) {
+ return 0;
+ }
+
+ ssl->s3->short_header = 1;
+ return 1;
+}
+
+
/* Negotiated Groups
*
* https://tools.ietf.org/html/rfc4492#section-5.1.2
@@ -2690,6 +2728,14 @@
ignore_parse_clienthello,
dont_add_serverhello,
},
+ {
+ TLSEXT_TYPE_short_header,
+ NULL,
+ ext_short_header_add_clienthello,
+ forbid_parse_serverhello,
+ ext_short_header_parse_clienthello,
+ dont_add_serverhello,
+ },
/* The final extension must be non-empty. WebSphere Application Server 7.0 is
* intolerant to the last extension being zero-length. See
* https://crbug.com/363583. */
@@ -2824,7 +2870,7 @@
goto err;
}
- memset(padding_bytes, 0, padding_len);
+ OPENSSL_memset(padding_bytes, 0, padding_len);
}
}
@@ -3187,8 +3233,8 @@
}
} else {
/* Check the key name matches. */
- if (memcmp(ticket, ssl_ctx->tlsext_tick_key_name,
- SSL_TICKET_KEY_NAME_LEN) != 0) {
+ if (OPENSSL_memcmp(ticket, ssl_ctx->tlsext_tick_key_name,
+ SSL_TICKET_KEY_NAME_LEN) != 0) {
goto done;
}
if (!HMAC_Init_ex(&hmac_ctx, ssl_ctx->tlsext_tick_hmac_key,
@@ -3231,7 +3277,7 @@
}
size_t plaintext_len;
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
- memcpy(plaintext, ciphertext, ciphertext_len);
+ OPENSSL_memcpy(plaintext, ciphertext, ciphertext_len);
plaintext_len = ciphertext_len;
#else
if (ciphertext_len >= INT_MAX) {
@@ -3256,7 +3302,7 @@
/* Copy the client's session ID into the new session, to denote the ticket has
* been accepted. */
- memcpy(session->session_id, session_id, session_id_len);
+ OPENSSL_memcpy(session->session_id, session_id, session_id_len);
session->session_id_length = session_id_len;
*out_session = session;
@@ -3443,7 +3489,7 @@
goto err;
}
- memcpy(ssl->s3->tlsext_channel_id, p, 64);
+ OPENSSL_memcpy(ssl->s3->tlsext_channel_id, p, 64);
ret = 1;
err:
diff --git a/src/ssl/test/async_bio.cc b/src/ssl/test/async_bio.cc
index 605b33a..fd35176 100644
--- a/src/ssl/test/async_bio.cc
+++ b/src/ssl/test/async_bio.cc
@@ -20,6 +20,8 @@
#include <openssl/bio.h>
#include <openssl/mem.h>
+#include "../../crypto/internal.h"
+
namespace {
@@ -110,7 +112,7 @@
if (a == NULL) {
return 0;
}
- memset(a, 0, sizeof(*a));
+ OPENSSL_memset(a, 0, sizeof(*a));
a->enforce_write_quota = true;
bio->init = 1;
bio->ptr = (char *)a;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index a3903e2..a98ff43 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -330,8 +330,8 @@
fprintf(stderr, "Output buffer too small.\n");
return ssl_private_key_failure;
}
- memcpy(out, test_state->private_key_result.data(),
- test_state->private_key_result.size());
+ OPENSSL_memcpy(out, test_state->private_key_result.data(),
+ test_state->private_key_result.size());
*out_len = test_state->private_key_result.size();
test_state->private_key_result.clear();
@@ -498,9 +498,9 @@
size_t certificate_types_len =
SSL_get0_certificate_types(ssl, &certificate_types);
if (certificate_types_len != config->expected_certificate_types.size() ||
- memcmp(certificate_types,
- config->expected_certificate_types.data(),
- certificate_types_len) != 0) {
+ OPENSSL_memcmp(certificate_types,
+ config->expected_certificate_types.data(),
+ certificate_types_len) != 0) {
fprintf(stderr, "certificate types mismatch\n");
return false;
}
@@ -626,8 +626,8 @@
if (!config->expected_advertised_alpn.empty() &&
(config->expected_advertised_alpn.size() != inlen ||
- memcmp(config->expected_advertised_alpn.data(),
- in, inlen) != 0)) {
+ OPENSSL_memcmp(config->expected_advertised_alpn.data(), in, inlen) !=
+ 0)) {
fprintf(stderr, "bad ALPN select callback inputs\n");
exit(1);
}
@@ -663,7 +663,7 @@
BUF_strlcpy(out_identity, config->psk_identity.c_str(),
max_identity_len);
- memcpy(out_psk, config->psk.data(), config->psk.size());
+ OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
return config->psk.size();
}
@@ -681,7 +681,7 @@
return 0;
}
- memcpy(out_psk, config->psk.data(), config->psk.size());
+ OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
return config->psk.size();
}
@@ -758,9 +758,9 @@
static const uint8_t kZeros[16] = {0};
if (encrypt) {
- memcpy(key_name, kZeros, sizeof(kZeros));
+ OPENSSL_memcpy(key_name, kZeros, sizeof(kZeros));
RAND_bytes(iv, 16);
- } else if (memcmp(key_name, kZeros, 16) != 0) {
+ } else if (OPENSSL_memcmp(key_name, kZeros, 16) != 0) {
return 0;
}
@@ -824,7 +824,7 @@
}
if (contents_len != sizeof(kCustomExtensionContents) - 1 ||
- memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
+ OPENSSL_memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
*out_alert_value = SSL_AD_DECODE_ERROR;
return 0;
}
@@ -862,7 +862,7 @@
return -1;
}
sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
+ OPENSSL_memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
@@ -928,17 +928,6 @@
return nullptr;
}
- if (!config->cipher_tls10.empty() &&
- !SSL_CTX_set_cipher_list_tls10(ssl_ctx.get(),
- config->cipher_tls10.c_str())) {
- return nullptr;
- }
- if (!config->cipher_tls11.empty() &&
- !SSL_CTX_set_cipher_list_tls11(ssl_ctx.get(),
- config->cipher_tls11.c_str())) {
- return nullptr;
- }
-
bssl::UniquePtr<DH> dh(DH_get_2048_256(NULL));
if (!dh) {
return nullptr;
@@ -994,7 +983,6 @@
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
}
- SSL_CTX_set_tls_channel_id_enabled(ssl_ctx.get(), 1);
SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
@@ -1053,6 +1041,14 @@
return nullptr;
}
+ if (config->enable_short_header) {
+ SSL_CTX_set_short_header_enabled(ssl_ctx.get(), 1);
+ }
+
+ if (config->enable_early_data) {
+ SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
+ }
+
return ssl_ctx;
}
@@ -1154,7 +1150,7 @@
// SSL_peek should synchronously return the same data.
int ret2 = SSL_peek(ssl, buf.get(), ret);
if (ret2 != ret ||
- memcmp(buf.get(), out, ret) != 0) {
+ OPENSSL_memcmp(buf.get(), out, ret) != 0) {
fprintf(stderr, "First and second SSL_peek did not match.\n");
return -1;
}
@@ -1162,7 +1158,7 @@
// SSL_read should synchronously return the same data and consume it.
ret2 = SSL_read(ssl, buf.get(), ret);
if (ret2 != ret ||
- memcmp(buf.get(), out, ret) != 0) {
+ OPENSSL_memcmp(buf.get(), out, ret) != 0) {
fprintf(stderr, "SSL_peek and SSL_read did not match.\n");
return -1;
}
@@ -1276,8 +1272,8 @@
unsigned next_proto_len;
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
if (next_proto_len != config->expected_next_proto.size() ||
- memcmp(next_proto, config->expected_next_proto.data(),
- next_proto_len) != 0) {
+ OPENSSL_memcmp(next_proto, config->expected_next_proto.data(),
+ next_proto_len) != 0) {
fprintf(stderr, "negotiated next proto mismatch\n");
return false;
}
@@ -1288,8 +1284,8 @@
unsigned alpn_proto_len;
SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
if (alpn_proto_len != config->expected_alpn.size() ||
- memcmp(alpn_proto, config->expected_alpn.data(),
- alpn_proto_len) != 0) {
+ OPENSSL_memcmp(alpn_proto, config->expected_alpn.data(),
+ alpn_proto_len) != 0) {
fprintf(stderr, "negotiated alpn proto mismatch\n");
return false;
}
@@ -1302,8 +1298,8 @@
return false;
}
if (config->expected_channel_id.size() != 64 ||
- memcmp(config->expected_channel_id.data(),
- channel_id, 64) != 0) {
+ OPENSSL_memcmp(config->expected_channel_id.data(), channel_id, 64) !=
+ 0) {
fprintf(stderr, "channel id mismatch\n");
return false;
}
@@ -1321,7 +1317,7 @@
size_t len;
SSL_get0_ocsp_response(ssl, &data, &len);
if (config->expected_ocsp_response.size() != len ||
- memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
+ OPENSSL_memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
fprintf(stderr, "OCSP response mismatch\n");
return false;
}
@@ -1332,8 +1328,8 @@
size_t len;
SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
if (config->expected_signed_cert_timestamps.size() != len ||
- memcmp(config->expected_signed_cert_timestamps.data(),
- data, len) != 0) {
+ OPENSSL_memcmp(config->expected_signed_cert_timestamps.data(), data,
+ len) != 0) {
fprintf(stderr, "SCT list mismatch\n");
return false;
}
@@ -1754,7 +1750,7 @@
// trip up the CBC record splitting code.
static const size_t kBufLen = 32769;
std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
- memset(buf.get(), 0x42, kBufLen);
+ OPENSSL_memset(buf.get(), 0x42, kBufLen);
static const size_t kRecordSizes[] = {
0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRecordSizes); i++) {
@@ -1768,6 +1764,19 @@
}
}
} else {
+ if (config->read_with_unfinished_write) {
+ if (!config->async) {
+ fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
+ return false;
+ }
+
+ int write_ret = SSL_write(ssl.get(),
+ reinterpret_cast<const uint8_t *>("unfinished"), 10);
+ if (SSL_get_error(ssl.get(), write_ret) != SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "Failed to leave unfinished write.\n");
+ return false;
+ }
+ }
if (config->shim_writes_first) {
if (WriteAll(ssl.get(), reinterpret_cast<const uint8_t *>("hello"),
5) < 0) {
@@ -1839,6 +1848,19 @@
GetTestState(ssl.get())->got_new_session ? "" : " not");
return false;
}
+
+ if (expect_new_session) {
+ bool got_early_data_info =
+ GetTestState(ssl.get())->new_session->ticket_max_early_data != 0;
+ if (config->expect_early_data_info != got_early_data_info) {
+ fprintf(
+ stderr,
+ "new session did%s include ticket_early_data_info, but we expected "
+ "the opposite\n",
+ got_early_data_info ? "" : " not");
+ return false;
+ }
+ }
}
if (out_session) {
diff --git a/src/ssl/test/packeted_bio.cc b/src/ssl/test/packeted_bio.cc
index 8331b4b..835df0e 100644
--- a/src/ssl/test/packeted_bio.cc
+++ b/src/ssl/test/packeted_bio.cc
@@ -21,6 +21,8 @@
#include <openssl/mem.h>
+#include "../../crypto/internal.h"
+
namespace {
@@ -33,8 +35,8 @@
struct PacketedBio {
PacketedBio(timeval *clock_arg, bool advance_clock_arg)
: clock(clock_arg), advance_clock(advance_clock_arg) {
- memset(&timeout, 0, sizeof(timeout));
- memset(&read_deadline, 0, sizeof(read_deadline));
+ OPENSSL_memset(&timeout, 0, sizeof(timeout));
+ OPENSSL_memset(&read_deadline, 0, sizeof(read_deadline));
}
bool HasTimeout() const {
@@ -209,7 +211,7 @@
if (outl > (int)len) {
outl = len;
}
- memcpy(out, buf, outl);
+ OPENSSL_memcpy(out, buf, outl);
OPENSSL_free(buf);
return outl;
}
@@ -217,7 +219,7 @@
static long PacketedCtrl(BIO *bio, int cmd, long num, void *ptr) {
if (cmd == BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT) {
- memcpy(&GetData(bio)->read_deadline, ptr, sizeof(timeval));
+ OPENSSL_memcpy(&GetData(bio)->read_deadline, ptr, sizeof(timeval));
return 1;
}
@@ -290,6 +292,6 @@
data->clock->tv_sec += data->clock->tv_usec / 1000000;
data->clock->tv_usec %= 1000000;
data->clock->tv_sec += data->timeout.tv_sec;
- memset(&data->timeout, 0, sizeof(data->timeout));
+ OPENSSL_memset(&data->timeout, 0, sizeof(data->timeout));
return true;
}
diff --git a/src/ssl/test/runner/alert.go b/src/ssl/test/runner/alert.go
index 8320b7e..652e9ee 100644
--- a/src/ssl/test/runner/alert.go
+++ b/src/ssl/test/runner/alert.go
@@ -23,7 +23,7 @@
alertRecordOverflow alert = 22
alertDecompressionFailure alert = 30
alertHandshakeFailure alert = 40
- alertNoCertficate alert = 41
+ alertNoCertificate alert = 41
alertBadCertificate alert = 42
alertUnsupportedCertificate alert = 43
alertCertificateRevoked alert = 44
@@ -37,6 +37,7 @@
alertProtocolVersion alert = 70
alertInsufficientSecurity alert = 71
alertInternalError alert = 80
+ alertInappropriateFallback alert = 86
alertUserCanceled alert = 90
alertNoRenegotiation alert = 100
alertMissingExtension alert = 109
@@ -55,6 +56,7 @@
alertRecordOverflow: "record overflow",
alertDecompressionFailure: "decompression failure",
alertHandshakeFailure: "handshake failure",
+ alertNoCertificate: "no certificate",
alertBadCertificate: "bad certificate",
alertUnsupportedCertificate: "unsupported certificate",
alertCertificateRevoked: "revoked certificate",
@@ -68,6 +70,7 @@
alertProtocolVersion: "protocol version not supported",
alertInsufficientSecurity: "insufficient security level",
alertInternalError: "internal error",
+ alertInappropriateFallback: "inappropriate fallback",
alertUserCanceled: "user canceled",
alertNoRenegotiation: "no renegotiation",
alertMissingExtension: "missing extension",
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index f5fedb0..96bc39a 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -95,15 +95,12 @@
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16
extensionCookie uint16 = 44 // draft-ietf-tls-tls13-16
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18
+ extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18
extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
extensionChannelID uint16 = 30032 // not IANA assigned
-)
-
-// TLS ticket extension numbers
-const (
- ticketExtensionCustom uint16 = 1234 // not IANA assigned
+ extensionShortHeader uint16 = 27463 // not IANA assigned
)
// TLS signaling cipher suite values
@@ -126,7 +123,8 @@
// TLS Elliptic Curve Point Formats
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
const (
- pointFormatUncompressed uint8 = 0
+ pointFormatUncompressed uint8 = 0
+ pointFormatCompressedPrime uint8 = 1
)
// TLS CertificateStatusType (RFC 3546)
@@ -225,6 +223,7 @@
SCTList []byte // signed certificate timestamp list
PeerSignatureAlgorithm signatureAlgorithm // algorithm used by the peer in the handshake
CurveID CurveID // the curve used in ECDHE
+ ShortHeader bool // whether the short header extension was negotiated
}
// ClientAuthType declares the policy the server will follow for
@@ -956,6 +955,19 @@
// receipt of a NewSessionTicket message.
ExpectNoNewSessionTicket bool
+ // SendTicketEarlyDataInfo, if non-zero, is the maximum amount of data that we
+ // will accept as early data, and gets sent in the ticket_early_data_info
+ // extension of the NewSessionTicket message.
+ SendTicketEarlyDataInfo uint32
+
+ // DuplicateTicketEarlyDataInfo causes an extra empty extension of
+ // ticket_early_data_info to be sent in NewSessionTicket.
+ DuplicateTicketEarlyDataInfo bool
+
+ // ExpectTicketEarlyDataInfo, if true, means that the client will fail upon
+ // absence of the ticket_early_data_info extension.
+ ExpectTicketEarlyDataInfo bool
+
// ExpectTicketAge, if non-zero, is the expected age of the ticket that the
// server receives from the client.
ExpectTicketAge time.Duration
@@ -1224,6 +1236,23 @@
// NoSignedCertificateTimestamps, if true, causes the client to not
// request signed certificate timestamps.
NoSignedCertificateTimestamps bool
+
+ // EnableShortHeader, if true, causes the TLS 1.3 short header extension
+ // to be enabled.
+ EnableShortHeader bool
+
+ // AlwaysNegotiateShortHeader, if true, causes the server to always
+ // negotiate the short header extension in ServerHello.
+ AlwaysNegotiateShortHeader bool
+
+ // ClearShortHeaderBit, if true, causes the server to send short headers
+ // without the high bit set.
+ ClearShortHeaderBit bool
+
+ // SendSupportedPointFormats, if not nil, is the list of supported point
+ // formats to send in ClientHello or ServerHello. If set to a non-nil
+ // empty slice, no extension will be sent.
+ SendSupportedPointFormats []byte
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 80a5b06..ee342fa 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -21,6 +21,8 @@
"time"
)
+var errNoCertificateAlert = errors.New("tls: no certificate alert")
+
// A Conn represents a secured connection.
// It implements the net.Conn interface.
type Conn struct {
@@ -163,6 +165,8 @@
trafficSecret []byte
+ shortHeader bool
+
config *Config
}
@@ -301,10 +305,17 @@
copy(hc.outSeq[:], hc.seq[:])
}
+func (hc *halfConn) isShortHeader() bool {
+ return hc.shortHeader && hc.cipher != nil
+}
+
func (hc *halfConn) recordHeaderLen() int {
if hc.isDTLS {
return dtlsRecordHeaderLen
}
+ if hc.isShortHeader() {
+ return 2
+ }
return tlsRecordHeaderLen
}
@@ -608,6 +619,9 @@
n := len(b.data) - recordHeaderLen
b.data[recordHeaderLen-2] = byte(n >> 8)
b.data[recordHeaderLen-1] = byte(n)
+ if hc.isShortHeader() && !hc.config.Bugs.ClearShortHeaderBit {
+ b.data[0] |= 0x80
+ }
hc.incSeq(true)
return true, 0
@@ -716,7 +730,7 @@
return c.dtlsDoReadRecord(want)
}
- recordHeaderLen := tlsRecordHeaderLen
+ recordHeaderLen := c.in.recordHeaderLen()
if c.rawInput == nil {
c.rawInput = c.in.newBlock()
@@ -736,19 +750,36 @@
}
return 0, nil, err
}
- typ := recordType(b.data[0])
- // No valid TLS record has a type of 0x80, however SSLv2 handshakes
- // start with a uint16 length where the MSB is set and the first record
- // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
- // an SSLv2 client.
- if want == recordTypeHandshake && typ == 0x80 {
- c.sendAlert(alertProtocolVersion)
- return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ var typ recordType
+ var vers uint16
+ var n int
+ if c.in.isShortHeader() {
+ typ = recordTypeApplicationData
+ vers = VersionTLS10
+ n = int(b.data[0])<<8 | int(b.data[1])
+ if n&0x8000 == 0 {
+ c.sendAlert(alertDecodeError)
+ return 0, nil, c.in.setErrorLocked(errors.New("tls: length did not have high bit set"))
+ }
+
+ n = n & 0x7fff
+ } else {
+ typ = recordType(b.data[0])
+
+ // No valid TLS record has a type of 0x80, however SSLv2 handshakes
+ // start with a uint16 length where the MSB is set and the first record
+ // is always < 256 bytes long. Therefore typ == 0x80 strongly suggests
+ // an SSLv2 client.
+ if want == recordTypeHandshake && typ == 0x80 {
+ c.sendAlert(alertProtocolVersion)
+ return 0, nil, c.in.setErrorLocked(errors.New("tls: unsupported SSLv2 handshake received"))
+ }
+
+ vers = uint16(b.data[1])<<8 | uint16(b.data[2])
+ n = int(b.data[3])<<8 | int(b.data[4])
}
- vers := uint16(b.data[1])<<8 | uint16(b.data[2])
- n := int(b.data[3])<<8 | int(b.data[4])
// Alerts sent near version negotiation do not have a well-defined
// record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer
// version is irrelevant.)
@@ -866,6 +897,11 @@
}
switch data[0] {
case alertLevelWarning:
+ if alert(data[1]) == alertNoCertificate {
+ c.in.freeBlock(b)
+ return errNoCertificateAlert
+ }
+
// drop on the floor
c.in.freeBlock(b)
goto Again
@@ -934,7 +970,7 @@
// L < c.out.Mutex.
func (c *Conn) sendAlert(err alert) error {
level := byte(alertLevelError)
- if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertficate {
+ if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertificate {
level = alertLevelWarning
}
return c.SendAlert(level, err)
@@ -1007,7 +1043,7 @@
}
func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
- recordHeaderLen := tlsRecordHeaderLen
+ recordHeaderLen := c.out.recordHeaderLen()
b := c.out.newBlock()
first := true
isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
@@ -1049,32 +1085,36 @@
}
}
b.resize(recordHeaderLen + explicitIVLen + m)
- b.data[0] = byte(typ)
- if c.vers >= VersionTLS13 && c.out.cipher != nil {
- b.data[0] = byte(recordTypeApplicationData)
- if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
- b.data[0] = byte(outerType)
+ // If using a short record header, the length will be filled in
+ // by encrypt.
+ if !c.out.isShortHeader() {
+ b.data[0] = byte(typ)
+ if c.vers >= VersionTLS13 && c.out.cipher != nil {
+ b.data[0] = byte(recordTypeApplicationData)
+ if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
+ b.data[0] = byte(outerType)
+ }
}
+ vers := c.vers
+ if vers == 0 || vers >= VersionTLS13 {
+ // Some TLS servers fail if the record version is
+ // greater than TLS 1.0 for the initial ClientHello.
+ //
+ // TLS 1.3 fixes the version number in the record
+ // layer to {3, 1}.
+ vers = VersionTLS10
+ }
+ if c.config.Bugs.SendRecordVersion != 0 {
+ vers = c.config.Bugs.SendRecordVersion
+ }
+ if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
+ vers = c.config.Bugs.SendInitialRecordVersion
+ }
+ b.data[1] = byte(vers >> 8)
+ b.data[2] = byte(vers)
+ b.data[3] = byte(m >> 8)
+ b.data[4] = byte(m)
}
- vers := c.vers
- if vers == 0 || vers >= VersionTLS13 {
- // Some TLS servers fail if the record version is
- // greater than TLS 1.0 for the initial ClientHello.
- //
- // TLS 1.3 fixes the version number in the record
- // layer to {3, 1}.
- vers = VersionTLS10
- }
- if c.config.Bugs.SendRecordVersion != 0 {
- vers = c.config.Bugs.SendRecordVersion
- }
- if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
- vers = c.config.Bugs.SendInitialRecordVersion
- }
- b.data[1] = byte(vers >> 8)
- b.data[2] = byte(vers)
- b.data[3] = byte(m >> 8)
- b.data[4] = byte(m)
if explicitIVLen > 0 {
explicitIV := b.data[recordHeaderLen : recordHeaderLen+explicitIVLen]
if explicitIVIsSeq {
@@ -1162,6 +1202,13 @@
// c.in.Mutex < L; c.out.Mutex < L.
func (c *Conn) readHandshake() (interface{}, error) {
data, err := c.doReadHandshake()
+ if err == errNoCertificateAlert {
+ if c.hand.Len() != 0 {
+ // The warning alert may not interleave with a handshake message.
+ return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+ }
+ return new(ssl3NoCertificateMsg), nil
+ }
if err != nil {
return nil, err
}
@@ -1404,6 +1451,10 @@
return errors.New("tls: no GREASE ticket extension found")
}
+ if c.config.Bugs.ExpectTicketEarlyDataInfo && newSessionTicket.earlyDataInfo == 0 {
+ return errors.New("tls: no ticket_early_data_info extension found")
+ }
+
if c.config.Bugs.ExpectNoNewSessionTicket {
return errors.New("tls: received unexpected NewSessionTicket")
}
@@ -1620,6 +1671,7 @@
state.SCTList = c.sctList
state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
state.CurveID = c.curveID
+ state.ShortHeader = c.in.shortHeader
}
return state
@@ -1715,10 +1767,12 @@
// TODO(davidben): Allow configuring these values.
m := &newSessionTicketMsg{
- version: c.vers,
- ticketLifetime: uint32(24 * time.Hour / time.Second),
- customExtension: c.config.Bugs.CustomTicketExtension,
- ticketAgeAdd: ticketAgeAdd,
+ version: c.vers,
+ ticketLifetime: uint32(24 * time.Hour / time.Second),
+ earlyDataInfo: c.config.Bugs.SendTicketEarlyDataInfo,
+ duplicateEarlyDataInfo: c.config.Bugs.DuplicateTicketEarlyDataInfo,
+ customExtension: c.config.Bugs.CustomTicketExtension,
+ ticketAgeAdd: ticketAgeAdd,
}
state := sessionState{
@@ -1781,3 +1835,8 @@
_, err := c.conn.Write(payload)
return err
}
+
+func (c *Conn) setShortHeader() {
+ c.in.shortHeader = true
+ c.out.shortHeader = true
+}
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index cb2befa..80a9bf1 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -25,12 +25,15 @@
"ECDSACurveMismatch-Verify-TLS13": "Fuzzer mode always accepts a signature.",
"InvalidChannelIDSignature-*": "Fuzzer mode always accepts a signature.",
+ "Resume-Server-CipherNotPreferred*": "Fuzzer mode does not encrypt tickets.",
"Resume-Server-DeclineBadCipher*": "Fuzzer mode does not encrypt tickets.",
"Resume-Server-DeclineCrossVersion*": "Fuzzer mode does not encrypt tickets.",
"TicketCallback-SingleCall-*": "Fuzzer mode does not encrypt tickets.",
"CorruptTicket-*": "Fuzzer mode does not encrypt tickets.",
"ShimTicketRewritable": "Fuzzer mode does not encrypt tickets.",
- "Resume-Server-*Binder*": "Fuzzer mode does not check binders."
+ "Resume-Server-*Binder*": "Fuzzer mode does not check binders.",
+
+ "SkipEarlyData*": "Trial decryption does not work with the NULL cipher."
}
}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 7fa7ea2..507ea40 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -81,6 +81,7 @@
srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
customExtension: c.config.Bugs.CustomExtension,
pskBinderFirst: c.config.Bugs.PSKBinderFirst,
+ shortHeaderSupported: c.config.Bugs.EnableShortHeader,
}
disableEMS := c.config.Bugs.NoExtendedMasterSecret
@@ -104,6 +105,10 @@
hello.compressionMethods = c.config.Bugs.SendCompressionMethods
}
+ if c.config.Bugs.SendSupportedPointFormats != nil {
+ hello.supportedPoints = c.config.Bugs.SendSupportedPointFormats
+ }
+
if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
if c.config.Bugs.BadRenegotiationInfo {
hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
@@ -684,6 +689,18 @@
hs.finishedHash.addEntropy(zeroSecret)
}
+ if hs.serverHello.shortHeader && !hs.hello.shortHeaderSupported {
+ return errors.New("tls: server sent unsolicited short header extension")
+ }
+
+ if hs.serverHello.shortHeader && hs.hello.hasEarlyData {
+ return errors.New("tls: server sent short header extension in response to early data")
+ }
+
+ if hs.serverHello.shortHeader {
+ c.setShortHeader()
+ }
+
// Switch to handshake traffic keys.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
@@ -1011,7 +1028,7 @@
// no_certificate warning alert.
if certRequested {
if c.vers == VersionSSL30 && chainToSend == nil {
- c.sendAlert(alertNoCertficate)
+ c.sendAlert(alertNoCertificate)
} else if !c.config.Bugs.SkipClientCertificate {
certMsg := new(certificateMsg)
if chainToSend != nil {
@@ -1291,6 +1308,10 @@
func (hs *clientHandshakeState) processServerHello() (bool, error) {
c := hs.c
+ if hs.serverHello.shortHeader {
+ return false, errors.New("tls: short header extension sent before TLS 1.3")
+ }
+
if hs.serverResumedSession() {
// For test purposes, assert that the server never accepts the
// resumption offer on renegotiation.
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 8a338f0..62309b8 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -167,6 +167,7 @@
customExtension string
hasGREASEExtension bool
pskBinderFirst bool
+ shortHeaderSupported bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -212,7 +213,8 @@
m.sctListSupported == m1.sctListSupported &&
m.customExtension == m1.customExtension &&
m.hasGREASEExtension == m1.hasGREASEExtension &&
- m.pskBinderFirst == m1.pskBinderFirst
+ m.pskBinderFirst == m1.pskBinderFirst &&
+ m.shortHeaderSupported == m1.shortHeaderSupported
}
func (m *clientHelloMsg) marshal() []byte {
@@ -314,9 +316,7 @@
extensions.addU16(extensionSupportedPoints)
supportedPointsList := extensions.addU16LengthPrefixed()
supportedPoints := supportedPointsList.addU8LengthPrefixed()
- for _, pointFormat := range m.supportedPoints {
- supportedPoints.addU8(pointFormat)
- }
+ supportedPoints.addBytes(m.supportedPoints)
}
if m.hasKeyShares {
extensions.addU16(extensionKeyShare)
@@ -430,6 +430,10 @@
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
+ if m.shortHeaderSupported {
+ extensions.addU16(extensionShortHeader)
+ extensions.addU16(0) // Length is always 0
+ }
// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
@@ -601,8 +605,7 @@
if length != l+1 {
return false
}
- m.supportedPoints = make([]uint8, l)
- copy(m.supportedPoints, data[1:])
+ m.supportedPoints = data[1 : 1+l]
case extensionSessionTicket:
// http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true
@@ -802,6 +805,11 @@
return false
}
m.sctListSupported = true
+ case extensionShortHeader:
+ if length != 0 {
+ return false
+ }
+ m.shortHeaderSupported = true
case extensionCustom:
m.customExtension = string(data[:length])
}
@@ -831,6 +839,7 @@
compressionMethod uint8
customExtension string
unencryptedALPN string
+ shortHeader bool
extensions serverExtensions
}
@@ -868,6 +877,11 @@
extensions := hello.addU16LengthPrefixed()
+ if m.shortHeader {
+ extensions.addU16(extensionShortHeader)
+ extensions.addU16(0) // Length
+ }
+
if vers >= VersionTLS13 {
if m.hasKeyShare {
extensions.addU16(extensionKeyShare)
@@ -996,6 +1010,11 @@
return false
}
m.earlyDataIndication = true
+ case extensionShortHeader:
+ if len(d) != 0 {
+ return false
+ }
+ m.shortHeader = true
default:
// Only allow the 3 extensions that are sent in
// the clear in TLS 1.3.
@@ -1071,6 +1090,7 @@
npnAfterAlpn bool
hasKeyShare bool
keyShare keyShareEntry
+ supportedPoints []uint8
}
func (m *serverExtensions) marshal(extensions *byteBuilder) {
@@ -1165,6 +1185,13 @@
keyExchange := keyShare.addU16LengthPrefixed()
keyExchange.addBytes(m.keyShare.keyExchange)
}
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.1.2
+ extensions.addU16(extensionSupportedPoints)
+ supportedPointsList := extensions.addU16LengthPrefixed()
+ supportedPoints := supportedPointsList.addU8LengthPrefixed()
+ supportedPoints.addBytes(m.supportedPoints)
+ }
}
func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
@@ -1265,7 +1292,15 @@
if version >= VersionTLS13 {
return false
}
- // Ignore this extension from the server.
+ // http://tools.ietf.org/html/rfc4492#section-5.5.2
+ if length < 1 {
+ return false
+ }
+ l := int(data[0])
+ if length != l+1 {
+ return false
+ }
+ m.supportedPoints = data[1 : 1+l]
case extensionSupportedCurves:
// The server can only send supported_curves in TLS 1.3.
if version < VersionTLS13 {
@@ -1968,13 +2003,15 @@
}
type newSessionTicketMsg struct {
- raw []byte
- version uint16
- ticketLifetime uint32
- ticketAgeAdd uint32
- ticket []byte
- customExtension string
- hasGREASEExtension bool
+ raw []byte
+ version uint16
+ ticketLifetime uint32
+ ticketAgeAdd uint32
+ ticket []byte
+ earlyDataInfo uint32
+ customExtension string
+ duplicateEarlyDataInfo bool
+ hasGREASEExtension bool
}
func (m *newSessionTicketMsg) marshal() []byte {
@@ -1996,8 +2033,16 @@
if m.version >= VersionTLS13 {
extensions := body.addU16LengthPrefixed()
+ if m.earlyDataInfo > 0 {
+ extensions.addU16(extensionTicketEarlyDataInfo)
+ extensions.addU16LengthPrefixed().addU32(m.earlyDataInfo)
+ if m.duplicateEarlyDataInfo {
+ extensions.addU16(extensionTicketEarlyDataInfo)
+ extensions.addU16LengthPrefixed().addU32(m.earlyDataInfo)
+ }
+ }
if len(m.customExtension) > 0 {
- extensions.addU16(ticketExtensionCustom)
+ extensions.addU16(extensionCustom)
extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
}
}
@@ -2043,28 +2088,37 @@
if len(data) < 2 {
return false
}
- extsLength := int(data[0])<<8 + int(data[1])
+
+ extensionsLength := int(data[0])<<8 | int(data[1])
data = data[2:]
- if len(data) < extsLength {
+ if extensionsLength != len(data) {
return false
}
- extensions := data[:extsLength]
- data = data[extsLength:]
- for len(extensions) > 0 {
- if len(extensions) < 4 {
+ for len(data) != 0 {
+ if len(data) < 4 {
return false
}
- extValue := uint16(extensions[0])<<8 | uint16(extensions[1])
- extLength := int(extensions[2])<<8 | int(extensions[3])
- if len(extensions) < 4+extLength {
+ extension := uint16(data[0])<<8 | uint16(data[1])
+ length := int(data[2])<<8 | int(data[3])
+ data = data[4:]
+ if len(data) < length {
return false
}
- extensions = extensions[4+extLength:]
- if isGREASEValue(extValue) {
- m.hasGREASEExtension = true
+ switch extension {
+ case extensionTicketEarlyDataInfo:
+ if length != 4 {
+ return false
+ }
+ m.earlyDataInfo = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+ default:
+ if isGREASEValue(extension) {
+ m.hasGREASEExtension = true
+ }
}
+
+ data = data[length:]
}
}
@@ -2240,6 +2294,10 @@
return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested
}
+// ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning
+// alert in the handshake.
+type ssl3NoCertificateMsg struct{}
+
func eqUint16s(x, y []uint16) bool {
if len(x) != len(y) {
return false
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 57566c5..1116d6c 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -365,6 +365,15 @@
versOverride: config.Bugs.SendServerHelloVersion,
customExtension: config.Bugs.CustomUnencryptedExtension,
unencryptedALPN: config.Bugs.SendUnencryptedALPN,
+ shortHeader: hs.clientHello.shortHeaderSupported && config.Bugs.EnableShortHeader,
+ }
+
+ if config.Bugs.AlwaysNegotiateShortHeader {
+ hs.hello.shortHeader = true
+ }
+
+ if hs.hello.shortHeader {
+ c.setShortHeader()
}
hs.hello.random = make([]byte, 32)
@@ -972,6 +981,7 @@
vers: versionToWire(c.vers, c.isDTLS),
versOverride: config.Bugs.SendServerHelloVersion,
compressionMethod: compressionNone,
+ shortHeader: config.Bugs.AlwaysNegotiateShortHeader,
}
hs.hello.random = make([]byte, 32)
@@ -1182,6 +1192,10 @@
serverExtensions.ticketSupported = true
}
+ if c.config.Bugs.SendSupportedPointFormats != nil {
+ serverExtensions.supportedPoints = c.config.Bugs.SendSupportedPointFormats
+ }
+
if !hs.clientHello.hasGREASEExtension && config.Bugs.ExpectGREASE {
return errors.New("tls: no GREASE extension found")
}
@@ -1438,7 +1452,13 @@
for _, cert := range certMsg.certificates {
certificates = append(certificates, cert.data)
}
- } else if c.vers != VersionSSL30 {
+ } else if c.vers == VersionSSL30 {
+ // In SSL 3.0, no certificate is signaled by a warning
+ // alert which we translate to ssl3NoCertificateMsg.
+ if _, ok := msg.(*ssl3NoCertificateMsg); !ok {
+ return errors.New("tls: client provided neither a certificate nor no_certificate warning alert")
+ }
+ } else {
// In TLS, the Certificate message is required. In SSL
// 3.0, the peer skips it when sending no certificates.
c.sendAlert(alertUnexpectedMessage)
@@ -1459,11 +1479,9 @@
return err
}
- if ok {
- msg, err = c.readHandshake()
- if err != nil {
- return err
- }
+ msg, err = c.readHandshake()
+ if err != nil {
+ return err
}
}
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index fc66cf6..ba78fce 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -383,6 +383,8 @@
// expectPeerCertificate, if not nil, is the certificate chain the peer
// is expected to send.
expectPeerCertificate *Certificate
+ // expectShortHeader is whether the short header extension should be negotiated.
+ expectShortHeader bool
}
var testCases []testCase
@@ -611,6 +613,10 @@
}
}
+ if test.expectShortHeader != connState.ShortHeader {
+ return fmt.Errorf("ShortHeader is %t, but we expected the opposite", connState.ShortHeader)
+ }
+
if test.exportKeyingMaterial > 0 {
actual := make([]byte, test.exportKeyingMaterial)
if _, err := io.ReadFull(tlsConn, actual); err != nil {
@@ -1315,13 +1321,15 @@
SendFallbackSCSV: true,
},
},
- shouldFail: true,
- expectedError: ":INAPPROPRIATE_FALLBACK:",
+ shouldFail: true,
+ expectedError: ":INAPPROPRIATE_FALLBACK:",
+ expectedLocalError: "remote error: inappropriate fallback",
},
{
testType: serverTest,
- name: "FallbackSCSV-VersionMatch",
+ name: "FallbackSCSV-VersionMatch-TLS13",
config: Config{
+ MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendFallbackSCSV: true,
},
@@ -2561,11 +2569,57 @@
expectedError: expectedClientError,
})
- if !shouldClientFail {
- // Ensure the maximum record size is accepted.
+ if shouldClientFail {
+ return
+ }
+
+ // Ensure the maximum record size is accepted.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: prefix + ver.name + "-" + suite.name + "-LargeRecord",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ flags: flags,
+ messageLen: maxPlaintext,
+ })
+
+ // Test bad records for all ciphers. Bad records are fatal in TLS
+ // and ignored in DTLS.
+ var shouldFail bool
+ var expectedError string
+ if protocol == tls {
+ shouldFail = true
+ expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
+ }
+
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: prefix + ver.name + "-" + suite.name + "-BadRecord",
+ config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
+ CipherSuites: []uint16{suite.id},
+ Certificates: []Certificate{cert},
+ PreSharedKey: []byte(psk),
+ PreSharedKeyIdentity: pskIdentity,
+ },
+ flags: flags,
+ damageFirstWrite: true,
+ messageLen: maxPlaintext,
+ shouldFail: shouldFail,
+ expectedError: expectedError,
+ })
+
+ if ver.version >= VersionTLS13 {
testCases = append(testCases, testCase{
protocol: protocol,
- name: prefix + ver.name + "-" + suite.name + "-LargeRecord",
+ name: prefix + ver.name + "-" + suite.name + "-ShortHeader",
config: Config{
MinVersion: ver.version,
MaxVersion: ver.version,
@@ -2573,36 +2627,13 @@
Certificates: []Certificate{cert},
PreSharedKey: []byte(psk),
PreSharedKeyIdentity: pskIdentity,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
},
- flags: flags,
- messageLen: maxPlaintext,
- })
-
- // Test bad records for all ciphers. Bad records are fatal in TLS
- // and ignored in DTLS.
- var shouldFail bool
- var expectedError string
- if protocol == tls {
- shouldFail = true
- expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
- }
-
- testCases = append(testCases, testCase{
- protocol: protocol,
- name: prefix + ver.name + "-" + suite.name + "-BadRecord",
- config: Config{
- MinVersion: ver.version,
- MaxVersion: ver.version,
- CipherSuites: []uint16{suite.id},
- Certificates: []Certificate{cert},
- PreSharedKey: []byte(psk),
- PreSharedKeyIdentity: pskIdentity,
- },
- flags: flags,
- damageFirstWrite: true,
- messageLen: maxPlaintext,
- shouldFail: shouldFail,
- expectedError: expectedError,
+ flags: append([]string{"-enable-short-header"}, flags...),
+ resumeSession: true,
+ expectShortHeader: true,
})
}
}
@@ -2774,94 +2805,6 @@
},
flags: []string{"-psk", "secret"},
})
-
- // versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
- // 1.1 specific cipher suite settings. A server is setup with the given
- // cipher lists and then a connection is made for each member of
- // expectations. The cipher suite that the server selects must match
- // the specified one.
- var versionSpecificCiphersTest = []struct {
- ciphersDefault, ciphersTLS10, ciphersTLS11 string
- // expectations is a map from TLS version to cipher suite id.
- expectations map[uint16]uint16
- }{
- {
- // Test that the null case (where no version-specific ciphers are set)
- // works as expected.
- "DES-CBC3-SHA:AES128-SHA", // default ciphers
- "", // no ciphers specifically for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS10: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- },
- },
- {
- // With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
- // cipher.
- "DES-CBC3-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "", // no ciphers specifically for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
- // cipher.
- "DES-CBC3-SHA:AES128-SHA", // default
- "", // no ciphers specifically for TLS ≥ 1.0
- "AES128-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS10: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
- },
- },
- {
- // With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
- // mask ciphers_tls10 for TLS 1.1 and 1.2.
- "DES-CBC3-SHA:AES128-SHA", // default
- "AES128-SHA", // these ciphers for TLS ≥ 1.0
- "AES256-SHA", // these ciphers for TLS ≥ 1.1
- map[uint16]uint16{
- VersionSSL30: TLS_RSA_WITH_3DES_EDE_CBC_SHA,
- VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
- VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
- VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
- },
- },
- }
-
- for i, test := range versionSpecificCiphersTest {
- for version, expectedCipherSuite := range test.expectations {
- flags := []string{"-cipher", test.ciphersDefault}
- if len(test.ciphersTLS10) > 0 {
- flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
- }
- if len(test.ciphersTLS11) > 0 {
- flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
- }
-
- testCases = append(testCases, testCase{
- testType: serverTest,
- name: fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
- config: Config{
- MaxVersion: version,
- MinVersion: version,
- CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
- },
- flags: flags,
- expectedCipher: expectedCipherSuite,
- })
- }
- }
}
func addBadECDSASignatureTests() {
@@ -6319,6 +6262,24 @@
expectedLocalError: "remote error: no renegotiation",
})
+ // Renegotiation is not allowed when there is an unfinished write.
+ testCases = append(testCases, testCase{
+ name: "Renegotiate-Client-UnfinishedWrite",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ },
+ renegotiate: 1,
+ flags: []string{
+ "-async",
+ "-renegotiate-freely",
+ "-read-with-unfinished-write",
+ },
+ shouldFail: true,
+ expectedError: ":NO_RENEGOTIATION:",
+ // We do not successfully send the no_renegotiation alert in
+ // this case. https://crbug.com/boringssl/130
+ })
+
// Stray HelloRequests during the handshake are ignored in TLS 1.2.
testCases = append(testCases, testCase{
name: "StrayHelloRequest",
@@ -8178,6 +8139,102 @@
},
resumeSession: true,
})
+
+ // Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
+ testCases = append(testCases, testCase{
+ name: "PointFormat-ServerHello-TLS12",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{pointFormatUncompressed},
+ },
+ },
+ })
+ testCases = append(testCases, testCase{
+ name: "PointFormat-EncryptedExtensions-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{pointFormatUncompressed},
+ },
+ },
+ shouldFail: true,
+ expectedError: ":ERROR_PARSING_EXTENSION:",
+ })
+
+ // Test that we tolerate unknown point formats, as long as
+ // pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
+ // check they are still functional.
+ testCases = append(testCases, testCase{
+ name: "PointFormat-Client-Tolerance",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+ },
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "PointFormat-Server-Tolerance",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+ },
+ },
+ })
+
+ // Test TLS 1.2 does not require the point format extension to be
+ // present.
+ testCases = append(testCases, testCase{
+ name: "PointFormat-Client-Missing",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{},
+ },
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "PointFormat-Server-Missing",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{},
+ },
+ },
+ })
+
+ // If the point format extension is present, uncompressed points must be
+ // offered. BoringSSL requires this whether or not ECDHE is used.
+ testCases = append(testCases, testCase{
+ name: "PointFormat-Client-MissingUncompressed",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+ },
+ },
+ shouldFail: true,
+ expectedError: ":ERROR_PARSING_EXTENSION:",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "PointFormat-Server-MissingUncompressed",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+ },
+ },
+ shouldFail: true,
+ expectedError: ":ERROR_PARSING_EXTENSION:",
+ })
}
func addTLS13RecordTests() {
@@ -8322,6 +8379,48 @@
expectedLocalError: "tls: invalid ticket age",
})
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-SendTicketEarlyDataInfo",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendTicketEarlyDataInfo: 16384,
+ },
+ },
+ flags: []string{
+ "-expect-early-data-info",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-DuplicateTicketEarlyDataInfo",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendTicketEarlyDataInfo: 16384,
+ DuplicateTicketEarlyDataInfo: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DUPLICATE_EXTENSION:",
+ expectedLocalError: "remote error: illegal parameter",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-ExpectTicketEarlyDataInfo",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExpectTicketEarlyDataInfo: true,
+ },
+ },
+ flags: []string{
+ "-enable-early-data",
+ },
+ })
}
func addChangeCipherSpecTests() {
@@ -9853,6 +9952,150 @@
}
}
+func addShortHeaderTests() {
+ // The short header extension may be negotiated as either client or
+ // server.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ expectShortHeader: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortHeader-Server",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ expectShortHeader: true,
+ })
+
+ // If the peer doesn't support it, it will not be negotiated.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-No-Yes-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ flags: []string{"-enable-short-header"},
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortHeader-No-Yes-Server",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ },
+ flags: []string{"-enable-short-header"},
+ })
+
+ // If we don't support it, it will not be negotiated.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-Yes-No-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortHeader-Yes-No-Server",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ })
+
+ // It will not be negotiated at TLS 1.2.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-TLS12-Client",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortHeader-TLS12-Server",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ })
+
+ // Servers reject early data and short header sent together.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ShortHeader-EarlyData",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ SendEarlyDataLength: 1,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
+
+ // Clients reject unsolicited short header extensions.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-Unsolicited",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ AlwaysNegotiateShortHeader: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-Unsolicited-TLS12",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ AlwaysNegotiateShortHeader: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_EXTENSION:",
+ })
+
+ // The high bit must be checked in short headers.
+ testCases = append(testCases, testCase{
+ name: "ShortHeader-ClearShortHeaderBit",
+ config: Config{
+ Bugs: ProtocolBugs{
+ EnableShortHeader: true,
+ ClearShortHeaderBit: true,
+ },
+ },
+ flags: []string{"-enable-short-header"},
+ shouldFail: true,
+ expectedError: ":DECODE_ERROR:",
+ expectedLocalError: "remote error: error decoding message",
+ })
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -9979,6 +10222,7 @@
addCertificateTests()
addRetainOnlySHA256ClientCertTests()
addECDSAKeyUsageTests()
+ addShortHeaderTests()
var wg sync.WaitGroup
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 492dd73..a06b5e5 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -81,8 +81,10 @@
{ "-tls-unique", &TestConfig::tls_unique },
{ "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal },
{ "-expect-no-session", &TestConfig::expect_no_session },
+ { "-expect-early-data-info", &TestConfig::expect_early_data_info },
{ "-use-ticket-callback", &TestConfig::use_ticket_callback },
{ "-renew-ticket", &TestConfig::renew_ticket },
+ { "-enable-early-data", &TestConfig::enable_early_data },
{ "-enable-client-custom-extension",
&TestConfig::enable_client_custom_extension },
{ "-enable-server-custom-extension",
@@ -115,6 +117,8 @@
&TestConfig::expect_sha256_client_cert_initial },
{ "-expect-sha256-client-cert-resume",
&TestConfig::expect_sha256_client_cert_resume },
+ { "-enable-short-header", &TestConfig::enable_short_header },
+ { "-read-with-unfinished-write", &TestConfig::read_with_unfinished_write },
};
const Flag<std::string> kStringFlags[] = {
@@ -135,8 +139,6 @@
{ "-psk-identity", &TestConfig::psk_identity },
{ "-srtp-profiles", &TestConfig::srtp_profiles },
{ "-cipher", &TestConfig::cipher },
- { "-cipher-tls10", &TestConfig::cipher_tls10 },
- { "-cipher-tls11", &TestConfig::cipher_tls11 },
{ "-export-label", &TestConfig::export_label },
{ "-export-context", &TestConfig::export_context },
{ "-expect-peer-cert-file", &TestConfig::expect_peer_cert_file },
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 4d6a336..1307d56 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -75,8 +75,6 @@
bool fail_second_ddos_callback = false;
bool fail_cert_callback = false;
std::string cipher;
- std::string cipher_tls10;
- std::string cipher_tls11;
bool handshake_never_done = false;
int export_keying_material = 0;
std::string export_label;
@@ -85,8 +83,10 @@
bool tls_unique = false;
bool expect_ticket_renewal = false;
bool expect_no_session = false;
+ bool expect_early_data_info = false;
bool use_ticket_callback = false;
bool renew_ticket = false;
+ bool enable_early_data = false;
bool enable_client_custom_extension = false;
bool enable_server_custom_extension = false;
bool custom_extension_skip = false;
@@ -125,6 +125,8 @@
bool retain_only_sha256_client_cert_resume = false;
bool expect_sha256_client_cert_initial = false;
bool expect_sha256_client_cert_resume = false;
+ bool enable_short_header = false;
+ bool read_with_unfinished_write = false;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
index 5a058b1..7347fc4 100644
--- a/src/ssl/tls13_both.c
+++ b/src/ssl/tls13_both.c
@@ -243,7 +243,8 @@
uint8_t alert;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
- OPENSSL_ARRAY_SIZE(ext_types))) {
+ OPENSSL_ARRAY_SIZE(ext_types),
+ 0 /* reject unknown */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
index 4a202d7..6f2bb21 100644
--- a/src/ssl/tls13_client.c
+++ b/src/ssl/tls13_client.c
@@ -78,7 +78,8 @@
uint8_t alert;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
- OPENSSL_ARRAY_SIZE(ext_types))) {
+ OPENSSL_ARRAY_SIZE(ext_types),
+ 0 /* reject unknown */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
@@ -182,7 +183,8 @@
}
assert(ssl->s3->have_version);
- memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+ OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random),
+ SSL3_RANDOM_SIZE);
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
if (cipher == NULL) {
@@ -200,16 +202,18 @@
}
/* Parse out the extensions. */
- int have_key_share = 0, have_pre_shared_key = 0;
- CBS key_share, pre_shared_key;
+ int have_key_share = 0, have_pre_shared_key = 0, have_short_header = 0;
+ CBS key_share, pre_shared_key, short_header;
const SSL_EXTENSION_TYPE ext_types[] = {
{TLSEXT_TYPE_key_share, &have_key_share, &key_share},
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
+ {TLSEXT_TYPE_short_header, &have_short_header, &short_header},
};
uint8_t alert;
if (!ssl_parse_extensions(&extensions, &alert, ext_types,
- OPENSSL_ARRAY_SIZE(ext_types))) {
+ OPENSSL_ARRAY_SIZE(ext_types),
+ 0 /* reject unknown */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
@@ -304,6 +308,23 @@
}
OPENSSL_free(dhe_secret);
+ /* Negotiate short record headers. */
+ if (have_short_header) {
+ if (CBS_len(&short_header) != 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->ctx->short_header_enabled) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
+ return ssl_hs_error;
+ }
+
+ ssl->s3->short_header = 1;
+ }
+
/* If there was no HelloRetryRequest, the version negotiation logic has
* already hashed the message. */
if (hs->received_hello_retry_request &&
@@ -311,7 +332,11 @@
return ssl_hs_error;
}
- if (!tls13_set_handshake_traffic(hs)) {
+ if (!tls13_derive_handshake_secrets(hs) ||
+ !tls13_set_traffic_key(ssl, evp_aead_open, hs->server_handshake_secret,
+ hs->hash_len) ||
+ !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
+ hs->hash_len)) {
return ssl_hs_error;
}
@@ -464,7 +489,8 @@
}
}
- if (!tls13_prepare_certificate(hs)) {
+ if (!ssl_auto_chain_if_needed(ssl) ||
+ !tls13_prepare_certificate(hs)) {
return ssl_hs_error;
}
@@ -612,6 +638,7 @@
}
int tls13_process_new_session_ticket(SSL *ssl) {
+ int ret = 0;
SSL_SESSION *session =
SSL_SESSION_dup(ssl->s3->established_session,
SSL_SESSION_INCLUDE_NONAUTH);
@@ -629,10 +656,34 @@
!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
CBS_len(&cbs) != 0) {
- SSL_SESSION_free(session);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- return 0;
+ goto err;
+ }
+
+ /* Parse out the extensions. */
+ int have_early_data_info = 0;
+ CBS early_data_info;
+ const SSL_EXTENSION_TYPE ext_types[] = {
+ {TLSEXT_TYPE_ticket_early_data_info, &have_early_data_info,
+ &early_data_info},
+ };
+
+ uint8_t alert;
+ if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+ OPENSSL_ARRAY_SIZE(ext_types),
+ 1 /* ignore unknown */)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ goto err;
+ }
+
+ if (have_early_data_info) {
+ if (!CBS_get_u32(&early_data_info, &session->ticket_max_early_data) ||
+ CBS_len(&early_data_info) != 0) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ goto err;
+ }
}
session->ticket_age_add_valid = 1;
@@ -641,11 +692,14 @@
if (ssl->ctx->new_session_cb != NULL &&
ssl->ctx->new_session_cb(ssl, session)) {
/* |new_session_cb|'s return value signals that it took ownership. */
- return 1;
+ session = NULL;
}
+ ret = 1;
+
+err:
SSL_SESSION_free(session);
- return 1;
+ return ret;
}
void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.c
index 4fca65b..ea9dce8 100644
--- a/src/ssl/tls13_enc.c
+++ b/src/ssl/tls13_enc.c
@@ -24,6 +24,7 @@
#include <openssl/hmac.h>
#include <openssl/mem.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -34,7 +35,7 @@
hs->hash_len = EVP_MD_size(digest);
/* Initialize the secret to the zero key. */
- memset(hs->secret, 0, hs->hash_len);
+ OPENSSL_memset(hs->secret, 0, hs->hash_len);
/* Initialize the rolling hashes and release the handshake buffer. */
if (!ssl3_init_handshake_hash(ssl)) {
@@ -166,10 +167,12 @@
/* Save the traffic secret. */
if (direction == evp_aead_open) {
- memmove(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
+ OPENSSL_memmove(ssl->s3->read_traffic_secret, traffic_secret,
+ traffic_secret_len);
ssl->s3->read_traffic_secret_len = traffic_secret_len;
} else {
- memmove(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
+ OPENSSL_memmove(ssl->s3->write_traffic_secret, traffic_secret,
+ traffic_secret_len);
ssl->s3->write_traffic_secret_len = traffic_secret_len;
}
@@ -185,39 +188,18 @@
static const char kTLS13LabelServerApplicationTraffic[] =
"server application traffic secret";
-int tls13_set_handshake_traffic(SSL_HANDSHAKE *hs) {
+int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- uint8_t client_traffic_secret[EVP_MAX_MD_SIZE];
- uint8_t server_traffic_secret[EVP_MAX_MD_SIZE];
- if (!derive_secret(hs, client_traffic_secret, hs->hash_len,
- (const uint8_t *)kTLS13LabelClientHandshakeTraffic,
- strlen(kTLS13LabelClientHandshakeTraffic)) ||
- !ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
- client_traffic_secret, hs->hash_len) ||
- !derive_secret(hs, server_traffic_secret, hs->hash_len,
- (const uint8_t *)kTLS13LabelServerHandshakeTraffic,
- strlen(kTLS13LabelServerHandshakeTraffic)) ||
- !ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
- server_traffic_secret, hs->hash_len)) {
- return 0;
- }
-
- if (ssl->server) {
- if (!tls13_set_traffic_key(ssl, evp_aead_open, client_traffic_secret,
- hs->hash_len) ||
- !tls13_set_traffic_key(ssl, evp_aead_seal, server_traffic_secret,
- hs->hash_len)) {
- return 0;
- }
- } else {
- if (!tls13_set_traffic_key(ssl, evp_aead_open, server_traffic_secret,
- hs->hash_len) ||
- !tls13_set_traffic_key(ssl, evp_aead_seal, client_traffic_secret,
- hs->hash_len)) {
- return 0;
- }
- }
- return 1;
+ return derive_secret(hs, hs->client_handshake_secret, hs->hash_len,
+ (const uint8_t *)kTLS13LabelClientHandshakeTraffic,
+ strlen(kTLS13LabelClientHandshakeTraffic)) &&
+ ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+ hs->client_handshake_secret, hs->hash_len) &&
+ derive_secret(hs, hs->server_handshake_secret, hs->hash_len,
+ (const uint8_t *)kTLS13LabelServerHandshakeTraffic,
+ strlen(kTLS13LabelServerHandshakeTraffic)) &&
+ ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+ hs->server_handshake_secret, hs->hash_len);
}
static const char kTLS13LabelExporter[] = "exporter master secret";
@@ -405,7 +387,7 @@
return 0;
}
- memcpy(msg + len - hash_len, verify_data, hash_len);
+ OPENSSL_memcpy(msg + len - hash_len, verify_data, hash_len);
return 1;
}
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
index 1aca634..750e47f 100644
--- a/src/ssl/tls13_server.c
+++ b/src/ssl/tls13_server.c
@@ -25,9 +25,15 @@
#include <openssl/rand.h>
#include <openssl/stack.h>
+#include "../crypto/internal.h"
#include "internal.h"
+/* kMaxEarlyDataAccepted is the advertised number of plaintext bytes of early
+ * data that will be accepted. This value should be slightly below
+ * kMaxEarlyDataSkipped in tls_record.c, which is measured in ciphertext. */
+static const size_t kMaxEarlyDataAccepted = 14336;
+
enum server_hs_state_t {
state_process_client_hello = 0,
state_select_parameters,
@@ -109,7 +115,8 @@
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_hs_error;
}
- memcpy(ssl->s3->client_random, client_hello.random, client_hello.random_len);
+ OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
+ client_hello.random_len);
/* TLS 1.3 requires the peer only advertise the null compression. */
if (client_hello.compression_methods_len != 1 ||
@@ -125,6 +132,12 @@
return ssl_hs_error;
}
+ /* The short record header extension is incompatible with early data. */
+ if (ssl->s3->skip_early_data && ssl->s3->short_header) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+ return ssl_hs_error;
+ }
+
hs->tls13_state = state_select_parameters;
return ssl_hs_ok;
}
@@ -191,6 +204,10 @@
}
}
+ if (!ssl_auto_chain_if_needed(ssl)) {
+ return ssl_hs_error;
+ }
+
SSL_CLIENT_HELLO client_hello;
if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
ssl->init_num)) {
@@ -389,8 +406,18 @@
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
- !ssl_ext_key_share_add_serverhello(hs, &extensions) ||
- !ssl_complete_message(ssl, &cbb)) {
+ !ssl_ext_key_share_add_serverhello(hs, &extensions)) {
+ goto err;
+ }
+
+ if (ssl->s3->short_header) {
+ if (!CBB_add_u16(&extensions, TLSEXT_TYPE_short_header) ||
+ !CBB_add_u16(&extensions, 0 /* empty extension */)) {
+ goto err;
+ }
+ }
+
+ if (!ssl_complete_message(ssl, &cbb)) {
goto err;
}
@@ -404,7 +431,11 @@
static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!tls13_set_handshake_traffic(hs)) {
+ if (!tls13_derive_handshake_secrets(hs) ||
+ !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
+ hs->hash_len) ||
+ !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
+ hs->hash_len)) {
return ssl_hs_error;
}
@@ -631,9 +662,6 @@
goto err;
}
- /* TODO(svaldez): Add support for sending 0RTT through TicketEarlyDataInfo
- * extension. */
-
CBB cbb, body, ticket, extensions;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_NEW_SESSION_TICKET) ||
@@ -645,6 +673,18 @@
goto err;
}
+ if (ssl->ctx->enable_early_data) {
+ session->ticket_max_early_data = kMaxEarlyDataAccepted;
+
+ CBB early_data_info;
+ if (!CBB_add_u16(&extensions, TLSEXT_TYPE_ticket_early_data_info) ||
+ !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
+ !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
+ !CBB_flush(&extensions)) {
+ goto err;
+ }
+ }
+
/* Add a fake extension. See draft-davidben-tls-grease-01. */
if (!CBB_add_u16(&extensions,
ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
diff --git a/src/ssl/tls_method.c b/src/ssl/tls_method.c
index 9effb36..4efed3f 100644
--- a/src/ssl/tls_method.c
+++ b/src/ssl/tls_method.c
@@ -61,6 +61,7 @@
#include <openssl/buf.h>
+#include "../crypto/internal.h"
#include "internal.h"
@@ -112,7 +113,7 @@
return 0;
}
- memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
+ OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
ssl->s3->aead_read_ctx = aead_ctx;
@@ -120,7 +121,7 @@
}
static int ssl3_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
- memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
+ OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
ssl->s3->aead_write_ctx = aead_ctx;
diff --git a/src/ssl/tls_record.c b/src/ssl/tls_record.c
index c52909c..362b0c2 100644
--- a/src/ssl/tls_record.c
+++ b/src/ssl/tls_record.c
@@ -125,10 +125,11 @@
* forever. */
static const uint8_t kMaxEmptyRecords = 32;
-/* kMaxEarlyDataSkipped is the maximum amount of data processed when skipping
- * over early data. Without this limit an attacker could send records at a
- * faster rate than we can process and cause trial decryption to loop
- * forever. */
+/* kMaxEarlyDataSkipped is the maximum number of rejected early data bytes that
+ * will be skipped. Without this limit an attacker could send records at a
+ * faster rate than we can process and cause trial decryption to loop forever.
+ * This value should be slightly above kMaxEarlyDataAccepted in tls13_server.c,
+ * which is measured in plaintext. */
static const size_t kMaxEarlyDataSkipped = 16384;
/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
@@ -144,6 +145,19 @@
SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher);
}
+static int ssl_uses_short_header(const SSL *ssl,
+ enum evp_aead_direction_t dir) {
+ if (!ssl->s3->short_header) {
+ return 0;
+ }
+
+ if (dir == evp_aead_open) {
+ return ssl->s3->aead_read_ctx != NULL;
+ }
+
+ return ssl->s3->aead_write_ctx != NULL;
+}
+
int ssl_record_sequence_update(uint8_t *seq, size_t seq_len) {
for (size_t i = seq_len - 1; i < seq_len; i--) {
++seq[i];
@@ -156,34 +170,46 @@
}
size_t ssl_record_prefix_len(const SSL *ssl) {
+ size_t header_len;
if (SSL_is_dtls(ssl)) {
- return DTLS1_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx);
+ header_len = DTLS1_RT_HEADER_LENGTH;
+ } else if (ssl_uses_short_header(ssl, evp_aead_open)) {
+ header_len = 2;
} else {
- return SSL3_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx);
+ header_len = SSL3_RT_HEADER_LENGTH;
}
+
+ return header_len + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx);
}
size_t ssl_seal_align_prefix_len(const SSL *ssl) {
if (SSL_is_dtls(ssl)) {
return DTLS1_RT_HEADER_LENGTH +
SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
- } else {
- size_t ret = SSL3_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
- if (ssl_needs_record_splitting(ssl)) {
- ret += SSL3_RT_HEADER_LENGTH;
- ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher);
- }
- return ret;
}
+
+ size_t header_len;
+ if (ssl_uses_short_header(ssl, evp_aead_seal)) {
+ header_len = 2;
+ } else {
+ header_len = SSL3_RT_HEADER_LENGTH;
+ }
+
+ size_t ret =
+ header_len + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
+ if (ssl_needs_record_splitting(ssl)) {
+ ret += header_len;
+ ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher);
+ }
+ return ret;
}
size_t SSL_max_seal_overhead(const SSL *ssl) {
size_t ret = SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
if (SSL_is_dtls(ssl)) {
ret += DTLS1_RT_HEADER_LENGTH;
+ } else if (ssl_uses_short_header(ssl, evp_aead_seal)) {
+ ret += 2;
} else {
ret += SSL3_RT_HEADER_LENGTH;
}
@@ -209,11 +235,31 @@
/* Decode the record header. */
uint8_t type;
uint16_t version, ciphertext_len;
- if (!CBS_get_u8(&cbs, &type) ||
- !CBS_get_u16(&cbs, &version) ||
- !CBS_get_u16(&cbs, &ciphertext_len)) {
- *out_consumed = SSL3_RT_HEADER_LENGTH;
- return ssl_open_record_partial;
+ size_t header_len;
+ if (ssl_uses_short_header(ssl, evp_aead_open)) {
+ if (!CBS_get_u16(&cbs, &ciphertext_len)) {
+ *out_consumed = 2;
+ return ssl_open_record_partial;
+ }
+
+ if ((ciphertext_len & 0x8000) == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return ssl_open_record_error;
+ }
+
+ ciphertext_len &= 0x7fff;
+ type = SSL3_RT_APPLICATION_DATA;
+ version = TLS1_VERSION;
+ header_len = 2;
+ } else {
+ if (!CBS_get_u8(&cbs, &type) ||
+ !CBS_get_u16(&cbs, &version) ||
+ !CBS_get_u16(&cbs, &ciphertext_len)) {
+ *out_consumed = SSL3_RT_HEADER_LENGTH;
+ return ssl_open_record_partial;
+ }
+ header_len = SSL3_RT_HEADER_LENGTH;
}
int version_ok;
@@ -245,12 +291,11 @@
/* Extract the body. */
CBS body;
if (!CBS_get_bytes(&cbs, &body, ciphertext_len)) {
- *out_consumed = SSL3_RT_HEADER_LENGTH + (size_t)ciphertext_len;
+ *out_consumed = header_len + (size_t)ciphertext_len;
return ssl_open_record_partial;
}
- ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
- SSL3_RT_HEADER_LENGTH);
+ ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in, header_len);
*out_consumed = in_len - CBS_len(&cbs);
@@ -352,21 +397,32 @@
static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
size_t max_out, uint8_t type, const uint8_t *in,
size_t in_len) {
- if (max_out < SSL3_RT_HEADER_LENGTH) {
+ assert(!buffers_alias(in, in_len, out, max_out));
+
+ const int short_header = ssl_uses_short_header(ssl, evp_aead_seal);
+ size_t header_len = short_header ? 2 : SSL3_RT_HEADER_LENGTH;
+
+ /* TLS 1.3 hides the actual record type inside the encrypted data. */
+ if (ssl->s3->have_version &&
+ ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+ ssl->s3->aead_write_ctx != NULL) {
+ if (in_len > in_len + header_len + 1 || max_out < in_len + header_len + 1) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ OPENSSL_memcpy(out + header_len, in, in_len);
+ out[header_len + in_len] = type;
+ in = out + header_len;
+ type = SSL3_RT_APPLICATION_DATA;
+ in_len++;
+ }
+
+ if (max_out < header_len) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return 0;
}
- /* Either |in| and |out| don't alias or |in| aligns with the
- * ciphertext. |tls_seal_record| forbids aliasing, but TLS 1.3 aliases them
- * internally. */
- assert(!buffers_alias(in, in_len, out, max_out) ||
- in ==
- out + SSL3_RT_HEADER_LENGTH +
- SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx));
-
- out[0] = type;
-
/* The TLS record-layer version number is meaningless and, starting in
* TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0
* ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version
@@ -376,29 +432,39 @@
(ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION)) {
wire_version = ssl->version;
}
- out[1] = wire_version >> 8;
- out[2] = wire_version & 0xff;
+ /* Write the non-length portions of the header. */
+ if (!short_header) {
+ out[0] = type;
+ out[1] = wire_version >> 8;
+ out[2] = wire_version & 0xff;
+ out += 3;
+ max_out -= 3;
+ }
+
+ /* Write the ciphertext, leaving two bytes for the length. */
size_t ciphertext_len;
- if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + SSL3_RT_HEADER_LENGTH,
- &ciphertext_len, max_out - SSL3_RT_HEADER_LENGTH,
- type, wire_version, ssl->s3->write_sequence, in,
- in_len) ||
+ if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + 2, &ciphertext_len,
+ max_out - 2, type, wire_version,
+ ssl->s3->write_sequence, in, in_len) ||
!ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
return 0;
}
- if (ciphertext_len >= 1 << 16) {
+ /* Fill in the length. */
+ if (ciphertext_len >= 1 << 15) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
}
- out[3] = ciphertext_len >> 8;
- out[4] = ciphertext_len & 0xff;
+ out[0] = ciphertext_len >> 8;
+ out[1] = ciphertext_len & 0xff;
+ if (short_header) {
+ out[0] |= 0x80;
+ }
- *out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len;
+ *out_len = header_len + ciphertext_len;
- ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out,
- SSL3_RT_HEADER_LENGTH);
+ ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out, header_len);
return 1;
}
@@ -410,25 +476,6 @@
}
size_t frag_len = 0;
-
- /* TLS 1.3 hides the actual record type inside the encrypted data. */
- if (ssl->s3->have_version &&
- ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
- ssl->s3->aead_write_ctx != NULL) {
- size_t padding = SSL3_RT_HEADER_LENGTH + 1;
-
- if (in_len > in_len + padding || max_out < in_len + padding) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
- }
-
- memmove(out + SSL3_RT_HEADER_LENGTH, in, in_len);
- out[SSL3_RT_HEADER_LENGTH + in_len] = type;
- in = out + SSL3_RT_HEADER_LENGTH;
- type = SSL3_RT_APPLICATION_DATA;
- in_len++;
- }
-
if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
ssl_needs_record_splitting(ssl)) {
if (!do_seal_record(ssl, out, &frag_len, max_out, type, in, 1)) {
@@ -439,6 +486,7 @@
out += frag_len;
max_out -= frag_len;
+ assert(!ssl_uses_short_header(ssl, evp_aead_seal));
#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len(
ssl->s3->aead_write_ctx->cipher) ==