summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Chromium Automerger <chromium-automerger@android>2014-09-26 00:30:54 +0000
committerAndroid Chromium Automerger <chromium-automerger@android>2014-09-26 00:30:54 +0000
commit885164b8d921ef7dba08b9e5ae031bf7350bf4ff (patch)
treebbdd45cda3f7f15eae3f9dfa9ac4d6a604d82479
parentf028ac1b7a2f3ca606ee44f7486a855588a0a7b1 (diff)
parent01fe820ab957514f6b83e511492de1b3c03649d5 (diff)
downloadsrc-885164b8d921ef7dba08b9e5ae031bf7350bf4ff.tar.gz
Merge third_party/boringssl/src from https://boringssl.googlesource.com/boringssl.git at 01fe820ab957514f6b83e511492de1b3c03649d5
This commit was generated by merge_from_chromium.py. Change-Id: Ic03398af24c5f9382f97f578539898b8d46d6036
-rw-r--r--crypto/bio/bio.c4
-rw-r--r--crypto/cpu-intel.c4
-rw-r--r--crypto/crypto.c18
-rw-r--r--crypto/digest/digest.c4
-rw-r--r--crypto/dsa/dsa.c33
-rw-r--r--crypto/pkcs8/pkcs12_test.c45
-rw-r--r--crypto/pkcs8/pkcs8.c141
-rw-r--r--include/openssl/base.h1
-rw-r--r--include/openssl/bio.h4
-rw-r--r--include/openssl/digest.h4
-rw-r--r--include/openssl/dsa.h8
-rw-r--r--include/openssl/pkcs8.h39
-rw-r--r--include/openssl/ssl.h18
-rw-r--r--ssl/CMakeLists.txt2
-rw-r--r--ssl/s23_clnt.c70
-rw-r--r--ssl/s3_lib.c92
-rw-r--r--ssl/ssl_algs.c4
-rw-r--r--ssl/ssl_ciph.c249
-rw-r--r--ssl/ssl_error.c2
-rw-r--r--ssl/ssl_lib.c10
-rw-r--r--ssl/ssl_locl.h12
-rw-r--r--ssl/ssl_test.c259
-rw-r--r--ssl/t1_enc.c4
-rw-r--r--ssl/t1_lib.c4
-rw-r--r--ssl/test/bssl_shim.cc56
-rw-r--r--ssl/test/runner/common.go15
-rw-r--r--ssl/test/runner/conn.go2
-rw-r--r--ssl/test/runner/handshake_client.go51
-rw-r--r--ssl/test/runner/handshake_messages.go106
-rw-r--r--ssl/test/runner/handshake_server.go42
-rw-r--r--ssl/test/runner/runner.go316
-rw-r--r--ssl/test/test_config.cc9
-rw-r--r--ssl/test/test_config.h6
-rw-r--r--tool/pkcs12.cc2
-rw-r--r--tool/tool.cc4
35 files changed, 1250 insertions, 390 deletions
diff --git a/crypto/bio/bio.c b/crypto/bio/bio.c
index a35ff65..7bd2976 100644
--- a/crypto/bio/bio.c
+++ b/crypto/bio/bio.c
@@ -351,6 +351,10 @@ size_t BIO_pending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
}
+size_t BIO_ctrl_pending(const BIO *bio) {
+ return BIO_pending(bio);
+}
+
size_t BIO_wpending(const BIO *bio) {
return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
}
diff --git a/crypto/cpu-intel.c b/crypto/cpu-intel.c
index e2efb2c..3dd08a9 100644
--- a/crypto/cpu-intel.c
+++ b/crypto/cpu-intel.c
@@ -61,7 +61,7 @@
#include <openssl/cpu.h>
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+#if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
#include <stdio.h>
#include <inttypes.h>
@@ -132,4 +132,4 @@ void OPENSSL_cpuid_setup(void) {
}
}
-#endif /* OPENSSL_X86 || OPENSSL_X86_64 */
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */
diff --git a/crypto/crypto.c b/crypto/crypto.c
index 78241da..ee7c405 100644
--- a/crypto/crypto.c
+++ b/crypto/crypto.c
@@ -16,14 +16,22 @@
#include "internal.h"
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+/* x86 and x86_64 need to record the result of a cpuid call for the asm to work
+ * correctly, unless compiled without asm code. */
+#define NEED_CPUID
-/* Currently, the only configurations which require a static initializer are x86
- * and x86_64. Don't bother emitting one in other cases. */
-#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && \
- !defined(BORINGSSL_NO_STATIC_INITIALIZER)
+#else
+
+/* Otherwise, don't emit a static initialiser. */
+
+#if !defined(BORINGSSL_NO_STATIC_INITIALIZER)
#define BORINGSSL_NO_STATIC_INITIALIZER
#endif
+#endif /* !OPENSSL_NO_ASM && (OPENSSL_X86 || OPENSSL_X86_64) */
+
#if defined(OPENSSL_WINDOWS)
#define OPENSSL_CDECL __cdecl
#else
@@ -45,7 +53,7 @@ __declspec(allocate(".CRT$XCU")) void(*library_init_constructor)(void) =
* BORINGSSL_NO_STATIC_INITIALIZER isn't defined, this is set as a static
* initializer. Otherwise, it is called by CRYPTO_library_init. */
static void OPENSSL_CDECL do_library_init(void) {
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
+#if defined(NEED_CPUID)
OPENSSL_cpuid_setup();
#endif
}
diff --git a/crypto/digest/digest.c b/crypto/digest/digest.c
index 2bfb0fa..3897c60 100644
--- a/crypto/digest/digest.c
+++ b/crypto/digest/digest.c
@@ -267,3 +267,7 @@ void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, uint32_t flags) {
uint32_t EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, uint32_t flags) {
return ctx->flags & flags;
}
+
+int EVP_add_digest(const EVP_MD *digest) {
+ return 1;
+}
diff --git a/crypto/dsa/dsa.c b/crypto/dsa/dsa.c
index 8c66ddf..25d15c0 100644
--- a/crypto/dsa/dsa.c
+++ b/crypto/dsa/dsa.c
@@ -60,6 +60,7 @@
#include <openssl/dsa.h>
#include <openssl/asn1.h>
+#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/ex_data.h>
@@ -332,3 +333,35 @@ int DSA_set_ex_data(DSA *d, int idx, void *arg) {
void *DSA_get_ex_data(const DSA *d, int idx) {
return CRYPTO_get_ex_data(&d->ex_data, idx);
}
+
+DH *DSA_dup_DH(const DSA *r) {
+ DH *ret = NULL;
+
+ if (r == NULL) {
+ goto err;
+ }
+ ret = DH_new();
+ if (ret == NULL) {
+ goto err;
+ }
+ if (r->q != NULL) {
+ ret->priv_length = BN_num_bits(r->q);
+ if ((ret->q = BN_dup(r->q)) == NULL) {
+ goto err;
+ }
+ }
+ if ((r->p != NULL && (ret->p = BN_dup(r->p)) == NULL) ||
+ (r->g != NULL && (ret->g = BN_dup(r->g)) == NULL) ||
+ (r->pub_key != NULL && (ret->pub_key = BN_dup(r->pub_key)) == NULL) ||
+ (r->priv_key != NULL && (ret->priv_key = BN_dup(r->priv_key)) == NULL)) {
+ goto err;
+ }
+
+ return ret;
+
+err:
+ if (ret != NULL) {
+ DH_free(ret);
+ }
+ return NULL;
+}
diff --git a/crypto/pkcs8/pkcs12_test.c b/crypto/pkcs8/pkcs12_test.c
index 6aea1eb..2292b77 100644
--- a/crypto/pkcs8/pkcs12_test.c
+++ b/crypto/pkcs8/pkcs12_test.c
@@ -705,13 +705,56 @@ static int test(const char *name, const uint8_t *der, size_t der_len) {
return 1;
}
+static int test_compat(const uint8_t *der, size_t der_len) {
+ PKCS12 *p12;
+ X509 *cert = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ EVP_PKEY *key;
+ BIO *bio;
+
+ bio = BIO_new_mem_buf((void*) der, der_len);
+
+ p12 = d2i_PKCS12_bio(bio, NULL);
+ if (p12 == NULL) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+ BIO_free(bio);
+
+ if (!PKCS12_parse(p12, "foo", &key, &cert, &ca_certs)) {
+ fprintf(stderr, "PKCS12_parse failed.\n");
+ BIO_print_errors_fp(stderr);
+ return 0;
+ }
+
+ if (key == NULL || cert == NULL) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+
+ EVP_PKEY_free(key);
+ X509_free(cert);
+
+ if (sk_X509_num(ca_certs) != 0) {
+ fprintf(stderr, "Bad result from PKCS12_parse.\n");
+ return 0;
+ }
+ sk_X509_free(ca_certs);
+
+ PKCS12_free(p12);
+
+ return 1;
+}
+
int main(int argc, char **argv) {
CRYPTO_library_init();
ERR_load_crypto_strings();
if (!test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
!test("NSS", kNSS, sizeof(kNSS)) ||
- !test("Windows", kWindows, sizeof(kWindows))) {
+ !test("Windows", kWindows, sizeof(kWindows)) ||
+ !test_compat(kWindows, sizeof(kWindows))) {
return 1;
}
diff --git a/crypto/pkcs8/pkcs8.c b/crypto/pkcs8/pkcs8.c
index 04fce98..58e400d 100644
--- a/crypto/pkcs8/pkcs8.c
+++ b/crypto/pkcs8/pkcs8.c
@@ -55,8 +55,12 @@
#include <openssl/pkcs8.h>
+#include <assert.h>
+#include <limits.h>
+
#include <openssl/asn1.h>
#include <openssl/bn.h>
+#include <openssl/buf.h>
#include <openssl/cipher.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -64,8 +68,6 @@
#include <openssl/mem.h>
#include <openssl/x509.h>
-#include <limits.h>
-
#include "../bytestring/internal.h"
#include "../evp/internal.h"
@@ -879,6 +881,7 @@ int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
/* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
* four. */
if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
+ CBS_len(&in) != 0 ||
!CBS_get_asn1_uint64(&pfx, &version)) {
OPENSSL_PUT_ERROR(PKCS8, PKCS12_parse, PKCS8_R_BAD_PKCS12_DATA);
goto err;
@@ -1015,3 +1018,137 @@ err:
return ret;
}
+
+void PKCS12_PBE_add(){};
+
+struct pkcs12_st {
+ uint8_t *ber_bytes;
+ size_t ber_len;
+};
+
+PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) {
+ PKCS12 *p12;
+
+ /* out_p12 must be NULL because we don't export the PKCS12 structure. */
+ assert(out_p12 == NULL);
+
+ p12 = OPENSSL_malloc(sizeof(PKCS12));
+ if (!p12) {
+ return NULL;
+ }
+
+ p12->ber_bytes = OPENSSL_malloc(ber_len);
+ if (!p12->ber_bytes) {
+ OPENSSL_free(p12);
+ return NULL;
+ }
+
+ memcpy(p12->ber_bytes, *ber_bytes, ber_len);
+ p12->ber_len = ber_len;
+ *ber_bytes += ber_len;
+
+ return p12;
+}
+
+PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
+ size_t used = 0;
+ BUF_MEM *buf;
+ const uint8_t *dummy;
+ static const size_t kMaxSize = 256 * 1024;
+ PKCS12 *ret = NULL;
+
+ buf = BUF_MEM_new();
+ if (buf == NULL) {
+ return NULL;
+ }
+ if (BUF_MEM_grow(buf, 8192) == 0) {
+ goto out;
+ }
+
+ for (;;) {
+ int n = BIO_read(bio, &buf->data[used], buf->length - used);
+ if (n < 0) {
+ goto out;
+ }
+
+ if (n == 0) {
+ break;
+ }
+ used += n;
+
+ if (used < buf->length) {
+ continue;
+ }
+
+ if (buf->length > kMaxSize ||
+ BUF_MEM_grow(buf, buf->length * 2) == 0) {
+ goto out;
+ }
+ }
+
+ dummy = (uint8_t*) buf->data;
+ ret = d2i_PKCS12(out_p12, &dummy, used);
+
+out:
+ BUF_MEM_free(buf);
+ return ret;
+}
+
+PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
+ BIO *bio;
+ PKCS12 *ret;
+
+ bio = BIO_new_fp(fp, 0 /* don't take ownership */);
+ if (!bio) {
+ return NULL;
+ }
+
+ ret = d2i_PKCS12_bio(bio, out_p12);
+ BIO_free(bio);
+ return ret;
+}
+
+int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
+ X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
+ CBS ber_bytes;
+ STACK_OF(X509) *ca_certs = NULL;
+ char ca_certs_alloced = 0;
+
+ if (out_ca_certs != NULL && *out_ca_certs != NULL) {
+ ca_certs = *out_ca_certs;
+ }
+
+ if (!ca_certs) {
+ ca_certs = sk_X509_new_null();
+ if (ca_certs == NULL) {
+ return 0;
+ }
+ ca_certs_alloced = 1;
+ }
+
+ CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
+ if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
+ if (ca_certs_alloced) {
+ sk_X509_free(ca_certs);
+ }
+ return 0;
+ }
+
+ *out_cert = NULL;
+ if (sk_X509_num(ca_certs) > 0) {
+ *out_cert = sk_X509_shift(ca_certs);
+ }
+
+ if (out_ca_certs) {
+ *out_ca_certs = ca_certs;
+ } else {
+ sk_X509_pop_free(ca_certs, X509_free);
+ }
+
+ return 1;
+}
+
+void PKCS12_free(PKCS12 *p12) {
+ OPENSSL_free(p12->ber_bytes);
+ OPENSSL_free(p12);
+}
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 079b1c4..52cb1e9 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -192,6 +192,7 @@ typedef struct hmac_ctx_st HMAC_CTX;
typedef struct md4_state_st MD4_CTX;
typedef struct md5_state_st MD5_CTX;
typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
+typedef struct pkcs12_st PKCS12;
typedef struct rand_meth_st RAND_METHOD;
typedef struct rsa_meth_st RSA_METHOD;
typedef struct rsa_st RSA;
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index da0a356..547a36a 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -235,6 +235,10 @@ OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp);
/* BIO_pending returns the number of bytes pending to be read. */
OPENSSL_EXPORT size_t BIO_pending(const BIO *bio);
+/* BIO_ctrl_pending calls |BIO_pending| and exists only for compatibility with
+ * OpenSSL. */
+OPENSSL_EXPORT size_t BIO_ctrl_pending(const BIO *bio);
+
/* BIO_wpending returns the number of bytes pending to be written. */
OPENSSL_EXPORT size_t BIO_wpending(const BIO *bio);
diff --git a/include/openssl/digest.h b/include/openssl/digest.h
index 291a548..6d8a165 100644
--- a/include/openssl/digest.h
+++ b/include/openssl/digest.h
@@ -200,6 +200,10 @@ OPENSSL_EXPORT size_t EVP_MD_block_size(const EVP_MD *md);
* |in|. It returns one on success and zero on error. */
OPENSSL_EXPORT int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+/* EVP_add_digest does nothing and returns one. It exists only for
+ * compatibility with OpenSSL. */
+OPENSSL_EXPORT int EVP_add_digest(const EVP_MD *digest);
+
/* Digest operation accessors. */
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index c8156fa..5e71ae2 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -291,6 +291,14 @@ OPENSSL_EXPORT int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx,
BIGNUM **out_kinv, BIGNUM **out_r);
+/* Conversion. */
+
+/* DSA_dup_DH returns a |DH| constructed from the parameters of |dsa|. This is
+ * sometimes needed when Diffie-Hellman parameters are stored in the form of
+ * DSA parameters. It returns an allocated |DH| on success or NULL on error. */
+OPENSSL_EXPORT DH *DSA_dup_DH(const DSA *dsa);
+
+
/* ex_data functions.
*
* These functions are wrappers. See |ex_data.h| for details. */
diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h
index 6feb7f1..8735387 100644
--- a/include/openssl/pkcs8.h
+++ b/include/openssl/pkcs8.h
@@ -59,6 +59,8 @@
#include <openssl/base.h>
+#include <stdio.h>
+
#include <openssl/x509.h>
#if defined(__cplusplus)
@@ -129,6 +131,43 @@ OPENSSL_EXPORT int PKCS12_get_key_and_certs(EVP_PKEY **out_key,
STACK_OF(X509) *out_certs,
CBS *in, const char *password);
+
+/* Deprecated functions. */
+
+/* PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. */
+OPENSSL_EXPORT void PKCS12_PBE_add();
+
+/* d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a
+ * |PKCS12| structure. The |out_p12| argument must be NULL. On exit,
+ * |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12|
+ * structure or NULL on error.
+ *
+ * Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len|
+ * bytes.*/
+OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
+ size_t ber_len);
+
+/* d2i_PKCS12_bio acts like |d2i_PKCS12| but reads from a |BIO|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12);
+
+/* d2i_PKCS12_fp acts like |d2i_PKCS12| but reads from a |FILE|. */
+OPENSSL_EXPORT PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12);
+
+/* PKCS12_parse calls |PKCS12_get_key_and_certs| on the ASN.1 data stored in
+ * |p12|. The |out_pkey| and |out_cert| arguments must not be NULL and, on
+ * successful exit, the private key and first certificate will be stored in
+ * them. The |out_ca_certs| argument may be NULL but, if not, then any extra
+ * certificates will be appended to |*out_ca_certs|. If |*out_ca_certs| is NULL
+ * then it will be set to a freshly allocated stack containing the extra certs.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS12_parse(const PKCS12 *p12, const char *password,
+ EVP_PKEY **out_pkey, X509 **out_cert,
+ STACK_OF(X509) **out_ca_certs);
+
+/* PKCS12_free frees |p12| and its contents. */
+OPENSSL_EXPORT void PKCS12_free(PKCS12 *p12);
+
#if defined(__cplusplus)
} /* extern C */
#endif
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 3838511..48ad549 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -522,13 +522,13 @@ struct ssl_session_st
#define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|\
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2)
-/* These next two were never actually used for anything since SSLeay
- * zap so we have some more flags.
- */
-/* The next flag deliberately changes the ciphertest, this is a check
- * for the PKCS#1 attack */
-#define SSL_OP_PKCS1_CHECK_1 0x0
-#define SSL_OP_PKCS1_CHECK_2 0x0
+/* The following flags do nothing and are included only to make it easier to
+ * compile code with BoringSSL. */
+#define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0
+#define SSL_OP_MICROSOFT_SESS_ID_BUG 0
+#define SSL_OP_NETSCAPE_CHALLENGE_BUG 0
+#define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0
+#define SSL_OP_TLS_BLOCK_PADDING_BUG 0
/* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
* when just a single record has been written): */
@@ -783,7 +783,7 @@ DECLARE_LHASH_OF(SSL_SESSION);
struct ssl_cipher_preference_list_st
{
STACK_OF(SSL_CIPHER) *ciphers;
- unsigned char *in_group_flags;
+ uint8_t *in_group_flags;
};
struct ssl_ctx_st
@@ -2790,6 +2790,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_R_UNPROCESSED_HANDSHAKE_DATA 440
#define SSL_R_HANDSHAKE_RECORD_BEFORE_CCS 441
#define SSL_R_SESSION_MAY_NOT_BE_CREATED 442
+#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
#define SSL_R_TLSV1_ALERT_DECRYPTION_FAILED 1021
@@ -2811,6 +2812,7 @@ OPENSSL_EXPORT void ERR_load_SSL_strings(void);
#define SSL_R_TLSV1_ALERT_PROTOCOL_VERSION 1070
#define SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY 1071
#define SSL_R_TLSV1_ALERT_INTERNAL_ERROR 1080
+#define SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK 1086
#define SSL_R_TLSV1_ALERT_USER_CANCELLED 1090
#define SSL_R_TLSV1_ALERT_NO_RENEGOTIATION 1100
#define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110
diff --git a/ssl/CMakeLists.txt b/ssl/CMakeLists.txt
index 3db8607..49f7c3d 100644
--- a/ssl/CMakeLists.txt
+++ b/ssl/CMakeLists.txt
@@ -53,4 +53,4 @@ add_executable(
ssl_test.c
)
-target_link_libraries(ssl_test crypto)
+target_link_libraries(ssl_test ssl crypto)
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index cec6f8c..ccb3e2c 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -121,16 +121,13 @@ static int ssl23_client_hello(SSL *s);
static int ssl23_get_server_hello(SSL *s);
static const SSL_METHOD *ssl23_get_client_method(int ver)
{
- if (ver == SSL3_VERSION)
- return(SSLv3_client_method());
- else if (ver == TLS1_VERSION)
- return(TLSv1_client_method());
- else if (ver == TLS1_1_VERSION)
- return(TLSv1_1_client_method());
- else if (ver == TLS1_2_VERSION)
- return(TLSv1_2_client_method());
- else
- return(NULL);
+ /* When SSL_set_session is called, do NOT switch to the version-specific
+ * method table. The server may still negotiate a different version when
+ * rejecting the session.
+ *
+ * TODO(davidben): Clean this up. This duplicates logic from the
+ * version-specific tables. https://crbug.com/403378 */
+ return SSLv23_client_method();
}
IMPLEMENT_ssl23_meth_func(SSLv23_client_method,
@@ -167,12 +164,6 @@ int ssl23_connect(SSL *s)
case SSL_ST_BEFORE|SSL_ST_CONNECT:
case SSL_ST_OK|SSL_ST_CONNECT:
- if (s->session != NULL)
- {
- OPENSSL_PUT_ERROR(SSL, ssl23_connect, SSL_R_SSL23_DOING_SESSION_ID_REUSE);
- ret= -1;
- goto end;
- }
s->server=0;
if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
@@ -288,17 +279,10 @@ static int ssl23_client_hello(SSL *s)
* TLS1>=1, it would be insufficient to pass SSL_NO_TLSv1, the
* answer is SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2.
*/
- mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1
- |SSL_OP_NO_SSLv3
- ;
-#if !defined(OPENSSL_NO_TLS1_2_CLIENT)
+ mask = SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3;
version = TLS1_2_VERSION;
-
if ((options & SSL_OP_NO_TLSv1_2) && (options & mask) != mask)
version = TLS1_1_VERSION;
-#else
- version = TLS1_1_VERSION;
-#endif
mask &= ~SSL_OP_NO_TLSv1_1;
if ((options & SSL_OP_NO_TLSv1_1) && (options & mask) != mask)
version = TLS1_VERSION;
@@ -310,13 +294,17 @@ static int ssl23_client_hello(SSL *s)
buf=(unsigned char *)s->init_buf->data;
if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
{
-#if 0
- /* don't reuse session-id's */
- if (!ssl_get_new_session(s,0))
+ /* Check if the session is resumable. If not, drop it. */
+ if (s->session != NULL)
{
- return(-1);
+ if (s->session->ssl_version > version ||
+ s->session->session_id_length == 0 ||
+ s->session->not_resumable)
+ {
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ }
}
-#endif
p=s->s3->client_random;
if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
@@ -370,8 +358,22 @@ static int ssl23_client_hello(SSL *s)
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
p += SSL3_RANDOM_SIZE;
- /* Session ID (zero since there is no reuse) */
- *(p++) = 0;
+ /* Session ID */
+ if (s->new_session || s->session == NULL)
+ i=0;
+ else
+ i=s->session->session_id_length;
+ *(p++)=i;
+ if (i != 0)
+ {
+ if (i > (int)sizeof(s->session->session_id))
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl23_client_hello, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+ memcpy(p,s->session->session_id,i);
+ p+=i;
+ }
/* Ciphers supported (using SSL 3.0/TLS 1.0 format) */
i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &p[2]);
@@ -568,9 +570,9 @@ static int ssl23_get_server_hello(SSL *s)
}
s->init_num=0;
- /* Since, if we are sending a ssl23 client hello, we are not
- * reusing a session-id */
- if (!ssl_get_new_session(s,0))
+ /* If there was no session to resume, now that the final version is
+ * determined, insert a fresh one. */
+ if (s->session == NULL && !ssl_get_new_session(s,0))
goto err;
return(SSL_connect(s));
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 479b6de..5a1b48d 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -178,7 +178,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF|SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD,
128,
128,
@@ -194,7 +194,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -210,7 +210,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
112,
168,
@@ -228,7 +228,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -245,7 +245,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -260,7 +260,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -275,7 +275,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -291,7 +291,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -307,7 +307,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -323,7 +323,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -340,7 +340,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -356,7 +356,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -374,7 +374,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -390,7 +390,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -406,7 +406,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -422,7 +422,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -439,7 +439,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -455,7 +455,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -471,7 +471,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -489,7 +489,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -505,7 +505,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -522,7 +522,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -538,7 +538,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -555,7 +555,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -571,7 +571,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -588,7 +588,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -604,7 +604,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -620,7 +620,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -636,7 +636,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -652,7 +652,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -668,7 +668,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -684,7 +684,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_RC4,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_MEDIUM,
+ SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -700,7 +700,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
128,
128,
@@ -716,7 +716,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT|TLS1_PRF,
256,
256,
@@ -735,7 +735,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
@@ -751,7 +751,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA384,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
@@ -767,7 +767,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128,
SSL_SHA256,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
128,
128,
@@ -783,7 +783,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256,
SSL_SHA384,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
256,
256,
@@ -801,7 +801,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -817,7 +817,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -834,7 +834,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
128,
@@ -850,7 +850,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES256GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
+ SSL_HIGH|SSL_FIPS,
SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
256,
@@ -868,7 +868,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_AES128GCM,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(4)|
SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD,
128,
@@ -885,7 +885,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
@@ -900,7 +900,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
@@ -915,7 +915,7 @@ const SSL_CIPHER ssl3_ciphers[]={
SSL_CHACHA20POLY1305,
SSL_AEAD,
SSL_TLSV1_2,
- SSL_NOT_EXP|SSL_HIGH,
+ SSL_HIGH,
SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256|SSL_CIPHER_ALGORITHM2_AEAD|FIXED_NONCE_LEN(0),
256,
0,
diff --git a/ssl/ssl_algs.c b/ssl/ssl_algs.c
index 9308d40..a1aa7b2 100644
--- a/ssl/ssl_algs.c
+++ b/ssl/ssl_algs.c
@@ -63,9 +63,7 @@ extern const ERR_STRING_DATA SSL_error_string_data[];
int SSL_library_init(void)
{
CRYPTO_library_init();
- ERR_load_crypto_strings();
- ERR_load_strings(SSL_error_string_data);
- ssl_load_ciphers();
+ SSL_load_error_strings();
return(1);
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 8361007..fbed548 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -147,34 +147,18 @@
#include "ssl_locl.h"
-#define SSL_ENC_3DES_IDX 0
-#define SSL_ENC_RC4_IDX 1
-#define SSL_ENC_AES128_IDX 2
-#define SSL_ENC_AES256_IDX 3
-#define SSL_ENC_NUM_IDX 4
-
-
-static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]= { 0 };
-
-#define SSL_MD_MD5_IDX 0
-#define SSL_MD_SHA1_IDX 1
-#define SSL_MD_SHA256_IDX 2
-#define SSL_MD_SHA384_IDX 3
-/*Constant SSL_MAX_DIGEST equal to size of digests array should be
- * defined in the
- * ssl_locl.h */
-#define SSL_MD_NUM_IDX SSL_MAX_DIGEST
-static const EVP_MD *ssl_digest_methods[SSL_MD_NUM_IDX] = { 0 };
-static const int ssl_mac_pkey_id[SSL_MD_NUM_IDX]={
- EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC, EVP_PKEY_HMAC,
+struct handshake_digest
+ {
+ long mask;
+ const EVP_MD *(*md_func)(void);
};
-static int ssl_mac_secret_size[SSL_MD_NUM_IDX] = { 0 };
-
-static const int ssl_handshake_digest_flag[SSL_MD_NUM_IDX]={
- SSL_HANDSHAKE_MAC_MD5, SSL_HANDSHAKE_MAC_SHA,
- SSL_HANDSHAKE_MAC_SHA256, SSL_HANDSHAKE_MAC_SHA384,
- };
+static const struct handshake_digest ssl_handshake_digests[SSL_MAX_DIGEST] = {
+ { SSL_HANDSHAKE_MAC_MD5, EVP_md5 },
+ { SSL_HANDSHAKE_MAC_SHA, EVP_sha1 },
+ { SSL_HANDSHAKE_MAC_SHA256, EVP_sha256 },
+ { SSL_HANDSHAKE_MAC_SHA384, EVP_sha384 },
+};
#define CIPHER_ADD 1
#define CIPHER_KILL 2
@@ -255,26 +239,6 @@ static const SSL_CIPHER cipher_aliases[]={
{0,SSL_TXT_FIPS,0, 0,0,0,0,0,SSL_FIPS, 0,0,0},
};
-void ssl_load_ciphers(void)
- {
- ssl_cipher_methods[SSL_ENC_3DES_IDX]= EVP_des_ede3_cbc();
- ssl_cipher_methods[SSL_ENC_RC4_IDX]= EVP_rc4();
- ssl_cipher_methods[SSL_ENC_AES128_IDX]= EVP_aes_128_cbc();
- ssl_cipher_methods[SSL_ENC_AES256_IDX]= EVP_aes_256_cbc();
-
- ssl_digest_methods[SSL_MD_MD5_IDX]= EVP_md5();
- ssl_mac_secret_size[SSL_MD_MD5_IDX]= EVP_MD_size(EVP_md5());
- assert(ssl_mac_secret_size[SSL_MD_MD5_IDX] >= 0);
- ssl_digest_methods[SSL_MD_SHA1_IDX]=EVP_sha1();
- ssl_mac_secret_size[SSL_MD_SHA1_IDX]= EVP_MD_size(EVP_sha1());
- assert(ssl_mac_secret_size[SSL_MD_SHA1_IDX] >= 0);
-
- ssl_digest_methods[SSL_MD_SHA256_IDX]= EVP_sha256();
- ssl_mac_secret_size[SSL_MD_SHA256_IDX]= EVP_MD_size(EVP_sha256());
- ssl_digest_methods[SSL_MD_SHA384_IDX]= EVP_sha384();
- ssl_mac_secret_size[SSL_MD_SHA384_IDX]= EVP_MD_size(EVP_sha384());
- }
-
/* ssl_cipher_get_evp_aead sets |*aead| to point to the correct EVP_AEAD object
* for |s->cipher|. It returns 1 on success and 0 on error. */
int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
@@ -314,7 +278,6 @@ int ssl_cipher_get_evp_aead(const SSL_SESSION *s, const EVP_AEAD **aead)
int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size)
{
- int i;
const SSL_CIPHER *c;
c=s->cipher;
@@ -330,39 +293,32 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
switch (c->algorithm_enc)
{
case SSL_3DES:
- i=SSL_ENC_3DES_IDX;
+ *enc = EVP_des_ede3_cbc();
break;
case SSL_RC4:
- i=SSL_ENC_RC4_IDX;
+ *enc = EVP_rc4();
break;
case SSL_AES128:
- i=SSL_ENC_AES128_IDX;
+ *enc = EVP_aes_128_cbc();
break;
case SSL_AES256:
- i=SSL_ENC_AES256_IDX;
+ *enc = EVP_aes_256_cbc();
break;
default:
- i= -1;
- break;
+ return 0;
}
- if ((i < 0) || (i >= SSL_ENC_NUM_IDX))
- *enc=NULL;
- else
- *enc=ssl_cipher_methods[i];
-
if (!ssl_cipher_get_mac(s, md, mac_pkey_type, mac_secret_size))
return 0;
- if ((*enc != NULL) && (*md != NULL) &&
- (!mac_pkey_type||*mac_pkey_type != NID_undef))
- {
+ assert(*enc != NULL && *md != NULL);
+
+ /* TODO(fork): enable the stitched cipher modes. */
+#if 0
if (s->ssl_version>>8 != TLS1_VERSION_MAJOR ||
s->ssl_version < TLS1_VERSION)
return 1;
- /* TODO(fork): enable the stitched cipher modes. */
-#if 0
if (c->algorithm_enc == SSL_RC4 &&
c->algorithm_mac == SSL_MD5 &&
(evp=EVP_get_cipherbyname("RC4-HMAC-MD5")))
@@ -376,15 +332,12 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
(evp=EVP_get_cipherbyname("AES-256-CBC-HMAC-SHA1")))
*enc = evp, *md = NULL;
#endif
- return(1);
- }
- else
- return(0);
+
+ return 1;
}
int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size)
{
- int i;
const SSL_CIPHER *c;
c=s->cipher;
@@ -393,49 +346,40 @@ int ssl_cipher_get_mac(const SSL_SESSION *s, const EVP_MD **md, int *mac_pkey_ty
switch (c->algorithm_mac)
{
case SSL_MD5:
- i=SSL_MD_MD5_IDX;
+ *md = EVP_md5();
break;
case SSL_SHA1:
- i=SSL_MD_SHA1_IDX;
+ *md = EVP_sha1();
break;
case SSL_SHA256:
- i=SSL_MD_SHA256_IDX;
+ *md = EVP_sha256();
break;
case SSL_SHA384:
- i=SSL_MD_SHA384_IDX;
+ *md = EVP_sha384();
break;
default:
- i= -1;
- break;
+ return 0;
}
- if ((i < 0) || (i >= SSL_MD_NUM_IDX))
+ if (mac_pkey_type != NULL)
{
- *md=NULL;
- if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef;
- if (mac_secret_size!=NULL) *mac_secret_size = 0;
+ *mac_pkey_type = EVP_PKEY_HMAC;
}
- else
+ if (mac_secret_size!=NULL)
{
- *md=ssl_digest_methods[i];
- if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i];
- if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
+ *mac_secret_size = EVP_MD_size(*md);
}
-
return 1;
}
int ssl_get_handshake_digest(int idx, long *mask, const EVP_MD **md)
{
- if (idx <0||idx>=SSL_MD_NUM_IDX)
+ if (idx < 0 || idx >= SSL_MAX_DIGEST)
{
return 0;
}
- *mask = ssl_handshake_digest_flag[idx];
- if (*mask)
- *md = ssl_digest_methods[idx];
- else
- *md = NULL;
+ *mask = ssl_handshake_digests[idx].mask;
+ *md = ssl_handshake_digests[idx].md_func();
return 1;
}
@@ -474,31 +418,8 @@ static void ll_append_head(CIPHER_ORDER **head, CIPHER_ORDER *curr,
*head=curr;
}
-static void ssl_cipher_get_disabled(unsigned long *mkey, unsigned long *auth, unsigned long *enc, unsigned long *mac, unsigned long *ssl)
- {
- *mkey = 0;
- *auth = 0;
- *enc = 0;
- *mac = 0;
- *ssl = 0;
-
- *enc |= (ssl_cipher_methods[SSL_ENC_3DES_IDX] == NULL) ? SSL_3DES:0;
- *enc |= (ssl_cipher_methods[SSL_ENC_RC4_IDX ] == NULL) ? SSL_RC4 :0;
- *enc |= (ssl_cipher_methods[SSL_ENC_AES128_IDX] == NULL) ? SSL_AES128:0;
- *enc |= (ssl_cipher_methods[SSL_ENC_AES256_IDX] == NULL) ? SSL_AES256:0;
-
- *mac |= (ssl_digest_methods[SSL_MD_MD5_IDX ] == NULL) ? SSL_MD5 :0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA1_IDX] == NULL) ? SSL_SHA1:0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA256_IDX] == NULL) ? SSL_SHA256:0;
- *mac |= (ssl_digest_methods[SSL_MD_SHA384_IDX] == NULL) ? SSL_SHA384:0;
-
- }
-
static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
int num_of_ciphers,
- unsigned long disabled_mkey, unsigned long disabled_auth,
- unsigned long disabled_enc, unsigned long disabled_mac,
- unsigned long disabled_ssl,
CIPHER_ORDER *co_list,
CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
{
@@ -518,12 +439,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
{
c = ssl_method->get_cipher(i);
/* drop those that use any of that is not available */
- if ((c != NULL) && c->valid &&
- !(c->algorithm_mkey & disabled_mkey) &&
- !(c->algorithm_auth & disabled_auth) &&
- !(c->algorithm_enc & disabled_enc) &&
- !(c->algorithm_mac & disabled_mac) &&
- !(c->algorithm_ssl & disabled_ssl))
+ if ((c != NULL) && c->valid)
{
co_list[co_list_num].cipher = c;
co_list[co_list_num].next = NULL;
@@ -569,19 +485,11 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
int num_of_group_aliases,
- unsigned long disabled_mkey, unsigned long disabled_auth,
- unsigned long disabled_enc, unsigned long disabled_mac,
- unsigned long disabled_ssl,
CIPHER_ORDER *head)
{
CIPHER_ORDER *ciph_curr;
const SSL_CIPHER **ca_curr;
int i;
- unsigned long mask_mkey = ~disabled_mkey;
- unsigned long mask_auth = ~disabled_auth;
- unsigned long mask_enc = ~disabled_enc;
- unsigned long mask_mac = ~disabled_mac;
- unsigned long mask_ssl = ~disabled_ssl;
/*
* First, add the real ciphers as already collected
@@ -603,32 +511,6 @@ static void ssl_cipher_collect_aliases(const SSL_CIPHER **ca_list,
*/
for (i = 0; i < num_of_group_aliases; i++)
{
- unsigned long algorithm_mkey = cipher_aliases[i].algorithm_mkey;
- unsigned long algorithm_auth = cipher_aliases[i].algorithm_auth;
- unsigned long algorithm_enc = cipher_aliases[i].algorithm_enc;
- unsigned long algorithm_mac = cipher_aliases[i].algorithm_mac;
- unsigned long algorithm_ssl = cipher_aliases[i].algorithm_ssl;
-
- if (algorithm_mkey)
- if ((algorithm_mkey & mask_mkey) == 0)
- continue;
-
- if (algorithm_auth)
- if ((algorithm_auth & mask_auth) == 0)
- continue;
-
- if (algorithm_enc)
- if ((algorithm_enc & mask_enc) == 0)
- continue;
-
- if (algorithm_mac)
- if ((algorithm_mac & mask_mac) == 0)
- continue;
-
- if (algorithm_ssl)
- if ((algorithm_ssl & mask_ssl) == 0)
- continue;
-
*ca_curr = cipher_aliases + i;
ca_curr++;
}
@@ -711,9 +593,7 @@ static void ssl_cipher_apply_rule(unsigned long cipher_id,
continue;
if (alg_ssl && !(alg_ssl & cp->algorithm_ssl))
continue;
- if ((algo_strength & SSL_EXP_MASK) && !(algo_strength & SSL_EXP_MASK & cp->algo_strength))
- continue;
- if ((algo_strength & SSL_STRONG_MASK) && !(algo_strength & SSL_STRONG_MASK & cp->algo_strength))
+ if (algo_strength && !(algo_strength & cp->algo_strength))
continue;
}
@@ -881,20 +761,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
{ rule = CIPHER_DEL; l++; }
else if (ch == '+')
{ rule = CIPHER_ORD; l++; }
- else if (ch == '!' && has_group)
- {
- OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
- retval = found = in_group = 0;
- break;
- }
else if (ch == '!')
{ rule = CIPHER_KILL; l++; }
- else if (ch == '@' && has_group)
- {
- OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
- retval = found = in_group = 0;
- break;
- }
else if (ch == '@')
{ rule = CIPHER_SPECIAL; l++; }
else if (ch == '[')
@@ -913,6 +781,16 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
else
{ rule = CIPHER_ADD; }
+ /* If preference groups are enabled, the only legal
+ * operator is +. Otherwise the in_group bits will get
+ * mixed up. */
+ if (has_group && rule != CIPHER_ADD)
+ {
+ OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+ retval = found = in_group = 0;
+ break;
+ }
+
if (ITEM_SEP(ch))
{
l++;
@@ -1040,26 +918,15 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
alg_mac = ca_list[j]->algorithm_mac;
}
- if (ca_list[j]->algo_strength & SSL_EXP_MASK)
+ if (ca_list[j]->algo_strength)
{
- if (algo_strength & SSL_EXP_MASK)
+ if (algo_strength)
{
- algo_strength &= (ca_list[j]->algo_strength & SSL_EXP_MASK) | ~SSL_EXP_MASK;
- if (!(algo_strength & SSL_EXP_MASK)) { found = 0; break; }
+ algo_strength &= ca_list[j]->algo_strength;
+ if (!algo_strength) { found = 0; break; }
}
else
- algo_strength |= ca_list[j]->algo_strength & SSL_EXP_MASK;
- }
-
- if (ca_list[j]->algo_strength & SSL_STRONG_MASK)
- {
- if (algo_strength & SSL_STRONG_MASK)
- {
- algo_strength &= (ca_list[j]->algo_strength & SSL_STRONG_MASK) | ~SSL_STRONG_MASK;
- if (!(algo_strength & SSL_STRONG_MASK)) { found = 0; break; }
- }
- else
- algo_strength |= ca_list[j]->algo_strength & SSL_STRONG_MASK;
+ algo_strength |= ca_list[j]->algo_strength;
}
if (ca_list[j]->valid)
@@ -1122,7 +989,6 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
}
- if (*l == '\0') break; /* done */
}
if (in_group)
@@ -1141,7 +1007,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
const char *rule_str, CERT *c)
{
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
- unsigned long disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl;
STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
@@ -1157,12 +1022,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
return NULL;
/*
- * To reduce the work to do we only want to process the compiled
- * in algorithms, so we first get the mask of disabled ciphers.
- */
- ssl_cipher_get_disabled(&disabled_mkey, &disabled_auth, &disabled_enc, &disabled_mac, &disabled_ssl);
-
- /*
* Now we have to collect the available ciphers from the compiled
* in ciphers. We cannot get more than the number compiled in, so
* it is used for allocation.
@@ -1179,7 +1038,6 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
}
ssl_cipher_collect_ciphers(ssl_method, num_of_ciphers,
- disabled_mkey, disabled_auth, disabled_enc, disabled_mac, disabled_ssl,
co_list, &head, &tail);
@@ -1242,13 +1100,10 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
ca_list = OPENSSL_malloc(sizeof(SSL_CIPHER *) * num_of_alias_max);
if (ca_list == NULL)
{
- OPENSSL_free(co_list);
OPENSSL_PUT_ERROR(SSL, ssl_create_cipher_list, ERR_R_MALLOC_FAILURE);
- return(NULL); /* Failure */
+ goto err;
}
- ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
- disabled_mkey, disabled_auth, disabled_enc,
- disabled_mac, disabled_ssl, head);
+ ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, head);
/*
* If the rule_string begins with DEFAULT, apply the default rule
diff --git a/ssl/ssl_error.c b/ssl/ssl_error.c
index f6120dc..0ba125b 100644
--- a/ssl/ssl_error.c
+++ b/ssl/ssl_error.c
@@ -453,6 +453,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED), "SSLV3_ALERT_CERTIFICATE_EXPIRED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED), "SSLV3_ALERT_CERTIFICATE_REVOKED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN), "SSLV3_ALERT_CERTIFICATE_UNKNOWN"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_CLOSE_NOTIFY), "SSLV3_ALERT_CLOSE_NOTIFY"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE), "SSLV3_ALERT_DECOMPRESSION_FAILURE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE), "SSLV3_ALERT_HANDSHAKE_FAILURE"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER), "SSLV3_ALERT_ILLEGAL_PARAMETER"},
@@ -472,6 +473,7 @@ const ERR_STRING_DATA SSL_error_string_data[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPTION_FAILED), "TLSV1_ALERT_DECRYPTION_FAILED"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_DECRYPT_ERROR), "TLSV1_ALERT_DECRYPT_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION), "TLSV1_ALERT_EXPORT_RESTRICTION"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK), "TLSV1_ALERT_INAPPROPRIATE_FALLBACK"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY), "TLSV1_ALERT_INSUFFICIENT_SECURITY"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_INTERNAL_ERROR), "TLSV1_ALERT_INTERNAL_ERROR"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV1_ALERT_NO_RENEGOTIATION), "TLSV1_ALERT_NO_RENEGOTIATION"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 1ad825a..720ab54 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -172,6 +172,13 @@ SSL3_ENC_METHOD ssl3_undef_enc_method={
int use_context)) ssl_undefined_function,
};
+/* Some error codes are special. Ensure the make_errors.go script
+ * never regresses this. */
+OPENSSL_COMPILE_ASSERT(
+ SSL_R_TLSV1_ALERT_NO_RENEGOTIATION ==
+ SSL_AD_NO_RENEGOTIATION + SSL_AD_REASON_OFFSET,
+ ssl_alert_reason_code_mismatch);
+
int SSL_clear(SSL *s)
{
@@ -1144,11 +1151,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
s->max_cert_list=larg;
return(l);
case SSL_CTRL_SET_MTU:
-#ifndef OPENSSL_NO_DTLS1
if (larg < (long)dtls1_min_mtu())
return 0;
-#endif
-
if (SSL_IS_DTLS(s))
{
s->d1->mtu = larg;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 2d10650..f9f3bed 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -359,14 +359,9 @@
/*
* Cipher strength information.
*/
-#define SSL_EXP_MASK 0x00000003L
-#define SSL_STRONG_MASK 0x000001fcL
-
-#define SSL_NOT_EXP 0x00000001L
-
-#define SSL_MEDIUM 0x00000040L
-#define SSL_HIGH 0x00000080L
-#define SSL_FIPS 0x00000100L
+#define SSL_MEDIUM 0x00000001L
+#define SSL_HIGH 0x00000002L
+#define SSL_FIPS 0x00000004L
/* we have used 000001ff - 23 bits left to go */
@@ -850,7 +845,6 @@ int ssl_cert_type(X509 *x,EVP_PKEY *pkey);
void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
int ssl_verify_alarm_type(long type);
-void ssl_load_ciphers(void);
int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
const SSL_CIPHER *ssl3_get_cipher_by_value(uint16_t value);
diff --git a/ssl/ssl_test.c b/ssl/ssl_test.c
index 97a1967..68889a0 100644
--- a/ssl/ssl_test.c
+++ b/ssl/ssl_test.c
@@ -14,14 +14,261 @@
#include <stdio.h>
-#include "openssl/ssl.h"
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+typedef struct {
+ int id;
+ int in_group_flag;
+} EXPECTED_CIPHER;
+
+typedef struct {
+ /* The rule string to apply. */
+ const char *rule;
+ /* The list of expected ciphers, in order, terminated with -1. */
+ const EXPECTED_CIPHER *expected;
+} CIPHER_TEST;
+
+/* Selecting individual ciphers should work. */
+static const char kRule1[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected1[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* + reorders selected ciphers to the end, keeping their relative
+ * order. */
+static const char kRule2[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "+aRSA";
+
+static const EXPECTED_CIPHER kExpected2[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* ! banishes ciphers from future selections. */
+static const char kRule3[] =
+ "!aRSA:"
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected3[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Multiple masks can be ANDed in a single rule. */
+static const char kRule4[] = "kRSA+AESGCM+AES128";
+
+static const EXPECTED_CIPHER kExpected4[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* - removes selected ciphers, but preserves their order for future
+ * selections. Select AES_128_GCM, but order the key exchanges RSA,
+ * DHE_RSA, ECDHE_RSA. */
+static const char kRule5[] =
+ "ALL:-kEECDH:-kEDH:-kRSA:-ALL:"
+ "AESGCM+AES128+aRSA";
+
+static const EXPECTED_CIPHER kExpected5[] = {
+ { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Unknown selectors are no-ops. */
+static const char kRule6[] =
+ "ECDHE-ECDSA-CHACHA20-POLY1305:"
+ "ECDHE-RSA-CHACHA20-POLY1305:"
+ "ECDHE-ECDSA-AES128-GCM-SHA256:"
+ "ECDHE-RSA-AES128-GCM-SHA256:"
+ "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4";
+
+static const EXPECTED_CIPHER kExpected6[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* Square brackets specify equi-preference groups. */
+static const char kRule7[] =
+ "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
+ "[ECDHE-RSA-CHACHA20-POLY1305]:"
+ "ECDHE-RSA-AES128-GCM-SHA256";
+
+static const EXPECTED_CIPHER kExpected7[] = {
+ { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305, 1 },
+ { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
+ { -1, -1 },
+};
+
+/* @STRENGTH performs a stable strength-sort of the selected
+ * ciphers and only the selected ciphers. */
+static const char kRule8[] =
+ /* To simplify things, banish all but {ECDHE_RSA,RSA} x
+ * {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1. */
+ "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
+ /* Order some ciphers backwards by strength. */
+ "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
+ /* Select ECDHE ones and sort them by strength. Ties should resolve
+ * based on the order above. */
+ "kEECDH:@STRENGTH:-ALL:"
+ /* Now bring back everything uses RSA. ECDHE_RSA should be first,
+ * sorted by strength. Then RSA, backwards by strength. */
+ "aRSA";
+
+static const EXPECTED_CIPHER kExpected8[] = {
+ { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 },
+ { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 },
+ { SSL3_CK_RSA_RC4_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
+ { TLS1_CK_RSA_WITH_AES_256_SHA, 0 },
+ { -1, -1 },
+};
+
+static CIPHER_TEST kCipherTests[] = {
+ { kRule1, kExpected1 },
+ { kRule2, kExpected2 },
+ { kRule3, kExpected3 },
+ { kRule4, kExpected4 },
+ { kRule5, kExpected5 },
+ { kRule6, kExpected6 },
+ { kRule7, kExpected7 },
+ { kRule8, kExpected8 },
+ { NULL, NULL },
+};
+
+static const char *kBadRules[] = {
+ /* Invalid brackets. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
+ "RSA]",
+ "[[RSA]]",
+ /* Operators inside brackets */
+ "[+RSA]",
+ /* Unknown directive. */
+ "@BOGUS",
+ /* Empty cipher lists error at SSL_CTX_set_cipher_list. */
+ "",
+ "BOGUS",
+ /* Invalid command. */
+ "?BAR",
+ /* Special operators are not allowed if groups are used. */
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
+ "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
+ NULL,
+};
+
+static void print_cipher_preference_list(
+ struct ssl_cipher_preference_list_st *list) {
+ size_t i;
+ int in_group = 0;
+ for (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]) {
+ fprintf(stderr, "\t[\n");
+ in_group = 1;
+ }
+ fprintf(stderr, "\t");
+ if (in_group) {
+ fprintf(stderr, " ");
+ }
+ fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
+ if (in_group && !list->in_group_flags[i]) {
+ fprintf(stderr, "\t]\n");
+ in_group = 0;
+ }
+ }
+}
+
+static int test_cipher_rule(CIPHER_TEST *t) {
+ int ret = 0;
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ size_t i;
+
+ if (!SSL_CTX_set_cipher_list(ctx, t->rule)) {
+ fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule);
+ BIO_print_errors_fp(stderr);
+ goto done;
+ }
+
+ /* Compare the two lists. */
+ for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+ const SSL_CIPHER *cipher =
+ sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
+ if (t->expected[i].id != SSL_CIPHER_get_id(cipher) ||
+ t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+ }
+
+ if (t->expected[i].id != -1) {
+ fprintf(stderr, "Error: cipher rule '%s' evaluted to:\n", t->rule);
+ print_cipher_preference_list(ctx->cipher_list);
+ goto done;
+ }
+
+ ret = 1;
+done:
+ SSL_CTX_free(ctx);
+ return ret;
+}
+
+static int test_cipher_rules(void) {
+ size_t i;
+ for (i = 0; kCipherTests[i].rule != NULL; i++) {
+ if (!test_cipher_rule(&kCipherTests[i])) {
+ return 0;
+ }
+ }
+
+ for (i = 0; kBadRules[i] != NULL; i++) {
+ SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+ if (SSL_CTX_set_cipher_list(ctx, kBadRules[i])) {
+ fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]);
+ return 0;
+ }
+ ERR_clear_error();
+ SSL_CTX_free(ctx);
+ }
+
+ return 1;
+}
int main(void) {
- /* Some error codes are special, but the make_errors.go script doesn't know
- * this. This test will catch the case where something regenerates the error
- * codes with the script but doesn't fix up the special ones. */
- if (SSL_R_TLSV1_ALERT_NO_RENEGOTIATION != 100 + SSL_AD_REASON_OFFSET) {
- fprintf(stderr, "SSL alert errors don't match up.\n");
+ SSL_library_init();
+
+ if (!test_cipher_rules()) {
return 1;
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 2f92524..ca6bf6c 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -596,7 +596,9 @@ int tls1_setup_key_block(SSL *s)
goto cipher_unavailable_err;
key_len = EVP_AEAD_key_length(aead);
iv_len = SSL_CIPHER_AEAD_FIXED_NONCE_LEN(s->session->cipher);
- if (!ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size))
+ if ((s->session->cipher->algorithm2 &
+ SSL_CIPHER_ALGORITHM2_STATEFUL_AEAD) &&
+ !ssl_cipher_get_mac(s->session, &hash, &mac_type, &mac_secret_size))
goto cipher_unavailable_err;
/* For "stateful" AEADs (i.e. compatibility with pre-AEAD
* cipher suites) the key length reported by
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index b9553a5..eccf875 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1783,7 +1783,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, CBS *cbs, int *out_alert)
!(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))
{
*out_alert = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
+ OPENSSL_PUT_ERROR(SSL, ssl_scan_clienthello_tlsext, SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
/* If no signature algorithms extension set default values */
@@ -2193,7 +2193,7 @@ static int ssl_check_serverhello_tlsext(SSL *s)
}
if (!found_uncompressed)
{
- OPENSSL_PUT_ERROR(SSL, ssl_add_serverhello_tlsext, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
+ OPENSSL_PUT_ERROR(SSL, ssl_check_serverhello_tlsext, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
return -1;
}
}
diff --git a/ssl/test/bssl_shim.cc b/ssl/test/bssl_shim.cc
index 0459afc..5ee7c65 100644
--- a/ssl/test/bssl_shim.cc
+++ b/ssl/test/bssl_shim.cc
@@ -139,6 +139,29 @@ static int next_proto_select_callback(SSL* ssl,
return SSL_TLSEXT_ERR_OK;
}
+static int alpn_select_callback(SSL* ssl,
+ const uint8_t** out,
+ uint8_t* outlen,
+ const uint8_t* in,
+ unsigned inlen,
+ void* arg) {
+ const TestConfig *config = GetConfigPtr(ssl);
+ if (config->select_alpn.empty())
+ return SSL_TLSEXT_ERR_NOACK;
+
+ if (!config->expected_advertised_alpn.empty() &&
+ (config->expected_advertised_alpn.size() != inlen ||
+ memcmp(config->expected_advertised_alpn.data(),
+ in, inlen) != 0)) {
+ fprintf(stderr, "bad ALPN select callback inputs\n");
+ exit(1);
+ }
+
+ *out = (const uint8_t*)config->select_alpn.data();
+ *outlen = config->select_alpn.size();
+ return SSL_TLSEXT_ERR_OK;
+}
+
static int cookie_generate_callback(SSL *ssl, uint8_t *cookie, size_t *cookie_len) {
*cookie_len = 32;
memset(cookie, 42, *cookie_len);
@@ -213,8 +236,13 @@ static SSL_CTX *setup_ctx(const TestConfig *config) {
SSL_CTX_set_next_protos_advertised_cb(
ssl_ctx, next_protos_advertised_callback, NULL);
- SSL_CTX_set_next_proto_select_cb(
- ssl_ctx, next_proto_select_callback, NULL);
+ if (!config->select_next_proto.empty()) {
+ SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_callback, NULL);
+ }
+
+ if (!config->select_alpn.empty()) {
+ SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_callback, NULL);
+ }
SSL_CTX_set_cookie_generate_cb(ssl_ctx, cookie_generate_callback);
SSL_CTX_set_cookie_verify_cb(ssl_ctx, cookie_verify_callback);
@@ -336,6 +364,13 @@ static int do_exchange(SSL_SESSION **out_session,
}
EVP_PKEY_free(pkey);
}
+ if (!config->host_name.empty()) {
+ SSL_set_tlsext_host_name(ssl, config->host_name.c_str());
+ }
+ if (!config->advertise_alpn.empty()) {
+ SSL_set_alpn_protos(ssl, (const uint8_t *)config->advertise_alpn.data(),
+ config->advertise_alpn.size());
+ }
BIO *bio = BIO_new_fd(fd, 1 /* take ownership */);
if (bio == NULL) {
@@ -376,8 +411,9 @@ static int do_exchange(SSL_SESSION **out_session,
return 2;
}
- if (is_resume && !SSL_session_reused(ssl)) {
- fprintf(stderr, "session was not reused\n");
+ if (is_resume && (SSL_session_reused(ssl) == config->expect_session_miss)) {
+ fprintf(stderr, "session was%s reused\n",
+ SSL_session_reused(ssl) ? "" : " not");
return 2;
}
@@ -422,6 +458,18 @@ static int do_exchange(SSL_SESSION **out_session,
}
}
+ if (!config->expected_alpn.empty()) {
+ const uint8_t *alpn_proto;
+ unsigned alpn_proto_len;
+ SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
+ if (alpn_proto_len != config->expected_alpn.size() ||
+ memcmp(alpn_proto, config->expected_alpn.data(),
+ alpn_proto_len) != 0) {
+ fprintf(stderr, "negotiated alpn proto mismatch\n");
+ return 2;
+ }
+ }
+
if (!config->expected_channel_id.empty()) {
uint8_t channel_id[64];
if (!SSL_get_tls_channel_id(ssl, channel_id, sizeof(channel_id))) {
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index f22f95a..cf244bc 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -76,6 +76,7 @@ const (
extensionSupportedCurves uint16 = 10
extensionSupportedPoints uint16 = 11
extensionSignatureAlgorithms uint16 = 13
+ extensionALPN uint16 = 16
extensionSessionTicket uint16 = 35
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
@@ -166,6 +167,7 @@ type ConnectionState struct {
CipherSuite uint16 // cipher suite in use (TLS_RSA_WITH_RC4_128_SHA, ...)
NegotiatedProtocol string // negotiated next protocol (from Config.NextProtos)
NegotiatedProtocolIsMutual bool // negotiated protocol was advertised by server
+ NegotiatedProtocolFromALPN bool // protocol negotiated with ALPN
ServerName string // server name requested by client, if any (server side only)
PeerCertificates []*x509.Certificate // certificate chain presented by remote peer
VerifiedChains [][]*x509.Certificate // verified chains built from PeerCertificates
@@ -449,6 +451,19 @@ type ProtocolBugs struct {
// SkipCipherVersionCheck causes the server to negotiate
// TLS 1.2 ciphers in earlier versions of TLS.
SkipCipherVersionCheck bool
+
+ // ExpectServerName, if not empty, is the hostname the client
+ // must specify in the server_name extension.
+ ExpectServerName string
+
+ // SwapNPNAndALPN switches the relative order between NPN and
+ // ALPN on the server. This is to test that server preference
+ // of ALPN works regardless of their relative order.
+ SwapNPNAndALPN bool
+
+ // AllowSessionVersionMismatch causes the server to resume sessions
+ // regardless of the version associated with the session.
+ AllowSessionVersionMismatch bool
}
func (c *Config) serverInit() {
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 47b6e61..9f0c328 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -47,6 +47,7 @@ type Conn struct {
clientProtocol string
clientProtocolFallback bool
+ usedALPN bool
channelID *ecdsa.PublicKey
@@ -1105,6 +1106,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.NegotiatedProtocol = c.clientProtocol
state.DidResume = c.didResume
state.NegotiatedProtocolIsMutual = !c.clientProtocolFallback
+ state.NegotiatedProtocolFromALPN = c.usedALPN
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 708d282..d78e767 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -43,6 +43,18 @@ func (c *Conn) clientHandshake() error {
c.sendHandshakeSeq = 0
c.recvHandshakeSeq = 0
+ nextProtosLength := 0
+ for _, proto := range c.config.NextProtos {
+ if l := len(proto); l == 0 || l > 255 {
+ return errors.New("tls: invalid NextProtos value")
+ } else {
+ nextProtosLength += 1 + l
+ }
+ }
+ if nextProtosLength > 0xffff {
+ return errors.New("tls: NextProtos values too large")
+ }
+
hello := &clientHelloMsg{
isDTLS: c.isDTLS,
vers: c.config.maxVersion(),
@@ -54,8 +66,10 @@ func (c *Conn) clientHandshake() error {
supportedPoints: []uint8{pointFormatUncompressed},
nextProtoNeg: len(c.config.NextProtos) > 0,
secureRenegotiation: true,
+ alpnProtocols: c.config.NextProtos,
duplicateExtension: c.config.Bugs.DuplicateExtension,
channelIDSupported: c.config.ChannelID != nil,
+ npnLast: c.config.Bugs.SwapNPNAndALPN,
}
if c.config.Bugs.SendClientVersion != 0 {
@@ -565,11 +579,32 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
return false, errors.New("tls: server selected unsupported compression format")
}
- if !hs.hello.nextProtoNeg && hs.serverHello.nextProtoNeg {
+ clientDidNPN := hs.hello.nextProtoNeg
+ clientDidALPN := len(hs.hello.alpnProtocols) > 0
+ serverHasNPN := hs.serverHello.nextProtoNeg
+ serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
+
+ if !clientDidNPN && serverHasNPN {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested NPN extension")
}
+ if !clientDidALPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised unrequested ALPN extension")
+ }
+
+ if serverHasNPN && serverHasALPN {
+ c.sendAlert(alertHandshakeFailure)
+ return false, errors.New("server advertised both NPN and ALPN extensions")
+ }
+
+ if serverHasALPN {
+ c.clientProtocol = hs.serverHello.alpnProtocol
+ c.clientProtocolFallback = false
+ c.usedALPN = true
+ }
+
if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
c.sendAlert(alertHandshakeFailure)
return false, errors.New("server advertised unrequested Channel ID extension")
@@ -750,20 +785,20 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
return serverAddr.String()
}
-// mutualProtocol finds the mutual Next Protocol Negotiation protocol given the
-// set of client and server supported protocols. The set of client supported
-// protocols must not be empty. It returns the resulting protocol and flag
+// mutualProtocol finds the mutual Next Protocol Negotiation or ALPN protocol
+// given list of possible protocols and a list of the preference order. The
+// first list must not be empty. It returns the resulting protocol and flag
// indicating if the fallback case was reached.
-func mutualProtocol(clientProtos, serverProtos []string) (string, bool) {
- for _, s := range serverProtos {
- for _, c := range clientProtos {
+func mutualProtocol(protos, preferenceProtos []string) (string, bool) {
+ for _, s := range preferenceProtos {
+ for _, c := range protos {
if s == c {
return s, false
}
}
}
- return clientProtos[0], true
+ return protos[0], true
}
// writeIntPadded writes x into b, padded up with leading zeros as
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index 472aa87..136360d 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -24,8 +24,10 @@ type clientHelloMsg struct {
sessionTicket []uint8
signatureAndHashes []signatureAndHash
secureRenegotiation bool
+ alpnProtocols []string
duplicateExtension bool
channelIDSupported bool
+ npnLast bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -51,8 +53,10 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
m.secureRenegotiation == m1.secureRenegotiation &&
+ eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
m.duplicateExtension == m1.duplicateExtension &&
- m.channelIDSupported == m1.channelIDSupported
+ m.channelIDSupported == m1.channelIDSupported &&
+ m.npnLast == m1.npnLast
}
func (m *clientHelloMsg) marshal() []byte {
@@ -103,6 +107,17 @@ func (m *clientHelloMsg) marshal() []byte {
if m.channelIDSupported {
numExtensions++
}
+ if len(m.alpnProtocols) > 0 {
+ extensionsLength += 2
+ for _, s := range m.alpnProtocols {
+ if l := len(s); l == 0 || l > 255 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength++
+ extensionsLength += len(s)
+ }
+ numExtensions++
+ }
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -147,7 +162,7 @@ func (m *clientHelloMsg) marshal() []byte {
z[1] = 0xff
z = z[4:]
}
- if m.nextProtoNeg {
+ if m.nextProtoNeg && !m.npnLast {
z[0] = byte(extensionNextProtoNeg >> 8)
z[1] = byte(extensionNextProtoNeg & 0xff)
// The length is always 0
@@ -266,11 +281,38 @@ func (m *clientHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if len(m.alpnProtocols) > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ lengths := z[2:]
+ z = z[6:]
+
+ stringsLength := 0
+ for _, s := range m.alpnProtocols {
+ l := len(s)
+ z[0] = byte(l)
+ copy(z[1:], s)
+ z = z[1+l:]
+ stringsLength += 1 + l
+ }
+
+ lengths[2] = byte(stringsLength >> 8)
+ lengths[3] = byte(stringsLength)
+ stringsLength += 2
+ lengths[0] = byte(stringsLength >> 8)
+ lengths[1] = byte(stringsLength)
+ }
if m.channelIDSupported {
z[0] = byte(extensionChannelID >> 8)
z[1] = byte(extensionChannelID & 0xff)
z = z[4:]
}
+ if m.nextProtoNeg && m.npnLast {
+ z[0] = byte(extensionNextProtoNeg >> 8)
+ z[1] = byte(extensionNextProtoNeg & 0xff)
+ // The length is always 0
+ z = z[4:]
+ }
if m.duplicateExtension {
// Add a duplicate bogus extension at the beginning and end.
z[0] = 0xff
@@ -342,6 +384,7 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.ticketSupported = false
m.sessionTicket = nil
m.signatureAndHashes = nil
+ m.alpnProtocols = nil
if len(data) == 0 {
// ClientHello is optionally followed by extension data
@@ -451,6 +494,24 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ if length < 2 {
+ return false
+ }
+ l := int(data[0])<<8 | int(data[1])
+ if l != length-2 {
+ return false
+ }
+ d := data[2:length]
+ for len(d) != 0 {
+ stringLen := int(d[0])
+ d = d[1:]
+ if stringLen == 0 || stringLen > len(d) {
+ return false
+ }
+ m.alpnProtocols = append(m.alpnProtocols, string(d[:stringLen]))
+ d = d[stringLen:]
+ }
case extensionChannelID:
if length > 0 {
return false
@@ -476,6 +537,7 @@ type serverHelloMsg struct {
ocspStapling bool
ticketSupported bool
secureRenegotiation bool
+ alpnProtocol string
duplicateExtension bool
channelIDRequested bool
}
@@ -498,6 +560,7 @@ func (m *serverHelloMsg) equal(i interface{}) bool {
m.ocspStapling == m1.ocspStapling &&
m.ticketSupported == m1.ticketSupported &&
m.secureRenegotiation == m1.secureRenegotiation &&
+ m.alpnProtocol == m1.alpnProtocol &&
m.duplicateExtension == m1.duplicateExtension &&
m.channelIDRequested == m1.channelIDRequested
}
@@ -536,6 +599,14 @@ func (m *serverHelloMsg) marshal() []byte {
if m.channelIDRequested {
numExtensions++
}
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ if alpnLen >= 256 {
+ panic("invalid ALPN protocol")
+ }
+ extensionsLength += 2 + 1 + alpnLen
+ numExtensions++
+ }
+
if numExtensions > 0 {
extensionsLength += 4 * numExtensions
length += 2 + extensionsLength
@@ -603,6 +674,20 @@ func (m *serverHelloMsg) marshal() []byte {
z[3] = 1
z = z[5:]
}
+ if alpnLen := len(m.alpnProtocol); alpnLen > 0 {
+ z[0] = byte(extensionALPN >> 8)
+ z[1] = byte(extensionALPN & 0xff)
+ l := 2 + 1 + alpnLen
+ z[2] = byte(l >> 8)
+ z[3] = byte(l)
+ l -= 2
+ z[4] = byte(l >> 8)
+ z[5] = byte(l)
+ l -= 1
+ z[6] = byte(l)
+ copy(z[7:], []byte(m.alpnProtocol))
+ z = z[7+alpnLen:]
+ }
if m.channelIDRequested {
z[0] = byte(extensionChannelID >> 8)
z[1] = byte(extensionChannelID & 0xff)
@@ -644,6 +729,7 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
m.nextProtos = nil
m.ocspStapling = false
m.ticketSupported = false
+ m.alpnProtocol = ""
if len(data) == 0 {
// ServerHello is optionally followed by extension data
@@ -698,6 +784,22 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
return false
}
m.secureRenegotiation = true
+ case extensionALPN:
+ d := data[:length]
+ if len(d) < 3 {
+ return false
+ }
+ l := int(d[0])<<8 | int(d[1])
+ if l != len(d)-2 {
+ return false
+ }
+ d = d[2:]
+ l = int(d[0])
+ if l != len(d)-1 {
+ return false
+ }
+ d = d[1:]
+ m.alpnProtocol = string(d)
case extensionChannelID:
if length > 0 {
return false
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 6d61fd5..1eb3f11 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -220,13 +220,22 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
c.serverName = hs.clientHello.serverName
}
- // Although sending an empty NPN extension is reasonable, Firefox has
- // had a bug around this. Best to send nothing at all if
- // config.NextProtos is empty. See
- // https://code.google.com/p/go/issues/detail?id=5445.
- if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
- hs.hello.nextProtoNeg = true
- hs.hello.nextProtos = config.NextProtos
+
+ if len(hs.clientHello.alpnProtocols) > 0 {
+ if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+ hs.hello.alpnProtocol = selectedProto
+ c.clientProtocol = selectedProto
+ c.usedALPN = true
+ }
+ } else {
+ // Although sending an empty NPN extension is reasonable, Firefox has
+ // had a bug around this. Best to send nothing at all if
+ // config.NextProtos is empty. See
+ // https://code.google.com/p/go/issues/detail?id=5445.
+ if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+ hs.hello.nextProtoNeg = true
+ hs.hello.nextProtos = config.NextProtos
+ }
}
if len(config.Certificates) == 0 {
@@ -237,6 +246,9 @@ Curves:
if len(hs.clientHello.serverName) > 0 {
hs.cert = config.getCertificateForName(hs.clientHello.serverName)
}
+ if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
+ return false, errors.New("tls: unexpected server name")
+ }
if hs.clientHello.channelIDSupported && config.RequestChannelID {
hs.hello.channelIDRequested = true
@@ -290,16 +302,22 @@ Curves:
func (hs *serverHandshakeState) checkForResumption() bool {
c := hs.c
- var ok bool
- if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+ if c.config.SessionTicketsDisabled {
return false
}
- if hs.sessionState.vers > hs.clientHello.vers {
+ var ok bool
+ if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
return false
}
- if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
- return false
+
+ if !c.config.Bugs.AllowSessionVersionMismatch {
+ if hs.sessionState.vers > hs.clientHello.vers {
+ return false
+ }
+ if vers, ok := c.config.mutualVersion(hs.sessionState.vers); !ok || vers != hs.sessionState.vers {
+ return false
+ }
}
cipherSuiteOk := false
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 64df21d..323f43f 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -97,6 +97,11 @@ const (
dtls
)
+const (
+ alpn = 1
+ npn = 2
+)
+
type testCase struct {
testType testType
protocol protocol
@@ -110,9 +115,18 @@ type testCase struct {
// expectedVersion, if non-zero, specifies the TLS version that must be
// negotiated.
expectedVersion uint16
+ // expectedResumeVersion, if non-zero, specifies the TLS version that
+ // must be negotiated on resumption. If zero, expectedVersion is used.
+ expectedResumeVersion uint16
// expectChannelID controls whether the connection should have
// negotiated a Channel ID with channelIDKey.
expectChannelID bool
+ // expectedNextProto controls whether the connection should
+ // negotiate a next protocol via NPN or ALPN.
+ expectedNextProto string
+ // expectedNextProtoType, if non-zero, is the expected next
+ // protocol negotiation mechanism.
+ expectedNextProtoType int
// messageLen is the length, in bytes, of the test message that will be
// sent.
messageLen int
@@ -121,8 +135,13 @@ type testCase struct {
// keyFile is the path to the private key to use for the server.
keyFile string
// resumeSession controls whether a second connection should be tested
- // which resumes the first session.
+ // which attempts to resume the first session.
resumeSession bool
+ // resumeConfig, if not nil, points to a Config to be used on
+ // resumption. SessionTicketKey and ClientSessionCache are copied from
+ // the initial connection's config. If nil, the initial connection's
+ // config is used.
+ resumeConfig *Config
// sendPrefix sends a prefix on the socket before actually performing a
// handshake.
sendPrefix string
@@ -202,36 +221,6 @@ var testCases = []testCase{
flags: []string{"-fallback-scsv"},
},
{
- testType: serverTest,
- name: "ServerNameExtension",
- config: Config{
- ServerName: "example.com",
- },
- flags: []string{"-expect-server-name", "example.com"},
- },
- {
- testType: clientTest,
- name: "DuplicateExtensionClient",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- },
- {
- testType: serverTest,
- name: "DuplicateExtensionServer",
- config: Config{
- Bugs: ProtocolBugs{
- DuplicateExtension: true,
- },
- },
- shouldFail: true,
- expectedLocalError: "remote error: error decoding message",
- },
- {
name: "ClientCertificateTypes",
config: Config{
ClientAuth: RequestClientCert,
@@ -497,7 +486,7 @@ var testCases = []testCase{
},
}
-func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) error {
+func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int, isResume bool) error {
if test.protocol == dtls {
conn = newPacketAdaptor(conn)
}
@@ -528,8 +517,15 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e
return err
}
- if vers := tlsConn.ConnectionState().Version; test.expectedVersion != 0 && vers != test.expectedVersion {
- return fmt.Errorf("got version %x, expected %x", vers, test.expectedVersion)
+ // TODO(davidben): move all per-connection expectations into a dedicated
+ // expectations struct that can be specified separately for the two
+ // legs.
+ expectedVersion := test.expectedVersion
+ if isResume && test.expectedResumeVersion != 0 {
+ expectedVersion = test.expectedResumeVersion
+ }
+ if vers := tlsConn.ConnectionState().Version; expectedVersion != 0 && vers != expectedVersion {
+ return fmt.Errorf("got version %x, expected %x", vers, expectedVersion)
}
if test.expectChannelID {
@@ -544,6 +540,18 @@ func doExchange(test *testCase, config *Config, conn net.Conn, messageLen int) e
}
}
+ if expected := test.expectedNextProto; expected != "" {
+ if actual := tlsConn.ConnectionState().NegotiatedProtocol; actual != expected {
+ return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
+ }
+ }
+
+ if test.expectedNextProtoType != 0 {
+ if (test.expectedNextProtoType == alpn) != tlsConn.ConnectionState().NegotiatedProtocolFromALPN {
+ return fmt.Errorf("next proto type mismatch")
+ }
+ }
+
if test.shimWritesFirst {
var buf [5]byte
_, err := io.ReadFull(tlsConn, buf[:])
@@ -705,12 +713,25 @@ func runTest(test *testCase, buildDir string) error {
}
}
- err := doExchange(test, &config, conn, test.messageLen)
+ err := doExchange(test, &config, conn, test.messageLen,
+ false /* not a resumption */)
conn.Close()
if err == nil && test.resumeSession {
- err = doExchange(test, &config, connResume, test.messageLen)
- connResume.Close()
+ var resumeConfig Config
+ if test.resumeConfig != nil {
+ resumeConfig = *test.resumeConfig
+ if len(resumeConfig.Certificates) == 0 {
+ resumeConfig.Certificates = []Certificate{getRSACertificate()}
+ }
+ resumeConfig.SessionTicketKey = config.SessionTicketKey
+ resumeConfig.ClientSessionCache = config.ClientSessionCache
+ } else {
+ resumeConfig = config
+ }
+ err = doExchange(test, &resumeConfig, connResume, test.messageLen,
+ true /* resumption */)
}
+ connResume.Close()
childErr := shim.Wait()
@@ -1159,13 +1180,14 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
protocol: protocol,
name: "NPN-Client" + suffix,
config: Config{
- CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
- NextProtos: []string{"foo"},
+ NextProtos: []string{"foo"},
Bugs: ProtocolBugs{
MaxHandshakeRecordLength: maxHandshakeRecordLength,
},
},
- flags: append(flags, "-select-next-proto", "foo"),
+ flags: append(flags, "-select-next-proto", "foo"),
+ expectedNextProto: "foo",
+ expectedNextProtoType: npn,
})
testCases = append(testCases, testCase{
protocol: protocol,
@@ -1180,6 +1202,8 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
flags: append(flags,
"-advertise-npn", "\x03foo\x03bar\x03baz",
"-expect-next-proto", "bar"),
+ expectedNextProto: "bar",
+ expectedNextProtoType: npn,
})
// Client does False Start and negotiates NPN.
@@ -1201,6 +1225,25 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol)
resumeSession: true,
})
+ // Client does False Start and negotiates ALPN.
+ testCases = append(testCases, testCase{
+ protocol: protocol,
+ name: "FalseStart-ALPN" + suffix,
+ config: Config{
+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+ NextProtos: []string{"foo"},
+ Bugs: ProtocolBugs{
+ ExpectFalseStart: true,
+ MaxHandshakeRecordLength: maxHandshakeRecordLength,
+ },
+ },
+ flags: append(flags,
+ "-false-start",
+ "-advertise-alpn", "\x03foo"),
+ shimWritesFirst: true,
+ resumeSession: true,
+ })
+
// False Start without session tickets.
testCases = append(testCases, testCase{
name: "FalseStart-SessionTicketsDisabled",
@@ -1372,6 +1415,197 @@ func addD5BugTests() {
})
}
+func addExtensionTests() {
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "DuplicateExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "DuplicateExtensionServer",
+ config: Config{
+ Bugs: ProtocolBugs{
+ DuplicateExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: error decoding message",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "example.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "mismatch.com",
+ },
+ },
+ flags: []string{"-host-name", "example.com"},
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ServerNameExtensionClient",
+ config: Config{
+ Bugs: ProtocolBugs{
+ ExpectServerName: "missing.com",
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "tls: unexpected server name",
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ServerNameExtensionServer",
+ config: Config{
+ ServerName: "example.com",
+ },
+ flags: []string{"-expect-server-name", "example.com"},
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "ALPNClient",
+ config: Config{
+ NextProtos: []string{"foo"},
+ },
+ flags: []string{
+ "-advertise-alpn", "\x03foo\x03bar\x03baz",
+ "-expect-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ // Test that the server prefers ALPN over NPN.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "ALPNServer-Preferred-Swapped",
+ config: Config{
+ NextProtos: []string{"foo", "bar", "baz"},
+ Bugs: ProtocolBugs{
+ SwapNPNAndALPN: true,
+ },
+ },
+ flags: []string{
+ "-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+ "-select-alpn", "foo",
+ "-advertise-npn", "\x03foo\x03bar\x03baz",
+ },
+ expectedNextProto: "foo",
+ expectedNextProtoType: alpn,
+ resumeSession: true,
+ })
+}
+
+func addResumptionVersionTests() {
+ // TODO(davidben): Once DTLS 1.2 is working, test that as well.
+ for _, sessionVers := range tlsVersions {
+ // TODO(davidben): SSLv3 is omitted here because runner does not
+ // support resumption with session IDs.
+ if sessionVers.version == VersionSSL30 {
+ continue
+ }
+ for _, resumeVers := range tlsVersions {
+ if resumeVers.version == VersionSSL30 {
+ continue
+ }
+ suffix := "-" + sessionVers.name + "-" + resumeVers.name
+
+ // TODO(davidben): Write equivalent tests for the server
+ // and clean up the server's logic. This requires being
+ // able to give the shim a different set of SSL_OP_NO_*
+ // flags between the initial connection and the
+ // resume. Perhaps resumption should be tested by
+ // serializing the SSL_SESSION and starting a second
+ // shim.
+ testCases = append(testCases, testCase{
+ name: "Resume-Client" + suffix,
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ Bugs: ProtocolBugs{
+ AllowSessionVersionMismatch: true,
+ },
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+
+ testCases = append(testCases, testCase{
+ name: "Resume-Client-NoResume" + suffix,
+ flags: []string{"-expect-session-miss"},
+ resumeSession: true,
+ config: Config{
+ MaxVersion: sessionVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ },
+ expectedVersion: sessionVers.version,
+ resumeConfig: &Config{
+ MaxVersion: resumeVers.version,
+ CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+ SessionTicketsDisabled: true,
+ },
+ expectedResumeVersion: resumeVers.version,
+ })
+ }
+ }
+}
+
func worker(statusChan chan statusMsg, c chan *testCase, buildDir string, wg *sync.WaitGroup) {
defer wg.Done()
@@ -1425,6 +1659,8 @@ func main() {
addClientAuthTests()
addVersionNegotiationTests()
addD5BugTests()
+ addExtensionTests()
+ addResumptionVersionTests()
for _, async := range []bool{false, true} {
for _, splitHandshake := range []bool{false, true} {
for _, protocol := range []protocol{tls, dtls} {
diff --git a/ssl/test/test_config.cc b/ssl/test/test_config.cc
index 41188af..70543cc 100644
--- a/ssl/test/test_config.cc
+++ b/ssl/test/test_config.cc
@@ -55,6 +55,7 @@ const BoolFlag kBoolFlags[] = {
{ "-cookie-exchange", &TestConfig::cookie_exchange },
{ "-shim-writes-first", &TestConfig::shim_writes_first },
{ "-tls-d5-bug", &TestConfig::tls_d5_bug },
+ { "-expect-session-miss", &TestConfig::expect_session_miss },
};
const size_t kNumBoolFlags = sizeof(kBoolFlags) / sizeof(kBoolFlags[0]);
@@ -67,6 +68,11 @@ const StringFlag kStringFlags[] = {
{ "-expect-next-proto", &TestConfig::expected_next_proto },
{ "-select-next-proto", &TestConfig::select_next_proto },
{ "-send-channel-id", &TestConfig::send_channel_id },
+ { "-host-name", &TestConfig::host_name },
+ { "-advertise-alpn", &TestConfig::advertise_alpn },
+ { "-expect-alpn", &TestConfig::expected_alpn },
+ { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
+ { "-select-alpn", &TestConfig::select_alpn },
};
const size_t kNumStringFlags = sizeof(kStringFlags) / sizeof(kStringFlags[0]);
@@ -97,7 +103,8 @@ TestConfig::TestConfig()
no_ssl3(false),
cookie_exchange(false),
shim_writes_first(false),
- tls_d5_bug(false) {
+ tls_d5_bug(false),
+ expect_session_miss(false) {
}
bool ParseConfig(int argc, char **argv, TestConfig *out_config) {
diff --git a/ssl/test/test_config.h b/ssl/test/test_config.h
index 208f19b..acce504 100644
--- a/ssl/test/test_config.h
+++ b/ssl/test/test_config.h
@@ -47,6 +47,12 @@ struct TestConfig {
std::string send_channel_id;
bool shim_writes_first;
bool tls_d5_bug;
+ std::string host_name;
+ std::string advertise_alpn;
+ std::string expected_alpn;
+ std::string expected_advertised_alpn;
+ std::string select_alpn;
+ bool expect_session_miss;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/tool/pkcs12.cc b/tool/pkcs12.cc
index 10ff630..d35ba0b 100644
--- a/tool/pkcs12.cc
+++ b/tool/pkcs12.cc
@@ -40,7 +40,7 @@ static const struct argument kArguments[] = {
},
};
-bool PKCS12(const std::vector<std::string> &args) {
+bool DoPKCS12(const std::vector<std::string> &args) {
std::map<std::string, std::string> args_map;
if (!ParseKeyValueArguments(&args_map, args, kArguments) ||
diff --git a/tool/tool.cc b/tool/tool.cc
index bf79a47..a0866d7 100644
--- a/tool/tool.cc
+++ b/tool/tool.cc
@@ -20,7 +20,7 @@
bool Client(const std::vector<std::string> &args);
-bool PKCS12(const std::vector<std::string> &args);
+bool DoPKCS12(const std::vector<std::string> &args);
bool Speed(const std::vector<std::string> &args);
static void usage(const char *name) {
@@ -45,7 +45,7 @@ int main(int argc, char **argv) {
} else if (tool == "s_client" || tool == "client") {
return !Client(args);
} else if (tool == "pkcs12") {
- return !PKCS12(args);
+ return !DoPKCS12(args);
} else {
usage(argv[0]);
return 1;