external/boringssl: Sync to 348f0d8db9c2a0eca0503ba654020209c579d552. am: 8437709157
am: 05e49fc79f
Change-Id: Ib0c7d49c20b9511327e60ab147940a127a6340d0
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index bcea3ff..b657833 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-9bbdf5832de8a2d395303c669b594fc61c791f4d
+348f0d8db9c2a0eca0503ba654020209c579d552
diff --git a/src/crypto/fipsmodule/ec/p256-x86_64_test.cc b/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
index 4600c76..a802bfb 100644
--- a/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
+++ b/src/crypto/fipsmodule/ec/p256-x86_64_test.cc
@@ -27,6 +27,7 @@
#include <openssl/mem.h>
#include "../bn/internal.h"
+#include "../../internal.h"
#include "../../test/file_test.h"
#include "../../test/test_util.h"
#include "p256-x86_64.h"
@@ -39,7 +40,7 @@
TEST(P256_X86_64Test, SelectW5) {
// Fill a table with some garbage input.
- P256_POINT table[16];
+ alignas(64) P256_POINT table[16];
for (size_t i = 0; i < 16; i++) {
OPENSSL_memset(table[i].X, 3 * i, sizeof(table[i].X));
OPENSSL_memset(table[i].Y, 3 * i + 1, sizeof(table[i].Y));
@@ -64,7 +65,7 @@
TEST(P256_X86_64Test, SelectW7) {
// Fill a table with some garbage input.
- P256_POINT_AFFINE table[64];
+ alignas(64) P256_POINT_AFFINE table[64];
for (size_t i = 0; i < 64; i++) {
OPENSSL_memset(table[i].X, 2 * i, sizeof(table[i].X));
OPENSSL_memset(table[i].Y, 2 * i + 1, sizeof(table[i].Y));
diff --git a/src/crypto/obj/obj_dat.h b/src/crypto/obj/obj_dat.h
index b3da0e8..dceaf03 100644
--- a/src/crypto/obj/obj_dat.h
+++ b/src/crypto/obj/obj_dat.h
@@ -57,7 +57,7 @@
/* This file is generated by crypto/obj/objects.go. */
-#define NUM_NID 950
+#define NUM_NID 959
static const uint8_t kObjectData[] = {
/* NID_rsadsi */
@@ -3444,6 +3444,16 @@
{"dh-cofactor-kdf", "dh-cofactor-kdf", NID_dh_cofactor_kdf, 0, NULL, 0},
{"X25519", "X25519", NID_X25519, 0, NULL, 0},
{"ED25519", "ED25519", NID_ED25519, 3, &kObjectData[6175], 0},
+ {"ChaCha20-Poly1305", "chacha20-poly1305", NID_chacha20_poly1305, 0, NULL,
+ 0},
+ {"KxRSA", "kx-rsa", NID_kx_rsa, 0, NULL, 0},
+ {"KxECDHE", "kx-ecdhe", NID_kx_ecdhe, 0, NULL, 0},
+ {"KxPSK", "kx-psk", NID_kx_psk, 0, NULL, 0},
+ {"AuthRSA", "auth-rsa", NID_auth_rsa, 0, NULL, 0},
+ {"AuthECDSA", "auth-ecdsa", NID_auth_ecdsa, 0, NULL, 0},
+ {"AuthPSK", "auth-psk", NID_auth_psk, 0, NULL, 0},
+ {"KxANY", "kx-any", NID_kx_any, 0, NULL, 0},
+ {"AuthANY", "auth-any", NID_auth_any, 0, NULL, 0},
};
static const unsigned kNIDsInShortNameOrder[] = {
@@ -3474,6 +3484,10 @@
426 /* AES-256-ECB */,
428 /* AES-256-OFB */,
914 /* AES-256-XTS */,
+ 958 /* AuthANY */,
+ 955 /* AuthECDSA */,
+ 956 /* AuthPSK */,
+ 954 /* AuthRSA */,
91 /* BF-CBC */,
93 /* BF-CFB */,
92 /* BF-ECB */,
@@ -3505,6 +3519,7 @@
13 /* CN */,
141 /* CRLReason */,
417 /* CSPName */,
+ 950 /* ChaCha20-Poly1305 */,
367 /* CrlID */,
391 /* DC */,
31 /* DES-CBC */,
@@ -3547,6 +3562,10 @@
645 /* ITU-T */,
646 /* JOINT-ISO-ITU-T */,
773 /* KISA */,
+ 957 /* KxANY */,
+ 952 /* KxECDHE */,
+ 953 /* KxPSK */,
+ 951 /* KxRSA */,
15 /* L */,
856 /* LocalKeySet */,
3 /* MD2 */,
@@ -4570,6 +4589,10 @@
484 /* associatedDomain */,
485 /* associatedName */,
501 /* audio */,
+ 958 /* auth-any */,
+ 955 /* auth-ecdsa */,
+ 956 /* auth-psk */,
+ 954 /* auth-rsa */,
882 /* authorityRevocationList */,
91 /* bf-cbc */,
93 /* bf-cfb */,
@@ -4640,6 +4663,7 @@
677 /* certicom-arc */,
517 /* certificate extensions */,
883 /* certificateRevocationList */,
+ 950 /* chacha20-poly1305 */,
54 /* challengePassword */,
407 /* characteristic-two-field */,
395 /* clearance */,
@@ -4982,6 +5006,10 @@
646 /* joint-iso-itu-t */,
150 /* keyBag */,
773 /* kisa */,
+ 957 /* kx-any */,
+ 952 /* kx-ecdhe */,
+ 953 /* kx-psk */,
+ 951 /* kx-rsa */,
477 /* lastModifiedBy */,
476 /* lastModifiedTime */,
157 /* localKeyID */,
diff --git a/src/crypto/obj/obj_mac.num b/src/crypto/obj/obj_mac.num
index 572a01b..6dbc0f1 100644
--- a/src/crypto/obj/obj_mac.num
+++ b/src/crypto/obj/obj_mac.num
@@ -938,3 +938,12 @@
dh_cofactor_kdf 947
X25519 948
ED25519 949
+chacha20_poly1305 950
+kx_rsa 951
+kx_ecdhe 952
+kx_psk 953
+auth_rsa 954
+auth_ecdsa 955
+auth_psk 956
+kx_any 957
+auth_any 958
diff --git a/src/crypto/obj/objects.txt b/src/crypto/obj/objects.txt
index 03056de..f1a6395 100644
--- a/src/crypto/obj/objects.txt
+++ b/src/crypto/obj/objects.txt
@@ -1336,3 +1336,19 @@
# See draft-ietf-curdle-pkix-04.
1 3 101 112 : ED25519
+
+ : ChaCha20-Poly1305 : chacha20-poly1305
+
+# NIDs for TLS 1.2 cipher suite key exchanges.
+ : KxRSA : kx-rsa
+ : KxECDHE : kx-ecdhe
+ : KxPSK : kx-psk
+
+# NIDs for TLS 1.2 cipher suite authentication types.
+ : AuthRSA : auth-rsa
+ : AuthECDSA : auth-ecdsa
+ : AuthPSK : auth-psk
+
+# TLS 1.3 cipher suites do not specify key exchange or authentication.
+ : KxANY : kx-any
+ : AuthANY : auth-any
diff --git a/src/crypto/pem/pem_pk8.c b/src/crypto/pem/pem_pk8.c
index 550661d..15385ec 100644
--- a/src/crypto/pem/pem_pk8.c
+++ b/src/crypto/pem/pem_pk8.c
@@ -176,6 +176,7 @@
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
+ OPENSSL_cleanse(psbuf, klen);
if (!p8inf)
return NULL;
ret = EVP_PKCS82PKEY(p8inf);
diff --git a/src/crypto/pem/pem_pkey.c b/src/crypto/pem/pem_pkey.c
index 058c031..9667550 100644
--- a/src/crypto/pem/pem_pkey.c
+++ b/src/crypto/pem/pem_pkey.c
@@ -114,6 +114,7 @@
}
p8inf = PKCS8_decrypt(p8, psbuf, klen);
X509_SIG_free(p8);
+ OPENSSL_cleanse(psbuf, klen);
if (!p8inf)
goto p8err;
ret = EVP_PKCS82PKEY(p8inf);
diff --git a/src/include/openssl/nid.h b/src/include/openssl/nid.h
index bc0ee33..afeb2de 100644
--- a/src/include/openssl/nid.h
+++ b/src/include/openssl/nid.h
@@ -4198,6 +4198,42 @@
#define NID_ED25519 949
#define OBJ_ED25519 1L, 3L, 101L, 112L
+#define SN_chacha20_poly1305 "ChaCha20-Poly1305"
+#define LN_chacha20_poly1305 "chacha20-poly1305"
+#define NID_chacha20_poly1305 950
+
+#define SN_kx_rsa "KxRSA"
+#define LN_kx_rsa "kx-rsa"
+#define NID_kx_rsa 951
+
+#define SN_kx_ecdhe "KxECDHE"
+#define LN_kx_ecdhe "kx-ecdhe"
+#define NID_kx_ecdhe 952
+
+#define SN_kx_psk "KxPSK"
+#define LN_kx_psk "kx-psk"
+#define NID_kx_psk 953
+
+#define SN_auth_rsa "AuthRSA"
+#define LN_auth_rsa "auth-rsa"
+#define NID_auth_rsa 954
+
+#define SN_auth_ecdsa "AuthECDSA"
+#define LN_auth_ecdsa "auth-ecdsa"
+#define NID_auth_ecdsa 955
+
+#define SN_auth_psk "AuthPSK"
+#define LN_auth_psk "auth-psk"
+#define NID_auth_psk 956
+
+#define SN_kx_any "KxANY"
+#define LN_kx_any "kx-any"
+#define NID_kx_any 957
+
+#define SN_auth_any "AuthANY"
+#define LN_auth_any "auth-any"
+#define NID_auth_any 958
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index a5ac325..63651b5 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -192,6 +192,10 @@
* crypto/x509. */
OPENSSL_EXPORT const SSL_METHOD *TLS_with_buffers_method(void);
+/* DTLS_with_buffers_method is like |DTLS_method|, but avoids all use of
+ * crypto/x509. */
+OPENSSL_EXPORT const SSL_METHOD *DTLS_with_buffers_method(void);
+
/* SSL_CTX_new returns a newly-allocated |SSL_CTX| with default settings or NULL
* on error. */
OPENSSL_EXPORT SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
@@ -1196,56 +1200,36 @@
* get the cipher suite value. */
OPENSSL_EXPORT uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_is_AES returns one if |cipher| uses AES (either GCM or CBC
- * mode). */
-OPENSSL_EXPORT int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_has_SHA1_HMAC returns one if |cipher| uses HMAC-SHA1. */
-OPENSSL_EXPORT int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_has_SHA256_HMAC returns one if |cipher| uses HMAC-SHA256. */
-OPENSSL_EXPORT int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_has_SHA384_HMAC returns one if |cipher| uses HMAC-SHA384. */
-OPENSSL_EXPORT int SSL_CIPHER_has_SHA384_HMAC(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_AEAD returns one if |cipher| uses an AEAD cipher. */
-OPENSSL_EXPORT int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_AESGCM returns one if |cipher| uses AES-GCM. */
-OPENSSL_EXPORT int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_AES128GCM returns one if |cipher| uses 128-bit AES-GCM. */
-OPENSSL_EXPORT int SSL_CIPHER_is_AES128GCM(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_AES128CBC returns one if |cipher| uses 128-bit AES in CBC
- * mode. */
-OPENSSL_EXPORT int SSL_CIPHER_is_AES128CBC(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_AES256CBC returns one if |cipher| uses 256-bit AES in CBC
- * mode. */
-OPENSSL_EXPORT int SSL_CIPHER_is_AES256CBC(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_CHACHA20POLY1305 returns one if |cipher| uses
- * CHACHA20_POLY1305. Note this includes both the RFC 7905 and
- * draft-agl-tls-chacha20poly1305-04 versions. */
-OPENSSL_EXPORT int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher);
-
-/* SSL_CIPHER_is_NULL returns one if |cipher| does not encrypt. */
-OPENSSL_EXPORT int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_is_aead returns one if |cipher| uses an AEAD cipher. */
+OPENSSL_EXPORT int SSL_CIPHER_is_aead(const SSL_CIPHER *cipher);
/* SSL_CIPHER_is_block_cipher returns one if |cipher| is a block cipher. */
OPENSSL_EXPORT int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_is_ECDSA returns one if |cipher| uses ECDSA. */
-OPENSSL_EXPORT int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_get_cipher_nid returns the NID for |cipher|'s bulk
+ * cipher. Possible values are |NID_aes_128_gcm|, |NID_aes_256_gcm|,
+ * |NID_chacha20_poly1305|, |NID_aes_128_cbc|, |NID_aes_256_cbc|, and
+ * |NID_des_ede3_cbc|. */
+OPENSSL_EXPORT int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_is_ECDHE returns one if |cipher| uses ECDHE. */
-OPENSSL_EXPORT int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_get_digest_nid returns the NID for |cipher|'s HMAC if it is a
+ * legacy cipher suite. For modern AEAD-based ciphers (see
+ * |SSL_CIPHER_is_aead|), it returns |NID_undef|.
+ *
+ * Note this function only returns the legacy HMAC digest, not the PRF hash. */
+OPENSSL_EXPORT int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_is_static_RSA returns one if |cipher| uses the static RSA key
- * exchange. */
-OPENSSL_EXPORT int SSL_CIPHER_is_static_RSA(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_get_kx_nid returns the NID for |cipher|'s key exchange. This may
+ * be |NID_kx_rsa|, |NID_kx_ecdhe|, or |NID_kx_psk| for TLS 1.2. In TLS 1.3,
+ * cipher suites do not specify the key exchange, so this function returns
+ * |NID_kx_any|. */
+OPENSSL_EXPORT int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_get_auth_nid returns the NID for |cipher|'s authentication
+ * type. This may be |NID_auth_rsa|, |NID_auth_ecdsa|, or |NID_auth_psk| for TLS
+ * 1.2. In TLS 1.3, cipher suites do not specify authentication, so this
+ * function returns |NID_auth_any|. */
+OPENSSL_EXPORT int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *cipher);
/* SSL_CIPHER_get_min_version returns the minimum protocol version required
* for |cipher|. */
@@ -1410,6 +1394,11 @@
* preference. */
OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
+/* SSL_CTX_cipher_in_group returns one if the |i|th cipher (see
+ * |SSL_CTX_get_ciphers|) is in the same equipreference group as the one
+ * following it and zero otherwise. */
+OPENSSL_EXPORT int SSL_CTX_cipher_in_group(const SSL_CTX *ctx, size_t i);
+
/* SSL_get_ciphers returns the cipher list for |ssl|, in order of preference. */
OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl);
@@ -3974,6 +3963,64 @@
* the session. */
OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
+/* TODO(davidben): Convert all the callers of these old |SSL_CIPHER| functions
+ * and remove them. */
+
+/* SSL_CIPHER_is_AEAD calls |SSL_CIPHER_is_aead|. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AES returns one if |cipher| uses AES (either GCM or CBC
+ * mode). Use |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_has_SHA1_HMAC returns one if |cipher| uses HMAC-SHA1. Use
+ * |SSL_CIPHER_get_digest_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_has_SHA256_HMAC returns one if |cipher| uses HMAC-SHA256. Use
+ * |SSL_CIPHER_get_digest_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_has_SHA384_HMAC returns one if |cipher| uses HMAC-SHA384. Use
+ * |SSL_CIPHER_get_digest_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_has_SHA384_HMAC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AESGCM returns one if |cipher| uses AES-GCM. Use
+ * |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AES128GCM returns one if |cipher| uses 128-bit AES-GCM. Use
+ * |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AES128GCM(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AES128CBC returns one if |cipher| uses 128-bit AES in CBC
+ * mode. Use |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AES128CBC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AES256CBC returns one if |cipher| uses 256-bit AES in CBC
+ * mode. Use |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AES256CBC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_CHACHA20POLY1305 returns one if |cipher| uses
+ * CHACHA20_POLY1305. Use |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_NULL returns one if |cipher| does not encrypt. Use
+ * |SSL_CIPHER_get_cipher_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_ECDSA returns one if |cipher| uses ECDSA. Use
+ * |SSL_CIPHER_get_auth_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_ECDHE returns one if |cipher| uses ECDHE. Use
+ * |SSL_CIPHER_get_kx_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_static_RSA returns one if |cipher| uses the static RSA key
+ * exchange. Use |SSL_CIPHER_get_kx_nid| instead. */
+OPENSSL_EXPORT int SSL_CIPHER_is_static_RSA(const SSL_CIPHER *cipher);
+
/* Private structures.
*
diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h
index 39cd07b..f213dba 100644
--- a/src/include/openssl/ssl3.h
+++ b/src/include/openssl/ssl3.h
@@ -339,7 +339,6 @@
#define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CLNT_HELLO_C (0x112 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CLNT_HELLO_D (0x113 | SSL_ST_ACCEPT)
/* write to client */
#define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT)
@@ -348,7 +347,6 @@
/* read from client */
#define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_KEY_EXCH_A (0x190 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_KEY_EXCH_B (0x191 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CERT_VRFY_A (0x1A0 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_CHANGE (0x1B0 | SSL_ST_ACCEPT)
#define SSL3_ST_SR_NEXT_PROTO_A (0x210 | SSL_ST_ACCEPT)
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index 2fa0183..2538d28 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -298,9 +298,7 @@
return frag;
}
-/* dtls1_process_handshake_record reads a record for the handshake and processes
- * it. It returns one on success and 0 or -1 on error. */
-static int dtls1_process_handshake_record(SSL *ssl) {
+int dtls1_read_message(SSL *ssl) {
SSL3_RECORD *rr = &ssl->s3->rrec;
if (rr->length == 0) {
int ret = dtls1_get_record(ssl);
@@ -419,63 +417,33 @@
return 1;
}
-int dtls1_get_message(SSL *ssl) {
- if (ssl->s3->tmp.reuse_message) {
- /* There must be a current message. */
- assert(ssl->init_msg != NULL);
- ssl->s3->tmp.reuse_message = 0;
- } else {
- dtls1_release_current_message(ssl, 0 /* don't free buffer */);
- }
-
- /* Process handshake records until the current message is ready. */
- while (!dtls1_is_current_message_complete(ssl)) {
- int ret = dtls1_process_handshake_record(ssl);
- if (ret <= 0) {
- return ret;
- }
+bool dtls1_get_message(SSL *ssl, SSLMessage *out) {
+ if (!dtls1_is_current_message_complete(ssl)) {
+ return false;
}
hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
SSL_MAX_HANDSHAKE_FLIGHT];
- assert(frag != NULL);
- assert(frag->reassembly == NULL);
- assert(ssl->d1->handshake_read_seq == frag->seq);
-
- if (ssl->init_msg == NULL) {
+ out->type = frag->type;
+ CBS_init(&out->body, frag->data + DTLS1_HM_HEADER_LENGTH, frag->msg_len);
+ CBS_init(&out->raw, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len);
+ out->is_v2_hello = false;
+ if (!ssl->s3->has_message) {
ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, frag->data,
frag->msg_len + DTLS1_HM_HEADER_LENGTH);
+ ssl->s3->has_message = 1;
}
-
- /* TODO(davidben): This function has a lot of implicit outputs. Simplify the
- * |ssl_get_message| API. */
- ssl->s3->tmp.message_type = frag->type;
- ssl->init_msg = frag->data + DTLS1_HM_HEADER_LENGTH;
- ssl->init_num = frag->msg_len;
- return 1;
+ return true;
}
-void dtls1_get_current_message(const SSL *ssl, CBS *out) {
- assert(dtls1_is_current_message_complete(ssl));
-
- hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
- SSL_MAX_HANDSHAKE_FLIGHT];
- CBS_init(out, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len);
-}
-
-void dtls1_release_current_message(SSL *ssl, int free_buffer) {
- if (ssl->init_msg == NULL) {
- return;
- }
-
+void dtls1_next_message(SSL *ssl) {
+ assert(ssl->s3->has_message);
assert(dtls1_is_current_message_complete(ssl));
size_t index = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
dtls1_hm_fragment_free(ssl->d1->incoming_messages[index]);
ssl->d1->incoming_messages[index] = NULL;
ssl->d1->handshake_read_seq++;
-
- ssl->init_msg = NULL;
- ssl->init_num = 0;
+ ssl->s3->has_message = 0;
}
void dtls_clear_incoming_messages(SSL *ssl) {
@@ -489,7 +457,7 @@
size_t current = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
for (size_t i = 0; i < SSL_MAX_HANDSHAKE_FLIGHT; i++) {
/* Skip the current message. */
- if (ssl->init_msg != NULL && i == current) {
+ if (ssl->s3->has_message && i == current) {
assert(dtls1_is_current_message_complete(ssl));
continue;
}
@@ -519,7 +487,7 @@
int dtls1_read_change_cipher_spec(SSL *ssl) {
/* Process handshake records until there is a ChangeCipherSpec. */
while (!ssl->d1->has_change_cipher_spec) {
- int ret = dtls1_process_handshake_record(ssl);
+ int ret = dtls1_read_message(ssl);
if (ret <= 0) {
return ret;
}
diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc
index 947cfce..9189427 100644
--- a/src/ssl/dtls_method.cc
+++ b/src/ssl/dtls_method.cc
@@ -113,8 +113,8 @@
dtls1_new,
dtls1_free,
dtls1_get_message,
- dtls1_get_current_message,
- dtls1_release_current_message,
+ dtls1_read_message,
+ dtls1_next_message,
dtls1_read_app_data,
dtls1_read_change_cipher_spec,
dtls1_read_close_notify,
@@ -141,6 +141,15 @@
return &kMethod;
}
+const SSL_METHOD *DTLS_with_buffers_method(void) {
+ static const SSL_METHOD kMethod = {
+ 0,
+ &kDTLSProtocolMethod,
+ &ssl_noop_x509_method,
+ };
+ return &kMethod;
+}
+
/* Legacy version-locked methods. */
const SSL_METHOD *DTLSv1_2_method(void) {
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 946316d..dd09797 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -492,7 +492,6 @@
case SSL3_ST_FINISH_CLIENT_HANDSHAKE:
ssl->method->on_handshake_complete(ssl);
- ssl->method->release_current_message(ssl, 1 /* free_buffer */);
SSL_SESSION_free(ssl->s3->established_session);
if (ssl->session != NULL) {
@@ -767,21 +766,19 @@
static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBS hello_verify_request, cookie;
- uint16_t server_version;
-
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+ if (msg.type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
ssl->d1->send_cookie = false;
- ssl->s3->tmp.reuse_message = 1;
return 1;
}
- CBS_init(&hello_verify_request, ssl->init_msg, ssl->init_num);
+ CBS hello_verify_request = msg.body, cookie;
+ uint16_t server_version;
if (!CBS_get_u16(&hello_verify_request, &server_version) ||
!CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
CBS_len(&cookie) > sizeof(ssl->d1->cookie) ||
@@ -795,20 +792,21 @@
ssl->d1->cookie_len = CBS_len(&cookie);
ssl->d1->send_cookie = true;
+ ssl->method->next_message(ssl);
return 1;
}
-static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out) {
+static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out,
+ const SSLMessage &msg) {
SSL *const ssl = hs->ssl;
- if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO &&
- ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
+ if (msg.type != SSL3_MT_SERVER_HELLO &&
+ msg.type != SSL3_MT_HELLO_RETRY_REQUEST) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
- CBS server_hello;
- CBS_init(&server_hello, ssl->init_msg, ssl->init_num);
+ CBS server_hello = msg.body;
if (!CBS_get_u16(&server_hello, out)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -817,8 +815,7 @@
/* The server version may also be in the supported_versions extension if
* applicable. */
- if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO ||
- *out != TLS1_2_VERSION) {
+ if (msg.type != SSL3_MT_SERVER_HELLO || *out != TLS1_2_VERSION) {
return 1;
}
@@ -872,7 +869,8 @@
static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
uint32_t err = ERR_peek_error();
if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
@@ -889,7 +887,7 @@
}
uint16_t server_version;
- if (!parse_server_version(hs, &server_version)) {
+ if (!parse_server_version(hs, &server_version, msg)) {
return -1;
}
@@ -925,14 +923,13 @@
ssl_clear_tls13_state(hs);
- if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
return -1;
}
- CBS server_hello, server_random, session_id;
+ CBS server_hello = msg.body, server_random, session_id;
uint16_t cipher_suite;
uint8_t compression_method;
- CBS_init(&server_hello, ssl->init_msg, ssl->init_num);
if (!CBS_skip(&server_hello, 2 /* version */) ||
!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
@@ -970,8 +967,8 @@
CBS_len(&session_id));
}
- const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite);
- if (c == NULL) {
+ const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
+ if (cipher == NULL) {
/* unknown cipher */
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -981,10 +978,10 @@
/* The cipher must be allowed in the selected version and enabled. */
uint32_t mask_a, mask_k;
ssl_get_client_disabled(ssl, &mask_a, &mask_k);
- if ((c->algorithm_mkey & mask_k) || (c->algorithm_auth & mask_a) ||
- SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
- SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl) ||
- !sk_SSL_CIPHER_find(SSL_get_ciphers(ssl), NULL, c)) {
+ if ((cipher->algorithm_mkey & mask_k) || (cipher->algorithm_auth & mask_a) ||
+ SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) ||
+ SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl) ||
+ !sk_SSL_CIPHER_find(SSL_get_ciphers(ssl), NULL, cipher)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
@@ -996,7 +993,7 @@
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
}
- if (ssl->session->cipher != c) {
+ if (ssl->session->cipher != cipher) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return -1;
@@ -1009,14 +1006,14 @@
return -1;
}
} else {
- hs->new_session->cipher = c;
+ hs->new_session->cipher = cipher;
}
- hs->new_cipher = c;
+ hs->new_cipher = cipher;
/* Now that the cipher is known, initialize the handshake hash and hash the
* ServerHello. */
- if (!hs->transcript.InitHash(ssl3_protocol_version(ssl), c->algorithm_prf) ||
- !ssl_hash_current_message(hs)) {
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl), hs->new_cipher) ||
+ !ssl_hash_message(hs, msg)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
@@ -1061,27 +1058,27 @@
return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
- CBS cbs;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
-
+ CBS body = msg.body;
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain;
- if (!ssl_parse_cert_chain(&alert, &chain, &hs->peer_pubkey, NULL, &cbs,
+ if (!ssl_parse_cert_chain(&alert, &chain, &hs->peer_pubkey, NULL, &body,
ssl->ctx->pool)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
@@ -1090,7 +1087,7 @@
hs->new_session->certs = chain.release();
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0 ||
- CBS_len(&cbs) != 0 ||
+ CBS_len(&body) != 0 ||
!ssl->ctx->x509_method->session_cache_objects(hs->new_session.get())) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -1131,30 +1128,30 @@
}
}
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
+ if (msg.type != SSL3_MT_CERTIFICATE_STATUS) {
/* A server may send status_request in ServerHello and then change
* its mind about sending CertificateStatus. */
- ssl->s3->tmp.reuse_message = 1;
return 1;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return -1;
}
- CBS certificate_status, ocsp_response;
+ CBS certificate_status = msg.body, ocsp_response;
uint8_t status_type;
- CBS_init(&certificate_status, ssl->init_msg, ssl->init_num);
if (!CBS_get_u8(&certificate_status, &status_type) ||
status_type != TLSEXT_STATUSTYPE_ocsp ||
!CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
@@ -1172,17 +1169,19 @@
return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
+ if (msg.type != SSL3_MT_SERVER_KEY_EXCHANGE) {
/* Some ciphers (pure PSK) have an optional ServerKeyExchange message. */
if (ssl_cipher_requires_server_key_exchange(hs->new_cipher)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
@@ -1190,22 +1189,16 @@
return -1;
}
- ssl->s3->tmp.reuse_message = 1;
return 1;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return -1;
}
- /* Retain a copy of the original CBS to compute the signature over. */
- CBS server_key_exchange;
- CBS_init(&server_key_exchange, ssl->init_msg, ssl->init_num);
- CBS server_key_exchange_orig = server_key_exchange;
-
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
-
+ CBS server_key_exchange = msg.body;
if (alg_a & SSL_aPSK) {
CBS psk_identity_hint;
@@ -1281,11 +1274,11 @@
}
/* At this point, |server_key_exchange| contains the signature, if any, while
- * |server_key_exchange_orig| contains the entire message. From that, derive
- * a CBS containing just the parameter. */
+ * |msg.body| contains the entire message. From that, derive a CBS containing
+ * just the parameter. */
CBS parameter;
- CBS_init(¶meter, CBS_data(&server_key_exchange_orig),
- CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
+ CBS_init(¶meter, CBS_data(&msg.body),
+ CBS_len(&msg.body) - CBS_len(&server_key_exchange));
/* ServerKeyExchange should be signed by the server's public key. */
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
@@ -1360,35 +1353,34 @@
return -1;
}
}
+
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int msg_ret = ssl->method->ssl_get_message(ssl);
- if (msg_ret <= 0) {
- return msg_ret;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
}
- if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO_DONE) {
- ssl->s3->tmp.reuse_message = 1;
+ if (msg.type == SSL3_MT_SERVER_HELLO_DONE) {
/* If we get here we don't need the handshake buffer as we won't be doing
* client auth. */
hs->transcript.FreeBuffer();
return 1;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_REQUEST) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE_REQUEST) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
- CBS cbs;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
-
/* Get the certificate types. */
- CBS certificate_types;
- if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
+ CBS body = msg.body, certificate_types;
+ if (!CBS_get_u8_length_prefixed(&body, &certificate_types)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
@@ -1402,7 +1394,7 @@
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
CBS supported_signature_algorithms;
- if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
+ if (!CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) ||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -1412,13 +1404,13 @@
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names =
- ssl_parse_client_CA_list(ssl, &alert, &cbs);
+ ssl_parse_client_CA_list(ssl, &alert, &body);
if (!ca_names) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return -1;
}
- if (CBS_len(&cbs) != 0) {
+ if (CBS_len(&body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
@@ -1427,28 +1419,31 @@
hs->cert_request = 1;
hs->ca_names = std::move(ca_names);
ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO_DONE) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO_DONE) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
/* ServerHelloDone is empty. */
- if (ssl->init_num > 0) {
+ if (CBS_len(&msg.body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
@@ -1793,19 +1788,19 @@
static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_NEW_SESSION_TICKET) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_NEW_SESSION_TICKET) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
- CBS new_session_ticket, ticket;
+ CBS new_session_ticket = msg.body, ticket;
uint32_t tlsext_tick_lifetime_hint;
- CBS_init(&new_session_ticket, ssl->init_msg, ssl->init_num);
if (!CBS_get_u32(&new_session_ticket, &tlsext_tick_lifetime_hint) ||
!CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
CBS_len(&new_session_ticket) != 0) {
@@ -1819,6 +1814,7 @@
* negotiating the extension. The value of |ticket_expected| is checked in
* |ssl_update_cache| so is cleared here to avoid an unnecessary update. */
hs->ticket_expected = 0;
+ ssl->method->next_message(ssl);
return 1;
}
@@ -1862,6 +1858,7 @@
ssl->session = renewed_session.release();
}
+ ssl->method->next_message(ssl);
return 1;
}
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 47fdc61..2d5b85e 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -172,7 +172,7 @@
namespace bssl {
-static int ssl3_process_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_read_client_hello(SSL_HANDSHAKE *hs);
static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
static int ssl3_select_parameters(SSL_HANDSHAKE *hs);
static int ssl3_send_server_hello(SSL_HANDSHAKE *hs);
@@ -203,7 +203,7 @@
break;
case SSL3_ST_SR_CLNT_HELLO_A:
- ret = ssl->method->ssl_get_message(ssl);
+ ret = ssl3_read_client_hello(hs);
if (ret <= 0) {
goto end;
}
@@ -211,24 +211,16 @@
break;
case SSL3_ST_SR_CLNT_HELLO_B:
- ret = ssl3_process_client_hello(hs);
- if (ret <= 0) {
- goto end;
- }
- hs->state = SSL3_ST_SR_CLNT_HELLO_C;
- break;
-
- case SSL3_ST_SR_CLNT_HELLO_C:
ret = ssl3_select_certificate(hs);
if (ret <= 0) {
goto end;
}
if (hs->state != SSL_ST_TLS13) {
- hs->state = SSL3_ST_SR_CLNT_HELLO_D;
+ hs->state = SSL3_ST_SR_CLNT_HELLO_C;
}
break;
- case SSL3_ST_SR_CLNT_HELLO_D:
+ case SSL3_ST_SR_CLNT_HELLO_C:
ret = ssl3_select_parameters(hs);
if (ret <= 0) {
goto end;
@@ -304,7 +296,6 @@
break;
case SSL3_ST_SR_KEY_EXCH_A:
- case SSL3_ST_SR_KEY_EXCH_B:
ret = ssl3_get_client_key_exchange(hs);
if (ret <= 0) {
goto end;
@@ -418,7 +409,6 @@
case SSL_ST_OK:
ssl->method->on_handshake_complete(ssl);
- ssl->method->release_current_message(ssl, 1 /* free_buffer */);
/* If we aren't retaining peer certificates then we can discard it
* now. */
@@ -687,15 +677,19 @@
return nullptr;
}
-static int ssl3_process_client_hello(SSL_HANDSHAKE *hs) {
+static int ssl3_read_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CLIENT_HELLO)) {
return -1;
}
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return -1;
@@ -760,6 +754,12 @@
static int ssl3_select_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
+ }
+
/* Call |cert_cb| to update server certificates if required. */
if (ssl->cert->cert_cb != NULL) {
int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
@@ -786,8 +786,7 @@
}
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
return -1;
}
@@ -806,9 +805,13 @@
static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
+ }
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
return -1;
}
@@ -914,9 +917,8 @@
/* Now that all parameters are known, initialize the handshake hash and hash
* the ClientHello. */
- if (!hs->transcript.InitHash(ssl3_protocol_version(ssl),
- hs->new_cipher->algorithm_prf) ||
- !ssl_hash_current_message(hs)) {
+ if (!hs->transcript.InitHash(ssl3_protocol_version(ssl), hs->new_cipher) ||
+ !ssl_hash_message(hs, msg)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
@@ -926,6 +928,7 @@
hs->transcript.FreeBuffer();
}
+ ssl->method->next_message(ssl);
return 1;
}
@@ -1177,14 +1180,15 @@
SSL *const ssl = hs->ssl;
assert(hs->cert_request);
- int msg_ret = ssl->method->ssl_get_message(ssl);
- if (msg_ret <= 0) {
- return msg_ret;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
}
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
+ if (msg.type != SSL3_MT_CERTIFICATE) {
if (ssl->version == SSL3_VERSION &&
- ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+ msg.type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
/* In SSL 3.0, the Certificate message is omitted to signal no
* certificate. */
if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
@@ -1196,7 +1200,6 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
hs->new_session->verify_result = X509_V_OK;
- ssl->s3->tmp.reuse_message = 1;
return 1;
}
@@ -1205,13 +1208,11 @@
return -1;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return -1;
}
- CBS certificate_msg;
- CBS_init(&certificate_msg, ssl->init_msg, ssl->init_num);
-
+ CBS certificate_msg = msg.body;
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<STACK_OF(CRYPTO_BUFFER)> chain;
if (!ssl_parse_cert_chain(&alert, &chain, &hs->peer_pubkey,
@@ -1254,36 +1255,32 @@
/* OpenSSL returns X509_V_OK when no certificates are received. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
hs->new_session->verify_result = X509_V_OK;
- return 1;
- }
-
- /* The hash will have been filled in. */
- if (ssl->retain_only_sha256_of_client_certs) {
+ } else if (ssl->retain_only_sha256_of_client_certs) {
+ /* The hash will have been filled in. */
hs->new_session->peer_sha256_valid = 1;
}
+ ssl->method->next_message(ssl);
return 1;
}
static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBS client_key_exchange;
uint8_t *premaster_secret = NULL;
size_t premaster_secret_len = 0;
uint8_t *decrypt_buf = NULL;
- if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
- int ret = ssl->method->ssl_get_message(ssl);
- if (ret <= 0) {
- return ret;
- }
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
return -1;
}
- CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
+ CBS client_key_exchange = msg.body;
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
@@ -1350,7 +1347,6 @@
goto err;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- hs->state = SSL3_ST_SR_KEY_EXCH_B;
goto err;
}
@@ -1488,7 +1484,7 @@
premaster_secret_len = new_len;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
goto err;
}
@@ -1502,6 +1498,7 @@
OPENSSL_cleanse(premaster_secret, premaster_secret_len);
OPENSSL_free(premaster_secret);
+ ssl->method->next_message(ssl);
return 1;
err:
@@ -1516,7 +1513,6 @@
static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBS certificate_verify, signature;
/* Only RSA and ECDSA client certificates are supported, so a
* CertificateVerify is required if and only if there's a client certificate.
@@ -1526,18 +1522,19 @@
return 1;
}
- int msg_ret = ssl->method->ssl_get_message(ssl);
- if (msg_ret <= 0) {
- return msg_ret;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE_VERIFY)) {
return -1;
}
- CBS_init(&certificate_verify, ssl->init_msg, ssl->init_num);
+ CBS certificate_verify = msg.body, signature;
- /* Determine the digest type if needbe. */
+ /* Determine the signature algorithm. */
uint16_t signature_algorithm = 0;
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
if (!CBS_get_u16(&certificate_verify, &signature_algorithm)) {
@@ -1603,10 +1600,11 @@
/* The handshake buffer is no longer necessary, and we may hash the current
* message.*/
hs->transcript.FreeBuffer();
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
@@ -1614,47 +1612,50 @@
* sets the next_proto member in s if found */
static int ssl3_get_next_proto(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_NEXT_PROTO) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_NEXT_PROTO) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
- CBS next_protocol, selected_protocol, padding;
- CBS_init(&next_protocol, ssl->init_msg, ssl->init_num);
+ CBS next_protocol = msg.body, selected_protocol, padding;
if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
!CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
CBS_len(&next_protocol) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- return 0;
+ return -1;
}
if (!CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
&ssl->s3->next_proto_negotiated_len)) {
- return 0;
+ return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int msg_ret = ssl->method->ssl_get_message(ssl);
- if (msg_ret <= 0) {
- return msg_ret;
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
+ if (ret <= 0) {
+ return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
- !tls1_verify_channel_id(hs) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CHANNEL_ID) ||
+ !tls1_verify_channel_id(hs, msg) ||
+ !ssl_hash_message(hs, msg)) {
return -1;
}
+ ssl->method->next_message(ssl);
return 1;
}
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 2d3557c..931ac82 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -338,10 +338,10 @@
size_t *out_fixed_iv_len, const SSL_CIPHER *cipher,
uint16_t version, int is_dtls);
-/* ssl_get_handshake_digest returns the |EVP_MD| corresponding to
- * |algorithm_prf| and the |version|. */
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
- uint16_t version);
+/* ssl_get_handshake_digest returns the |EVP_MD| corresponding to |version| and
+ * |cipher|. */
+const EVP_MD *ssl_get_handshake_digest(uint16_t version,
+ const SSL_CIPHER *cipher);
/* ssl_create_cipher_list evaluates |rule_str| according to the ciphers in
* |ssl_method|. It sets |*out_cipher_list| to a newly-allocated
@@ -397,7 +397,7 @@
* the handshake transcript. Subsequent calls to |Update| will update the
* rolling hash. It returns one on success and zero on failure. It is an error
* to call this function after the handshake buffer is released. */
- bool InitHash(uint16_t version, int algorithm_prf);
+ bool InitHash(uint16_t version, const SSL_CIPHER *cipher);
const uint8_t *buffer_data() const {
return reinterpret_cast<const uint8_t *>(buffer_->data);
@@ -825,6 +825,15 @@
/* Handshake messages. */
+struct SSLMessage {
+ bool is_v2_hello;
+ uint8_t type;
+ CBS body;
+ /* raw is the entire serialized handshake message, including the TLS or DTLS
+ * message header. */
+ CBS raw;
+};
+
/* SSL_MAX_HANDSHAKE_FLIGHT is the number of messages, including
* ChangeCipherSpec, in the longest handshake flight. Currently this is the
* client's second leg in a full handshake when client certificates, NPN, and
@@ -835,6 +844,11 @@
* in a handshake message for |ssl|. */
size_t ssl_max_handshake_message_len(const SSL *ssl);
+/* ssl_read_message reads a message for the old |BIO|-based state machine. On
+ * success, it returns one and sets |*out| to the current message. Otherwise, it
+ * returns <= 0. */
+int ssl_read_message(SSL *ssl, SSLMessage *out);
+
/* dtls_clear_incoming_messages releases all buffered incoming messages. */
void dtls_clear_incoming_messages(SSL *ssl);
@@ -1048,7 +1062,7 @@
* up to the binders has a valid signature using the value of |session|'s
* resumption secret. It returns 1 on success, and 0 on failure. */
int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
- CBS *binders);
+ const SSLMessage &msg, CBS *binders);
/* Handshake functions. */
@@ -1058,7 +1072,6 @@
ssl_hs_ok,
ssl_hs_read_message,
ssl_hs_flush,
- ssl_hs_flush_and_read_message,
ssl_hs_x509_lookup,
ssl_hs_channel_id_lookup,
ssl_hs_private_key_operation,
@@ -1307,9 +1320,9 @@
/* ssl_handshake_free releases all memory associated with |hs|. */
void ssl_handshake_free(SSL_HANDSHAKE *hs);
-/* ssl_check_message_type checks if the current message has type |type|. If so
- * it returns one. Otherwise, it sends an alert and returns zero. */
-int ssl_check_message_type(SSL *ssl, int type);
+/* ssl_check_message_type checks if |msg| has type |type|. If so it returns
+ * one. Otherwise, it sends an alert and returns zero. */
+int ssl_check_message_type(SSL *ssl, const SSLMessage &msg, int type);
/* tls13_handshake runs the TLS 1.3 handshake. It returns one on success and <=
* 0 on error. It sets |out_early_return| to one if we've completed the
@@ -1323,15 +1336,17 @@
/* tls13_post_handshake processes a post-handshake message. It returns one on
* success and zero on failure. */
-int tls13_post_handshake(SSL *ssl);
+int tls13_post_handshake(SSL *ssl, const SSLMessage &msg);
-int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous);
-int tls13_process_certificate_verify(SSL_HANDSHAKE *hs);
+int tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
+ int allow_anonymous);
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs, const SSLMessage &msg);
-/* tls13_process_finished processes the current message as a Finished message
- * from the peer. If |use_saved_value| is one, the verify_data is compared
- * against |hs->expected_client_finished| rather than computed fresh. */
-int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value);
+/* tls13_process_finished processes |msg| as a Finished message from the
+ * peer. If |use_saved_value| is one, the verify_data is compared against
+ * |hs->expected_client_finished| rather than computed fresh. */
+int tls13_process_finished(SSL_HANDSHAKE *hs, const SSLMessage &msg,
+ int use_saved_value);
int tls13_add_certificate(SSL_HANDSHAKE *hs);
@@ -1341,7 +1356,7 @@
enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs);
int tls13_add_finished(SSL_HANDSHAKE *hs);
-int tls13_process_new_session_ticket(SSL *ssl);
+int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg);
int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
size_t *out_secret_len,
@@ -1419,8 +1434,8 @@
/* ClientHello functions. */
-int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
- size_t in_len);
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+ const SSLMessage &msg);
int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
CBS *out, uint16_t extension_type);
@@ -1554,6 +1569,10 @@
* crypto/x509. */
extern const SSL_X509_METHOD ssl_crypto_x509_method;
+/* ssl_noop_x509_method provides the |SSL_X509_METHOD| functions that avoid
+ * crypto/x509. */
+extern const SSL_X509_METHOD ssl_noop_x509_method;
+
struct SSL3_RECORD {
/* type is the record type. */
uint8_t type;
@@ -1644,6 +1663,10 @@
* V2ClientHello rather than received from the peer directly. */
unsigned is_v2_hello:1;
+ /* has_message is true if the current handshake message has been returned
+ * at least once by |get_message| and false otherwise. */
+ unsigned has_message:1;
+
/* initial_handshake_complete is true if the initial handshake has
* completed. */
unsigned initial_handshake_complete:1;
@@ -1707,10 +1730,6 @@
* TODO(davidben): Move everything not needed after the handshake completes to
* |hs| and remove this. */
struct {
- int message_type;
-
- int reuse_message;
-
uint8_t new_mac_secret_len;
uint8_t new_key_len;
uint8_t new_fixed_iv_len;
@@ -1891,11 +1910,6 @@
BUF_MEM *init_buf; /* buffer used during init */
- /* init_msg is a pointer to the current handshake message body. */
- const uint8_t *init_msg;
- /* init_num is the length of the current handshake message body. */
- uint32_t init_num;
-
SSL3_STATE *s3; /* SSLv3 variables */
DTLS1_STATE *d1; /* DTLSv1 variables */
@@ -2135,9 +2149,9 @@
int ssl3_get_finished(SSL_HANDSHAKE *hs);
int ssl3_send_alert(SSL *ssl, int level, int desc);
-int ssl3_get_message(SSL *ssl);
-void ssl3_get_current_message(const SSL *ssl, CBS *out);
-void ssl3_release_current_message(SSL *ssl, int free_buffer);
+bool ssl3_get_message(SSL *ssl, SSLMessage *out);
+int ssl3_read_message(SSL *ssl);
+void ssl3_next_message(SSL *ssl);
int ssl3_send_finished(SSL_HANDSHAKE *hs);
int ssl3_dispatch_alert(SSL *ssl);
@@ -2174,9 +2188,9 @@
* the pending flight. It returns one on success and zero on error. */
int ssl_add_message_cbb(SSL *ssl, CBB *cbb);
-/* ssl_hash_current_message incorporates the current handshake message into the
- * handshake hash. It returns one on success and zero on allocation failure. */
-int ssl_hash_current_message(SSL_HANDSHAKE *hs);
+/* ssl_hash_message incorporates |msg| into the handshake hash. It returns one
+ * on success and zero on allocation failure. */
+bool ssl_hash_message(SSL_HANDSHAKE *hs, const SSLMessage &msg);
/* dtls1_get_record reads a new input record. On success, it places it in
* |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
@@ -2214,9 +2228,9 @@
int dtls1_connect(SSL *ssl);
void dtls1_free(SSL *ssl);
-int dtls1_get_message(SSL *ssl);
-void dtls1_get_current_message(const SSL *ssl, CBS *out);
-void dtls1_release_current_message(SSL *ssl, int free_buffer);
+bool dtls1_get_message(SSL *ssl, SSLMessage *out);
+int dtls1_read_message(SSL *ssl);
+void dtls1_next_message(SSL *ssl);
int dtls1_dispatch_alert(SSL *ssl);
int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which);
@@ -2278,10 +2292,10 @@
const uint8_t *ticket, size_t ticket_len, const uint8_t *session_id,
size_t session_id_len);
-/* tls1_verify_channel_id processes the current message as a Channel ID message,
- * and verifies the signature. If the key is valid, it saves the Channel ID and
- * returns one. Otherwise, it returns zero. */
-int tls1_verify_channel_id(SSL_HANDSHAKE *hs);
+/* tls1_verify_channel_id processes |msg| as a Channel ID message, and verifies
+ * the signature. If the key is valid, it saves the Channel ID and returns
+ * one. Otherwise, it returns zero. */
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg);
/* tls1_write_channel_id generates a Channel ID message and puts the output in
* |cbb|. |ssl->tlsext_channel_id_private| must already be set before calling.
@@ -2355,21 +2369,19 @@
char is_dtls;
int (*ssl_new)(SSL *ssl);
void (*ssl_free)(SSL *ssl);
- /* ssl_get_message reads the next handshake message. On success, it returns
- * one and sets |ssl->s3->tmp.message_type|, |ssl->init_msg|, and
- * |ssl->init_num|. Otherwise, it returns <= 0. */
- int (*ssl_get_message)(SSL *ssl);
- /* get_current_message sets |*out| to the current handshake message. This
- * includes the protocol-specific message header. */
- void (*get_current_message)(const SSL *ssl, CBS *out);
- /* release_current_message is called to release the current handshake message.
- * If |free_buffer| is one, buffers will also be released. */
- void (*release_current_message)(SSL *ssl, int free_buffer);
+ /* get_message sets |*out| to the current handshake message and returns true
+ * if one has been received. It returns false if more input is needed. */
+ bool (*get_message)(SSL *ssl, bssl::SSLMessage *out);
+ /* read_message reads additional handshake data for |get_message|. On success,
+ * it returns one. Otherwise, it returns <= 0. */
+ int (*read_message)(SSL *ssl);
+ /* next_message is called to release the current handshake message. */
+ void (*next_message)(SSL *ssl);
/* read_app_data reads up to |len| bytes of application data into |buf|. On
* success, it returns the number of bytes read. Otherwise, it returns <= 0
* and sets |*out_got_handshake| to whether the failure was due to a
- * post-handshake handshake message. If so, it fills in the current message as
- * in |ssl_get_message|. */
+ * post-handshake handshake message. If so, any handshake messages consumed
+ * may be read with |get_message|. */
int (*read_app_data)(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
int peek);
int (*read_change_cipher_spec)(SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index 4d53d53..9c4aa7f 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -187,12 +187,11 @@
void ssl_handshake_free(SSL_HANDSHAKE *hs) { Delete(hs); }
-int ssl_check_message_type(SSL *ssl, int type) {
- if (ssl->s3->tmp.message_type != type) {
+int ssl_check_message_type(SSL *ssl, const SSLMessage &msg, int type) {
+ if (msg.type != type) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- ERR_add_error_dataf("got type %d, wanted type %d",
- ssl->s3->tmp.message_type, type);
+ ERR_add_error_dataf("got type %d, wanted type %d", msg.type, type);
return 0;
}
@@ -422,12 +421,13 @@
int ssl3_get_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int ret = ssl->method->ssl_get_message(ssl);
+ SSLMessage msg;
+ int ret = ssl_read_message(ssl, &msg);
if (ret <= 0) {
return ret;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_FINISHED)) {
return -1;
}
@@ -437,12 +437,11 @@
if (!hs->transcript.GetFinishedMAC(finished, &finished_len,
SSL_get_session(ssl), !ssl->server,
ssl3_protocol_version(ssl)) ||
- !ssl_hash_current_message(hs)) {
+ !ssl_hash_message(hs, msg)) {
return -1;
}
- int finished_ok = ssl->init_num == finished_len &&
- CRYPTO_memcmp(ssl->init_msg, finished, finished_len) == 0;
+ int finished_ok = CBS_mem_equal(&msg.body, finished, finished_len);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
finished_ok = 1;
#endif
@@ -469,6 +468,7 @@
}
}
+ ssl->method->next_message(ssl);
return 1;
}
@@ -515,6 +515,16 @@
return kMaxMessageLen;
}
+int ssl_read_message(SSL *ssl, SSLMessage *out) {
+ while (!ssl->method->get_message(ssl, out)) {
+ int ret = ssl->method->read_message(ssl);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+ return 1;
+}
+
static int extend_handshake_buffer(SSL *ssl, size_t length) {
if (!BUF_MEM_reserve(ssl->init_buf, length)) {
return -1;
@@ -682,7 +692,62 @@
return 1;
}
-int ssl3_get_message(SSL *ssl) {
+/* TODO(davidben): Remove |out_bytes_needed| and inline into |ssl3_get_message|
+ * when the entire record is copied into |init_buf|. */
+static bool parse_message(SSL *ssl, SSLMessage *out, size_t *out_bytes_needed) {
+ if (ssl->init_buf == NULL) {
+ *out_bytes_needed = 4;
+ return false;
+ }
+
+ CBS cbs;
+ uint32_t len;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t *>(ssl->init_buf->data),
+ ssl->init_buf->length);
+ if (!CBS_get_u8(&cbs, &out->type) ||
+ !CBS_get_u24(&cbs, &len)) {
+ *out_bytes_needed = 4;
+ return false;
+ }
+
+ if (!CBS_get_bytes(&cbs, &out->body, len)) {
+ *out_bytes_needed = 4 + len;
+ return false;
+ }
+
+ CBS_init(&out->raw, reinterpret_cast<const uint8_t *>(ssl->init_buf->data),
+ 4 + len);
+ out->is_v2_hello = ssl->s3->is_v2_hello;
+ if (!ssl->s3->has_message) {
+ if (!out->is_v2_hello) {
+ ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE,
+ CBS_data(&out->raw), CBS_len(&out->raw));
+ }
+ ssl->s3->has_message = 1;
+ }
+ return true;
+}
+
+bool ssl3_get_message(SSL *ssl, SSLMessage *out) {
+ size_t unused;
+ return parse_message(ssl, out, &unused);
+}
+
+int ssl3_read_message(SSL *ssl) {
+ SSLMessage msg;
+ size_t bytes_needed;
+ if (parse_message(ssl, &msg, &bytes_needed)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ /* Enforce the limit so the peer cannot force us to buffer 16MB. */
+ if (bytes_needed > 4 + ssl_max_handshake_message_len(ssl)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+ return -1;
+ }
+
/* Re-create the handshake buffer if needed. */
if (ssl->init_buf == NULL) {
ssl->init_buf = BUF_MEM_new();
@@ -691,85 +756,45 @@
}
}
+ /* Bypass the record layer for the first message to handle V2ClientHello. */
if (ssl->server && !ssl->s3->v2_hello_done) {
- /* Bypass the record layer for the first message to handle V2ClientHello. */
int ret = read_v2_client_hello(ssl);
- if (ret <= 0) {
- return ret;
+ if (ret > 0) {
+ ssl->s3->v2_hello_done = 1;
}
- ssl->s3->v2_hello_done = 1;
- }
-
- if (ssl->s3->tmp.reuse_message) {
- /* There must be a current message. */
- assert(ssl->init_msg != NULL);
- ssl->s3->tmp.reuse_message = 0;
- } else {
- ssl3_release_current_message(ssl, 0 /* don't free buffer */);
- }
-
- /* Read the message header, if we haven't yet. */
- int ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH);
- if (ret <= 0) {
return ret;
}
- /* Parse out the length. Cap it so the peer cannot force us to buffer up to
- * 2^24 bytes. */
- const uint8_t *p = (uint8_t *)ssl->init_buf->data;
- size_t msg_len = (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | p[3];
- if (msg_len > ssl_max_handshake_message_len(ssl)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- return -1;
- }
-
- /* Read the message body, if we haven't yet. */
- ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH + msg_len);
- if (ret <= 0) {
- return ret;
- }
-
- /* We have now received a complete message. */
- if (ssl->init_msg == NULL && !ssl->s3->is_v2_hello) {
- ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE,
- ssl->init_buf->data, ssl->init_buf->length);
- }
-
- ssl->s3->tmp.message_type = ((const uint8_t *)ssl->init_buf->data)[0];
- ssl->init_msg = (uint8_t*)ssl->init_buf->data + SSL3_HM_HEADER_LENGTH;
- ssl->init_num = ssl->init_buf->length - SSL3_HM_HEADER_LENGTH;
- return 1;
+ return extend_handshake_buffer(ssl, bytes_needed);
}
-void ssl3_get_current_message(const SSL *ssl, CBS *out) {
- CBS_init(out, (uint8_t *)ssl->init_buf->data, ssl->init_buf->length);
-}
-
-int ssl_hash_current_message(SSL_HANDSHAKE *hs) {
- /* V2ClientHellos are hashed implicitly. */
- if (hs->ssl->s3->is_v2_hello) {
- return 1;
+bool ssl_hash_message(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
+ /* V2ClientHello messages are pre-hashed. */
+ if (msg.is_v2_hello) {
+ return true;
}
- CBS cbs;
- hs->ssl->method->get_current_message(hs->ssl, &cbs);
- return hs->transcript.Update(CBS_data(&cbs), CBS_len(&cbs));
+ return hs->transcript.Update(CBS_data(&msg.raw), CBS_len(&msg.raw));
}
-void ssl3_release_current_message(SSL *ssl, int free_buffer) {
- if (ssl->init_msg != NULL) {
- /* |init_buf| never contains data beyond the current message. */
- assert(SSL3_HM_HEADER_LENGTH + ssl->init_num == ssl->init_buf->length);
-
- /* Clear the current message. */
- ssl->init_msg = NULL;
- ssl->init_num = 0;
- ssl->init_buf->length = 0;
- ssl->s3->is_v2_hello = 0;
+void ssl3_next_message(SSL *ssl) {
+ SSLMessage msg;
+ if (!ssl3_get_message(ssl, &msg) ||
+ ssl->init_buf == NULL ||
+ ssl->init_buf->length < CBS_len(&msg.raw)) {
+ assert(0);
+ return;
}
- if (free_buffer) {
+ OPENSSL_memmove(ssl->init_buf->data, ssl->init_buf->data + CBS_len(&msg.raw),
+ ssl->init_buf->length - CBS_len(&msg.raw));
+ ssl->init_buf->length -= CBS_len(&msg.raw);
+ ssl->s3->is_v2_hello = 0;
+ ssl->s3->has_message = 0;
+
+ /* Post-handshake messages are rare, so release the buffer after every
+ * message. During the handshake, |on_handshake_complete| will release it. */
+ if (!SSL_in_init(ssl) && ssl->init_buf->length == 0) {
BUF_MEM_free(ssl->init_buf);
ssl->init_buf = NULL;
}
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index 262df6d..4f802df 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -377,8 +377,6 @@
assert(!ssl->s3->aead_read_ctx->is_null_cipher());
*out_got_handshake = 0;
- ssl->method->release_current_message(ssl, 0 /* don't free buffer */);
-
SSL3_RECORD *rr = &ssl->s3->rrec;
for (;;) {
@@ -413,7 +411,7 @@
}
/* Parse post-handshake handshake messages. */
- int ret = ssl3_get_message(ssl);
+ int ret = ssl3_read_message(ssl);
if (ret <= 0) {
return ret;
}
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index f1a215f..de4a4b4 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -742,9 +742,9 @@
return 1;
}
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
- uint16_t version) {
- switch (algorithm_prf) {
+const EVP_MD *ssl_get_handshake_digest(uint16_t version,
+ const SSL_CIPHER *cipher) {
+ switch (cipher->algorithm_prf) {
case SSL_HANDSHAKE_MAC_DEFAULT:
return version >= TLS1_2_VERSION ? EVP_sha256() : EVP_md5_sha1();
case SSL_HANDSHAKE_MAC_SHA256:
@@ -752,6 +752,7 @@
case SSL_HANDSHAKE_MAC_SHA384:
return EVP_sha384();
default:
+ assert(0);
return NULL;
}
}
@@ -1454,10 +1455,80 @@
return (cipher->algorithm_mac & SSL_SHA384) != 0;
}
-int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher) {
+int SSL_CIPHER_is_aead(const SSL_CIPHER *cipher) {
return (cipher->algorithm_mac & SSL_AEAD) != 0;
}
+int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *cipher) {
+ switch (cipher->algorithm_enc) {
+ case SSL_eNULL:
+ return NID_undef;
+ case SSL_3DES:
+ return NID_des_ede3_cbc;
+ case SSL_AES128:
+ return NID_aes_128_cbc;
+ case SSL_AES256:
+ return NID_aes_256_cbc;
+ case SSL_AES128GCM:
+ return NID_aes_128_gcm;
+ case SSL_AES256GCM:
+ return NID_aes_256_gcm;
+ case SSL_CHACHA20POLY1305:
+ return NID_chacha20_poly1305;
+ }
+ assert(0);
+ return NID_undef;
+}
+
+int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *cipher) {
+ switch (cipher->algorithm_mac) {
+ case SSL_AEAD:
+ return NID_undef;
+ case SSL_SHA1:
+ return NID_sha1;
+ case SSL_SHA256:
+ return NID_sha256;
+ case SSL_SHA384:
+ return NID_sha384;
+ }
+ assert(0);
+ return NID_undef;
+}
+
+int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *cipher) {
+ switch (cipher->algorithm_mkey) {
+ case SSL_kRSA:
+ return NID_kx_rsa;
+ case SSL_kECDHE:
+ return NID_kx_ecdhe;
+ case SSL_kPSK:
+ return NID_kx_psk;
+ case SSL_kGENERIC:
+ return NID_kx_any;
+ }
+ assert(0);
+ return NID_undef;
+}
+
+int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *cipher) {
+ switch (cipher->algorithm_auth) {
+ case SSL_aRSA:
+ return NID_auth_rsa;
+ case SSL_aECDSA:
+ return NID_auth_ecdsa;
+ case SSL_aPSK:
+ return NID_auth_psk;
+ case SSL_aGENERIC:
+ return NID_auth_any;
+ }
+ assert(0);
+ return NID_undef;
+}
+
+int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher) {
+ return SSL_CIPHER_is_aead(cipher);
+}
+
int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher) {
return (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) != 0;
}
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 6611dd2..10128d8 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -833,7 +833,11 @@
return SSL_do_handshake(ssl);
}
-static int ssl_do_renegotiate(SSL *ssl) {
+static int ssl_do_post_handshake(SSL *ssl, const SSLMessage &msg) {
+ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ return tls13_post_handshake(ssl, msg);
+ }
+
/* We do not accept renegotiations as a server or SSL 3.0. SSL 3.0 will be
* removed entirely in the future and requires retaining more data for
* renegotiation_info. */
@@ -841,8 +845,7 @@
goto no_renegotiation;
}
- if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_REQUEST ||
- ssl->init_num != 0) {
+ if (msg.type != SSL3_MT_HELLO_REQUEST || CBS_len(&msg.body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST);
return 0;
@@ -893,14 +896,6 @@
return 0;
}
-static int ssl_do_post_handshake(SSL *ssl) {
- if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
- return ssl_do_renegotiate(ssl);
- }
-
- return tls13_post_handshake(ssl);
-}
-
static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) {
ssl_reset_error_state(ssl);
@@ -938,11 +933,14 @@
continue;
}
- /* Handle the post-handshake message and try again. */
- if (!ssl_do_post_handshake(ssl)) {
- return -1;
+ SSLMessage msg;
+ while (ssl->method->get_message(ssl, &msg)) {
+ /* Handle the post-handshake message and try again. */
+ if (!ssl_do_post_handshake(ssl, msg)) {
+ return -1;
+ }
+ ssl->method->next_message(ssl);
}
- ssl->method->release_current_message(ssl, 1 /* free buffer */);
}
}
@@ -1660,10 +1658,17 @@
return 1;
}
-OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) {
+STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) {
return ctx->cipher_list->ciphers;
}
+int SSL_CTX_cipher_in_group(const SSL_CTX *ctx, size_t i) {
+ if (i >= sk_SSL_CIPHER_num(ctx->cipher_list->ciphers)) {
+ return 0;
+ }
+ return ctx->cipher_list->in_group_flags[i];
+}
+
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) {
if (ssl == NULL) {
return NULL;
@@ -2466,8 +2471,6 @@
BUF_MEM_free(ssl->init_buf);
ssl->init_buf = NULL;
- ssl->init_msg = NULL;
- ssl->init_num = 0;
/* The ssl->d1->mtu is simultaneously configuration (preserved across
* clear) and connection-specific state (gets reset).
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 1830723..a1c21dc 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -368,8 +368,8 @@
}
const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session) {
- return ssl_get_handshake_digest(session->cipher->algorithm_prf,
- SSL_SESSION_protocol_version(session));
+ return ssl_get_handshake_digest(SSL_SESSION_protocol_version(session),
+ session->cipher);
}
int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
diff --git a/src/ssl/ssl_stat.cc b/src/ssl/ssl_stat.cc
index 22149e2..56e4f2b 100644
--- a/src/ssl/ssl_stat.cc
+++ b/src/ssl/ssl_stat.cc
@@ -188,9 +188,6 @@
case SSL3_ST_SR_KEY_EXCH_A:
return "SSLv3 read client key exchange A";
- case SSL3_ST_SR_KEY_EXCH_B:
- return "SSLv3 read client key exchange B";
-
case SSL3_ST_SR_CERT_VRFY_A:
return "SSLv3 read certificate verify A";
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 4556fb7..898cd04 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -361,12 +361,13 @@
":X25519:P-256",
};
-static std::string CipherListToString(ssl_cipher_preference_list_st *list) {
+static std::string CipherListToString(SSL_CTX *ctx) {
bool in_group = false;
std::string ret;
- for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
- if (!in_group && list->in_group_flags[i]) {
+ const STACK_OF(SSL_CIPHER) *ciphers = SSL_CTX_get_ciphers(ctx);
+ for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+ const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
+ if (!in_group && SSL_CTX_cipher_in_group(ctx, i)) {
ret += "\t[\n";
in_group = true;
}
@@ -376,7 +377,7 @@
}
ret += SSL_CIPHER_get_name(cipher);
ret += "\n";
- if (in_group && !list->in_group_flags[i]) {
+ if (in_group && !SSL_CTX_cipher_in_group(ctx, i)) {
ret += "\t]\n";
in_group = false;
}
@@ -384,16 +385,17 @@
return ret;
}
-static bool CipherListsEqual(ssl_cipher_preference_list_st *list,
+static bool CipherListsEqual(SSL_CTX *ctx,
const std::vector<ExpectedCipher> &expected) {
- if (sk_SSL_CIPHER_num(list->ciphers) != expected.size()) {
+ const STACK_OF(SSL_CIPHER) *ciphers = SSL_CTX_get_ciphers(ctx);
+ if (sk_SSL_CIPHER_num(ciphers) != expected.size()) {
return false;
}
for (size_t i = 0; i < expected.size(); i++) {
- const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
+ const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
if (expected[i].id != SSL_CIPHER_get_id(cipher) ||
- expected[i].in_group_flag != list->in_group_flags[i]) {
+ expected[i].in_group_flag != !!SSL_CTX_cipher_in_group(ctx, i)) {
return false;
}
}
@@ -409,18 +411,18 @@
// Test lax mode.
ASSERT_TRUE(SSL_CTX_set_cipher_list(ctx.get(), t.rule));
- EXPECT_TRUE(CipherListsEqual(ctx->cipher_list, t.expected))
+ EXPECT_TRUE(CipherListsEqual(ctx.get(), t.expected))
<< "Cipher rule evaluated to:\n"
- << CipherListToString(ctx->cipher_list);
+ << CipherListToString(ctx.get());
// Test strict mode.
if (t.strict_fail) {
EXPECT_FALSE(SSL_CTX_set_strict_cipher_list(ctx.get(), t.rule));
} else {
ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), t.rule));
- EXPECT_TRUE(CipherListsEqual(ctx->cipher_list, t.expected))
+ EXPECT_TRUE(CipherListsEqual(ctx.get(), t.expected))
<< "Cipher rule evaluated to:\n"
- << CipherListToString(ctx->cipher_list);
+ << CipherListToString(ctx.get());
}
}
@@ -439,9 +441,8 @@
ASSERT_TRUE(ctx);
ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), rule));
- for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
- EXPECT_FALSE(SSL_CIPHER_is_NULL(
- sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i)));
+ for (const SSL_CIPHER *cipher : SSL_CTX_get_ciphers(ctx.get())) {
+ EXPECT_FALSE(SSL_CIPHER_is_NULL(cipher));
}
}
}
@@ -785,30 +786,119 @@
ExpectDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method);
}
-TEST(SSLTest, CipherGetStandardName) {
+TEST(SSLTest, CipherProperties) {
static const struct {
int id;
const char *standard_name;
+ int cipher_nid;
+ int digest_nid;
+ int kx_nid;
+ int auth_nid;
} kTests[] = {
- {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
- {TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
- "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
- {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},
- {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
- {TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
- "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"},
- {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
- {TLS1_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"},
- {TLS1_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"},
- {TLS1_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"},
+ {
+ SSL3_CK_RSA_DES_192_CBC3_SHA,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ NID_des_ede3_cbc,
+ NID_sha1,
+ NID_kx_rsa,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_RSA_WITH_AES_128_SHA,
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
+ NID_aes_128_cbc,
+ NID_sha1,
+ NID_kx_rsa,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
+ "TLS_PSK_WITH_AES_256_CBC_SHA",
+ NID_aes_256_cbc,
+ NID_sha1,
+ NID_kx_psk,
+ NID_auth_psk,
+ },
+ {
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ NID_aes_128_cbc,
+ NID_sha256,
+ NID_kx_ecdhe,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ NID_aes_256_cbc,
+ NID_sha384,
+ NID_kx_ecdhe,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ NID_aes_128_gcm,
+ NID_undef,
+ NID_kx_ecdhe,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ NID_aes_128_gcm,
+ NID_undef,
+ NID_kx_ecdhe,
+ NID_auth_ecdsa,
+ },
+ {
+ TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ NID_aes_256_gcm,
+ NID_undef,
+ NID_kx_ecdhe,
+ NID_auth_ecdsa,
+ },
+ {
+ TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ NID_aes_128_cbc,
+ NID_sha1,
+ NID_kx_ecdhe,
+ NID_auth_psk,
+ },
+ {
+ TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ NID_chacha20_poly1305,
+ NID_undef,
+ NID_kx_ecdhe,
+ NID_auth_rsa,
+ },
+ {
+ TLS1_CK_AES_256_GCM_SHA384,
+ "TLS_AES_256_GCM_SHA384",
+ NID_aes_256_gcm,
+ NID_undef,
+ NID_kx_any,
+ NID_auth_any,
+ },
+ {
+ TLS1_CK_AES_128_GCM_SHA256,
+ "TLS_AES_128_GCM_SHA256",
+ NID_aes_128_gcm,
+ NID_undef,
+ NID_kx_any,
+ NID_auth_any,
+ },
+ {
+ TLS1_CK_CHACHA20_POLY1305_SHA256,
+ "TLS_CHACHA20_POLY1305_SHA256",
+ NID_chacha20_poly1305,
+ NID_undef,
+ NID_kx_any,
+ NID_auth_any,
+ },
};
for (const auto &t : kTests) {
@@ -821,6 +911,11 @@
bssl::UniquePtr<char> rfc_name(SSL_CIPHER_get_rfc_name(cipher));
ASSERT_TRUE(rfc_name);
EXPECT_STREQ(t.standard_name, rfc_name.get());
+
+ EXPECT_EQ(t.cipher_nid, SSL_CIPHER_get_cipher_nid(cipher));
+ EXPECT_EQ(t.digest_nid, SSL_CIPHER_get_digest_nid(cipher));
+ EXPECT_EQ(t.kx_nid, SSL_CIPHER_get_kx_nid(cipher));
+ EXPECT_EQ(t.auth_nid, SSL_CIPHER_get_auth_nid(cipher));
}
}
diff --git a/src/ssl/ssl_transcript.cc b/src/ssl/ssl_transcript.cc
index 4a00d0f..2dfaf76 100644
--- a/src/ssl/ssl_transcript.cc
+++ b/src/ssl/ssl_transcript.cc
@@ -178,8 +178,8 @@
return true;
}
-bool SSLTranscript::InitHash(uint16_t version, int algorithm_prf) {
- const EVP_MD *md = ssl_get_handshake_digest(algorithm_prf, version);
+bool SSLTranscript::InitHash(uint16_t version, const SSL_CIPHER *cipher) {
+ const EVP_MD *md = ssl_get_handshake_digest(version, cipher);
/* To support SSL 3.0's Finished and CertificateVerify constructions,
* EVP_md5_sha1() is split into MD5 and SHA-1 halves. When SSL 3.0 is removed,
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index 2349df0..d4a6ee9 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -483,25 +483,19 @@
}
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
+ const SSL_SESSION *session = SSL_get_session(ssl);
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
- return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length,
- TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ return ssl3_prf(out, out_len, session->master_key,
+ session->master_key_length, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
- const EVP_MD *digest = ssl_get_handshake_digest(
- SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
- if (digest == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length,
- TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
- ssl->s3->server_random, SSL3_RANDOM_SIZE,
- ssl->s3->client_random, SSL3_RANDOM_SIZE);
+ const EVP_MD *digest = SSL_SESSION_get_digest(session);
+ return tls1_prf(digest, out, out_len, session->master_key,
+ session->master_key_length, TLS_MD_KEY_EXPANSION_CONST,
+ TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random,
+ SSL3_RANDOM_SIZE, ssl->s3->client_random, SSL3_RANDOM_SIZE);
}
int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
@@ -545,15 +539,11 @@
OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
}
- const EVP_MD *digest = ssl_get_handshake_digest(
- SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
- if (digest == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
- SSL_get_session(ssl)->master_key_length, label, label_len,
- seed, seed_len, NULL, 0);
+ const SSL_SESSION *session = SSL_get_session(ssl);
+ const EVP_MD *digest = SSL_SESSION_get_digest(session);
+ int ret = tls1_prf(digest, out, out_len, session->master_key,
+ session->master_key_length, label, label_len, seed,
+ seed_len, NULL, 0);
OPENSSL_free(seed);
return ret;
}
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 27a942a..39f4be6 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -204,12 +204,12 @@
return ret;
}
-int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
- size_t in_len) {
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
+ const SSLMessage &msg) {
OPENSSL_memset(out, 0, sizeof(*out));
out->ssl = ssl;
- out->client_hello = in;
- out->client_hello_len = in_len;
+ out->client_hello = CBS_data(&msg.body);
+ out->client_hello_len = CBS_len(&msg.body);
CBS client_hello, random, session_id;
CBS_init(&client_hello, out->client_hello, out->client_hello_len);
@@ -3276,14 +3276,12 @@
return 0;
}
-int tls1_verify_channel_id(SSL_HANDSHAKE *hs) {
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
SSL *const ssl = hs->ssl;
- uint16_t extension_type;
- CBS extension, channel_id;
-
/* A Channel ID handshake message is structured to contain multiple
* extensions, but the only one that can be present is Channel ID. */
- CBS_init(&channel_id, ssl->init_msg, ssl->init_num);
+ uint16_t extension_type;
+ CBS channel_id = msg.body, extension;
if (!CBS_get_u16(&channel_id, &extension_type) ||
!CBS_get_u16_length_prefixed(&channel_id, &extension) ||
CBS_len(&channel_id) != 0 ||
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index b8c2785..b402f38 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -573,6 +573,10 @@
// end_of_early_data alert.
SkipEndOfEarlyData bool
+ // SkipCertificateVerify, if true causes peer to skip sending a
+ // CertificateVerify message after the Certificate message.
+ SkipCertificateVerify bool
+
// EarlyChangeCipherSpec causes the client to send an early
// ChangeCipherSpec message before the ClientKeyExchange. A value of
// zero disables this behavior. One and two configure variants for 0.9.8
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 834be40..9fa49b5 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -2,8 +2,7 @@
"DisabledTests": {
"BadCBCPadding*": "Fuzzer mode has no CBC padding.",
- "BadFinished-*": "Fuzzer mode ignores Finished checks.",
- "FalseStart-BadFinished": "Fuzzer mode ignores Finished checks.",
+ "*BadFinished*": "Fuzzer mode ignores Finished checks.",
"TrailingMessageData-*Finished*": "Fuzzer mode ignores Finished checks.",
"DTLSIgnoreBadPackets*": "Fuzzer mode has no bad packets.",
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 33c1b12..7423726 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -974,8 +974,10 @@
certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
}
- hs.writeClientHash(certVerify.marshal())
- c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ if !c.config.Bugs.SkipCertificateVerify {
+ hs.writeClientHash(certVerify.marshal())
+ c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ }
}
}
@@ -1200,8 +1202,10 @@
return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
}
- hs.writeClientHash(certVerify.marshal())
- c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ if !c.config.Bugs.SkipCertificateVerify {
+ hs.writeClientHash(certVerify.marshal())
+ c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ }
}
// flushHandshake will be called in sendFinished.
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 614bb50..194244d 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -863,8 +863,10 @@
certVerify.signatureAlgorithm = config.Bugs.SendSignatureAlgorithm
}
- hs.writeServerHash(certVerify.marshal())
- c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ if !config.Bugs.SkipCertificateVerify {
+ hs.writeServerHash(certVerify.marshal())
+ c.writeRecord(recordTypeHandshake, certVerify.marshal())
+ }
} else if hs.sessionState != nil {
// Pick up certificates from the session instead.
if len(hs.sessionState.certificates) > 0 {
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 9898101..7e64fe5 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -1512,6 +1512,24 @@
},
{
testType: serverTest,
+ name: "ServerSkipCertificateVerify",
+ config: Config{
+ MaxVersion: VersionTLS12,
+ Certificates: []Certificate{rsaChainCertificate},
+ Bugs: ProtocolBugs{
+ SkipCertificateVerify: true,
+ },
+ },
+ expectPeerCertificate: &rsaChainCertificate,
+ flags: []string{
+ "-require-any-client-certificate",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ expectedLocalError: "remote error: unexpected message",
+ },
+ {
+ testType: serverTest,
name: "Alert",
config: Config{
Bugs: ProtocolBugs{
@@ -4229,21 +4247,20 @@
testType: serverTest,
name: "TLS13Experiment-EarlyData-Server",
config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- TLS13Variant: TLS13Experiment,
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendEarlyData: [][]byte{{1, 2, 3, 4}},
ExpectEarlyDataAccepted: true,
ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
},
+ tls13Variant: TLS13Experiment,
messageCount: 2,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-accept-early-data",
- "-tls13-variant", "1",
},
})
@@ -4251,21 +4268,20 @@
testType: serverTest,
name: "TLS13RecordTypeExperiment-EarlyData-Server",
config: Config{
- MaxVersion: VersionTLS13,
- MinVersion: VersionTLS13,
- TLS13Variant: TLS13RecordTypeExperiment,
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendEarlyData: [][]byte{{1, 2, 3, 4}},
ExpectEarlyDataAccepted: true,
ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
},
},
+ tls13Variant: TLS13RecordTypeExperiment,
messageCount: 2,
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-accept-early-data",
- "-tls13-variant", "2",
},
})
@@ -10637,26 +10653,24 @@
testType: serverTest,
name: "SkipEarlyData-TLS13Experiment",
config: Config{
- MaxVersion: VersionTLS13,
- TLS13Variant: TLS13Experiment,
+ MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendFakeEarlyDataLength: 4,
},
},
- flags: []string{"-tls13-variant", "1"},
+ tls13Variant: TLS13Experiment,
})
testCases = append(testCases, testCase{
testType: serverTest,
name: "SkipEarlyData-TLS13RecordTypeExperiment",
config: Config{
- MaxVersion: VersionTLS13,
- TLS13Variant: TLS13RecordTypeExperiment,
+ MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
SendFakeEarlyDataLength: 4,
},
},
- flags: []string{"-tls13-variant", "2"},
+ tls13Variant: TLS13RecordTypeExperiment,
})
testCases = append(testCases, testCase{
@@ -11772,7 +11786,8 @@
Bugs: ProtocolBugs{
SendEarlyData: [][]byte{{1, 2, 3, 4}},
SendStrayEarlyHandshake: true,
- ExpectEarlyDataAccepted: true},
+ ExpectEarlyDataAccepted: true,
+ },
},
resumeSession: true,
shouldFail: true,
@@ -11800,6 +11815,100 @@
"-expect-version", strconv.Itoa(VersionTLS13),
},
})
+
+ // Test that client and server both notice handshake errors after data
+ // has started flowing.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-Client-BadFinished",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ BadFinished: true,
+ },
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-accept-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ expectedLocalError: "remote error: error decrypting message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-EarlyData-Server-BadFinished",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ SendEarlyData: [][]byte{{1, 2, 3, 4}},
+ ExpectEarlyDataAccepted: true,
+ ExpectHalfRTTData: [][]byte{{254, 253, 252, 251}},
+ BadFinished: true,
+ },
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-accept-early-data",
+ },
+ shouldFail: true,
+ expectedError: ":DIGEST_CHECK_FAILED:",
+ expectedLocalError: "remote error: error decrypting message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "TLS13-ServerSkipCertificateVerify",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Certificates: []Certificate{rsaChainCertificate},
+ Bugs: ProtocolBugs{
+ SkipCertificateVerify: true,
+ },
+ },
+ expectPeerCertificate: &rsaChainCertificate,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+ "-require-any-client-certificate",
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-ClientSkipCertificateVerify",
+ config: Config{
+ MinVersion: VersionTLS13,
+ MaxVersion: VersionTLS13,
+ Certificates: []Certificate{rsaChainCertificate},
+ Bugs: ProtocolBugs{
+ SkipCertificateVerify: true,
+ },
+ },
+ expectPeerCertificate: &rsaChainCertificate,
+ flags: []string{
+ "-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+ "-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_MESSAGE:",
+ expectedLocalError: "remote error: unexpected message",
+ })
}
func addTLS13CipherPreferenceTests() {
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 1c2e7f7..39e0cb3 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -46,21 +46,16 @@
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
return -1;
- case ssl_hs_flush:
- case ssl_hs_flush_and_read_message: {
+ case ssl_hs_flush: {
int ret = ssl->method->flush_flight(ssl);
if (ret <= 0) {
return ret;
}
- if (hs->wait != ssl_hs_flush_and_read_message) {
- break;
- }
- hs->wait = ssl_hs_read_message;
- SSL_FALLTHROUGH;
+ break;
}
case ssl_hs_read_message: {
- int ret = ssl->method->ssl_get_message(ssl);
+ int ret = ssl->method->read_message(ssl);
if (ret <= 0) {
return ret;
}
@@ -190,14 +185,14 @@
return 1;
}
-int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
+int tls13_process_certificate(SSL_HANDSHAKE *hs, const SSLMessage &msg,
+ int allow_anonymous) {
SSL *const ssl = hs->ssl;
- CBS cbs, context, certificate_list;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
+ CBS body = msg.body, context, certificate_list;
+ if (!CBS_get_u8_length_prefixed(&body, &context) ||
CBS_len(&context) != 0 ||
- !CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
- CBS_len(&cbs) != 0) {
+ !CBS_get_u24_length_prefixed(&body, &certificate_list) ||
+ CBS_len(&body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return 0;
@@ -356,19 +351,18 @@
return 1;
}
-int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs, const SSLMessage &msg) {
SSL *const ssl = hs->ssl;
if (hs->peer_pubkey == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- CBS cbs, signature;
+ CBS body = msg.body, signature;
uint16_t signature_algorithm;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u16(&cbs, &signature_algorithm) ||
- !CBS_get_u16_length_prefixed(&cbs, &signature) ||
- CBS_len(&cbs) != 0) {
+ if (!CBS_get_u16(&body, &signature_algorithm) ||
+ !CBS_get_u16_length_prefixed(&body, &signature) ||
+ CBS_len(&body) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return 0;
@@ -381,19 +375,19 @@
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
- uint8_t *msg = NULL;
- size_t msg_len;
+ uint8_t *input = NULL;
+ size_t input_len;
if (!tls13_get_cert_verify_signature_input(
- hs, &msg, &msg_len,
+ hs, &input, &input_len,
ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return 0;
}
- UniquePtr<uint8_t> free_msg(msg);
+ UniquePtr<uint8_t> free_input(input);
int sig_ok = ssl_public_key_verify(ssl, CBS_data(&signature),
CBS_len(&signature), signature_algorithm,
- hs->peer_pubkey.get(), msg, msg_len);
+ hs->peer_pubkey.get(), input, input_len);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
sig_ok = 1;
ERR_clear_error();
@@ -407,7 +401,8 @@
return 1;
}
-int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) {
+int tls13_process_finished(SSL_HANDSHAKE *hs, const SSLMessage &msg,
+ int use_saved_value) {
SSL *const ssl = hs->ssl;
uint8_t verify_data_buf[EVP_MAX_MD_SIZE];
const uint8_t *verify_data;
@@ -424,9 +419,7 @@
verify_data = verify_data_buf;
}
- int finished_ok =
- ssl->init_num == verify_data_len &&
- CRYPTO_memcmp(verify_data, ssl->init_msg, verify_data_len) == 0;
+ int finished_ok = CBS_mem_equal(&msg.body, verify_data, verify_data_len);
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
finished_ok = 1;
#endif
@@ -584,12 +577,11 @@
return 1;
}
-static int tls13_receive_key_update(SSL *ssl) {
- CBS cbs;
+static int tls13_receive_key_update(SSL *ssl, const SSLMessage &msg) {
+ CBS body = msg.body;
uint8_t key_update_request;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u8(&cbs, &key_update_request) ||
- CBS_len(&cbs) != 0 ||
+ if (!CBS_get_u8(&body, &key_update_request) ||
+ CBS_len(&body) != 0 ||
(key_update_request != SSL_KEY_UPDATE_NOT_REQUESTED &&
key_update_request != SSL_KEY_UPDATE_REQUESTED)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -605,9 +597,10 @@
if (key_update_request == SSL_KEY_UPDATE_REQUESTED &&
!ssl->s3->key_update_pending) {
ScopedCBB cbb;
- CBB body;
- if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_KEY_UPDATE) ||
- !CBB_add_u8(&body, SSL_KEY_UPDATE_NOT_REQUESTED) ||
+ CBB body_cbb;
+ if (!ssl->method->init_message(ssl, cbb.get(), &body_cbb,
+ SSL3_MT_KEY_UPDATE) ||
+ !CBB_add_u8(&body_cbb, SSL_KEY_UPDATE_NOT_REQUESTED) ||
!ssl_add_message_cbb(ssl, cbb.get()) ||
!tls13_rotate_traffic_key(ssl, evp_aead_seal)) {
return 0;
@@ -623,8 +616,8 @@
return 1;
}
-int tls13_post_handshake(SSL *ssl) {
- if (ssl->s3->tmp.message_type == SSL3_MT_KEY_UPDATE) {
+int tls13_post_handshake(SSL *ssl, const SSLMessage &msg) {
+ if (msg.type == SSL3_MT_KEY_UPDATE) {
ssl->s3->key_update_count++;
if (ssl->s3->key_update_count > kMaxKeyUpdates) {
OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES);
@@ -632,14 +625,13 @@
return 0;
}
- return tls13_receive_key_update(ssl);
+ return tls13_receive_key_update(ssl, msg);
}
ssl->s3->key_update_count = 0;
- if (ssl->s3->tmp.message_type == SSL3_MT_NEW_SESSION_TICKET &&
- !ssl->server) {
- return tls13_process_new_session_ticket(ssl);
+ if (msg.type == SSL3_MT_NEW_SESSION_TICKET && !ssl->server) {
+ return tls13_process_new_session_ticket(ssl, msg);
}
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 2940265..83066be 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -33,16 +33,15 @@
namespace bssl {
enum client_hs_state_t {
- state_process_hello_retry_request = 0,
+ state_read_hello_retry_request = 0,
state_send_second_client_hello,
- state_process_server_hello,
+ state_read_server_hello,
state_process_change_cipher_spec,
- state_process_encrypted_extensions,
- state_continue_second_server_flight,
- state_process_certificate_request,
- state_process_server_certificate,
- state_process_server_certificate_verify,
- state_process_server_finished,
+ state_read_encrypted_extensions,
+ state_read_certificate_request,
+ state_read_server_certificate,
+ state_read_server_certificate_verify,
+ state_read_server_finished,
state_send_end_of_early_data,
state_send_client_certificate,
state_send_client_certificate_verify,
@@ -52,21 +51,24 @@
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
-static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
- hs->tls13_state = state_process_server_hello;
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (msg.type != SSL3_MT_HELLO_RETRY_REQUEST) {
+ hs->tls13_state = state_read_server_hello;
return ssl_hs_ok;
}
- CBS cbs, extensions;
+ CBS body = msg.body, extensions;
uint16_t server_version;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u16(&cbs, &server_version) ||
- !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+ if (!CBS_get_u16(&body, &server_version) ||
+ !CBS_get_u16_length_prefixed(&body, &extensions) ||
/* HelloRetryRequest may not be empty. */
CBS_len(&extensions) == 0 ||
- CBS_len(&cbs) != 0) {
+ CBS_len(&body) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -140,10 +142,11 @@
hs->retry_group = group_id;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
+ ssl->method->next_message(ssl);
hs->received_hello_retry_request = 1;
hs->tls13_state = state_send_second_client_hello;
/* 0-RTT is rejected if we receive a HelloRetryRequest. */
@@ -163,30 +166,33 @@
return ssl_hs_error;
}
- hs->tls13_state = state_process_server_hello;
- return ssl_hs_flush_and_read_message;
+ hs->tls13_state = state_read_server_hello;
+ return ssl_hs_flush;
}
-static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
return ssl_hs_error;
}
- CBS cbs, server_random, session_id, extensions;
+ CBS body = msg.body, server_random, session_id, extensions;
uint16_t server_version;
uint16_t cipher_suite;
uint8_t compression_method;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u16(&cbs, &server_version) ||
- !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) ||
+ if (!CBS_get_u16(&body, &server_version) ||
+ !CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
(ssl->version == TLS1_3_EXPERIMENT_VERSION &&
- !CBS_get_u8_length_prefixed(&cbs, &session_id)) ||
- !CBS_get_u16(&cbs, &cipher_suite) ||
+ !CBS_get_u8_length_prefixed(&body, &session_id)) ||
+ !CBS_get_u16(&body, &cipher_suite) ||
(ssl->version == TLS1_3_EXPERIMENT_VERSION &&
- (!CBS_get_u8(&cbs, &compression_method) || compression_method != 0)) ||
- !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
- CBS_len(&cbs) != 0) {
+ (!CBS_get_u8(&body, &compression_method) || compression_method != 0)) ||
+ !CBS_get_u16_length_prefixed(&body, &extensions) ||
+ CBS_len(&body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
@@ -337,10 +343,12 @@
}
OPENSSL_free(dhe_secret);
- if (!ssl_hash_current_message(hs) ||
+ if (!ssl_hash_message(hs, msg) ||
!tls13_derive_handshake_secrets(hs)) {
return ssl_hs_error;
}
+
+ ssl->method->next_message(ssl);
hs->tls13_state = state_process_change_cipher_spec;
return ssl->version == TLS1_3_EXPERIMENT_VERSION
? ssl_hs_read_change_cipher_spec
@@ -365,23 +373,26 @@
}
}
- hs->tls13_state = state_process_encrypted_extensions;
- return ssl_hs_read_message;
+ hs->tls13_state = state_read_encrypted_extensions;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_encrypted_extensions(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
return ssl_hs_error;
}
- CBS cbs;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!ssl_parse_serverhello_tlsext(hs, &cbs)) {
+ CBS body = msg.body;
+ if (!ssl_parse_serverhello_tlsext(hs, &body)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
- if (CBS_len(&cbs) != 0) {
+ if (CBS_len(&body) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -412,42 +423,42 @@
}
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_continue_second_server_flight;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_certificate_request;
if (hs->in_early_data && !ssl->early_data_accepted) {
return ssl_hs_early_data_rejected;
}
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_continue_second_server_flight(SSL_HANDSHAKE *hs) {
- hs->tls13_state = state_process_certificate_request;
- return ssl_hs_read_message;
-}
-
-static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_certificate_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* CertificateRequest may only be sent in non-resumption handshakes. */
if (ssl->s3->session_reused) {
- hs->tls13_state = state_process_server_finished;
+ hs->tls13_state = state_read_server_finished;
return ssl_hs_ok;
}
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+
/* CertificateRequest is optional. */
- if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
- hs->tls13_state = state_process_server_certificate;
+ if (msg.type != SSL3_MT_CERTIFICATE_REQUEST) {
+ hs->tls13_state = state_read_server_certificate;
return ssl_hs_ok;
}
- CBS cbs, context, supported_signature_algorithms;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
+ CBS body = msg.body, context, supported_signature_algorithms;
+ if (!CBS_get_u8_length_prefixed(&body, &context) ||
/* The request context is always empty during the handshake. */
CBS_len(&context) != 0 ||
- !CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
+ !CBS_get_u16_length_prefixed(&body, &supported_signature_algorithms) ||
CBS_len(&supported_signature_algorithms) == 0 ||
!tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
@@ -457,7 +468,7 @@
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<STACK_OF(CRYPTO_BUFFER)> ca_names =
- ssl_parse_client_CA_list(ssl, &alert, &cbs);
+ ssl_parse_client_CA_list(ssl, &alert, &body);
if (!ca_names) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
@@ -465,8 +476,8 @@
/* Ignore extensions. */
CBS extensions;
- if (!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
- CBS_len(&cbs) != 0) {
+ if (!CBS_get_u16_length_prefixed(&body, &extensions) ||
+ CBS_len(&body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
@@ -476,60 +487,76 @@
hs->ca_names = std::move(ca_names);
ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_server_certificate;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_server_certificate;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
- !tls13_process_certificate(hs, 0 /* certificate required */) ||
- !ssl_hash_current_message(hs)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE) ||
+ !tls13_process_certificate(hs, msg, 0 /* certificate required */) ||
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_server_certificate_verify;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_server_certificate_verify;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_server_certificate_verify(
+static enum ssl_hs_wait_t do_read_server_certificate_verify(
SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
return ssl_hs_error;
case ssl_verify_retry:
- hs->tls13_state = state_process_server_certificate_verify;
+ hs->tls13_state = state_read_server_certificate_verify;
return ssl_hs_certificate_verify;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
- !tls13_process_certificate_verify(hs) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE_VERIFY) ||
+ !tls13_process_certificate_verify(hs, msg) ||
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_server_finished;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_server_finished;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_server_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
- !tls13_process_finished(hs, 0 /* don't use saved value */) ||
- !ssl_hash_current_message(hs) ||
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_FINISHED) ||
+ !tls13_process_finished(hs, msg, 0 /* don't use saved value */) ||
+ !ssl_hash_message(hs, msg) ||
/* Update the secret to the master secret and derive traffic keys. */
!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
!tls13_derive_application_secrets(hs)) {
return ssl_hs_error;
}
+ ssl->method->next_message(ssl);
hs->tls13_state = state_send_end_of_early_data;
return ssl_hs_ok;
}
@@ -662,35 +689,32 @@
enum client_hs_state_t state =
static_cast<enum client_hs_state_t>(hs->tls13_state);
switch (state) {
- case state_process_hello_retry_request:
- ret = do_process_hello_retry_request(hs);
+ case state_read_hello_retry_request:
+ ret = do_read_hello_retry_request(hs);
break;
case state_send_second_client_hello:
ret = do_send_second_client_hello(hs);
break;
- case state_process_server_hello:
- ret = do_process_server_hello(hs);
+ case state_read_server_hello:
+ ret = do_read_server_hello(hs);
break;
case state_process_change_cipher_spec:
ret = do_process_change_cipher_spec(hs);
break;
- case state_process_encrypted_extensions:
- ret = do_process_encrypted_extensions(hs);
+ case state_read_encrypted_extensions:
+ ret = do_read_encrypted_extensions(hs);
break;
- case state_continue_second_server_flight:
- ret = do_continue_second_server_flight(hs);
+ case state_read_certificate_request:
+ ret = do_read_certificate_request(hs);
break;
- case state_process_certificate_request:
- ret = do_process_certificate_request(hs);
+ case state_read_server_certificate:
+ ret = do_read_server_certificate(hs);
break;
- case state_process_server_certificate:
- ret = do_process_server_certificate(hs);
+ case state_read_server_certificate_verify:
+ ret = do_read_server_certificate_verify(hs);
break;
- case state_process_server_certificate_verify:
- ret = do_process_server_certificate_verify(hs);
- break;
- case state_process_server_finished:
- ret = do_process_server_finished(hs);
+ case state_read_server_finished:
+ ret = do_read_server_finished(hs);
break;
case state_send_end_of_early_data:
ret = do_send_end_of_early_data(hs);
@@ -717,7 +741,7 @@
return ssl_hs_ok;
}
-int tls13_process_new_session_ticket(SSL *ssl) {
+int tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg) {
UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(ssl->s3->established_session,
SSL_SESSION_INCLUDE_NONAUTH));
if (!session) {
@@ -727,14 +751,13 @@
ssl_session_rebase_time(ssl, session.get());
uint32_t server_timeout;
- CBS cbs, ticket, extensions;
- CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!CBS_get_u32(&cbs, &server_timeout) ||
- !CBS_get_u32(&cbs, &session->ticket_age_add) ||
- !CBS_get_u16_length_prefixed(&cbs, &ticket) ||
+ CBS body = msg.body, ticket, extensions;
+ if (!CBS_get_u32(&body, &server_timeout) ||
+ !CBS_get_u32(&body, &session->ticket_age_add) ||
+ !CBS_get_u16_length_prefixed(&body, &ticket) ||
!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
- !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
- CBS_len(&cbs) != 0) {
+ !CBS_get_u16_length_prefixed(&body, &extensions) ||
+ CBS_len(&body) != 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return 0;
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index 1ae4849..39e80be 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -33,8 +33,8 @@
namespace bssl {
static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version,
- int algorithm_prf) {
- if (!hs->transcript.InitHash(version, algorithm_prf)) {
+ const SSL_CIPHER *cipher) {
+ if (!hs->transcript.InitHash(version, cipher)) {
return 0;
}
@@ -47,8 +47,7 @@
}
int tls13_init_key_schedule(SSL_HANDSHAKE *hs) {
- if (!init_key_schedule(hs, ssl3_protocol_version(hs->ssl),
- hs->new_cipher->algorithm_prf)) {
+ if (!init_key_schedule(hs, ssl3_protocol_version(hs->ssl), hs->new_cipher)) {
return 0;
}
@@ -59,7 +58,7 @@
int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
return init_key_schedule(hs, SSL_SESSION_protocol_version(ssl->session),
- ssl->session->cipher->algorithm_prf);
+ ssl->session->cipher);
}
int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
@@ -243,9 +242,6 @@
"application traffic secret";
int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
- const EVP_MD *digest = ssl_get_handshake_digest(
- SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
-
uint8_t *secret;
size_t secret_len;
if (direction == evp_aead_open) {
@@ -256,6 +252,7 @@
secret_len = ssl->s3->write_traffic_secret_len;
}
+ const EVP_MD *digest = SSL_SESSION_get_digest(SSL_get_session(ssl));
if (!hkdf_expand_label(secret, digest, secret, secret_len,
(const uint8_t *)kTLS13LabelApplicationTraffic,
strlen(kTLS13LabelApplicationTraffic), NULL, 0,
@@ -323,15 +320,14 @@
const char *label, size_t label_len,
const uint8_t *context, size_t context_len,
int use_context) {
- const EVP_MD *digest = ssl_get_handshake_digest(
- SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
-
const uint8_t *hash = NULL;
size_t hash_len = 0;
if (use_context) {
hash = context;
hash_len = context_len;
}
+
+ const EVP_MD *digest = SSL_SESSION_get_digest(SSL_get_session(ssl));
return hkdf_expand_label(out, digest, ssl->s3->exporter_secret,
ssl->s3->exporter_secret_len, (const uint8_t *)label,
label_len, hash, hash_len, out_len);
@@ -402,23 +398,21 @@
}
int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
- CBS *binders) {
+ const SSLMessage &msg, CBS *binders) {
size_t hash_len = hs->transcript.DigestLen();
- /* Get the full ClientHello, including message header. It must be large enough
- * to exclude the binders. */
- CBS message;
- hs->ssl->method->get_current_message(hs->ssl, &message);
- if (CBS_len(&message) < CBS_len(binders) + 2) {
+ /* The message must be large enough to exclude the binders. */
+ if (CBS_len(&msg.raw) < CBS_len(binders) + 2) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
- /* Hash a ClientHello prefix up to the binders. For now, this assumes we only
- * ever verify PSK binders on initial ClientHellos. */
+ /* Hash a ClientHello prefix up to the binders. This includes the header. For
+ * now, this assumes we only ever verify PSK binders on initial
+ * ClientHellos. */
uint8_t context[EVP_MAX_MD_SIZE];
unsigned context_len;
- if (!EVP_Digest(CBS_data(&message), CBS_len(&message) - CBS_len(binders) - 2,
+ if (!EVP_Digest(CBS_data(&msg.raw), CBS_len(&msg.raw) - CBS_len(binders) - 2,
context, &context_len, hs->transcript.Digest(), NULL)) {
return 0;
}
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 03f8bdd..2b802c4 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -42,17 +42,17 @@
state_select_parameters = 0,
state_select_session,
state_send_hello_retry_request,
- state_process_second_client_hello,
+ state_read_second_client_hello,
state_send_server_hello,
state_send_server_certificate_verify,
state_send_server_finished,
state_read_second_client_flight,
state_process_change_cipher_spec,
state_process_end_of_early_data,
- state_process_client_certificate,
- state_process_client_certificate_verify,
- state_process_channel_id,
- state_process_client_finished,
+ state_read_client_certificate,
+ state_read_client_certificate_verify,
+ state_read_channel_id,
+ state_read_client_finished,
state_send_new_session_ticket,
state_done,
};
@@ -213,11 +213,12 @@
/* At this point, most ClientHello extensions have already been processed by
* the common handshake logic. Resolve the remaining non-PSK parameters. */
SSL *const ssl = hs->ssl;
-
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num) ||
- client_hello.session_id_len > sizeof(hs->session_id)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -246,7 +247,7 @@
/* The PRF hash is now known. Set up the key schedule and hash the
* ClientHello. */
if (!tls13_init_key_schedule(hs) ||
- !ssl_hash_current_message(hs)) {
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
@@ -256,7 +257,8 @@
static enum ssl_ticket_aead_result_t select_session(
SSL_HANDSHAKE *hs, uint8_t *out_alert, UniquePtr<SSL_SESSION> *out_session,
- int32_t *out_ticket_age_skew, const SSL_CLIENT_HELLO *client_hello) {
+ int32_t *out_ticket_age_skew, const SSLMessage &msg,
+ const SSL_CLIENT_HELLO *client_hello) {
SSL *const ssl = hs->ssl;
*out_session = NULL;
@@ -331,7 +333,7 @@
(int32_t)client_ticket_age - (int32_t)server_ticket_age;
/* Check the PSK binder. */
- if (!tls13_verify_psk_binder(hs, session.get(), &binders)) {
+ if (!tls13_verify_psk_binder(hs, session.get(), msg, &binders)) {
*out_alert = SSL_AD_DECRYPT_ERROR;
return ssl_ticket_aead_error;
}
@@ -342,9 +344,12 @@
static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -352,7 +357,7 @@
uint8_t alert = SSL_AD_DECODE_ERROR;
UniquePtr<SSL_SESSION> session;
- switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew,
+ switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew, msg,
&client_hello)) {
case ssl_ticket_aead_ignore_ticket:
assert(!session);
@@ -458,12 +463,14 @@
if (need_retry) {
ssl->early_data_accepted = 0;
ssl->s3->skip_early_data = 1;
+ ssl->method->next_message(ssl);
hs->tls13_state = state_send_hello_retry_request;
return ssl_hs_ok;
}
return ssl_hs_error;
}
+ ssl->method->next_message(ssl);
hs->tls13_state = state_send_server_hello;
return ssl_hs_ok;
}
@@ -485,19 +492,21 @@
return ssl_hs_error;
}
- hs->tls13_state = state_process_second_client_hello;
- return ssl_hs_flush_and_read_message;
+ hs->tls13_state = state_read_second_client_hello;
+ return ssl_hs_flush;
}
-static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_second_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
}
-
SSL_CLIENT_HELLO client_hello;
- if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ if (!ssl_client_hello_init(ssl, &client_hello, msg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -513,10 +522,11 @@
return ssl_hs_error;
}
- if (!ssl_hash_current_message(hs)) {
+ if (!ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
+ ssl->method->next_message(ssl);
hs->tls13_state = state_send_server_hello;
return ssl_hs_ok;
}
@@ -669,7 +679,8 @@
static_cast<uint8_t>(hs->hash_len)};
if (!hs->transcript.Update(header, sizeof(header)) ||
!hs->transcript.Update(hs->expected_client_finished, hs->hash_len) ||
- !tls13_derive_resumption_secret(hs) || !add_new_session_tickets(hs)) {
+ !tls13_derive_resumption_secret(hs) ||
+ !add_new_session_tickets(hs)) {
return ssl_hs_error;
}
}
@@ -713,12 +724,12 @@
hs->hash_len)) {
return ssl_hs_error;
}
- hs->tls13_state = ssl->early_data_accepted ? state_process_client_finished
- : state_process_client_certificate;
- return ssl_hs_read_message;
+ hs->tls13_state = ssl->early_data_accepted ? state_read_client_finished
+ : state_read_client_certificate;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_client_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!hs->cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
@@ -726,74 +737,94 @@
hs->new_session->verify_result = X509_V_OK;
/* Skip this state. */
- hs->tls13_state = state_process_channel_id;
+ hs->tls13_state = state_read_channel_id;
return ssl_hs_ok;
}
const int allow_anonymous =
(ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
-
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
- !tls13_process_certificate(hs, allow_anonymous) ||
- !ssl_hash_current_message(hs)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE) ||
+ !tls13_process_certificate(hs, msg, allow_anonymous) ||
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_client_certificate_verify;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_client_certificate_verify;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_client_certificate_verify(
+static enum ssl_hs_wait_t do_read_client_certificate_verify(
SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
/* Skip this state. */
- hs->tls13_state = state_process_channel_id;
+ hs->tls13_state = state_read_channel_id;
return ssl_hs_ok;
}
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+
switch (ssl_verify_peer_cert(hs)) {
case ssl_verify_ok:
break;
case ssl_verify_invalid:
return ssl_hs_error;
case ssl_verify_retry:
- hs->tls13_state = state_process_client_certificate_verify;
+ hs->tls13_state = state_read_client_certificate_verify;
return ssl_hs_certificate_verify;
}
- if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
- !tls13_process_certificate_verify(hs) ||
- !ssl_hash_current_message(hs)) {
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE_VERIFY) ||
+ !tls13_process_certificate_verify(hs, msg) ||
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_channel_id;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_channel_id;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
- if (!hs->ssl->s3->tlsext_channel_id_valid) {
- hs->tls13_state = state_process_client_finished;
+static enum ssl_hs_wait_t do_read_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (!ssl->s3->tlsext_channel_id_valid) {
+ hs->tls13_state = state_read_client_finished;
return ssl_hs_ok;
}
- if (!ssl_check_message_type(hs->ssl, SSL3_MT_CHANNEL_ID) ||
- !tls1_verify_channel_id(hs) ||
- !ssl_hash_current_message(hs)) {
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_CHANNEL_ID) ||
+ !tls1_verify_channel_id(hs, msg) ||
+ !ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
- hs->tls13_state = state_process_client_finished;
- return ssl_hs_read_message;
+ ssl->method->next_message(ssl);
+ hs->tls13_state = state_read_client_finished;
+ return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_read_client_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
+ SSLMessage msg;
+ if (!ssl->method->get_message(ssl, &msg)) {
+ return ssl_hs_read_message;
+ }
+ if (!ssl_check_message_type(ssl, msg, SSL3_MT_FINISHED) ||
/* If early data was accepted, we've already computed the client Finished
* and derived the resumption secret. */
- !tls13_process_finished(hs, ssl->early_data_accepted) ||
+ !tls13_process_finished(hs, msg, ssl->early_data_accepted) ||
/* evp_aead_seal keys have already been switched. */
!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
hs->hash_len)) {
@@ -801,17 +832,19 @@
}
if (!ssl->early_data_accepted) {
- if (!ssl_hash_current_message(hs) ||
+ if (!ssl_hash_message(hs, msg) ||
!tls13_derive_resumption_secret(hs)) {
return ssl_hs_error;
}
/* We send post-handshake tickets as part of the handshake in 1-RTT. */
hs->tls13_state = state_send_new_session_ticket;
- return ssl_hs_ok;
+ } else {
+ /* We already sent half-RTT tickets. */
+ hs->tls13_state = state_done;
}
- hs->tls13_state = state_done;
+ ssl->method->next_message(ssl);
return ssl_hs_ok;
}
@@ -846,8 +879,8 @@
case state_send_hello_retry_request:
ret = do_send_hello_retry_request(hs);
break;
- case state_process_second_client_hello:
- ret = do_process_second_client_hello(hs);
+ case state_read_second_client_hello:
+ ret = do_read_second_client_hello(hs);
break;
case state_send_server_hello:
ret = do_send_server_hello(hs);
@@ -867,17 +900,17 @@
case state_process_change_cipher_spec:
ret = do_process_change_cipher_spec(hs);
break;
- case state_process_client_certificate:
- ret = do_process_client_certificate(hs);
+ case state_read_client_certificate:
+ ret = do_read_client_certificate(hs);
break;
- case state_process_client_certificate_verify:
- ret = do_process_client_certificate_verify(hs);
+ case state_read_client_certificate_verify:
+ ret = do_read_client_certificate_verify(hs);
break;
- case state_process_channel_id:
- ret = do_process_channel_id(hs);
+ case state_read_channel_id:
+ ret = do_read_channel_id(hs);
break;
- case state_process_client_finished:
- ret = do_process_client_finished(hs);
+ case state_read_client_finished:
+ ret = do_read_client_finished(hs);
break;
case state_send_new_session_ticket:
ret = do_send_new_session_ticket(hs);
diff --git a/src/ssl/tls_method.cc b/src/ssl/tls_method.cc
index 02f5c07..2fe4be3 100644
--- a/src/ssl/tls_method.cc
+++ b/src/ssl/tls_method.cc
@@ -69,7 +69,21 @@
static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; }
-static void ssl3_on_handshake_complete(SSL *ssl) {}
+static void ssl3_on_handshake_complete(SSL *ssl) {
+ /* The handshake should have released its final message. */
+ assert(!ssl->s3->has_message);
+
+ /* During the handshake, |init_buf| is retained. Release if it there is no
+ * excess in it.
+ *
+ * TODO(davidben): The second check is always true but will not be once we
+ * switch to copying the entire handshake record. Replace this comment with an
+ * explanation when that happens and a TODO to reject it. */
+ if (ssl->init_buf != NULL && ssl->init_buf->length == 0) {
+ BUF_MEM_free(ssl->init_buf);
+ ssl->init_buf = NULL;
+ }
+}
static int ssl3_set_read_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
if (ssl->s3->rrec.length != 0) {
@@ -99,8 +113,8 @@
ssl3_new,
ssl3_free,
ssl3_get_message,
- ssl3_get_current_message,
- ssl3_release_current_message,
+ ssl3_read_message,
+ ssl3_next_message,
ssl3_read_app_data,
ssl3_read_change_cipher_spec,
ssl3_read_close_notify,
@@ -151,7 +165,7 @@
static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
-static const SSL_X509_METHOD ssl_noop_x509_method = {
+const SSL_X509_METHOD ssl_noop_x509_method = {
ssl_noop_x509_check_client_CA_names,
ssl_noop_x509_clear,
ssl_noop_x509_free,
diff --git a/src/tool/client.cc b/src/tool/client.cc
index f7a8259..d3a3115 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -297,6 +297,26 @@
return cb(ssl.get(), sock);
}
+static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
+ if (in == "draft") {
+ *out = tls13_default;
+ return true;
+ }
+ if (in == "experiment") {
+ *out = tls13_experiment;
+ return true;
+ }
+ if (in == "record-type") {
+ *out = tls13_record_type_experiment;
+ return true;
+ }
+ if (in == "no-session-id") {
+ *out = tls13_no_session_id_experiment;
+ return true;
+ }
+ return false;
+}
+
bool Client(const std::vector<std::string> &args) {
if (!InitSocketLibrary()) {
return false;
@@ -464,9 +484,13 @@
}
if (args_map.count("-tls13-variant") != 0) {
- SSL_CTX_set_tls13_variant(ctx.get(),
- static_cast<enum tls13_variant_t>(
- atoi(args_map["-tls13-variant"].c_str())));
+ tls13_variant_t variant;
+ if (!GetTLS13Variant(&variant, args_map["-tls13-variant"])) {
+ fprintf(stderr, "Unknown TLS 1.3 variant: %s\n",
+ args_map["-tls13-variant"].c_str());
+ return false;
+ }
+ SSL_CTX_set_tls13_variant(ctx.get(), variant);
}
if (args_map.count("-ed25519") != 0) {