diff options
author | Robert Sloan <varomodt@google.com> | 2018-04-16 08:36:46 -0700 |
---|---|---|
committer | Robert Sloan <varomodt@google.com> | 2018-04-16 08:36:54 -0700 |
commit | 15c0b3594be4cd3bd18a44be8eef0429a0cb072f (patch) | |
tree | 96fc5654e0d9b96afdd5a2c47a9515d06aea73ed /src | |
parent | dc2f609faa3d5fa920e2c42a39750dca1a247c8f (diff) | |
download | boringssl-15c0b3594be4cd3bd18a44be8eef0429a0cb072f.tar.gz |
external/boringssl: Sync to 9f0e7cb314ae64234b928fd379381ae9760a9a5f.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/f11ea19043f2b3ee42e4a76d0645914347e1a36e..9f0e7cb314ae64234b928fd379381ae9760a9a5f
Test: BoringSSL CTS Presubmits.
Change-Id: I9296845fe9db4baae2afc03328c5bc17f76a752f
Diffstat (limited to 'src')
34 files changed, 302 insertions, 284 deletions
diff --git a/src/crypto/asn1/a_strnid.c b/src/crypto/asn1/a_strnid.c index 379a79fb..efbf0fa8 100644 --- a/src/crypto/asn1/a_strnid.c +++ b/src/crypto/asn1/a_strnid.c @@ -223,6 +223,7 @@ ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) return ttmp; if (!stable) return NULL; + sk_ASN1_STRING_TABLE_sort(stable); found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd); if (!found) return NULL; diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c index 9f4639f2..57527122 100644 --- a/src/crypto/crypto.c +++ b/src/crypto/crypto.c @@ -164,31 +164,21 @@ int CRYPTO_has_asm(void) { #endif } -const char *SSLeay_version(int unused) { - return "BoringSSL"; -} +const char *SSLeay_version(int unused) { return "BoringSSL"; } -const char *OpenSSL_version(int unused) { - return "BoringSSL"; -} +const char *OpenSSL_version(int unused) { return "BoringSSL"; } -unsigned long SSLeay(void) { - return OPENSSL_VERSION_NUMBER; -} +unsigned long SSLeay(void) { return OPENSSL_VERSION_NUMBER; } -unsigned long OpenSSL_version_num(void) { - return OPENSSL_VERSION_NUMBER; -} +unsigned long OpenSSL_version_num(void) { return OPENSSL_VERSION_NUMBER; } -int CRYPTO_malloc_init(void) { - return 1; -} +int CRYPTO_malloc_init(void) { return 1; } + +int OPENSSL_malloc_init(void) { return 1; } void ENGINE_load_builtin_engines(void) {} -int ENGINE_register_all_complete(void) { - return 1; -} +int ENGINE_register_all_complete(void) { return 1; } void OPENSSL_load_builtin_modules(void) {} diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c index f6b44123..7aa32186 100644 --- a/src/crypto/stack/stack.c +++ b/src/crypto/stack/stack.c @@ -223,7 +223,7 @@ void *sk_delete_ptr(_STACK *sk, void *p) { return NULL; } -int sk_find(_STACK *sk, size_t *out_index, void *p) { +int sk_find(const _STACK *sk, size_t *out_index, void *p) { if (sk == NULL) { return 0; } @@ -245,7 +245,17 @@ int sk_find(_STACK *sk, size_t *out_index, void *p) { return 0; } - sk_sort(sk); + if (!sk_is_sorted(sk)) { + for (size_t i = 0; i < sk->num; i++) { + if (sk->comp((const void **)&p, (const void **)&sk->data[i]) == 0) { + if (out_index) { + *out_index = i; + } + return 1; + } + } + return 0; + } // sk->comp is a function that takes pointers to pointers to elements, but // qsort and bsearch take a comparison function that just takes pointers to diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c index 635b851f..b3bfffeb 100644 --- a/src/crypto/x509/by_dir.c +++ b/src/crypto/x509/by_dir.c @@ -387,6 +387,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, */ CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock); tmp = NULL; + sk_X509_OBJECT_sort(xl->store_ctx->objs); if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) { tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx); } @@ -404,6 +405,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, */ if (!hent) { htmp.hash = h; + sk_BY_DIR_HASH_sort(ent->hashes); if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) hent = sk_BY_DIR_HASH_value(ent->hashes, idx); } @@ -422,6 +424,7 @@ static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name, ok = 0; goto finish; } + sk_BY_DIR_HASH_sort(ent->hashes); } else if (hent->suffix < k) hent->suffix = k; diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c index 1a841dbe..ea01427c 100644 --- a/src/crypto/x509/x509_lu.c +++ b/src/crypto/x509/x509_lu.c @@ -473,6 +473,7 @@ static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, } size_t idx; + sk_X509_OBJECT_sort(h); if (!sk_X509_OBJECT_find(h, &idx, &stmp)) return -1; @@ -604,6 +605,7 @@ X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, size_t idx, i; X509_OBJECT *obj; + sk_X509_OBJECT_sort(h); if (!sk_X509_OBJECT_find(h, &idx, x)) { return NULL; } diff --git a/src/crypto/x509/x509_trs.c b/src/crypto/x509/x509_trs.c index c7dfcad6..f899424b 100644 --- a/src/crypto/x509/x509_trs.c +++ b/src/crypto/x509/x509_trs.c @@ -158,6 +158,7 @@ int X509_TRUST_get_by_id(int id) tmp.trust = id; if (!trtable) return -1; + sk_X509_TRUST_sort(trtable); if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) { return -1; } diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c index 43353c6b..84ec838b 100644 --- a/src/crypto/x509/x509_vpm.c +++ b/src/crypto/x509/x509_vpm.c @@ -614,6 +614,7 @@ int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param) } else { size_t idx; + sk_X509_VERIFY_PARAM_sort(param_table); if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) { ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx); X509_VERIFY_PARAM_free(ptmp); @@ -649,6 +650,7 @@ const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name) pm.name = (char *)name; if (param_table) { size_t idx; + sk_X509_VERIFY_PARAM_sort(param_table); if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm)) return sk_X509_VERIFY_PARAM_value(param_table, idx); } diff --git a/src/crypto/x509v3/pcy_cache.c b/src/crypto/x509v3/pcy_cache.c index b8a4be27..755c0795 100644 --- a/src/crypto/x509v3/pcy_cache.c +++ b/src/crypto/x509v3/pcy_cache.c @@ -93,6 +93,7 @@ static int policy_cache_create(X509 *x, /* * Duplicate policy OIDs are illegal: reject if matches found. */ + sk_X509_POLICY_DATA_sort(cache->data); if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { if (cache->anyPolicy) { ret = -1; @@ -262,6 +263,7 @@ X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache, X509_POLICY_DATA tmp; tmp.valid_policy = (ASN1_OBJECT *)id; + sk_X509_POLICY_DATA_sort(cache->data); if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp)) return NULL; return sk_X509_POLICY_DATA_value(cache->data, idx); diff --git a/src/crypto/x509v3/pcy_node.c b/src/crypto/x509v3/pcy_node.c index b3edfe48..6682282c 100644 --- a/src/crypto/x509v3/pcy_node.c +++ b/src/crypto/x509v3/pcy_node.c @@ -83,6 +83,7 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes, n.valid_policy = (ASN1_OBJECT *)id; l.data = &n; + sk_X509_POLICY_NODE_sort(nodes); if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l)) return NULL; diff --git a/src/crypto/x509v3/pcy_tree.c b/src/crypto/x509v3/pcy_tree.c index 256fe88e..136b45f5 100644 --- a/src/crypto/x509v3/pcy_tree.c +++ b/src/crypto/x509v3/pcy_tree.c @@ -543,9 +543,11 @@ static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes, *pnodes = policy_node_cmp_new(); if (!*pnodes) return 0; - } else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) + } else { + sk_X509_POLICY_NODE_sort(*pnodes); + if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy)) return 1; - + } if (!sk_X509_POLICY_NODE_push(*pnodes, pcy)) return 0; diff --git a/src/crypto/x509v3/v3_lib.c b/src/crypto/x509v3/v3_lib.c index 8f5435d7..d5eda3dd 100644 --- a/src/crypto/x509v3/v3_lib.c +++ b/src/crypto/x509v3/v3_lib.c @@ -116,6 +116,7 @@ const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid) if (!ext_list) return NULL; + sk_X509V3_EXT_METHOD_sort(ext_list); if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp)) return NULL; return sk_X509V3_EXT_METHOD_value(ext_list, idx); diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c index 324de85a..f70a804c 100644 --- a/src/crypto/x509v3/v3_purp.c +++ b/src/crypto/x509v3/v3_purp.c @@ -205,6 +205,7 @@ int X509_PURPOSE_get_by_id(int purpose) if (!xptable) return -1; + sk_X509_PURPOSE_sort(xptable); if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp)) return -1; return idx + X509_PURPOSE_COUNT; diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c index 7d109ee6..589e296d 100644 --- a/src/crypto/x509v3/v3_utl.c +++ b/src/crypto/x509v3/v3_utl.c @@ -650,6 +650,7 @@ static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) if (!*sk) return 0; /* Don't add duplicates */ + sk_OPENSSL_STRING_sort(*sk); if (sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data)) return 1; emtmp = BUF_strdup((char *)email->data); diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h index bd41d114..e2d15fa4 100644 --- a/src/include/openssl/base.h +++ b/src/include/openssl/base.h @@ -155,7 +155,7 @@ extern "C" { // A consumer may use this symbol in the preprocessor to temporarily build // against multiple revisions of BoringSSL at the same time. It is not // recommended to do so for longer than is necessary. -#define BORINGSSL_API_VERSION 7 +#define BORINGSSL_API_VERSION 8 #if defined(BORINGSSL_SHARED_LIBRARY) diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h index ccf5012c..cc6fc3ca 100644 --- a/src/include/openssl/crypto.h +++ b/src/include/openssl/crypto.h @@ -92,6 +92,9 @@ OPENSSL_EXPORT unsigned long OpenSSL_version_num(void); // CRYPTO_malloc_init returns one. OPENSSL_EXPORT int CRYPTO_malloc_init(void); +// OPENSSL_malloc_init returns one. +OPENSSL_EXPORT int OPENSSL_malloc_init(void); + // ENGINE_load_builtin_engines does nothing. OPENSSL_EXPORT void ENGINE_load_builtin_engines(void); diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h index d22d396c..2922473b 100644 --- a/src/include/openssl/ssl.h +++ b/src/include/openssl/ssl.h @@ -1749,6 +1749,15 @@ OPENSSL_EXPORT void SSL_SESSION_get0_ticket(const SSL_SESSION *session, OPENSSL_EXPORT uint32_t SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session); +// SSL_SESSION_get0_cipher returns the cipher negotiated by the connection which +// established |session|. +// +// Note that, in TLS 1.3, there is no guarantee that resumptions with |session| +// will use that cipher. Prefer calling |SSL_get_current_cipher| on the |SSL| +// instead. +OPENSSL_EXPORT const SSL_CIPHER *SSL_SESSION_get0_cipher( + const SSL_SESSION *session); + // Session caching. // diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h index 625f66e4..6975db63 100644 --- a/src/include/openssl/stack.h +++ b/src/include/openssl/stack.h @@ -163,12 +163,17 @@ OPENSSL_EXPORT void *sk_delete(_STACK *sk, size_t where); OPENSSL_EXPORT void *sk_delete_ptr(_STACK *sk, void *p); // sk_find returns the first value in the stack equal to |p|. If a comparison -// function has been set on the stack, then equality is defined by it and the -// stack will be sorted if need be so that a binary search can be used. -// Otherwise pointer equality is used. If a matching element is found, its -// index is written to |*out_index| (if |out_index| is not NULL) and one is -// returned. Otherwise zero is returned. -OPENSSL_EXPORT int sk_find(_STACK *sk, size_t *out_index, void *p); +// function has been set on the stack, equality is defined by it, otherwise +// pointer equality is used. If the stack is sorted, then a binary search is +// used, otherwise a linear search is performed. If a matching element is found, +// its index is written to +// |*out_index| (if |out_index| is not NULL) and one is returned. Otherwise zero +// is returned. +// +// Note this differs from OpenSSL. The type signature is slightly different, and +// OpenSSL's sk_find will implicitly sort |sk| if it has a comparison function +// defined. +OPENSSL_EXPORT int sk_find(const _STACK *sk, size_t *out_index, void *p); // sk_shift removes and returns the first element in the stack, or returns NULL // if the stack is empty. @@ -302,8 +307,8 @@ struct StackTraits {}; } \ \ static inline OPENSSL_UNUSED int sk_##name##_find( \ - STACK_OF(name) *sk, size_t *out_index, ptrtype p) { \ - return sk_find((_STACK *)sk, out_index, (void *)p); \ + const STACK_OF(name) *sk, size_t *out_index, ptrtype p) { \ + return sk_find((const _STACK *)sk, out_index, (void *)p); \ } \ \ static inline OPENSSL_UNUSED ptrtype sk_##name##_shift(STACK_OF(name) *sk) { \ diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc index 5e795fa3..d3486015 100644 --- a/src/ssl/dtls_record.cc +++ b/src/ssl/dtls_record.cc @@ -219,8 +219,8 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, return ssl_open_record_discard; } - ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, - in.subspan(0, DTLS1_RT_HEADER_LENGTH)); + Span<const uint8_t> header = in.subspan(0, DTLS1_RT_HEADER_LENGTH); + ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header); uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1]; if (epoch != ssl->d1->r_epoch || @@ -235,7 +235,7 @@ enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, // discard the body in-place. if (!ssl->s3->aead_read_ctx->Open( - out, type, version, sequence, + out, type, version, sequence, header, MakeSpan(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) { // Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347. // Clear the error queue of any errors decryption may have added. Drop the @@ -328,25 +328,25 @@ int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, OPENSSL_memcpy(&out[5], &seq[2], 6); size_t ciphertext_len; - if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len, - max_out - DTLS1_RT_HEADER_LENGTH, type, record_version, - &out[3] /* seq */, in, in_len) || - !ssl_record_sequence_update(&seq[2], 6)) { + if (!aead->CiphertextLen(&ciphertext_len, in_len, 0)) { + OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); return 0; } + out[11] = ciphertext_len >> 8; + out[12] = ciphertext_len & 0xff; + Span<const uint8_t> header = MakeConstSpan(out, DTLS1_RT_HEADER_LENGTH); - if (ciphertext_len >= 1 << 16) { - OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + size_t len_copy; + if (!aead->Seal(out + DTLS1_RT_HEADER_LENGTH, &len_copy, + max_out - DTLS1_RT_HEADER_LENGTH, type, record_version, + &out[3] /* seq */, header, in, in_len) || + !ssl_record_sequence_update(&seq[2], 6)) { return 0; } - out[11] = ciphertext_len >> 8; - out[12] = ciphertext_len & 0xff; + assert(ciphertext_len == len_copy); *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len; - - ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, - MakeSpan(out, DTLS1_RT_HEADER_LENGTH)); - + ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header); return 1; } diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc index dd73c83e..2cbbaebb 100644 --- a/src/ssl/handoff.cc +++ b/src/ssl/handoff.cc @@ -133,10 +133,6 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) { s3->session_reused ? ssl->session : s3->hs->new_session.get(); if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) || !CBB_add_asn1_uint64(&seq, kHandbackVersion) || - !CBB_add_asn1_uint64(&seq, ssl->version) || - !CBB_add_asn1_uint64(&seq, ssl->conf_max_version) || - !CBB_add_asn1_uint64(&seq, ssl->conf_min_version) || - !CBB_add_asn1_uint64(&seq, ssl->max_send_fragment) || !CBB_add_asn1_octet_string(&seq, s3->read_sequence, sizeof(s3->read_sequence)) || !CBB_add_asn1_octet_string(&seq, s3->write_sequence, @@ -148,7 +144,6 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) { !CBB_add_asn1_octet_string(&seq, read_iv, iv_len) || !CBB_add_asn1_octet_string(&seq, write_iv, iv_len) || !CBB_add_asn1_bool(&seq, s3->session_reused) || - !CBB_add_asn1_bool(&seq, s3->send_connection_binding) || !CBB_add_asn1_bool(&seq, s3->tlsext_channel_id_valid) || !ssl_session_serialize(session, &seq) || !CBB_add_asn1_octet_string(&seq, s3->next_proto_negotiated.data(), @@ -160,14 +155,8 @@ bool SSL_serialize_handback(const SSL *ssl, CBB *out) { hostname_len) || !CBB_add_asn1_octet_string(&seq, s3->tlsext_channel_id, sizeof(s3->tlsext_channel_id)) || - !CBB_add_asn1_uint64(&seq, ssl->options) || - !CBB_add_asn1_uint64(&seq, ssl->mode) || - !CBB_add_asn1_uint64(&seq, ssl->max_cert_list) || - !CBB_add_asn1_bool(&seq, ssl->quiet_shutdown) || - !CBB_add_asn1_bool(&seq, ssl->tlsext_channel_id_enabled) || - !CBB_add_asn1_bool(&seq, ssl->retain_only_sha256_of_client_certs) || - !CBB_add_asn1_bool(&seq, ssl->token_binding_negotiated) || - !CBB_add_asn1_uint64(&seq, ssl->negotiated_token_binding_param) || + !CBB_add_asn1_bool(&seq, ssl->s3->token_binding_negotiated) || + !CBB_add_asn1_uint64(&seq, ssl->s3->negotiated_token_binding_param) || !CBB_add_asn1_bool(&seq, s3->hs->next_proto_neg_seen) || !CBB_add_asn1_bool(&seq, s3->hs->cert_request) || !CBB_add_asn1_bool(&seq, s3->hs->extended_master_secret) || @@ -191,16 +180,12 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { } SSL3_STATE *const s3 = ssl->s3; - uint64_t handback_version, version, conf_max_version, conf_min_version, - max_send_fragment, options, mode, max_cert_list, - negotiated_token_binding_param, cipher; + uint64_t handback_version, negotiated_token_binding_param, cipher; CBS seq, read_seq, write_seq, server_rand, client_rand, read_iv, write_iv, next_proto, alpn, hostname, channel_id, transcript, key_share; - int session_reused, send_connection_binding, channel_id_valid, quiet_shutdown, - channel_id_enabled, retain_only_sha256, cert_request, - extended_master_secret, ticket_expected, token_binding_negotiated, - next_proto_neg_seen; + int session_reused, channel_id_valid, cert_request, extended_master_secret, + ticket_expected, token_binding_negotiated, next_proto_neg_seen; SSL_SESSION *session = nullptr; CBS handback_cbs(handback); @@ -210,11 +195,7 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { return false; } - if (!CBS_get_asn1_uint64(&seq, &version) || - !CBS_get_asn1_uint64(&seq, &conf_max_version) || - !CBS_get_asn1_uint64(&seq, &conf_min_version) || - !CBS_get_asn1_uint64(&seq, &max_send_fragment) || - !CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) || + if (!CBS_get_asn1(&seq, &read_seq, CBS_ASN1_OCTETSTRING) || CBS_len(&read_seq) != sizeof(s3->read_sequence) || !CBS_get_asn1(&seq, &write_seq, CBS_ASN1_OCTETSTRING) || CBS_len(&write_seq) != sizeof(s3->write_sequence) || @@ -229,7 +210,6 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { !CBS_get_asn1(&seq, &read_iv, CBS_ASN1_OCTETSTRING) || !CBS_get_asn1(&seq, &write_iv, CBS_ASN1_OCTETSTRING) || !CBS_get_asn1_bool(&seq, &session_reused) || - !CBS_get_asn1_bool(&seq, &send_connection_binding) || !CBS_get_asn1_bool(&seq, &channel_id_valid)) { return false; } @@ -253,12 +233,6 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { CBS_len(&channel_id) != sizeof(s3->tlsext_channel_id) || !CBS_copy_bytes(&channel_id, s3->tlsext_channel_id, sizeof(s3->tlsext_channel_id)) || - !CBS_get_asn1_uint64(&seq, &options) || - !CBS_get_asn1_uint64(&seq, &mode) || - !CBS_get_asn1_uint64(&seq, &max_cert_list) || - !CBS_get_asn1_bool(&seq, &quiet_shutdown) || - !CBS_get_asn1_bool(&seq, &channel_id_enabled) || - !CBS_get_asn1_bool(&seq, &retain_only_sha256) || !CBS_get_asn1_bool(&seq, &token_binding_negotiated) || !CBS_get_asn1_uint64(&seq, &negotiated_token_binding_param) || !CBS_get_asn1_bool(&seq, &next_proto_neg_seen) || @@ -277,21 +251,14 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { return false; } - ssl->version = version; - ssl->conf_max_version = conf_max_version; - ssl->conf_min_version = conf_min_version; - ssl->max_send_fragment = max_send_fragment; + ssl->version = session->ssl_version; ssl->do_handshake = ssl_server_handshake; ssl->server = true; - ssl->options = options; - ssl->mode = mode; - ssl->max_cert_list = max_cert_list; s3->have_version = true; s3->hs->state = CBS_len(&transcript) == 0 ? state12_finish_server_handshake : state12_read_client_certificate; s3->session_reused = session_reused; - s3->send_connection_binding = send_connection_binding; s3->tlsext_channel_id_valid = channel_id_valid; s3->next_proto_negotiated.CopyFrom(next_proto); s3->alpn_selected.CopyFrom(alpn); @@ -307,11 +274,8 @@ bool SSL_apply_handback(SSL *ssl, Span<const uint8_t> handback) { s3->hostname.reset(hostname_str); } - ssl->quiet_shutdown = quiet_shutdown; - ssl->tlsext_channel_id_enabled = channel_id_enabled; - ssl->retain_only_sha256_of_client_certs = retain_only_sha256; - ssl->token_binding_negotiated = token_binding_negotiated; - ssl->negotiated_token_binding_param = + s3->token_binding_negotiated = token_binding_negotiated; + s3->negotiated_token_binding_param = static_cast<uint8_t>(negotiated_token_binding_param); s3->hs->next_proto_neg_seen = next_proto_neg_seen; s3->hs->wait = ssl_hs_flush; diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc index 0b352c2b..087645d2 100644 --- a/src/ssl/handshake_client.cc +++ b/src/ssl/handshake_client.cc @@ -740,7 +740,7 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) { return ssl_hs_error; } - if (ssl->token_binding_negotiated && + if (ssl->s3->token_binding_negotiated && (!hs->extended_master_secret || !ssl->s3->send_connection_binding)) { OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI); ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc index 5f2f41fd..7ade8fca 100644 --- a/src/ssl/handshake_server.cc +++ b/src/ssl/handshake_server.cc @@ -334,7 +334,7 @@ static const SSL_CIPHER *ssl3_choose_cipher( SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello, const struct ssl_cipher_preference_list_st *server_pref) { SSL *const ssl = hs->ssl; - STACK_OF(SSL_CIPHER) *prio, *allow; + const STACK_OF(SSL_CIPHER) *prio, *allow; // in_group_flags will either be NULL, or will point to an array of bytes // which indicate equal-preference groups in the |prio| stack. See the // comment about |in_group_flags| in the |ssl_cipher_preference_list_st| diff --git a/src/ssl/internal.h b/src/ssl/internal.h index e884b636..f4dc96f1 100644 --- a/src/ssl/internal.h +++ b/src/ssl/internal.h @@ -657,19 +657,26 @@ class SSLAEADContext { bool SuffixLen(size_t *out_suffix_len, size_t in_len, size_t extra_in_len) const; + // CiphertextLen calculates the total ciphertext length written by + // |SealScatter| and writes it to |*out_len|. It returns true on success and + // false on error. |in_len| and |extra_in_len| should equal the argument of + // the same names passed to |SealScatter|. + bool CiphertextLen(size_t *out_len, size_t in_len, size_t extra_in_len) const; + // Open authenticates and decrypts |in| in-place. On success, it sets |*out| // to the plaintext in |in| and returns true. Otherwise, it returns // false. The output will always be |ExplicitNonceLen| bytes ahead of |in|. bool Open(Span<uint8_t> *out, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], Span<uint8_t> in); + const uint8_t seqnum[8], Span<const uint8_t> header, + Span<uint8_t> in); // Seal encrypts and authenticates |in_len| bytes from |in| and writes the // result to |out|. It returns true on success and false on error. // // If |in| and |out| alias then |out| + |ExplicitNonceLen| must be == |in|. bool Seal(uint8_t *out, size_t *out_len, size_t max_out, uint8_t type, - uint16_t record_version, const uint8_t seqnum[8], const uint8_t *in, - size_t in_len); + uint16_t record_version, const uint8_t seqnum[8], + Span<const uint8_t> header, const uint8_t *in, size_t in_len); // SealScatter encrypts and authenticates |in_len| bytes from |in| and splits // the result between |out_prefix|, |out| and |out_suffix|. It returns one on @@ -688,17 +695,20 @@ class SSLAEADContext { // alias anything. bool SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], const uint8_t *in, size_t in_len, - const uint8_t *extra_in, size_t extra_in_len); + const uint8_t seqnum[8], Span<const uint8_t> header, + const uint8_t *in, size_t in_len, const uint8_t *extra_in, + size_t extra_in_len); bool GetIV(const uint8_t **out_iv, size_t *out_iv_len) const; private: - // GetAdditionalData writes the additional data into |out| and returns the - // number of bytes written. - size_t GetAdditionalData(uint8_t out[13], uint8_t type, - uint16_t record_version, const uint8_t seqnum[8], - size_t plaintext_len, size_t ciphertext_len); + // GetAdditionalData returns the additional data, writing into |storage| if + // necessary. + Span<const uint8_t> GetAdditionalData(uint8_t storage[13], uint8_t type, + uint16_t record_version, + const uint8_t seqnum[8], + size_t plaintext_len, + Span<const uint8_t> header); const SSL_CIPHER *cipher_; ScopedEVP_AEAD_CTX ctx_; @@ -717,6 +727,9 @@ class SSLAEADContext { // randomly generated, rather than derived from the sequence // number. bool random_variable_nonce_ : 1; + // xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the + // variable nonce rather than prepended. + bool xor_fixed_nonce_ : 1; // omit_length_in_ad_ is true if the length should be omitted in the // AEAD's ad parameter. bool omit_length_in_ad_ : 1; @@ -725,12 +738,8 @@ class SSLAEADContext { bool omit_version_in_ad_ : 1; // omit_ad_ is true if the AEAD's ad parameter should be omitted. bool omit_ad_ : 1; - // tls13_ad_ is true if the AEAD's ad parameter should be based on the - // TLS 1.3 format. - bool tls13_ad_ : 1; - // xor_fixed_nonce_ is true if the fixed nonce should be XOR'd into the - // variable nonce rather than prepended. - bool xor_fixed_nonce_ : 1; + // ad_is_header_ is true if the AEAD's ad parameter is the record header. + bool ad_is_header_ : 1; }; @@ -2299,6 +2308,10 @@ struct SSL3_STATE { // key_update_count is the number of consecutive KeyUpdates received. uint8_t key_update_count = 0; + // The negotiated Token Binding key parameter. Only valid if + // |token_binding_negotiated| is set. + uint8_t negotiated_token_binding_param = 0; + // skip_early_data instructs the record layer to skip unexpected early data // messages when 0RTT is rejected. bool skip_early_data:1; @@ -2348,6 +2361,9 @@ struct SSL3_STATE { // fired, were it not a draft. bool draft_downgrade:1; + // token_binding_negotiated is set if Token Binding was negotiated. + bool token_binding_negotiated:1; + // hs_buf is the buffer of handshake data to process. UniquePtr<BUF_MEM> hs_buf; @@ -2671,10 +2687,6 @@ struct SSLConnection { uint8_t *token_binding_params; size_t token_binding_params_len; - // The negotiated Token Binding key parameter. Only valid if - // |token_binding_negotiated| is set. - uint8_t negotiated_token_binding_param; - // Contains the QUIC transport params that this endpoint will send. uint8_t *quic_transport_params; size_t quic_transport_params_len; @@ -2706,9 +2718,6 @@ struct SSLConnection { // we'll advertise support. bool tlsext_channel_id_enabled:1; - // token_binding_negotiated is set if Token Binding was negotiated. - bool token_binding_negotiated:1; - // retain_only_sha256_of_client_certs is true if we should compute the SHA256 // hash of the peer's certificate and then discard it to save memory and // session space. Only effective on the server side. diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc index a3fc8d7b..baa5a174 100644 --- a/src/ssl/s3_lib.cc +++ b/src/ssl/s3_lib.cc @@ -177,7 +177,8 @@ SSL3_STATE::SSL3_STATE() key_update_pending(false), wpend_pending(false), early_data_accepted(false), - draft_downgrade(false) {} + draft_downgrade(false), + token_binding_negotiated(false) {} SSL3_STATE::~SSL3_STATE() {} diff --git a/src/ssl/ssl_aead_ctx.cc b/src/ssl/ssl_aead_ctx.cc index e6b3ee93..363c959e 100644 --- a/src/ssl/ssl_aead_ctx.cc +++ b/src/ssl/ssl_aead_ctx.cc @@ -40,11 +40,11 @@ SSLAEADContext::SSLAEADContext(uint16_t version_arg, bool is_dtls_arg, is_dtls_(is_dtls_arg), variable_nonce_included_in_record_(false), random_variable_nonce_(false), + xor_fixed_nonce_(false), omit_length_in_ad_(false), omit_version_in_ad_(false), omit_ad_(false), - tls13_ad_(false), - xor_fixed_nonce_(false) { + ad_is_header_(false) { OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_)); } @@ -136,7 +136,7 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create( aead_ctx->variable_nonce_len_ = 8; aead_ctx->variable_nonce_included_in_record_ = false; if (ssl_is_draft28(version)) { - aead_ctx->tls13_ad_ = true; + aead_ctx->ad_is_header_ = true; } else { aead_ctx->omit_ad_ = true; } @@ -198,6 +198,22 @@ bool SSLAEADContext::SuffixLen(size_t *out_suffix_len, const size_t in_len, extra_in_len); } +bool SSLAEADContext::CiphertextLen(size_t *out_len, const size_t in_len, + const size_t extra_in_len) const { + size_t len; + if (!SuffixLen(&len, in_len, extra_in_len)) { + return false; + } + len += ExplicitNonceLen(); + len += in_len; + if (len < in_len || len >= 0xffff) { + OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW); + return false; + } + *out_len = len; + return true; +} + size_t SSLAEADContext::MaxOverhead() const { return ExplicitNonceLen() + (is_null_cipher() || FUZZER_MODE @@ -205,38 +221,34 @@ size_t SSLAEADContext::MaxOverhead() const { : EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(ctx_.get()))); } -size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type, - uint16_t record_version, - const uint8_t seqnum[8], - size_t plaintext_len, - size_t ciphertext_len) { - if (omit_ad_) { - return 0; +Span<const uint8_t> SSLAEADContext::GetAdditionalData( + uint8_t storage[13], uint8_t type, uint16_t record_version, + const uint8_t seqnum[8], size_t plaintext_len, Span<const uint8_t> header) { + if (ad_is_header_) { + return header; } - size_t len = 0; - if (!tls13_ad_) { - OPENSSL_memcpy(out, seqnum, 8); - len += 8; + if (omit_ad_) { + return {}; } - out[len++] = type; + + OPENSSL_memcpy(storage, seqnum, 8); + size_t len = 8; + storage[len++] = type; if (!omit_version_in_ad_) { - out[len++] = static_cast<uint8_t>((record_version >> 8)); - out[len++] = static_cast<uint8_t>(record_version); + storage[len++] = static_cast<uint8_t>((record_version >> 8)); + storage[len++] = static_cast<uint8_t>(record_version); } - if (tls13_ad_) { - out[len++] = static_cast<uint8_t>((ciphertext_len >> 8)); - out[len++] = static_cast<uint8_t>(ciphertext_len); - } else if (!omit_length_in_ad_) { - out[len++] = static_cast<uint8_t>((plaintext_len >> 8)); - out[len++] = static_cast<uint8_t>(plaintext_len); + if (!omit_length_in_ad_) { + storage[len++] = static_cast<uint8_t>((plaintext_len >> 8)); + storage[len++] = static_cast<uint8_t>(plaintext_len); } - return len; + return MakeConstSpan(storage, len); } bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type, uint16_t record_version, const uint8_t seqnum[8], - Span<uint8_t> in) { + Span<const uint8_t> header, Span<uint8_t> in) { if (is_null_cipher() || FUZZER_MODE) { // Handle the initial NULL cipher. *out = in; @@ -255,9 +267,10 @@ bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type, } plaintext_len = in.size() - overhead; } - uint8_t ad[13]; - size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, - plaintext_len, in.size()); + + uint8_t ad_storage[13]; + Span<const uint8_t> ad = GetAdditionalData(ad_storage, type, record_version, + seqnum, plaintext_len, header); // Assemble the nonce. uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; @@ -298,7 +311,8 @@ bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type, // Decrypt in-place. size_t len; if (!EVP_AEAD_CTX_open(ctx_.get(), in.data(), &len, in.size(), nonce, - nonce_len, in.data(), in.size(), ad, ad_len)) { + nonce_len, in.data(), in.size(), ad.data(), + ad.size())) { return false; } *out = in.subspan(0, len); @@ -308,7 +322,8 @@ bool SSLAEADContext::Open(Span<uint8_t> *out, uint8_t type, bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], const uint8_t *in, + const uint8_t seqnum[8], + Span<const uint8_t> header, const uint8_t *in, size_t in_len, const uint8_t *extra_in, size_t extra_in_len) { const size_t prefix_len = ExplicitNonceLen(); @@ -331,9 +346,9 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, return true; } - uint8_t ad[13]; - size_t ad_len = GetAdditionalData(ad, type, record_version, seqnum, in_len, - in_len + suffix_len); + uint8_t ad_storage[13]; + Span<const uint8_t> ad = GetAdditionalData(ad_storage, type, record_version, + seqnum, in_len, header); // Assemble the nonce. uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH]; @@ -384,15 +399,15 @@ bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out, size_t written_suffix_len; bool result = !!EVP_AEAD_CTX_seal_scatter( ctx_.get(), out, out_suffix, &written_suffix_len, suffix_len, nonce, - nonce_len, in, in_len, extra_in, extra_in_len, ad, ad_len); + nonce_len, in, in_len, extra_in, extra_in_len, ad.data(), ad.size()); assert(!result || written_suffix_len == suffix_len); return result; } bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len, uint8_t type, uint16_t record_version, - const uint8_t seqnum[8], const uint8_t *in, - size_t in_len) { + const uint8_t seqnum[8], Span<const uint8_t> header, + const uint8_t *in, size_t in_len) { const size_t prefix_len = ExplicitNonceLen(); size_t suffix_len; if (!SuffixLen(&suffix_len, in_len, 0)) { @@ -410,7 +425,7 @@ bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len, } if (!SealScatter(out, out + prefix_len, out + prefix_len + in_len, type, - record_version, seqnum, in, in_len, 0, 0)) { + record_version, seqnum, header, in, in_len, 0, 0)) { return false; } *out_len = prefix_len + in_len + suffix_len; diff --git a/src/ssl/ssl_file.cc b/src/ssl/ssl_file.cc index bafa64ab..ca4b0be2 100644 --- a/src/ssl/ssl_file.cc +++ b/src/ssl/ssl_file.cc @@ -165,6 +165,7 @@ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file) { } // Check for duplicates. + sk_X509_NAME_sort(sk); if (sk_X509_NAME_find(sk, NULL, xn)) { continue; } @@ -223,6 +224,7 @@ int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack, } // Check for duplicates. + sk_X509_NAME_sort(stack); if (sk_X509_NAME_find(stack, NULL, xn)) { continue; } diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc index 2a076c33..c7f6f88f 100644 --- a/src/ssl/ssl_key_share.cc +++ b/src/ssl/ssl_key_share.cc @@ -248,11 +248,11 @@ UniquePtr<SSLKeyShare> SSLKeyShare::Create(uint16_t group_id) { UniquePtr<SSLKeyShare> SSLKeyShare::Create(CBS *in) { uint64_t group; - if (!CBS_get_asn1_uint64(in, &group)) { + if (!CBS_get_asn1_uint64(in, &group) || group > 0xffff) { return nullptr; } - UniquePtr<SSLKeyShare> key_share = Create(static_cast<uint64_t>(group)); - if (!key_share->Deserialize(in)) { + UniquePtr<SSLKeyShare> key_share = Create(static_cast<uint16_t>(group)); + if (!key_share || !key_share->Deserialize(in)) { return nullptr; } return key_share; diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc index 63125042..14fb0ff5 100644 --- a/src/ssl/ssl_lib.cc +++ b/src/ssl/ssl_lib.cc @@ -2164,11 +2164,11 @@ int SSL_set_token_binding_params(SSL *ssl, const uint8_t *params, size_t len) { } int SSL_is_token_binding_negotiated(const SSL *ssl) { - return ssl->token_binding_negotiated; + return ssl->s3->token_binding_negotiated; } uint8_t SSL_get_negotiated_token_binding_param(const SSL *ssl) { - return ssl->negotiated_token_binding_param; + return ssl->s3->negotiated_token_binding_param; } size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) { diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc index 34e7b317..bc2c14c1 100644 --- a/src/ssl/ssl_session.cc +++ b/src/ssl/ssl_session.cc @@ -990,6 +990,10 @@ uint32_t SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session) { return session->tlsext_tick_lifetime_hint; } +const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *session) { + return session->cipher; +} + SSL_SESSION *SSL_magic_pending_session_ptr(void) { return (SSL_SESSION *)&g_pending_session_magic; } diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc index 97c0c4b9..2d3a6646 100644 --- a/src/ssl/t1_lib.cc +++ b/src/ssl/t1_lib.cc @@ -2528,8 +2528,8 @@ static bool ext_token_binding_parse_serverhello(SSL_HANDSHAKE *hs, for (size_t i = 0; i < ssl->token_binding_params_len; ++i) { if (param == ssl->token_binding_params[i]) { - ssl->negotiated_token_binding_param = param; - ssl->token_binding_negotiated = true; + ssl->s3->negotiated_token_binding_param = param; + ssl->s3->token_binding_negotiated = true; return true; } } @@ -2547,7 +2547,7 @@ static bool select_tb_param(SSL *ssl, Span<const uint8_t> peer_params) { uint8_t tb_param = ssl->token_binding_params[i]; for (uint8_t peer_param : peer_params) { if (tb_param == peer_param) { - ssl->negotiated_token_binding_param = tb_param; + ssl->s3->negotiated_token_binding_param = tb_param; return true; } } @@ -2587,14 +2587,14 @@ static bool ext_token_binding_parse_clienthello(SSL_HANDSHAKE *hs, return true; } - ssl->token_binding_negotiated = true; + ssl->s3->token_binding_negotiated = true; return true; } static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { SSL *const ssl = hs->ssl; - if (!ssl->token_binding_negotiated) { + if (!ssl->s3->token_binding_negotiated) { return true; } @@ -2603,7 +2603,7 @@ static bool ext_token_binding_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { !CBB_add_u16_length_prefixed(out, &contents) || !CBB_add_u16(&contents, hs->negotiated_token_binding_version) || !CBB_add_u8_length_prefixed(&contents, ¶ms) || - !CBB_add_u8(¶ms, ssl->negotiated_token_binding_param) || + !CBB_add_u8(¶ms, ssl->s3->negotiated_token_binding_param) || !CBB_flush(out)) { return false; } @@ -3220,7 +3220,7 @@ static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs, static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) { SSL *const ssl = hs->ssl; - if (ssl->token_binding_negotiated && + if (ssl->s3->token_binding_negotiated && !(SSL_get_secure_renegotiation_support(ssl) && SSL_get_extms_support(ssl))) { OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_TB_WITHOUT_EMS_OR_RI); diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc index aa054563..6e328b89 100644 --- a/src/ssl/tls13_client.cc +++ b/src/ssl/tls13_client.cc @@ -436,7 +436,7 @@ static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) { return ssl_hs_error; } if (ssl->s3->tlsext_channel_id_valid || hs->received_custom_extension || - ssl->token_binding_negotiated) { + ssl->s3->token_binding_negotiated) { OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION_ON_EARLY_DATA); return ssl_hs_error; } diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc index 3bd67866..9d7f5e07 100644 --- a/src/ssl/tls13_server.cc +++ b/src/ssl/tls13_server.cc @@ -391,7 +391,7 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { // Channel ID is incompatible with 0-RTT. !ssl->s3->tlsext_channel_id_valid && // If Token Binding is negotiated, reject 0-RTT. - !ssl->token_binding_negotiated && + !ssl->s3->token_binding_negotiated && // Custom extensions is incompatible with 0-RTT. hs->custom_extensions.received == 0 && // The negotiated ALPN must match the one in the ticket. diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc index 3152e7a2..a2e4a20f 100644 --- a/src/ssl/tls_record.cc +++ b/src/ssl/tls_record.cc @@ -258,8 +258,8 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, return ssl_open_record_partial; } - ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, - in.subspan(0, SSL3_RT_HEADER_LENGTH)); + Span<const uint8_t> header = in.subspan(0, SSL3_RT_HEADER_LENGTH); + ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, header); *out_consumed = in.size() - CBS_len(&cbs); @@ -288,7 +288,7 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, // Decrypt the body in-place. if (!ssl->s3->aead_read_ctx->Open( - out, type, version, ssl->s3->read_sequence, + out, type, version, ssl->s3->read_sequence, header, MakeSpan(const_cast<uint8_t *>(CBS_data(&body)), CBS_len(&body)))) { if (ssl->s3->skip_early_data && !ssl->s3->aead_read_ctx->is_null_cipher()) { ERR_clear_error(); @@ -376,27 +376,22 @@ ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, uint8_t *out_suffix, uint8_t type, const uint8_t *in, const size_t in_len) { + SSLAEADContext *aead = ssl->s3->aead_write_ctx.get(); uint8_t *extra_in = NULL; size_t extra_in_len = 0; - if (!ssl->s3->aead_write_ctx->is_null_cipher() && - ssl->s3->aead_write_ctx->ProtocolVersion() >= TLS1_3_VERSION) { + if (!aead->is_null_cipher() && + aead->ProtocolVersion() >= TLS1_3_VERSION) { // TLS 1.3 hides the actual record type inside the encrypted data. extra_in = &type; extra_in_len = 1; } - size_t suffix_len; - if (!ssl->s3->aead_write_ctx->SuffixLen(&suffix_len, in_len, extra_in_len)) { - OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); - return 0; - } - size_t ciphertext_len = - ssl->s3->aead_write_ctx->ExplicitNonceLen() + suffix_len; - if (ciphertext_len + in_len < ciphertext_len) { + size_t suffix_len, ciphertext_len; + if (!aead->SuffixLen(&suffix_len, in_len, extra_in_len) || + !aead->CiphertextLen(&ciphertext_len, in_len, extra_in_len)) { OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE); return 0; } - ciphertext_len += in_len; assert(in == out || !buffers_alias(in, in_len, out, in_len)); assert(!buffers_alias(in, in_len, out_prefix, ssl_record_prefix_len(ssl))); @@ -408,28 +403,27 @@ static int do_seal_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out, out_prefix[0] = type; } - uint16_t record_version = ssl->s3->aead_write_ctx->RecordVersion(); + uint16_t record_version = aead->RecordVersion(); out_prefix[1] = record_version >> 8; out_prefix[2] = record_version & 0xff; out_prefix[3] = ciphertext_len >> 8; out_prefix[4] = ciphertext_len & 0xff; + Span<const uint8_t> header = MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH); - if (!ssl->s3->aead_write_ctx->SealScatter( - out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, out_prefix[0], - record_version, ssl->s3->write_sequence, in, in_len, extra_in, - extra_in_len) || + if (!aead->SealScatter(out_prefix + SSL3_RT_HEADER_LENGTH, out, out_suffix, + out_prefix[0], record_version, ssl->s3->write_sequence, + header, in, in_len, extra_in, extra_in_len) || !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) { return 0; } - ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, - MakeSpan(out_prefix, SSL3_RT_HEADER_LENGTH)); + ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, header); return 1; } static size_t tls_seal_scatter_prefix_len(const SSL *ssl, uint8_t type, - size_t in_len) { + size_t in_len) { size_t ret = SSL3_RT_HEADER_LENGTH; if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 && ssl_needs_record_splitting(ssl)) { diff --git a/src/tool/speed.cc b/src/tool/speed.cc index d95fa9e8..ed3484a9 100644 --- a/src/tool/speed.cc +++ b/src/tool/speed.cc @@ -142,68 +142,89 @@ static bool TimeFunction(TimeResults *results, std::function<bool()> func) { return true; } -static bool SpeedRSA(const std::string &key_name, RSA *key, - const std::string &selected) { - if (!selected.empty() && key_name.find(selected) == std::string::npos) { +static bool SpeedRSA(const std::string &selected) { + if (!selected.empty() && selected.find("RSA") == std::string::npos) { return true; } - std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key)]); - const uint8_t fake_sha256_hash[32] = {0}; - unsigned sig_len; + static const struct { + const char *name; + const uint8_t *key; + const size_t key_len; + } kRSAKeys[] = { + {"RSA 2048", kDERRSAPrivate2048, kDERRSAPrivate2048Len}, + {"RSA 4096", kDERRSAPrivate4096, kDERRSAPrivate4096Len}, + }; - TimeResults results; - if (!TimeFunction(&results, - [key, &sig, &fake_sha256_hash, &sig_len]() -> bool { - // Usually during RSA signing we're using a long-lived |RSA| that has - // already had all of its |BN_MONT_CTX|s constructed, so it makes - // sense to use |key| directly here. - return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), - sig.get(), &sig_len, key); - })) { - fprintf(stderr, "RSA_sign failed.\n"); - ERR_print_errors_fp(stderr); - return false; - } - results.Print(key_name + " signing"); + for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kRSAKeys); i++) { + const std::string name = kRSAKeys[i].name; - if (!TimeFunction(&results, - [key, &fake_sha256_hash, &sig, sig_len]() -> bool { - return RSA_verify(NID_sha256, fake_sha256_hash, - sizeof(fake_sha256_hash), sig.get(), sig_len, key); - })) { - fprintf(stderr, "RSA_verify failed.\n"); - ERR_print_errors_fp(stderr); - return false; - } - results.Print(key_name + " verify (same key)"); - - if (!TimeFunction(&results, - [key, &fake_sha256_hash, &sig, sig_len]() -> bool { - // Usually during RSA verification we have to parse an RSA key from a - // certificate or similar, in which case we'd need to construct a new - // RSA key, with a new |BN_MONT_CTX| for the public modulus. If we were - // to use |key| directly instead, then these costs wouldn't be - // accounted for. - bssl::UniquePtr<RSA> verify_key(RSA_new()); - if (!verify_key) { - return false; - } - verify_key->n = BN_dup(key->n); - verify_key->e = BN_dup(key->e); - if (!verify_key->n || - !verify_key->e) { - return false; - } - return RSA_verify(NID_sha256, fake_sha256_hash, - sizeof(fake_sha256_hash), sig.get(), sig_len, - verify_key.get()); - })) { - fprintf(stderr, "RSA_verify failed.\n"); - ERR_print_errors_fp(stderr); - return false; + bssl::UniquePtr<RSA> key( + RSA_private_key_from_bytes(kRSAKeys[i].key, kRSAKeys[i].key_len)); + if (key == nullptr) { + fprintf(stderr, "Failed to parse %s key.\n", name.c_str()); + ERR_print_errors_fp(stderr); + return false; + } + + std::unique_ptr<uint8_t[]> sig(new uint8_t[RSA_size(key.get())]); + const uint8_t fake_sha256_hash[32] = {0}; + unsigned sig_len; + + TimeResults results; + if (!TimeFunction(&results, + [&key, &sig, &fake_sha256_hash, &sig_len]() -> bool { + // Usually during RSA signing we're using a long-lived |RSA| that has + // already had all of its |BN_MONT_CTX|s constructed, so it makes + // sense to use |key| directly here. + return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), + sig.get(), &sig_len, key.get()); + })) { + fprintf(stderr, "RSA_sign failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + results.Print(name + " signing"); + + if (!TimeFunction(&results, + [&key, &fake_sha256_hash, &sig, sig_len]() -> bool { + return RSA_verify( + NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash), + sig.get(), sig_len, key.get()); + })) { + fprintf(stderr, "RSA_verify failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + results.Print(name + " verify (same key)"); + + if (!TimeFunction(&results, + [&key, &fake_sha256_hash, &sig, sig_len]() -> bool { + // Usually during RSA verification we have to parse an RSA key from a + // certificate or similar, in which case we'd need to construct a new + // RSA key, with a new |BN_MONT_CTX| for the public modulus. If we + // were to use |key| directly instead, then these costs wouldn't be + // accounted for. + bssl::UniquePtr<RSA> verify_key(RSA_new()); + if (!verify_key) { + return false; + } + verify_key->n = BN_dup(key->n); + verify_key->e = BN_dup(key->e); + if (!verify_key->n || + !verify_key->e) { + return false; + } + return RSA_verify(NID_sha256, fake_sha256_hash, + sizeof(fake_sha256_hash), sig.get(), sig_len, + verify_key.get()); + })) { + fprintf(stderr, "RSA_verify failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + results.Print(name + " verify (fresh key)"); } - results.Print(key_name + " verify (fresh key)"); return true; } @@ -381,7 +402,7 @@ static bool SpeedAEADOpen(const EVP_AEAD *aead, const std::string &name, static bool SpeedHashChunk(const EVP_MD *md, const std::string &name, size_t chunk_len) { - EVP_MD_CTX *ctx = EVP_MD_CTX_create(); + bssl::ScopedEVP_MD_CTX ctx; uint8_t scratch[8192]; if (chunk_len > sizeof(scratch)) { @@ -389,13 +410,13 @@ static bool SpeedHashChunk(const EVP_MD *md, const std::string &name, } TimeResults results; - if (!TimeFunction(&results, [ctx, md, chunk_len, &scratch]() -> bool { + if (!TimeFunction(&results, [&ctx, md, chunk_len, &scratch]() -> bool { uint8_t digest[EVP_MAX_MD_SIZE]; unsigned int md_len; - return EVP_DigestInit_ex(ctx, md, NULL /* ENGINE */) && - EVP_DigestUpdate(ctx, scratch, chunk_len) && - EVP_DigestFinal_ex(ctx, digest, &md_len); + return EVP_DigestInit_ex(ctx.get(), md, NULL /* ENGINE */) && + EVP_DigestUpdate(ctx.get(), scratch, chunk_len) && + EVP_DigestFinal_ex(ctx.get(), digest, &md_len); })) { fprintf(stderr, "EVP_DigestInit_ex failed.\n"); ERR_print_errors_fp(stderr); @@ -403,9 +424,6 @@ static bool SpeedHashChunk(const EVP_MD *md, const std::string &name, } results.PrintWithBytes(name, chunk_len); - - EVP_MD_CTX_destroy(ctx); - return true; } static bool SpeedHash(const EVP_MD *md, const std::string &name, @@ -745,32 +763,6 @@ bool Speed(const std::vector<std::string> &args) { g_timeout_seconds = atoi(args_map["-timeout"].c_str()); } - bssl::UniquePtr<RSA> key( - RSA_private_key_from_bytes(kDERRSAPrivate2048, kDERRSAPrivate2048Len)); - if (key == nullptr) { - fprintf(stderr, "Failed to parse RSA key.\n"); - ERR_print_errors_fp(stderr); - return false; - } - - if (!SpeedRSA("RSA 2048", key.get(), selected)) { - return false; - } - - key.reset( - RSA_private_key_from_bytes(kDERRSAPrivate4096, kDERRSAPrivate4096Len)); - if (key == nullptr) { - fprintf(stderr, "Failed to parse 4096-bit RSA key.\n"); - ERR_print_errors_fp(stderr); - return 1; - } - - if (!SpeedRSA("RSA 4096", key.get(), selected)) { - return false; - } - - key.reset(); - // kTLSADLen is the number of bytes of additional data that TLS passes to // AEADs. static const size_t kTLSADLen = 13; @@ -780,7 +772,8 @@ bool Speed(const std::vector<std::string> &args) { // knowledge in them and construct a couple of the AD bytes internally. static const size_t kLegacyADLen = kTLSADLen - 2; - if (!SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) || + if (!SpeedRSA(selected) || + !SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) || !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) || !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen, selected) || diff --git a/src/util/generate_build_files.py b/src/util/generate_build_files.py index f2b10dec..caed812b 100644 --- a/src/util/generate_build_files.py +++ b/src/util/generate_build_files.py @@ -294,11 +294,13 @@ class GN(object): out.write(self.header) self.PrintVariableSection(out, 'crypto_sources', - files['crypto'] + files['crypto_headers'] + + files['crypto'] + files['crypto_internal_headers']) + self.PrintVariableSection(out, 'crypto_headers', + files['crypto_headers']) self.PrintVariableSection(out, 'ssl_sources', - files['ssl'] + files['ssl_headers'] + - files['ssl_internal_headers']) + files['ssl'] + files['ssl_internal_headers']) + self.PrintVariableSection(out, 'ssl_headers', files['ssl_headers']) for ((osname, arch), asm_files) in asm_outputs: self.PrintVariableSection( |