diff options
author | Robert Sloan <varomodt@google.com> | 2017-08-15 08:35:57 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-08-15 08:35:57 +0000 |
commit | 05e49fc79f61f4be37c1bb5bee2931524d1939c6 (patch) | |
tree | 09d7afa7182dcddf7240fece9f03fa5ba282a6f4 | |
parent | 4d4e66ef23e65d3b5ae5e9cb944fc648bfd97bdd (diff) | |
parent | 843770915703e4d21d7f1776be72e769812f9f1e (diff) | |
download | boringssl-05e49fc79f61f4be37c1bb5bee2931524d1939c6.tar.gz |
external/boringssl: Sync to 348f0d8db9c2a0eca0503ba654020209c579d552.
am: 8437709157
Change-Id: I3a1caa5439bab960cdeddd11a9fd7e5a68c5452d
36 files changed, 1242 insertions, 743 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION index bcea3ffc..b6578334 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 4600c76e..a802bfb5 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, SelectW5) { 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 b3da0e89..dceaf03d 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 @@ static const ASN1_OBJECT kObjects[NUM_NID] = { {"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 @@ static const unsigned kNIDsInShortNameOrder[] = { 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 @@ static const unsigned kNIDsInShortNameOrder[] = { 13 /* CN */, 141 /* CRLReason */, 417 /* CSPName */, + 950 /* ChaCha20-Poly1305 */, 367 /* CrlID */, 391 /* DC */, 31 /* DES-CBC */, @@ -3547,6 +3562,10 @@ static const unsigned kNIDsInShortNameOrder[] = { 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 @@ static const unsigned kNIDsInLongNameOrder[] = { 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 @@ static const unsigned kNIDsInLongNameOrder[] = { 677 /* certicom-arc */, 517 /* certificate extensions */, 883 /* certificateRevocationList */, + 950 /* chacha20-poly1305 */, 54 /* challengePassword */, 407 /* characteristic-two-field */, 395 /* clearance */, @@ -4982,6 +5006,10 @@ static const unsigned kNIDsInLongNameOrder[] = { 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 572a01b0..6dbc0f13 100644 --- a/src/crypto/obj/obj_mac.num +++ b/src/crypto/obj/obj_mac.num @@ -938,3 +938,12 @@ dh_std_kdf 946 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 03056deb..f1a63955 100644 --- a/src/crypto/obj/objects.txt +++ b/src/crypto/obj/objects.txt @@ -1336,3 +1336,19 @@ secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme # 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 550661d6..15385eca 100644 --- a/src/crypto/pem/pem_pk8.c +++ b/src/crypto/pem/pem_pk8.c @@ -176,6 +176,7 @@ EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, } 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 058c0311..96675509 100644 --- a/src/crypto/pem/pem_pkey.c +++ b/src/crypto/pem/pem_pkey.c @@ -114,6 +114,7 @@ EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, } 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 bc0ee338..afeb2dea 100644 --- a/src/include/openssl/nid.h +++ b/src/include/openssl/nid.h @@ -4198,6 +4198,42 @@ extern "C" { #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 a5ac3251..63651b5c 100644 --- a/src/include/openssl/ssl.h +++ b/src/include/openssl/ssl.h @@ -192,6 +192,10 @@ OPENSSL_EXPORT const SSL_METHOD *DTLS_method(void); * 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 @@ OPENSSL_EXPORT const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value); * 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 @@ OPENSSL_EXPORT int SSL_set_cipher_list(SSL *ssl, const char *str); * 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 @@ OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl); * 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 39cd07b9..f213dba7 100644 --- a/src/include/openssl/ssl3.h +++ b/src/include/openssl/ssl3.h @@ -339,7 +339,6 @@ OPENSSL_COMPILE_ASSERT( #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 @@ OPENSSL_COMPILE_ASSERT( /* 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 2fa0183c..2538d28d 100644 --- a/src/ssl/d1_both.cc +++ b/src/ssl/d1_both.cc @@ -298,9 +298,7 @@ static hm_fragment *dtls1_get_incoming_message( 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 @@ static int dtls1_process_handshake_record(SSL *ssl) { 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 @@ int dtls_has_incoming_messages(const SSL *ssl) { 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_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr, 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 947cfceb..91894276 100644 --- a/src/ssl/dtls_method.cc +++ b/src/ssl/dtls_method.cc @@ -113,8 +113,8 @@ static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = { 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 @@ const SSL_METHOD *DTLS_method(void) { 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 946316db..dd09797c 100644 --- a/src/ssl/handshake_client.cc +++ b/src/ssl/handshake_client.cc @@ -492,7 +492,6 @@ int ssl3_connect(SSL_HANDSHAKE *hs) { 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 ssl3_send_client_hello(SSL_HANDSHAKE *hs) { 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 @@ static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs) { 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 @@ static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out) { /* 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 parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out) { 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { } 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { /* 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) { } } + 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 @@ static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) { } /* 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 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) { 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_send_channel_id(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) { * 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 @@ static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) { 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 47fdc61c..2d5b85e5 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 @@ int ssl3_accept(SSL_HANDSHAKE *hs) { 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 @@ int ssl3_accept(SSL_HANDSHAKE *hs) { 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 @@ int ssl3_accept(SSL_HANDSHAKE *hs) { 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 @@ int ssl3_accept(SSL_HANDSHAKE *hs) { 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 @@ static const SSL_CIPHER *ssl3_choose_cipher( 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_process_client_hello(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_select_certificate(SSL_HANDSHAKE *hs) { } 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_certificate(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { /* 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 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) { hs->transcript.FreeBuffer(); } + ssl->method->next_message(ssl); return 1; } @@ -1177,14 +1180,15 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) { /* 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 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) { /* 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 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { premaster_secret_len = new_len; } - if (!ssl_hash_current_message(hs)) { + if (!ssl_hash_message(hs, msg)) { goto err; } @@ -1502,6 +1498,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) { OPENSSL_cleanse(premaster_secret, premaster_secret_len); OPENSSL_free(premaster_secret); + ssl->method->next_message(ssl); return 1; err: @@ -1516,7 +1513,6 @@ err: 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 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) { 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 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) { /* 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 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) { * 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 2d3557cd..931ac827 100644 --- a/src/ssl/internal.h +++ b/src/ssl/internal.h @@ -338,10 +338,10 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, 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 @@ class SSLTranscript { * 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 @@ int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len); /* 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 @@ int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len); * 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 @@ int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len); * 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 @@ enum ssl_hs_wait_t { 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 *ssl_handshake_new(SSL *ssl); /* 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 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs); /* 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 @@ int tls13_add_certificate(SSL_HANDSHAKE *hs); 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 @@ int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret, /* 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 @@ struct SSLCertConfig { * 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 @@ struct SSL3_STATE { * 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 @@ struct SSL3_STATE { * 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 @@ struct SSLConnection { 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 @@ void ssl_update_cache(SSL_HANDSHAKE *hs, int mode); 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 @@ int dtls1_flush_flight(SSL *ssl); * 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_accept(SSL *ssl); 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 @@ enum ssl_ticket_aead_result_t ssl_process_ticket( 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 @@ struct ssl_protocol_method_st { 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 4d53d535..9c4aa7ff 100644 --- a/src/ssl/s3_both.cc +++ b/src/ssl/s3_both.cc @@ -187,12 +187,11 @@ SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) { 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_send_finished(SSL_HANDSHAKE *hs) { 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 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs) { 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 @@ int ssl3_get_finished(SSL_HANDSHAKE *hs) { } } + ssl->method->next_message(ssl); return 1; } @@ -515,6 +515,16 @@ size_t ssl_max_handshake_message_len(const SSL *ssl) { 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,94 +692,109 @@ static int read_v2_client_hello(SSL *ssl) { return 1; } -int ssl3_get_message(SSL *ssl) { - /* Re-create the handshake buffer if needed. */ +/* 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) { - ssl->init_buf = BUF_MEM_new(); - if (ssl->init_buf == NULL) { - return -1; - } + *out_bytes_needed = 4; + return false; } - 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; + 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->v2_hello_done = 1; + ssl->s3->has_message = 1; } + return true; +} - 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 */); - } +bool ssl3_get_message(SSL *ssl, SSLMessage *out) { + size_t unused; + return parse_message(ssl, out, &unused); +} - /* Read the message header, if we haven't yet. */ - int ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH); - if (ret <= 0) { - return ret; +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; } - /* 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)) { + /* 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; } - /* 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; + /* Re-create the handshake buffer if needed. */ + if (ssl->init_buf == NULL) { + ssl->init_buf = BUF_MEM_new(); + if (ssl->init_buf == NULL) { + return -1; + } } - /* 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); + /* Bypass the record layer for the first message to handle V2ClientHello. */ + if (ssl->server && !ssl->s3->v2_hello_done) { + int ret = read_v2_client_hello(ssl); + if (ret > 0) { + ssl->s3->v2_hello_done = 1; + } + return ret; } - 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 262df6df..4f802df7 100644 --- a/src/ssl/s3_pkt.cc +++ b/src/ssl/s3_pkt.cc @@ -377,8 +377,6 @@ int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len, 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 @@ int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len, } /* 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 f1a215fc..de4a4b49 100644 --- a/src/ssl/ssl_cipher.cc +++ b/src/ssl/ssl_cipher.cc @@ -742,9 +742,9 @@ int ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, 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 @@ const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf, case SSL_HANDSHAKE_MAC_SHA384: return EVP_sha384(); default: + assert(0); return NULL; } } @@ -1454,10 +1455,80 @@ int SSL_CIPHER_has_SHA384_HMAC(const SSL_CIPHER *cipher) { 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 6611dd25..10128d82 100644 --- a/src/ssl/ssl_lib.cc +++ b/src/ssl/ssl_lib.cc @@ -833,7 +833,11 @@ int SSL_accept(SSL *ssl) { 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 @@ static int ssl_do_renegotiate(SSL *ssl) { 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 @@ no_renegotiation: 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 @@ static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) { 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 @@ int SSL_set_tmp_dh(SSL *ssl, const DH *dh) { 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 @@ int SSL_clear(SSL *ssl) { 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 18307237..a1c21dc8 100644 --- a/src/ssl/ssl_session.cc +++ b/src/ssl/ssl_session.cc @@ -368,8 +368,8 @@ uint16_t SSL_SESSION_protocol_version(const SSL_SESSION *session) { } 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 22149e25..56e4f2bc 100644 --- a/src/ssl/ssl_stat.cc +++ b/src/ssl/ssl_stat.cc @@ -188,9 +188,6 @@ const char *SSL_state_string_long(const SSL *ssl) { 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 4556fb77..898cd04b 100644 --- a/src/ssl/ssl_test.cc +++ b/src/ssl/ssl_test.cc @@ -361,12 +361,13 @@ static const char *kBadCurvesLists[] = { ":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 @@ static std::string CipherListToString(ssl_cipher_preference_list_st *list) { } 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 @@ static std::string CipherListToString(ssl_cipher_preference_list_st *list) { 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(SSLTest, CipherRules) { // 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 @@ TEST(SSLTest, CipherRules) { 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 @@ TEST(SSLTest, DefaultVersion) { 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 @@ TEST(SSLTest, CipherGetStandardName) { 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 4a00d0f2..2dfaf76f 100644 --- a/src/ssl/ssl_transcript.cc +++ b/src/ssl/ssl_transcript.cc @@ -178,8 +178,8 @@ static bool InitDigestWithData(EVP_MD_CTX *ctx, const EVP_MD *md, 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 2349df03..d4a6ee9f 100644 --- a/src/ssl/t1_enc.cc +++ b/src/ssl/t1_enc.cc @@ -483,25 +483,19 @@ size_t SSL_get_key_block_len(const SSL *ssl) { } 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 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, 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 27a942a8..39f4be62 100644 --- a/src/ssl/t1_lib.cc +++ b/src/ssl/t1_lib.cc @@ -204,12 +204,12 @@ done: 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 @@ int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { 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 b8c27859..b402f382 100644 --- a/src/ssl/test/runner/common.go +++ b/src/ssl/test/runner/common.go @@ -573,6 +573,10 @@ type ProtocolBugs struct { // 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 834be404..9fa49b5b 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 33c1b128..7423726e 100644 --- a/src/ssl/test/runner/handshake_client.go +++ b/src/ssl/test/runner/handshake_client.go @@ -974,8 +974,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { 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 @@ func (hs *clientHandshakeState) doFullHandshake() error { 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 614bb504..194244d6 100644 --- a/src/ssl/test/runner/handshake_server.go +++ b/src/ssl/test/runner/handshake_server.go @@ -863,8 +863,10 @@ ResendHelloRetryRequest: 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 9898101f..7e64fe5f 100644 --- a/src/ssl/test/runner/runner.go +++ b/src/ssl/test/runner/runner.go @@ -1512,6 +1512,24 @@ read alert 1 0 }, { 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 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { 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 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { 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 @@ func addTLS13HandshakeTests() { 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 @@ func addTLS13HandshakeTests() { Bugs: ProtocolBugs{ SendEarlyData: [][]byte{{1, 2, 3, 4}}, SendStrayEarlyHandshake: true, - ExpectEarlyDataAccepted: true}, + ExpectEarlyDataAccepted: true, + }, }, resumeSession: true, shouldFail: true, @@ -11800,6 +11815,100 @@ func addTLS13HandshakeTests() { "-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 1c2e7f75..39e0cb32 100644 --- a/src/ssl/tls13_both.cc +++ b/src/ssl/tls13_both.cc @@ -46,21 +46,16 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) { 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 @@ int tls13_get_cert_verify_signature_input( 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 @@ int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) { 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 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) { } 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 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) { 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 @@ int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) { 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 @@ int tls13_add_finished(SSL_HANDSHAKE *hs) { 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 @@ static int tls13_receive_key_update(SSL *ssl) { 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 @@ static int tls13_receive_key_update(SSL *ssl) { 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 @@ int tls13_post_handshake(SSL *ssl) { 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 29402652..83066be5 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 @@ enum client_hs_state_t { 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 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { } 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 @@ static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) { } } - 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 @@ static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) { } } - 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 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) { /* 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 @@ static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) { 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 ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) { 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); - break; - case state_continue_second_server_flight: - ret = do_continue_second_server_flight(hs); + case state_read_encrypted_extensions: + ret = do_read_encrypted_extensions(hs); break; - case state_process_certificate_request: - ret = do_process_certificate_request(hs); + case state_read_certificate_request: + ret = do_read_certificate_request(hs); break; - case state_process_server_certificate: - ret = do_process_server_certificate(hs); + case state_read_server_certificate: + ret = do_read_server_certificate(hs); break; - case state_process_server_certificate_verify: - ret = do_process_server_certificate_verify(hs); + case state_read_server_certificate_verify: + ret = do_read_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 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) { 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 @@ int tls13_process_new_session_ticket(SSL *ssl) { 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 1ae4849d..39e80be5 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 @@ static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version, } 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_key_schedule(SSL_HANDSHAKE *hs) { 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 @@ static const char kTLS13LabelApplicationTraffic[] = "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 @@ int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) { 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 @@ int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, const char *label, size_t label_len, const uint8_t *context, size_t context_len, int use_context) { - const EVP_MD *digest = ssl_get_handshake_digest( - SSL_get_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_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len) { } 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 03f8bddf..2b802c47 100644 --- a/src/ssl/tls13_server.cc +++ b/src/ssl/tls13_server.cc @@ -42,17 +42,17 @@ enum server_hs_state_t { 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 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { /* 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 @@ static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { /* 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_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_ticket_aead_result_t select_session( (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_ticket_aead_result_t select_session( 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 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) { 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 enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_change_cipher_spec(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) { 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 @@ static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) { } 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 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { 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 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) { 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 02f5c076..2fe4be3b 100644 --- a/src/ssl/tls_method.cc +++ b/src/ssl/tls_method.cc @@ -69,7 +69,21 @@ namespace bssl { 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 @@ static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = { 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 int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; } 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 f7a82598..d3a3115e 100644 --- a/src/tool/client.cc +++ b/src/tool/client.cc @@ -297,6 +297,26 @@ static bool DoConnection(SSL_CTX *ctx, 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 @@ bool Client(const std::vector<std::string> &args) { } 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) { |