Merge "Rename target.linux[_x86[_64]] to target.linux_glibc[_x86[_64]]"
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index e46e525..7112211 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-3a18bf04745c0ef9850efeec1a52e402c4392388
+575334657fcb66a4861c9d125430b2aef60476a6
diff --git a/src/PORTING.md b/src/PORTING.md
index c9a16d6..bf3807a 100644
--- a/src/PORTING.md
+++ b/src/PORTING.md
@@ -6,17 +6,27 @@
library compiles and, on failure, consult the documentation in the header files
and see if problematic features can be removed.
-In some cases, BoringSSL-specific code may be necessary. In that case, the
-`OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro
-should also be used in lieu of the presence of any particular function to detect
-OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary.
-Before using the preprocessor, however, contact the BoringSSL maintainers about
-the missing APIs. If not an intentionally removed feature, BoringSSL will
-typically add compatibility functions for convenience.
+BoringSSL's `OPENSSL_VERSION_NUMBER` matches the OpenSSL version it targets.
+Version checks for OpenSSL should ideally work as-is in BoringSSL. BoringSSL
+also defines upstream's `OPENSSL_NO_*` feature macros corresponding to removed
+features. If the preprocessor is needed, use these version checks or feature
+macros where possible, especially when patching third-party projects. Such
+patches are more generally useful to OpenSSL consumers and thus more
+appropriate to send upstream.
-For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros
-corresponding to removed features. These may also be used to disable code which
-uses a removed feature.
+In some cases, BoringSSL-specific code may be necessary. Use the
+`OPENSSL_IS_BORINGSSL` preprocessor macro in `#ifdef`s. However, first contact
+the BoringSSL maintainers about the missing APIs. We will typically add
+compatibility functions for convenience. In particular, *contact BoringSSL
+maintainers before working around missing OpenSSL 1.1.0 accessors*. BoringSSL
+was originally derived from OpenSSL 1.0.2 but now targets OpenSSL 1.1.0. Some
+newer APIs may be missing but can be added on request. (Not all projects have
+been ported to OpenSSL 1.1.0, so BoringSSL also remains largely compatible with
+OpenSSL 1.0.2.)
+
+The `OPENSSL_IS_BORINGSSL` macro may also be used to distinguish OpenSSL from
+BoringSSL in configure scripts. Do not use the presence or absence of particular
+symbols to detect BoringSSL.
Note: BoringSSL does *not* have a stable API or ABI. It must be updated with its
consumers. It is not suitable for, say, a system library in a traditional Linux
@@ -39,15 +49,19 @@
Most notably, the `STACK_OF(T)` types have all been converted to use `size_t`
instead of `int` for indices and lengths.
-### Reference counts
+### Reference counts and opaque types
Some external consumers increment reference counts directly by calling
-`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value.
+`CRYPTO_add` with the corresponding `CRYPTO_LOCK_*` value. These APIs no longer
+exist in BoringSSL. Instead, code which increments reference counts should call
+the corresponding `FOO_up_ref` function, such as `EVP_PKEY_up_ref`.
-These APIs no longer exist in BoringSSL. Instead, code which increments
-reference counts should call the corresponding `FOO_up_ref` function, such as
-`EVP_PKEY_up_ref`. Note that not all of these APIs are present in OpenSSL and
-may require `#ifdef`s.
+BoringSSL also hides some structs which were previously exposed in OpenSSL
+1.0.2, particularly in libssl. Use the relevant accessors instead.
+
+Note that some of these APIs were added in OpenSSL 1.1.0, so projects which do
+not yet support 1.1.0 may need additional `#ifdef`s. Projects supporting OpenSSL
+1.1.0 should not require modification.
### Error codes
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
index f4441d2..ea727f3 100644
--- a/src/crypto/asn1/asn1_lib.c
+++ b/src/crypto/asn1/asn1_lib.c
@@ -435,3 +435,8 @@
{
return M_ASN1_STRING_data(x);
}
+
+const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+ return x->data;
+}
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 4e88966..3e788b8 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -555,3 +555,82 @@
}
int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
+
+static struct CRYPTO_STATIC_MUTEX g_index_lock = CRYPTO_STATIC_MUTEX_INIT;
+static int g_index = BIO_TYPE_START;
+
+int BIO_get_new_index(void) {
+ CRYPTO_STATIC_MUTEX_lock_write(&g_index_lock);
+ // If |g_index| exceeds 255, it will collide with the flags bits.
+ int ret = g_index > 255 ? -1 : g_index++;
+ CRYPTO_STATIC_MUTEX_unlock_write(&g_index_lock);
+ return ret;
+}
+
+BIO_METHOD *BIO_meth_new(int type, const char *name) {
+ BIO_METHOD *method = OPENSSL_malloc(sizeof(BIO_METHOD));
+ if (method == NULL) {
+ return NULL;
+ }
+ OPENSSL_memset(method, 0, sizeof(BIO_METHOD));
+ method->type = type;
+ method->name = name;
+ return method;
+}
+
+void BIO_meth_free(BIO_METHOD *method) {
+ OPENSSL_free(method);
+}
+
+int BIO_meth_set_create(BIO_METHOD *method,
+ int (*create)(BIO *)) {
+ method->create = create;
+ return 1;
+}
+
+int BIO_meth_set_destroy(BIO_METHOD *method,
+ int (*destroy)(BIO *)) {
+ method->destroy = destroy;
+ return 1;
+}
+
+int BIO_meth_set_write(BIO_METHOD *method,
+ int (*write)(BIO *, const char *, int)) {
+ method->bwrite = write;
+ return 1;
+}
+
+int BIO_meth_set_read(BIO_METHOD *method,
+ int (*read)(BIO *, char *, int)) {
+ method->bread = read;
+ return 1;
+}
+
+int BIO_meth_set_gets(BIO_METHOD *method,
+ int (*gets)(BIO *, char *, int)) {
+ method->bgets = gets;
+ return 1;
+}
+
+int BIO_meth_set_ctrl(BIO_METHOD *method,
+ long (*ctrl)(BIO *, int, long, void *)) {
+ method->ctrl = ctrl;
+ return 1;
+}
+
+void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
+
+void *BIO_get_data(BIO *bio) { return bio->ptr; }
+
+void BIO_set_init(BIO *bio, int init) { bio->init = init; }
+
+int BIO_get_init(BIO *bio) { return bio->init; }
+
+void BIO_set_shutdown(BIO *bio, int shutdown) { bio->shutdown = shutdown; }
+
+int BIO_get_shutdown(BIO *bio) { return bio->shutdown; }
+
+int BIO_meth_set_puts(BIO_METHOD *method, int (*puts)(BIO *, const char *)) {
+ // Ignore the parameter. We implement |BIO_puts| using |BIO_write|.
+ return 1;
+}
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index aee3521..390cd8b 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -156,10 +156,18 @@
return "BoringSSL";
}
+const char *OpenSSL_version(int unused) {
+ return "BoringSSL";
+}
+
unsigned long SSLeay(void) {
return OPENSSL_VERSION_NUMBER;
}
+unsigned long OpenSSL_version_num(void) {
+ return OPENSSL_VERSION_NUMBER;
+}
+
int CRYPTO_malloc_init(void) {
return 1;
}
@@ -171,3 +179,8 @@
}
void OPENSSL_load_builtin_modules(void) {}
+
+int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) {
+ CRYPTO_library_init();
+ return 1;
+}
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index 3356776..04e245e 100644
--- a/src/crypto/dh/dh.c
+++ b/src/crypto/dh/dh.c
@@ -124,6 +124,20 @@
}
}
+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
+ if (pub_key != NULL) {
+ BN_free(dh->pub_key);
+ dh->pub_key = pub_key;
+ }
+
+ if (priv_key != NULL) {
+ BN_free(dh->priv_key);
+ dh->priv_key = priv_key;
+ }
+
+ return 1;
+}
+
void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
const BIGNUM **out_g) {
if (out_p != NULL) {
@@ -137,6 +151,30 @@
}
}
+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
+ if ((dh->p == NULL && p == NULL) ||
+ (dh->g == NULL && g == NULL)) {
+ return 0;
+ }
+
+ if (p != NULL) {
+ BN_free(dh->p);
+ dh->p = p;
+ }
+
+ if (q != NULL) {
+ BN_free(dh->q);
+ dh->q = q;
+ }
+
+ if (g == NULL) {
+ BN_free(dh->g);
+ dh->g = g;
+ }
+
+ return 1;
+}
+
int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
// We generate DH parameters as follows
// find a prime q which is prime_bits/2 bits long.
diff --git a/src/crypto/digest_extra/digest_extra.c b/src/crypto/digest_extra/digest_extra.c
index ab7ff59..4b4bb38 100644
--- a/src/crypto/digest_extra/digest_extra.c
+++ b/src/crypto/digest_extra/digest_extra.c
@@ -62,7 +62,6 @@
#include <openssl/bytestring.h>
#include <openssl/nid.h>
-#include "internal.h"
#include "../internal.h"
@@ -120,22 +119,22 @@
static const struct {
uint8_t oid[9];
uint8_t oid_len;
- const EVP_MD *(*md_func) (void);
+ int nid;
} kMDOIDs[] = {
// 1.2.840.113549.2.4
- { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, EVP_md4 },
+ { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, NID_md4 },
// 1.2.840.113549.2.5
- { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, EVP_md5 },
+ { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, NID_md5 },
// 1.3.14.3.2.26
- { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, EVP_sha1 },
+ { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, NID_sha1 },
// 2.16.840.1.101.3.4.2.1
- { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, EVP_sha256 },
+ { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, NID_sha256 },
// 2.16.840.1.101.3.4.2.2
- { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, EVP_sha384 },
+ { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, NID_sha384 },
// 2.16.840.1.101.3.4.2.3
- { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, EVP_sha512 },
+ { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, NID_sha512 },
// 2.16.840.1.101.3.4.2.4
- { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
+ { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, NID_sha224 },
};
static const EVP_MD *cbs_to_md(const CBS *cbs) {
@@ -143,7 +142,7 @@
if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
0) {
- return kMDOIDs[i].md_func();
+ return EVP_get_digestbynid(kMDOIDs[i].nid);
}
}
@@ -192,6 +191,41 @@
return ret;
}
+int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md) {
+ CBB algorithm, oid, null;
+ if (!CBB_add_asn1(cbb, &algorithm, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
+ OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ int found = 0;
+ int nid = EVP_MD_type(md);
+ for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
+ if (nid == kMDOIDs[i].nid) {
+ if (!CBB_add_bytes(&oid, kMDOIDs[i].oid, kMDOIDs[i].oid_len)) {
+ OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
+ return 0;
+ }
+
+ if (!CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+ !CBB_flush(cbb)) {
+ OPENSSL_PUT_ERROR(DIGEST, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
const EVP_MD *EVP_get_digestbyname(const char *name) {
for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
const char *short_name = nid_to_digest_mapping[i].short_name;
diff --git a/src/crypto/digest_extra/digest_test.cc b/src/crypto/digest_extra/digest_test.cc
index 96fa778..910c731 100644
--- a/src/crypto/digest_extra/digest_test.cc
+++ b/src/crypto/digest_extra/digest_test.cc
@@ -21,6 +21,7 @@
#include <gtest/gtest.h>
#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
#include <openssl/crypto.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -31,6 +32,7 @@
#include <openssl/sha.h>
#include "../internal.h"
+#include "../test/test_util.h"
struct MD {
@@ -215,3 +217,44 @@
EXPECT_EQ(EVP_md5_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1)));
EXPECT_EQ(EVP_sha1(), EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1)));
}
+
+TEST(DigestTest, ASN1) {
+ bssl::ScopedCBB cbb;
+ ASSERT_TRUE(CBB_init(cbb.get(), 0));
+ EXPECT_FALSE(EVP_marshal_digest_algorithm(cbb.get(), EVP_md5_sha1()));
+
+ static const uint8_t kSHA256[] = {0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01, 0x05, 0x00};
+ static const uint8_t kSHA256NoParam[] = {0x30, 0x0b, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03,
+ 0x04, 0x02, 0x01};
+ static const uint8_t kSHA256GarbageParam[] = {
+ 0x30, 0x0e, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x65, 0x03, 0x04, 0x02, 0x01, 0x02, 0x01, 0x2a};
+
+ // Serialize SHA-256.
+ cbb.Reset();
+ ASSERT_TRUE(CBB_init(cbb.get(), 0));
+ ASSERT_TRUE(EVP_marshal_digest_algorithm(cbb.get(), EVP_sha256()));
+ uint8_t *der;
+ size_t der_len;
+ ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
+ bssl::UniquePtr<uint8_t> free_der(der);
+ EXPECT_EQ(Bytes(kSHA256), Bytes(der, der_len));
+
+ // Parse SHA-256.
+ CBS cbs;
+ CBS_init(&cbs, kSHA256, sizeof(kSHA256));
+ EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ // Missing parameters are tolerated for compatibility.
+ CBS_init(&cbs, kSHA256NoParam, sizeof(kSHA256NoParam));
+ EXPECT_EQ(EVP_sha256(), EVP_parse_digest_algorithm(&cbs));
+ EXPECT_EQ(0u, CBS_len(&cbs));
+
+ // Garbage parameters are not.
+ CBS_init(&cbs, kSHA256GarbageParam, sizeof(kSHA256GarbageParam));
+ EXPECT_FALSE(EVP_parse_digest_algorithm(&cbs));
+}
diff --git a/src/crypto/digest_extra/internal.h b/src/crypto/digest_extra/internal.h
deleted file mode 100644
index 1df200e..0000000
--- a/src/crypto/digest_extra/internal.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright (c) 2017, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#ifndef OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H
-#define OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
-
-
-#if defined(__cplusplus)
-} // extern C
-#endif
-
-#endif // OPENSSL_HEADER_DIGEST_EXTRA_INTERNAL
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index 1dfc567..61f0c6c 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -153,6 +153,46 @@
}
}
+int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key) {
+ if (dsa->pub_key == NULL && pub_key == NULL) {
+ return 0;
+ }
+
+ if (pub_key != NULL) {
+ BN_free(dsa->pub_key);
+ dsa->pub_key = pub_key;
+ }
+ if (priv_key != NULL) {
+ BN_free(dsa->priv_key);
+ dsa->priv_key = priv_key;
+ }
+
+ return 1;
+}
+
+int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
+ if ((dsa->p == NULL && p == NULL) ||
+ (dsa->q == NULL && q == NULL) ||
+ (dsa->g == NULL && g == NULL)) {
+ return 0;
+ }
+
+ if (p != NULL) {
+ BN_free(dsa->p);
+ dsa->p = p;
+ }
+ if (q != NULL) {
+ BN_free(dsa->q);
+ dsa->q = q;
+ }
+ if (g != NULL) {
+ BN_free(dsa->g);
+ dsa->g = g;
+ }
+
+ return 1;
+}
+
int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
size_t seed_len, int *out_counter,
unsigned long *out_h, BN_GENCB *cb) {
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
index 16d78b7..34b2e70 100644
--- a/src/crypto/evp/p_dsa_asn1.c
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -151,8 +151,8 @@
// Calculate the public key.
ctx = BN_CTX_new();
if (ctx == NULL ||
- !BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
- NULL)) {
+ !BN_mod_exp_mont_consttime(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p,
+ ctx, NULL)) {
goto err;
}
diff --git a/src/crypto/fipsmodule/cipher/cipher.c b/src/crypto/fipsmodule/cipher/cipher.c
index 00d8390..7b00c3f 100644
--- a/src/crypto/fipsmodule/cipher/cipher.c
+++ b/src/crypto/fipsmodule/cipher/cipher.c
@@ -125,6 +125,11 @@
return 1;
}
+void EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ EVP_CIPHER_CTX_init(ctx);
+}
+
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
ENGINE *engine, const uint8_t *key, const uint8_t *iv,
int enc) {
diff --git a/src/crypto/fipsmodule/digest/digest.c b/src/crypto/fipsmodule/digest/digest.c
index 8afd1e1..1c35809 100644
--- a/src/crypto/fipsmodule/digest/digest.c
+++ b/src/crypto/fipsmodule/digest/digest.c
@@ -79,7 +79,7 @@
OPENSSL_memset(ctx, 0, sizeof(EVP_MD_CTX));
}
-EVP_MD_CTX *EVP_MD_CTX_create(void) {
+EVP_MD_CTX *EVP_MD_CTX_new(void) {
EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
if (ctx) {
@@ -89,6 +89,8 @@
return ctx;
}
+EVP_MD_CTX *EVP_MD_CTX_create(void) { return EVP_MD_CTX_new(); }
+
int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) {
OPENSSL_free(ctx->md_data);
@@ -102,7 +104,7 @@
return 1;
}
-void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) {
+void EVP_MD_CTX_free(EVP_MD_CTX *ctx) {
if (!ctx) {
return;
}
@@ -111,6 +113,8 @@
OPENSSL_free(ctx);
}
+void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx) { EVP_MD_CTX_free(ctx); }
+
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) {
if (in == NULL || in->digest == NULL) {
OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_INPUT_NOT_INITIALIZED);
@@ -162,6 +166,11 @@
return EVP_MD_CTX_copy_ex(out, in);
}
+void EVP_MD_CTX_reset(EVP_MD_CTX *ctx) {
+ EVP_MD_CTX_cleanup(ctx);
+ EVP_MD_CTX_init(ctx);
+}
+
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *engine) {
if (ctx->digest != type) {
assert(type->ctx_size != 0);
diff --git a/src/crypto/fipsmodule/hmac/hmac.c b/src/crypto/fipsmodule/hmac/hmac.c
index 5c098db..fb57bf2 100644
--- a/src/crypto/fipsmodule/hmac/hmac.c
+++ b/src/crypto/fipsmodule/hmac/hmac.c
@@ -87,6 +87,14 @@
EVP_MD_CTX_init(&ctx->md_ctx);
}
+HMAC_CTX *HMAC_CTX_new(void) {
+ HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
+ if (ctx != NULL) {
+ HMAC_CTX_init(ctx);
+ }
+ return ctx;
+}
+
void HMAC_CTX_cleanup(HMAC_CTX *ctx) {
EVP_MD_CTX_cleanup(&ctx->i_ctx);
EVP_MD_CTX_cleanup(&ctx->o_ctx);
@@ -94,6 +102,15 @@
OPENSSL_cleanse(ctx, sizeof(HMAC_CTX));
}
+void HMAC_CTX_free(HMAC_CTX *ctx) {
+ if (ctx == NULL) {
+ return;
+ }
+
+ HMAC_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, size_t key_len,
const EVP_MD *md, ENGINE *impl) {
if (md == NULL) {
@@ -193,6 +210,11 @@
return 1;
}
+void HMAC_CTX_reset(HMAC_CTX *ctx) {
+ HMAC_CTX_cleanup(ctx);
+ HMAC_CTX_init(ctx);
+}
+
int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md) {
if (key && md) {
HMAC_CTX_init(ctx);
diff --git a/src/crypto/fipsmodule/rsa/rsa.c b/src/crypto/fipsmodule/rsa/rsa.c
index 17348c1..d001d7b 100644
--- a/src/crypto/fipsmodule/rsa/rsa.c
+++ b/src/crypto/fipsmodule/rsa/rsa.c
@@ -193,6 +193,69 @@
}
}
+int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
+ if ((rsa->n == NULL && n == NULL) ||
+ (rsa->e == NULL && e == NULL)) {
+ return 0;
+ }
+
+ if (n != NULL) {
+ BN_free(rsa->n);
+ rsa->n = n;
+ }
+ if (e != NULL) {
+ BN_free(rsa->e);
+ rsa->e = e;
+ }
+ if (d != NULL) {
+ BN_free(rsa->d);
+ rsa->d = d;
+ }
+
+ return 1;
+}
+
+int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q) {
+ if ((rsa->p == NULL && p == NULL) ||
+ (rsa->q == NULL && q == NULL)) {
+ return 0;
+ }
+
+ if (p != NULL) {
+ BN_free(rsa->p);
+ rsa->p = p;
+ }
+ if (q != NULL) {
+ BN_free(rsa->q);
+ rsa->q = q;
+ }
+
+ return 1;
+}
+
+int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) {
+ if ((rsa->dmp1 == NULL && dmp1 == NULL) ||
+ (rsa->dmq1 == NULL && dmq1 == NULL) ||
+ (rsa->iqmp == NULL && iqmp == NULL)) {
+ return 0;
+ }
+
+ if (dmp1 != NULL) {
+ BN_free(rsa->dmp1);
+ rsa->dmp1 = dmp1;
+ }
+ if (dmq1 != NULL) {
+ BN_free(rsa->dmq1);
+ rsa->dmq1 = dmq1;
+ }
+ if (iqmp != NULL) {
+ BN_free(rsa->iqmp);
+ rsa->iqmp = iqmp;
+ }
+
+ return 1;
+}
+
int RSA_public_encrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
int padding) {
size_t out_len;
diff --git a/src/crypto/obj/obj.c b/src/crypto/obj/obj.c
index 3968515..52e265b 100644
--- a/src/crypto/obj/obj.c
+++ b/src/crypto/obj/obj.c
@@ -172,6 +172,22 @@
return OPENSSL_memcmp(a->data, b->data, a->length);
}
+const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj) {
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ return obj->data;
+}
+
+size_t OBJ_length(const ASN1_OBJECT *obj) {
+ if (obj == NULL || obj->length < 0) {
+ return 0;
+ }
+
+ return (size_t)obj->length;
+}
+
// obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
// an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
// unsigned int in the array.
diff --git a/src/crypto/pkcs8/pkcs8_x509.c b/src/crypto/pkcs8/pkcs8_x509.c
index ace5f33..b3e2d93 100644
--- a/src/crypto/pkcs8/pkcs8_x509.c
+++ b/src/crypto/pkcs8/pkcs8_x509.c
@@ -71,7 +71,6 @@
#include "internal.h"
#include "../bytestring/internal.h"
-#include "../digest_extra/internal.h"
#include "../internal.h"
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index d4f6bba..3339523 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -299,7 +299,8 @@
return (0);
}
-int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
+int X509_signature_print(BIO *bp, const X509_ALGOR *sigalg,
+ const ASN1_STRING *sig)
{
if (BIO_puts(bp, " Signature Algorithm: ") <= 0)
return 0;
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index f2371bd..1014a05 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -434,6 +434,19 @@
}
}
+int X509_OBJECT_get_type(const X509_OBJECT *a)
+{
+ return a->type;
+}
+
+X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
+{
+ if (a == NULL || a->type != X509_LU_X509) {
+ return NULL;
+ }
+ return a->data.x509;
+}
+
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
X509_NAME *name, int *pnmatch)
{
@@ -496,6 +509,11 @@
return sk_X509_OBJECT_value(h, idx);
}
+STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st)
+{
+ return st->objs;
+}
+
STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
{
int i, idx, cnt;
@@ -684,6 +702,11 @@
return X509_VERIFY_PARAM_set1(ctx->param, param);
}
+X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
+{
+ return ctx->param;
+}
+
void X509_STORE_set_verify_cb(X509_STORE *ctx,
int (*verify_cb) (int, X509_STORE_CTX *))
{
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
index 67c1842..413a20d 100644
--- a/src/crypto/x509/x509_set.c
+++ b/src/crypto/x509/x509_set.c
@@ -124,6 +124,11 @@
return (in != NULL);
}
+const ASN1_TIME *X509_get0_notBefore(const X509 *x)
+{
+ return x->cert_info->validity->notBefore;
+}
+
int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
{
ASN1_TIME *in;
@@ -141,6 +146,11 @@
return (in != NULL);
}
+const ASN1_TIME *X509_get0_notAfter(const X509 *x)
+{
+ return x->cert_info->validity->notAfter;
+}
+
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
{
if ((x == NULL) || (x->cert_info == NULL))
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index 5228d01..8e258fe 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -2176,6 +2176,11 @@
ctx->untrusted = sk;
}
+STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx)
+{
+ return ctx->untrusted;
+}
+
void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
{
ctx->crls = sk;
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
index 9852415..0980463 100644
--- a/src/crypto/x509/x_name.c
+++ b/src/crypto/x509/x_name.c
@@ -534,3 +534,8 @@
}
IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
+
+int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne)
+{
+ return ne->set;
+}
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 9edfa00..01464a1 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -313,7 +313,7 @@
return length;
}
-void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg,
const X509 *x)
{
if (psig)
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 45d4848..2ef4c97 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -660,6 +660,7 @@
OPENSSL_EXPORT void ASN1_STRING_length_set(ASN1_STRING *x, int n);
OPENSSL_EXPORT int ASN1_STRING_type(ASN1_STRING *x);
OPENSSL_EXPORT unsigned char * ASN1_STRING_data(ASN1_STRING *x);
+OPENSSL_EXPORT const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x);
DECLARE_ASN1_FUNCTIONS(ASN1_BIT_STRING)
OPENSSL_EXPORT int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a,unsigned char **pp);
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 2be5ed0..aa65b4a 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -135,8 +135,12 @@
#define OPENSSL_NO_THREADS
#endif
+#if !defined(OPENSSL_NO_THREADS)
+#define OPENSSL_THREADS
+#endif
+
#define OPENSSL_IS_BORINGSSL
-#define OPENSSL_VERSION_NUMBER 0x100020af
+#define OPENSSL_VERSION_NUMBER 0x1010007f
#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
// BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL
@@ -318,6 +322,7 @@
typedef struct hmac_ctx_st HMAC_CTX;
typedef struct md4_state_st MD4_CTX;
typedef struct md5_state_st MD5_CTX;
+typedef struct ossl_init_settings_st OPENSSL_INIT_SETTINGS;
typedef struct pkcs12_st PKCS12;
typedef struct pkcs8_priv_key_info_st PKCS8_PRIV_KEY_INFO;
typedef struct private_key_st X509_PKEY;
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 095ac75..b397696 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -218,6 +218,18 @@
// values.
OPENSSL_EXPORT int BIO_method_type(const BIO *bio);
+// These are passed to the BIO callback
+#define BIO_CB_FREE 0x01
+#define BIO_CB_READ 0x02
+#define BIO_CB_WRITE 0x03
+#define BIO_CB_PUTS 0x04
+#define BIO_CB_GETS 0x05
+#define BIO_CB_CTRL 0x06
+
+// The callback is called before and after the underling operation,
+// The BIO_CB_RETURN flag indicates if it is after the call
+#define BIO_CB_RETURN 0x80
+
// bio_info_cb is the type of a callback function that can be called for most
// BIO operations. The |event| argument is one of |BIO_CB_*| and can be ORed
// with |BIO_CB_RETURN| if the callback is being made after the operation in
@@ -348,6 +360,11 @@
//
// |BIO_ctrl_pending| returns the number of bytes currently stored.
+// BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
+// flag" is passed to a BIO function.
+#define BIO_NOCLOSE 0
+#define BIO_CLOSE 1
+
// BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer.
OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void);
@@ -589,22 +606,72 @@
OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
-// BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
-// flag" is passed to a BIO function.
-#define BIO_NOCLOSE 0
-#define BIO_CLOSE 1
+// Custom BIOs.
+//
+// Consumers can create custom |BIO|s by filling in a |BIO_METHOD| and using
+// low-level control functions to set state.
-// These are passed to the BIO callback
-#define BIO_CB_FREE 0x01
-#define BIO_CB_READ 0x02
-#define BIO_CB_WRITE 0x03
-#define BIO_CB_PUTS 0x04
-#define BIO_CB_GETS 0x05
-#define BIO_CB_CTRL 0x06
+// BIO_get_new_index returns a new "type" value for a custom |BIO|.
+OPENSSL_EXPORT int BIO_get_new_index(void);
-// The callback is called before and after the underling operation,
-// The BIO_CB_RETURN flag indicates if it is after the call
-#define BIO_CB_RETURN 0x80
+// BIO_meth_new returns a newly-allocated |BIO_METHOD| or NULL on allocation
+// error. The |type| specifies the type that will be returned by
+// |BIO_method_type|. If this is unnecessary, this value may be zero. The |name|
+// parameter is vestigial and may be NULL.
+//
+// Use the |BIO_meth_set_*| functions below to initialize the |BIO_METHOD|. The
+// function implementations may use |BIO_set_data| and |BIO_get_data| to add
+// method-specific state to associated |BIO|s. Additionally, |BIO_set_init| must
+// be called after an associated |BIO| is fully initialized.
+OPENSSL_EXPORT BIO_METHOD *BIO_meth_new(int type, const char *name);
+
+// BIO_meth_free releases memory associated with |method|.
+OPENSSL_EXPORT void BIO_meth_free(BIO_METHOD *method);
+
+// BIO_meth_set_create sets a function to be called on |BIO_new| for |method|
+// and returns one. The function should return one on success and zero on
+// error.
+OPENSSL_EXPORT int BIO_meth_set_create(BIO_METHOD *method,
+ int (*create)(BIO *));
+
+// BIO_meth_set_destroy sets a function to release data associated with a |BIO|
+// and returns one. The function's return value is ignored.
+OPENSSL_EXPORT int BIO_meth_set_destroy(BIO_METHOD *method,
+ int (*destroy)(BIO *));
+
+// BIO_meth_set_write sets the implementation of |BIO_write| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_write(BIO_METHOD *method,
+ int (*write)(BIO *, const char *, int));
+
+// BIO_meth_set_read sets the implementation of |BIO_read| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_read(BIO_METHOD *method,
+ int (*read)(BIO *, char *, int));
+
+// BIO_meth_set_gets sets the implementation of |BIO_gets| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_gets(BIO_METHOD *method,
+ int (*gets)(BIO *, char *, int));
+
+// BIO_meth_set_ctrl sets the implementation of |BIO_ctrl| for |method| and
+// returns one.
+OPENSSL_EXPORT int BIO_meth_set_ctrl(BIO_METHOD *method,
+ long (*ctrl)(BIO *, int, long, void *));
+
+// BIO_set_data sets custom data on |bio|. It may be retried with
+// |BIO_get_data|.
+OPENSSL_EXPORT void BIO_set_data(BIO *bio, void *ptr);
+
+// BIO_get_data returns custom data on |bio| set by |BIO_get_data|.
+OPENSSL_EXPORT void *BIO_get_data(BIO *bio);
+
+// BIO_set_init sets whether |bio| has been fully initialized. Until fully
+// initialized, |BIO_read| and |BIO_write| will fail.
+OPENSSL_EXPORT void BIO_set_init(BIO *bio, int init);
+
+// BIO_get_init returns whether |bio| has been fully initialized.
+OPENSSL_EXPORT int BIO_get_init(BIO *bio);
// These are values of the |cmd| argument to |BIO_ctrl|.
#define BIO_CTRL_RESET 1 // opt - rewind/zero etc
@@ -643,6 +710,17 @@
// BIO_set_write_buffer_size returns zero.
OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
+// BIO_set_shutdown sets a method-specific "shutdown" bit on |bio|.
+OPENSSL_EXPORT void BIO_set_shutdown(BIO *bio, int shutdown);
+
+// BIO_get_shutdown returns the method-specific "shutdown" bit.
+OPENSSL_EXPORT int BIO_get_shutdown(BIO *bio);
+
+// BIO_meth_set_puts returns one. |BIO_puts| is implemented with |BIO_write| in
+// BoringSSL.
+OPENSSL_EXPORT int BIO_meth_set_puts(BIO_METHOD *method,
+ int (*puts)(BIO *, const char *));
+
// Private functions
@@ -681,10 +759,16 @@
#define BIO_TYPE_ASN1 (22 | 0x0200) // filter
#define BIO_TYPE_COMP (23 | 0x0200) // filter
+// |BIO_TYPE_DESCRIPTOR| denotes that the |BIO| responds to the |BIO_C_SET_FD|
+// (|BIO_set_fd|) and |BIO_C_GET_FD| (|BIO_get_fd|) control hooks.
#define BIO_TYPE_DESCRIPTOR 0x0100 // socket, fd, connect or accept
#define BIO_TYPE_FILTER 0x0200
#define BIO_TYPE_SOURCE_SINK 0x0400
+// BIO_TYPE_START is the first user-allocated |BIO| type. No pre-defined type,
+// flag bits aside, may exceed this value.
+#define BIO_TYPE_START 128
+
struct bio_method_st {
int type;
const char *name;
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index a09b49c..66f6204 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -17,6 +17,8 @@
#include <openssl/base.h>
+#include <openssl/span.h>
+
#if defined(__cplusplus)
extern "C" {
#endif
@@ -37,6 +39,13 @@
struct cbs_st {
const uint8_t *data;
size_t len;
+
+#if !defined(BORINGSSL_NO_CXX)
+ // Allow implicit conversions to bssl::Span<const uint8_t>.
+ operator bssl::Span<const uint8_t>() const {
+ return bssl::MakeConstSpan(data, len);
+ }
+#endif
};
// CBS_init sets |cbs| to point to |data|. It does not take ownership of
diff --git a/src/include/openssl/cipher.h b/src/include/openssl/cipher.h
index 7fbee8b..5c380a1 100644
--- a/src/include/openssl/cipher.h
+++ b/src/include/openssl/cipher.h
@@ -135,6 +135,10 @@
OPENSSL_EXPORT int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out,
const EVP_CIPHER_CTX *in);
+// EVP_CIPHER_CTX_reset calls |EVP_CIPHER_CTX_cleanup| followed by
+// |EVP_CIPHER_CTX_init|.
+OPENSSL_EXPORT void EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
+
// Cipher context configuration.
diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h
index c94f39f..dc87dd2 100644
--- a/src/include/openssl/crypto.h
+++ b/src/include/openssl/crypto.h
@@ -63,7 +63,7 @@
// OPENSSL_VERSION_TEXT contains a string the identifies the version of
// “OpenSSL”. node.js requires a version number in this text.
-#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2 (compatible; BoringSSL)"
+#define OPENSSL_VERSION_TEXT "OpenSSL 1.1.0 (compatible; BoringSSL)"
#define SSLEAY_VERSION 0
@@ -71,10 +71,20 @@
// "BoringSSL".
OPENSSL_EXPORT const char *SSLeay_version(int unused);
+#define OPENSSL_VERSION 0
+
+// OpenSSL_version is a compatibility function that returns the string
+// "BoringSSL".
+OPENSSL_EXPORT const char *OpenSSL_version(int unused);
+
// SSLeay is a compatibility function that returns OPENSSL_VERSION_NUMBER from
// base.h.
OPENSSL_EXPORT unsigned long SSLeay(void);
+// OpenSSL_version_num is a compatibility function that returns
+// OPENSSL_VERSION_NUMBER from base.h.
+OPENSSL_EXPORT unsigned long OpenSSL_version_num(void);
+
// CRYPTO_malloc_init returns one.
OPENSSL_EXPORT int CRYPTO_malloc_init(void);
@@ -87,6 +97,19 @@
// OPENSSL_load_builtin_modules does nothing.
OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void);
+#define OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS 0
+#define OPENSSL_INIT_LOAD_CRYPTO_STRINGS 0
+#define OPENSSL_INIT_ADD_ALL_CIPHERS 0
+#define OPENSSL_INIT_ADD_ALL_DIGESTS 0
+#define OPENSSL_INIT_NO_ADD_ALL_CIPHERS 0
+#define OPENSSL_INIT_NO_ADD_ALL_DIGESTS 0
+#define OPENSSL_INIT_LOAD_CONFIG 0
+#define OPENSSL_INIT_NO_LOAD_CONFIG 0
+
+// OPENSSL_init_crypto calls |CRYPTO_library_init| and returns one.
+OPENSSL_EXPORT int OPENSSL_init_crypto(uint64_t opts,
+ const OPENSSL_INIT_SETTINGS *settings);
+
#if defined(__cplusplus)
} // extern C
diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h
index d78bbeb..ae24c25 100644
--- a/src/include/openssl/dh.h
+++ b/src/include/openssl/dh.h
@@ -92,11 +92,22 @@
OPENSSL_EXPORT void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
const BIGNUM **out_priv_key);
+// DH_set0_key sets |dh|'s public and private key to the specified values. If
+// NULL, the field is left unchanged. On success, it takes ownership of each
+// argument and returns one. Otherwise, it returns zero.
+OPENSSL_EXPORT int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
+
// DH_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dh|'s p,
// q, and g parameters, respectively.
OPENSSL_EXPORT void DH_get0_pqg(const DH *dh, const BIGNUM **out_p,
const BIGNUM **out_q, const BIGNUM **out_g);
+// DH_set0_pqg sets |dh|'s p, q, and g parameters to the specified values. If
+// NULL, the field is left unchanged. On success, it takes ownership of each
+// argument and returns one. Otherwise, it returns zero. |q| may be NULL, but
+// |p| and |g| must either be specified or already configured on |dh|.
+OPENSSL_EXPORT int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+
// Standard parameters.
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
index ad6dd50..81f5892 100644
--- a/src/include/openssl/digest.h
+++ b/src/include/openssl/digest.h
@@ -106,21 +106,25 @@
// same as setting the structure to zero.
OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
-// EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns
-// it, or NULL on allocation failure.
-OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void);
+// EVP_MD_CTX_new allocates and initialises a fresh |EVP_MD_CTX| and returns
+// it, or NULL on allocation failure. The caller must use |EVP_MD_CTX_free| to
+// release the resulting object.
+OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_new(void);
// EVP_MD_CTX_cleanup frees any resources owned by |ctx| and resets it to a
// freshly initialised state. It does not free |ctx| itself. It returns one.
OPENSSL_EXPORT int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx);
-// EVP_MD_CTX_destroy calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself.
-OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
+// EVP_MD_CTX_free calls |EVP_MD_CTX_cleanup| and then frees |ctx| itself.
+OPENSSL_EXPORT void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
// EVP_MD_CTX_copy_ex sets |out|, which must already be initialised, to be a
// copy of |in|. It returns one on success and zero on error.
OPENSSL_EXPORT int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
+// EVP_MD_CTX_reset calls |EVP_MD_CTX_cleanup| followed by |EVP_MD_CTX_init|.
+OPENSSL_EXPORT void EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
+
// Digest operations.
@@ -201,6 +205,43 @@
#define EVP_MD_FLAG_DIGALGID_ABSENT 2
+// Digest operation accessors.
+
+// EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not
+// been set.
+OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
+// will crash if a digest hasn't been set on |ctx|.
+OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_block_size returns the block size of the digest function used by
+// |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|.
+OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
+
+// EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
+// (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
+// |ctx|.
+OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
+
+
+// ASN.1 functions.
+//
+// These functions allow code to parse and serialize AlgorithmIdentifiers for
+// hash functions.
+
+// EVP_parse_digest_algorithm parses an AlgorithmIdentifier structure containing
+// a hash function OID (for example, 2.16.840.1.101.3.4.2.1 is SHA-256) and
+// advances |cbs|. The parameters field may either be omitted or a NULL. It
+// returns the digest function or NULL on error.
+OPENSSL_EXPORT const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
+
+// EVP_marshal_digest_algorithm marshals |md| as an AlgorithmIdentifier
+// structure and appends the result to |cbb|. It returns one on success and zero
+// on error.
+OPENSSL_EXPORT int EVP_marshal_digest_algorithm(CBB *cbb, const EVP_MD *md);
+
+
// Deprecated functions.
// EVP_MD_CTX_copy sets |out|, which must /not/ be initialised, to be a copy of
@@ -221,25 +262,11 @@
// interface will always fail.
OPENSSL_EXPORT const EVP_MD *EVP_dss1(void);
+// EVP_MD_CTX_create calls |EVP_MD_CTX_new|.
+OPENSSL_EXPORT EVP_MD_CTX *EVP_MD_CTX_create(void);
-// Digest operation accessors.
-
-// EVP_MD_CTX_md returns the underlying digest function, or NULL if one has not
-// been set.
-OPENSSL_EXPORT const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
-// will crash if a digest hasn't been set on |ctx|.
-OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_block_size returns the block size of the digest function used by
-// |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|.
-OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
-
-// EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
-// (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
-// |ctx|.
-OPENSSL_EXPORT int EVP_MD_CTX_type(const EVP_MD_CTX *ctx);
+// EVP_MD_CTX_destroy calls |EVP_MD_CTX_free|.
+OPENSSL_EXPORT void EVP_MD_CTX_destroy(EVP_MD_CTX *ctx);
struct evp_md_pctx_ops;
@@ -269,7 +296,7 @@
namespace bssl {
-BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_destroy)
+BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_free)
using ScopedEVP_MD_CTX =
internal::StackAllocated<EVP_MD_CTX, int, EVP_MD_CTX_init,
diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h
index 2b4c08b..315e7ca 100644
--- a/src/include/openssl/dsa.h
+++ b/src/include/openssl/dsa.h
@@ -101,6 +101,21 @@
OPENSSL_EXPORT void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p,
const BIGNUM **out_q, const BIGNUM **out_g);
+// DSA_set0_key sets |dsa|'s public and private key to |pub_key| and |priv_key|,
+// respectively, if non-NULL. On success, it takes ownership of each argument
+// and returns one. Otherwise, it returns zero.
+//
+// |priv_key| may be NULL, but |pub_key| must either be non-NULL or already
+// configured on |dsa|.
+OPENSSL_EXPORT int DSA_set0_key(DSA *dsa, BIGNUM *pub_key, BIGNUM *priv_key);
+
+// DSA_set0_pqg sets |dsa|'s parameters to |p|, |q|, and |g|, if non-NULL, and
+// takes ownership of them. On success, it takes ownership of each argument and
+// returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |dsa|.
+OPENSSL_EXPORT int DSA_set0_pqg(DSA *dsa, BIGNUM *p, BIGNUM *q, BIGNUM *g);
+
// Parameter generation.
diff --git a/src/include/openssl/hmac.h b/src/include/openssl/hmac.h
index 1754d7f..8491b8d 100644
--- a/src/include/openssl/hmac.h
+++ b/src/include/openssl/hmac.h
@@ -87,13 +87,20 @@
// HMAC_CTX_init initialises |ctx| for use in an HMAC operation. It's assumed
// that HMAC_CTX objects will be allocated on the stack thus no allocation
-// function is provided. If needed, allocate |sizeof(HMAC_CTX)| and call
-// |HMAC_CTX_init| on it.
+// function is provided.
OPENSSL_EXPORT void HMAC_CTX_init(HMAC_CTX *ctx);
-// HMAC_CTX_cleanup frees data owned by |ctx|.
+// HMAC_CTX_new allocates and initialises a new |HMAC_CTX| and returns it, or
+// NULL on allocation failure. The caller must use |HMAC_CTX_free| to release
+// the resulting object.
+OPENSSL_EXPORT HMAC_CTX *HMAC_CTX_new(void);
+
+// HMAC_CTX_cleanup frees data owned by |ctx|. It does not free |ctx| itself.
OPENSSL_EXPORT void HMAC_CTX_cleanup(HMAC_CTX *ctx);
+// HMAC_CTX_free calls |HMAC_CTX_cleanup| and then frees |ctx| itself.
+OPENSSL_EXPORT void HMAC_CTX_free(HMAC_CTX *ctx);
+
// HMAC_Init_ex sets up an initialised |HMAC_CTX| to use |md| as the hash
// function and |key| as the key. For a non-initial call, |md| may be NULL, in
// which case the previous hash function will be used. If the hash function has
@@ -131,6 +138,9 @@
// on error.
OPENSSL_EXPORT int HMAC_CTX_copy_ex(HMAC_CTX *dest, const HMAC_CTX *src);
+// HMAC_CTX_reset calls |HMAC_CTX_cleanup| followed by |HMAC_CTX_init|.
+OPENSSL_EXPORT void HMAC_CTX_reset(HMAC_CTX *ctx);
+
// Deprecated functions.
@@ -161,6 +171,8 @@
namespace bssl {
+BORINGSSL_MAKE_DELETER(HMAC_CTX, HMAC_CTX_free)
+
using ScopedHMAC_CTX =
internal::StackAllocated<HMAC_CTX, void, HMAC_CTX_init, HMAC_CTX_cleanup>;
diff --git a/src/include/openssl/obj.h b/src/include/openssl/obj.h
index ae1a4ec..2bdc3b7 100644
--- a/src/include/openssl/obj.h
+++ b/src/include/openssl/obj.h
@@ -91,6 +91,12 @@
// less than, equal to or greater than |b|, respectively.
OPENSSL_EXPORT int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b);
+// OBJ_get0_data returns a pointer to the DER representation of |obj|.
+OPENSSL_EXPORT const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj);
+
+// OBJ_length returns the length of the DER representation of |obj|.
+OPENSSL_EXPORT size_t OBJ_length(const ASN1_OBJECT *obj);
+
// Looking up nids.
diff --git a/src/include/openssl/opensslconf.h b/src/include/openssl/opensslconf.h
index db409d9..3c6ffd8 100644
--- a/src/include/openssl/opensslconf.h
+++ b/src/include/openssl/opensslconf.h
@@ -19,18 +19,23 @@
#define OPENSSL_HEADER_OPENSSLCONF_H
+#define OPENSSL_NO_ASYNC
#define OPENSSL_NO_BF
+#define OPENSSL_NO_BLAKE2
#define OPENSSL_NO_BUF_FREELISTS
#define OPENSSL_NO_CAMELLIA
#define OPENSSL_NO_CAPIENG
#define OPENSSL_NO_CAST
#define OPENSSL_NO_CMS
#define OPENSSL_NO_COMP
+#define OPENSSL_NO_CT
#define OPENSSL_NO_DANE
#define OPENSSL_NO_DEPRECATED
+#define OPENSSL_NO_DGRAM
#define OPENSSL_NO_DYNAMIC_ENGINE
#define OPENSSL_NO_EC_NISTP_64_GCC_128
#define OPENSSL_NO_EC2M
+#define OPENSSL_NO_EGD
#define OPENSSL_NO_ENGINE
#define OPENSSL_NO_GMP
#define OPENSSL_NO_GOST
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index d463f85..3f45318 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -108,6 +108,29 @@
const BIGNUM **out_dmq1,
const BIGNUM **out_iqmp);
+// RSA_set0_key sets |rsa|'s modulus, public exponent, and private exponent to
+// |n|, |e|, and |d| respectively, if non-NULL. On success, it takes ownership
+// of each argument and returns one. Otherwise, it returns zero.
+//
+// |d| may be NULL, but |n| and |e| must either be non-NULL or already
+// configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d);
+
+// RSA_set0_factors sets |rsa|'s prime factors to |p| and |q|, if non-NULL, and
+// takes ownership of them. On success, it takes ownership of each argument and
+// returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_factors(RSA *rsa, BIGNUM *p, BIGNUM *q);
+
+// RSA_set0_crt_params sets |rsa|'s CRT parameters to |dmp1|, |dmq1|, and
+// |iqmp|, if non-NULL, and takes ownership of them. On success, it takes
+// ownership of its parameters and returns one. Otherwise, it returns zero.
+//
+// Each argument must either be non-NULL or already configured on |rsa|.
+OPENSSL_EXPORT int RSA_set0_crt_params(RSA *rsa, BIGNUM *dmp1, BIGNUM *dmq1,
+ BIGNUM *iqmp);
+
// Key generation.
diff --git a/src/include/openssl/span.h b/src/include/openssl/span.h
index 08c4518..d447314 100644
--- a/src/include/openssl/span.h
+++ b/src/include/openssl/span.h
@@ -92,13 +92,15 @@
template <typename T>
class Span : private internal::SpanBase<const T> {
private:
- template <bool B, class V = void>
- using enable_if_t = typename std::enable_if<B, V>::type;
-
// Heuristically test whether C is a container type that can be converted into
// a Span by checking for data() and size() member functions.
+ //
+ // TODO(davidben): Switch everything to std::enable_if_t when we remove
+ // support for MSVC 2015. Although we could write our own enable_if_t and MSVC
+ // 2015 has std::enable_if_t anyway, MSVC 2015's SFINAE implementation is
+ // problematic and does not work below unless we write the ::type at use.
template <typename C>
- using EnableIfContainer = enable_if_t<
+ using EnableIfContainer = std::enable_if<
std::is_convertible<decltype(std::declval<C>().data()), T *>::value &&
std::is_integral<decltype(std::declval<C>().size())>::value>;
@@ -109,12 +111,14 @@
template <size_t N>
constexpr Span(T (&array)[N]) : Span(array, N) {}
- template <typename C, typename = EnableIfContainer<C>,
- typename = enable_if_t<std::is_const<T>::value, C>>
+ template <
+ typename C, typename = typename EnableIfContainer<C>::type,
+ typename = typename std::enable_if<std::is_const<T>::value, C>::type>
Span(const C &container) : data_(container.data()), size_(container.size()) {}
- template <typename C, typename = EnableIfContainer<C>,
- typename = enable_if_t<!std::is_const<T>::value, C>>
+ template <
+ typename C, typename = typename EnableIfContainer<C>::type,
+ typename = typename std::enable_if<!std::is_const<T>::value, C>::type>
explicit Span(C &container)
: data_(container.data()), size_(container.size()) {}
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index d6f6149..a85fc9c 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -1074,11 +1074,20 @@
OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,
pem_password_cb *cb);
+// SSL_CTX_get_default_passwd_cb returns the callback set by
+// |SSL_CTX_set_default_passwd_cb|.
+OPENSSL_EXPORT pem_password_cb *SSL_CTX_get_default_passwd_cb(
+ const SSL_CTX *ctx);
+
// SSL_CTX_set_default_passwd_cb_userdata sets the userdata parameter for
// |ctx|'s password callback.
OPENSSL_EXPORT void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx,
void *data);
+// SSL_CTX_get_default_passwd_cb_userdata returns the userdata parameter set by
+// |SSL_CTX_set_default_passwd_cb_userdata|.
+OPENSSL_EXPORT void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx);
+
// Custom private keys.
@@ -1709,6 +1718,35 @@
const uint8_t *sid_ctx,
size_t sid_ctx_len);
+// SSL_SESSION_should_be_single_use returns one if |session| should be
+// single-use (TLS 1.3 and later) and zero otherwise.
+//
+// If this function returns one, clients retain multiple sessions and use each
+// only once. This prevents passive observers from correlating connections with
+// tickets. See draft-ietf-tls-tls13-18, appendix B.5. If it returns zero,
+// |session| cannot be used without leaking a correlator.
+OPENSSL_EXPORT int SSL_SESSION_should_be_single_use(const SSL_SESSION *session);
+
+// SSL_SESSION_is_resumable returns one if |session| is resumable and zero
+// otherwise.
+OPENSSL_EXPORT int SSL_SESSION_is_resumable(const SSL_SESSION *session);
+
+// SSL_SESSION_has_ticket returns one if |session| has a ticket and zero
+// otherwise.
+OPENSSL_EXPORT int SSL_SESSION_has_ticket(const SSL_SESSION *session);
+
+// SSL_SESSION_get0_ticket sets |*out_ticket| and |*out_len| to |session|'s
+// ticket, or NULL and zero if it does not have one. |out_ticket| may be NULL
+// if only the ticket length is needed.
+OPENSSL_EXPORT void SSL_SESSION_get0_ticket(const SSL_SESSION *session,
+ const uint8_t **out_ticket,
+ size_t *out_len);
+
+// SSL_SESSION_get_ticket_lifetime_hint returns ticket lifetime hint of
+// |session| in seconds or zero if none was set.
+OPENSSL_EXPORT uint32_t
+SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
+
// Session caching.
//
@@ -1745,6 +1783,12 @@
// e.g., different cipher suite settings or client certificates should also use
// separate session caches between those contexts. Servers should also partition
// session caches between SNI hosts with |SSL_CTX_set_session_id_context|.
+//
+// Note also, in TLS 1.2 and earlier, offering sessions allows passive observers
+// to correlate different client connections. TLS 1.3 and later fix this,
+// provided clients use sessions at most once. Session caches are managed by the
+// caller in BoringSSL, so this must be implemented externally. See
+// |SSL_SESSION_should_be_single_use| for details.
// SSL_SESS_CACHE_OFF disables all session caching.
#define SSL_SESS_CACHE_OFF 0x0000
@@ -1854,9 +1898,6 @@
// session cache.
OPENSSL_EXPORT unsigned long SSL_CTX_sess_get_cache_size(const SSL_CTX *ctx);
-// SSL_CTX_sessions returns |ctx|'s internal session cache.
-OPENSSL_EXPORT LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
-
// SSL_CTX_sess_number returns the number of sessions in |ctx|'s internal
// session cache.
OPENSSL_EXPORT size_t SSL_CTX_sess_number(const SSL_CTX *ctx);
@@ -1933,18 +1974,14 @@
//
// If the internal session cache is enabled, the callback is only consulted if
// the internal cache does not return a match.
-//
-// The callback's |id| parameter is not const for historical reasons, but the
-// contents may not be modified.
OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
- SSL_CTX *ctx,
- SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *id, int id_len,
- int *out_copy));
+ SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *id,
+ int id_len, int *out_copy));
// SSL_CTX_sess_get_get_cb returns the callback set by
// |SSL_CTX_sess_set_get_cb|.
OPENSSL_EXPORT SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
- SSL *ssl, uint8_t *id, int id_len, int *out_copy);
+ SSL *ssl, const uint8_t *id, int id_len, int *out_copy);
// SSL_magic_pending_session_ptr returns a magic |SSL_SESSION|* which indicates
// that the session isn't currently unavailable. |SSL_get_error| will then
@@ -3973,6 +4010,24 @@
// the session.
OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
+#define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_LOAD_SSL_STRINGS 0
+#define OPENSSL_INIT_SSL_DEFAULT 0
+
+// OPENSSL_init_ssl calls |CRYPTO_library_init| and returns one.
+OPENSSL_EXPORT int OPENSSL_init_ssl(uint64_t opts,
+ const OPENSSL_INIT_SETTINGS *settings);
+
+#if !defined(BORINGSSL_NO_CXX)
+// SSL_CTX_sess_set_get_cb is a legacy C++ overload of |SSL_CTX_sess_set_get_cb|
+// which supports the old callback signature.
+//
+// TODO(davidben): Remove this once Node is compatible with OpenSSL 1.1.0.
+extern "C++" OPENSSL_EXPORT void SSL_CTX_sess_set_get_cb(
+ SSL_CTX *ctx, SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *id,
+ int id_len, int *out_copy));
+#endif
+
// Private structures.
//
@@ -4221,8 +4276,10 @@
// it.
int (*new_session_cb)(SSL *ssl, SSL_SESSION *sess);
void (*remove_session_cb)(SSL_CTX *ctx, SSL_SESSION *sess);
- SSL_SESSION *(*get_session_cb)(SSL *ssl, uint8_t *data, int len,
+ SSL_SESSION *(*get_session_cb)(SSL *ssl, const uint8_t *data, int len,
int *copy);
+ SSL_SESSION *(*get_session_cb_legacy)(SSL *ssl, uint8_t *data, int len,
+ int *copy);
CRYPTO_refcount_t references;
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 62bd5f8..7db9466 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -575,7 +575,8 @@
OPENSSL_EXPORT int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki);
OPENSSL_EXPORT int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent);
-OPENSSL_EXPORT int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig);
+OPENSSL_EXPORT int X509_signature_print(BIO *bp, const X509_ALGOR *alg,
+ const ASN1_STRING *sig);
OPENSSL_EXPORT int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);
OPENSSL_EXPORT int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx);
@@ -686,6 +687,7 @@
OPENSSL_EXPORT X509_NAME *X509_NAME_dup(X509_NAME *xn);
OPENSSL_EXPORT X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne);
+OPENSSL_EXPORT int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne);
OPENSSL_EXPORT int X509_cmp_time(const ASN1_TIME *s, time_t *t);
OPENSSL_EXPORT int X509_cmp_current_time(const ASN1_TIME *s);
@@ -756,8 +758,8 @@
OPENSSL_EXPORT int i2d_X509_AUX(X509 *a,unsigned char **pp);
OPENSSL_EXPORT X509 * d2i_X509_AUX(X509 **a,const unsigned char **pp,long length);
-OPENSSL_EXPORT void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
- const X509 *x);
+OPENSSL_EXPORT void X509_get0_signature(const ASN1_BIT_STRING **psig,
+ const X509_ALGOR **palg, const X509 *x);
OPENSSL_EXPORT int X509_get_signature_nid(const X509 *x);
OPENSSL_EXPORT int X509_alias_set1(X509 *x, unsigned char *name, int len);
@@ -816,7 +818,9 @@
OPENSSL_EXPORT int X509_set_subject_name(X509 *x, X509_NAME *name);
OPENSSL_EXPORT X509_NAME * X509_get_subject_name(X509 *a);
OPENSSL_EXPORT int X509_set_notBefore(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT const ASN1_TIME *X509_get0_notBefore(const X509 *x);
OPENSSL_EXPORT int X509_set_notAfter(X509 *x, const ASN1_TIME *tm);
+OPENSSL_EXPORT const ASN1_TIME *X509_get0_notAfter(const X509 *x);
OPENSSL_EXPORT int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);
OPENSSL_EXPORT EVP_PKEY * X509_get_pubkey(X509 *x);
OPENSSL_EXPORT ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
index 4abd9cd..991cbda 100644
--- a/src/include/openssl/x509_vfy.h
+++ b/src/include/openssl/x509_vfy.h
@@ -423,16 +423,20 @@
OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
OPENSSL_EXPORT int X509_OBJECT_up_ref_count(X509_OBJECT *a);
OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a);
+OPENSSL_EXPORT int X509_OBJECT_get_type(const X509_OBJECT *a);
+OPENSSL_EXPORT X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a);
OPENSSL_EXPORT X509_STORE *X509_STORE_new(void );
OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store);
OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v);
+OPENSSL_EXPORT STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *st);
OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
OPENSSL_EXPORT STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *st, X509_NAME *nm);
OPENSSL_EXPORT int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags);
OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust);
OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+OPENSSL_EXPORT X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx);
/* X509_STORE_set0_additional_untrusted sets a stack of additional, untrusted
* certificates that are available for chain building. This function does not
* take ownership of the stack. */
@@ -513,6 +517,8 @@
OPENSSL_EXPORT STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx);
OPENSSL_EXPORT void X509_STORE_CTX_set_cert(X509_STORE_CTX *c,X509 *x);
OPENSSL_EXPORT void X509_STORE_CTX_set_chain(X509_STORE_CTX *c,STACK_OF(X509) *sk);
+OPENSSL_EXPORT STACK_OF(X509) *
+ X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx);
OPENSSL_EXPORT void X509_STORE_CTX_set0_crls(X509_STORE_CTX *c,STACK_OF(X509_CRL) *sk);
OPENSSL_EXPORT int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
OPENSSL_EXPORT int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust);
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index ab499df..c2f6479 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -535,19 +535,17 @@
return 1;
}
-int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
- size_t *out_len) {
- *out_msg = NULL;
- if (!CBB_finish(cbb, out_msg, out_len) ||
- *out_len < DTLS1_HM_HEADER_LENGTH) {
+int dtls1_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg) {
+ if (!CBBFinishArray(cbb, out_msg) ||
+ out_msg->size() < DTLS1_HM_HEADER_LENGTH) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(*out_msg);
return 0;
}
// Fix up the header. Copy the fragment length into the total message
// length.
- OPENSSL_memcpy(*out_msg + 1, *out_msg + DTLS1_HM_HEADER_LENGTH - 3, 3);
+ OPENSSL_memcpy(out_msg->data() + 1,
+ out_msg->data() + DTLS1_HM_HEADER_LENGTH - 3, 3);
return 1;
}
@@ -555,7 +553,7 @@
// outgoing flight. It returns one on success and zero on error. In both cases,
// it takes ownership of |data| and releases it with |OPENSSL_free| when
// done.
-static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) {
+static int add_outgoing(SSL *ssl, int is_ccs, Array<uint8_t> data) {
if (ssl->d1->outgoing_messages_complete) {
// If we've begun writing a new flight, we received the peer flight. Discard
// the timer and the our flight.
@@ -566,10 +564,10 @@
static_assert(SSL_MAX_HANDSHAKE_FLIGHT <
(1 << 8 * sizeof(ssl->d1->outgoing_messages_len)),
"outgoing_messages_len is too small");
- if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT) {
+ if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT ||
+ data.size() > 0xffffffff) {
assert(0);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(data);
return 0;
}
@@ -577,9 +575,8 @@
// TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript
// on hs.
if (ssl->s3->hs != NULL &&
- !ssl->s3->hs->transcript.Update(data, len)) {
+ !ssl->s3->hs->transcript.Update(data.data(), data.size())) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- OPENSSL_free(data);
return 0;
}
ssl->d1->handshake_write_seq++;
@@ -587,7 +584,8 @@
DTLS_OUTGOING_MESSAGE *msg =
&ssl->d1->outgoing_messages[ssl->d1->outgoing_messages_len];
- msg->data = data;
+ size_t len;
+ data.Release(&msg->data, &len);
msg->len = len;
msg->epoch = ssl->d1->w_epoch;
msg->is_ccs = is_ccs;
@@ -596,12 +594,12 @@
return 1;
}
-int dtls1_add_message(SSL *ssl, uint8_t *data, size_t len) {
- return add_outgoing(ssl, 0 /* handshake */, data, len);
+int dtls1_add_message(SSL *ssl, Array<uint8_t> data) {
+ return add_outgoing(ssl, 0 /* handshake */, std::move(data));
}
int dtls1_add_change_cipher_spec(SSL *ssl) {
- return add_outgoing(ssl, 1 /* ChangeCipherSpec */, NULL, 0);
+ return add_outgoing(ssl, 1 /* ChangeCipherSpec */, Array<uint8_t>());
}
int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 6746582..c10c40f 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -114,6 +114,8 @@
#include <assert.h>
+#include <utility>
+
#include "../crypto/internal.h"
#include "internal.h"
@@ -144,15 +146,7 @@
}
SSL_HANDSHAKE::~SSL_HANDSHAKE() {
- OPENSSL_free(cookie);
- OPENSSL_free(key_share_bytes);
- OPENSSL_free(ecdh_public_key);
- OPENSSL_free(peer_sigalgs);
- OPENSSL_free(peer_supported_group_list);
- OPENSSL_free(peer_key);
- OPENSSL_free(server_params);
ssl->ctx->x509_method->hs_flush_cached_ca_names(this);
- OPENSSL_free(certificate_types);
OPENSSL_free(key_block);
}
@@ -179,10 +173,9 @@
}
int ssl_add_message_cbb(SSL *ssl, CBB *cbb) {
- uint8_t *msg;
- size_t len;
- if (!ssl->method->finish_message(ssl, cbb, &msg, &len) ||
- !ssl->method->add_message(ssl, msg, len)) {
+ Array<uint8_t> msg;
+ if (!ssl->method->finish_message(ssl, cbb, &msg) ||
+ !ssl->method->add_message(ssl, std::move(msg))) {
return 0;
}
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 3916692..b2d5384 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -338,21 +338,19 @@
return 0;
}
- uint8_t *msg = NULL;
- size_t len;
- if (!ssl->method->finish_message(ssl, cbb.get(), &msg, &len)) {
+ Array<uint8_t> msg;
+ if (!ssl->method->finish_message(ssl, cbb.get(), &msg)) {
return 0;
}
// Now that the length prefixes have been computed, fill in the placeholder
// PSK binder.
if (hs->needs_psk_binder &&
- !tls13_write_psk_binder(hs, msg, len)) {
- OPENSSL_free(msg);
+ !tls13_write_psk_binder(hs, msg.data(), msg.size())) {
return 0;
}
- return ssl->method->add_message(ssl, msg, len);
+ return ssl->method->add_message(ssl, std::move(msg));
}
static int parse_server_version(SSL_HANDSHAKE *hs, uint16_t *out,
@@ -602,14 +600,19 @@
return ssl_hs_ok;
}
+ // Clear some TLS 1.3 state that no longer needs to be retained.
+ hs->key_share.reset();
+ hs->key_share_bytes.Reset();
+
+ // A TLS 1.2 server would not know to skip the early data we offered. Report
+ // an error code sooner. The caller may use this error code to implement the
+ // fallback described in draft-ietf-tls-tls13-18 appendix C.3.
if (hs->early_data_offered) {
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_ON_EARLY_DATA);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
return ssl_hs_error;
}
- ssl_clear_tls13_state(hs);
-
if (!ssl_check_message_type(ssl, msg, SSL3_MT_SERVER_HELLO)) {
return ssl_hs_error;
}
@@ -977,7 +980,7 @@
// Initialize ECDH and save the peer public key for later.
hs->key_share = SSLKeyShare::Create(group_id);
if (!hs->key_share ||
- !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
+ !hs->peer_key.CopyFrom(point)) {
return ssl_hs_error;
}
} else if (!(alg_k & SSL_kPSK)) {
@@ -1106,8 +1109,7 @@
return ssl_hs_error;
}
- if (!CBS_stow(&certificate_types, &hs->certificate_types,
- &hs->num_certificate_types)) {
+ if (!hs->certificate_types.CopyFrom(certificate_types)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
@@ -1229,8 +1231,7 @@
return ssl_hs_error;
}
- uint8_t *pms = NULL;
- size_t pms_len = 0;
+ Array<uint8_t> pms;
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
@@ -1240,7 +1241,7 @@
if (alg_a & SSL_aPSK) {
if (ssl->psk_client_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
- goto err;
+ return ssl_hs_error;
}
char identity[PSK_MAX_IDENTITY_LEN + 1];
@@ -1251,7 +1252,7 @@
if (psk_len == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
+ return ssl_hs_error;
}
assert(psk_len <= PSK_MAX_PSK_LEN);
@@ -1259,7 +1260,7 @@
hs->new_session->psk_identity = BUF_strdup(identity);
if (hs->new_session->psk_identity == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return ssl_hs_error;
}
// Write out psk_identity.
@@ -1268,29 +1269,26 @@
!CBB_add_bytes(&child, (const uint8_t *)identity,
OPENSSL_strnlen(identity, sizeof(identity))) ||
!CBB_flush(&body)) {
- goto err;
+ return ssl_hs_error;
}
}
- // Depending on the key exchange method, compute |pms| and |pms_len|.
+ // Depending on the key exchange method, compute |pms|.
if (alg_k & SSL_kRSA) {
- pms_len = SSL_MAX_MASTER_KEY_LENGTH;
- pms = (uint8_t *)OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ if (!pms.Init(SSL_MAX_MASTER_KEY_LENGTH)) {
+ return ssl_hs_error;
}
RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey.get());
if (rsa == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
+ return ssl_hs_error;
}
pms[0] = hs->client_version >> 8;
pms[1] = hs->client_version & 0xff;
if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
- goto err;
+ return ssl_hs_error;
}
CBB child, *enc_pms = &body;
@@ -1298,56 +1296,50 @@
// In TLS, there is a length prefix.
if (ssl->version > SSL3_VERSION) {
if (!CBB_add_u16_length_prefixed(&body, &child)) {
- goto err;
+ return ssl_hs_error;
}
enc_pms = &child;
}
uint8_t *ptr;
if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
- !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
- RSA_PKCS1_PADDING) ||
+ !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms.data(),
+ pms.size(), RSA_PKCS1_PADDING) ||
!CBB_did_write(enc_pms, enc_pms_len) ||
!CBB_flush(&body)) {
- goto err;
+ return ssl_hs_error;
}
} else if (alg_k & SSL_kECDHE) {
// Generate a keypair and serialize the public half.
CBB child;
if (!CBB_add_u8_length_prefixed(&body, &child)) {
- goto err;
+ return ssl_hs_error;
}
// Compute the premaster.
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!hs->key_share->Accept(&child, &pms, &pms_len, &alert, hs->peer_key,
- hs->peer_key_len)) {
+ if (!hs->key_share->Accept(&child, &pms, &alert, hs->peer_key)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return ssl_hs_error;
}
if (!CBB_flush(&body)) {
- goto err;
+ return ssl_hs_error;
}
// The key exchange state may now be discarded.
hs->key_share.reset();
- OPENSSL_free(hs->peer_key);
- hs->peer_key = NULL;
- hs->peer_key_len = 0;
+ hs->peer_key.Reset();
} else if (alg_k & SSL_kPSK) {
// For plain PSK, other_secret is a block of 0s with the same length as
// the pre-shared key.
- pms_len = psk_len;
- pms = (uint8_t *)OPENSSL_malloc(pms_len);
- if (pms == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ if (!pms.Init(psk_len)) {
+ return ssl_hs_error;
}
- OPENSSL_memset(pms, 0, pms_len);
+ OPENSSL_memset(pms.data(), 0, pms.size());
} else {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto err;
+ return ssl_hs_error;
}
// For a PSK cipher suite, other_secret is combined with the pre-shared
@@ -1358,40 +1350,33 @@
uint8_t *new_pms;
size_t new_pms_len;
- if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms_len) ||
+ if (!CBB_init(pms_cbb.get(), 2 + psk_len + 2 + pms.size()) ||
!CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
- !CBB_add_bytes(&child, pms, pms_len) ||
+ !CBB_add_bytes(&child, pms.data(), pms.size()) ||
!CBB_add_u16_length_prefixed(pms_cbb.get(), &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
!CBB_finish(pms_cbb.get(), &new_pms, &new_pms_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return ssl_hs_error;
}
- OPENSSL_free(pms);
- pms = new_pms;
- pms_len = new_pms_len;
+ pms.Reset(new_pms, new_pms_len);
}
// The message must be added to the finished hash before calculating the
// master secret.
if (!ssl_add_message_cbb(ssl, cbb.get())) {
- goto err;
+ return ssl_hs_error;
}
hs->new_session->master_key_length = tls1_generate_master_secret(
- hs, hs->new_session->master_key, pms, pms_len);
+ hs, hs->new_session->master_key, pms.data(), pms.size());
if (hs->new_session->master_key_length == 0) {
- goto err;
+ return ssl_hs_error;
}
hs->new_session->extended_master_secret = hs->extended_master_secret;
- OPENSSL_free(pms);
hs->state = state_send_client_certificate_verify;
return ssl_hs_ok;
-
-err:
- OPENSSL_free(pms);
- return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index a38e25f..5507250 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -818,7 +818,7 @@
assert(alg_k & SSL_kPSK);
}
- if (!CBB_finish(cbb.get(), &hs->server_params, &hs->server_params_len)) {
+ if (!CBBFinishArray(cbb.get(), &hs->server_params)) {
return ssl_hs_error;
}
}
@@ -830,7 +830,7 @@
static enum ssl_hs_wait_t do_send_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (hs->server_params_len == 0) {
+ if (hs->server_params.size() == 0) {
hs->state = state_send_server_hello_done;
return ssl_hs_ok;
}
@@ -840,9 +840,9 @@
if (!ssl->method->init_message(ssl, cbb.get(), &body,
SSL3_MT_SERVER_KEY_EXCHANGE) ||
// |hs->server_params| contains a prefix for signing.
- hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
- !CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
- hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
+ hs->server_params.size() < 2 * SSL3_RANDOM_SIZE ||
+ !CBB_add_bytes(&body, hs->server_params.data() + 2 * SSL3_RANDOM_SIZE,
+ hs->server_params.size() - 2 * SSL3_RANDOM_SIZE)) {
return ssl_hs_error;
}
@@ -876,8 +876,8 @@
size_t sig_len;
switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
- signature_algorithm, hs->server_params,
- hs->server_params_len)) {
+ signature_algorithm, hs->server_params.data(),
+ hs->server_params.size())) {
case ssl_private_key_success:
if (!CBB_did_write(&child, sig_len)) {
return ssl_hs_error;
@@ -894,9 +894,7 @@
return ssl_hs_error;
}
- OPENSSL_free(hs->server_params);
- hs->server_params = NULL;
- hs->server_params_len = 0;
+ hs->server_params.Reset();
hs->state = state_send_server_hello_done;
return ssl_hs_ok;
@@ -1048,12 +1046,6 @@
static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
-
- ssl_hs_wait_t ret = ssl_hs_error;
- uint8_t *premaster_secret = NULL;
- size_t premaster_secret_len = 0;
- uint8_t *decrypt_buf = NULL;
-
SSLMessage msg;
if (!ssl->method->get_message(ssl, &msg)) {
return ssl_hs_read_message;
@@ -1077,25 +1069,25 @@
((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return ssl_hs_error;
}
if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
CBS_contains_zero_byte(&psk_identity)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
- goto err;
+ return ssl_hs_error;
}
if (!CBS_strdup(&psk_identity, &hs->new_session->psk_identity)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return ssl_hs_error;
}
}
- // Depending on the key exchange method, compute |premaster_secret| and
- // |premaster_secret_len|.
+ // Depending on the key exchange method, compute |premaster_secret|.
+ Array<uint8_t> premaster_secret;
if (alg_k & SSL_kRSA) {
CBS encrypted_premaster_secret;
if (ssl->version > SSL3_VERSION) {
@@ -1104,63 +1096,56 @@
CBS_len(&client_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return ssl_hs_error;
}
} else {
encrypted_premaster_secret = client_key_exchange;
}
// Allocate a buffer large enough for an RSA decryption.
- const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey.get());
- decrypt_buf = (uint8_t *)OPENSSL_malloc(rsa_size);
- if (decrypt_buf == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ Array<uint8_t> decrypt_buf;
+ if (!decrypt_buf.Init(EVP_PKEY_size(hs->local_pubkey.get()))) {
+ return ssl_hs_error;
}
// Decrypt with no padding. PKCS#1 padding will be removed as part of the
// timing-sensitive code below.
size_t decrypt_len;
- switch (ssl_private_key_decrypt(hs, decrypt_buf, &decrypt_len, rsa_size,
+ switch (ssl_private_key_decrypt(hs, decrypt_buf.data(), &decrypt_len,
+ decrypt_buf.size(),
CBS_data(&encrypted_premaster_secret),
CBS_len(&encrypted_premaster_secret))) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
- goto err;
+ return ssl_hs_error;
case ssl_private_key_retry:
- ret = ssl_hs_private_key_operation;
- goto err;
+ return ssl_hs_private_key_operation;
}
- if (decrypt_len != rsa_size) {
+ if (decrypt_len != decrypt_buf.size()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
- goto err;
+ return ssl_hs_error;
}
// Prepare a random premaster, to be used on invalid padding. See RFC 5246,
// section 7.4.7.1.
- premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
- premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
- if (premaster_secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
- goto err;
+ if (!premaster_secret.Init(SSL_MAX_MASTER_KEY_LENGTH) ||
+ !RAND_bytes(premaster_secret.data(), premaster_secret.size())) {
+ return ssl_hs_error;
}
// The smallest padded premaster is 11 bytes of overhead. Small keys are
// publicly invalid.
- if (decrypt_len < 11 + premaster_secret_len) {
+ if (decrypt_len < 11 + premaster_secret.size()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
- goto err;
+ return ssl_hs_error;
}
// Check the padding. See RFC 3447, section 7.2.2.
- size_t padding_len = decrypt_len - premaster_secret_len;
+ size_t padding_len = decrypt_len - premaster_secret.size();
uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
constant_time_eq_int_8(decrypt_buf[1], 2);
for (size_t i = 2; i < padding_len - 1; i++) {
@@ -1177,13 +1162,10 @@
// Select, in constant time, either the decrypted premaster or the random
// premaster based on |good|.
- for (size_t i = 0; i < premaster_secret_len; i++) {
+ for (size_t i = 0; i < premaster_secret.size(); i++) {
premaster_secret[i] = constant_time_select_8(
good, decrypt_buf[padding_len + i], premaster_secret[i]);
}
-
- OPENSSL_free(decrypt_buf);
- decrypt_buf = NULL;
} else if (alg_k & SSL_kECDHE) {
// Parse the ClientKeyExchange.
CBS peer_key;
@@ -1191,15 +1173,14 @@
CBS_len(&client_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
- goto err;
+ return ssl_hs_error;
}
// Compute the premaster.
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!hs->key_share->Finish(&premaster_secret, &premaster_secret_len, &alert,
- CBS_data(&peer_key), CBS_len(&peer_key))) {
+ if (!hs->key_share->Finish(&premaster_secret, &alert, peer_key)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
- goto err;
+ return ssl_hs_error;
}
// The key exchange state may now be discarded.
@@ -1207,7 +1188,7 @@
} else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
- goto err;
+ return ssl_hs_error;
}
// For a PSK cipher suite, the actual pre-master secret is combined with the
@@ -1216,7 +1197,7 @@
if (ssl->psk_server_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return ssl_hs_error;
}
// Look up the key for the identity.
@@ -1226,24 +1207,21 @@
if (psk_len > PSK_MAX_PSK_LEN) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
+ return ssl_hs_error;
} else if (psk_len == 0) {
// PSK related to the given identity not found.
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
- goto err;
+ return ssl_hs_error;
}
if (alg_k & SSL_kPSK) {
// In plain PSK, other_secret is a block of 0s with the same length as the
// pre-shared key.
- premaster_secret_len = psk_len;
- premaster_secret = (uint8_t *)OPENSSL_malloc(premaster_secret_len);
- if (premaster_secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ if (!premaster_secret.Init(psk_len)) {
+ return ssl_hs_error;
}
- OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
+ OPENSSL_memset(premaster_secret.data(), 0, premaster_secret.size());
}
ScopedCBB new_premaster;
@@ -1251,47 +1229,36 @@
uint8_t *new_data;
size_t new_len;
if (!CBB_init(new_premaster.get(),
- 2 + psk_len + 2 + premaster_secret_len) ||
+ 2 + psk_len + 2 + premaster_secret.size()) ||
!CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
- !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
+ !CBB_add_bytes(&child, premaster_secret.data(),
+ premaster_secret.size()) ||
!CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
!CBB_finish(new_premaster.get(), &new_data, &new_len)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return ssl_hs_error;
}
- OPENSSL_cleanse(premaster_secret, premaster_secret_len);
- OPENSSL_free(premaster_secret);
- premaster_secret = new_data;
- premaster_secret_len = new_len;
+ premaster_secret.Reset(new_data, new_len);
}
if (!ssl_hash_message(hs, msg)) {
- goto err;
+ return ssl_hs_error;
}
// Compute the master secret.
hs->new_session->master_key_length = tls1_generate_master_secret(
- hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);
+ hs, hs->new_session->master_key, premaster_secret.data(),
+ premaster_secret.size());
if (hs->new_session->master_key_length == 0) {
- goto err;
+ return ssl_hs_error;
}
hs->new_session->extended_master_secret = hs->extended_master_secret;
ssl->method->next_message(ssl);
hs->state = state_read_client_certificate_verify;
- ret = ssl_hs_ok;
-
-err:
- if (premaster_secret != NULL) {
- OPENSSL_cleanse(premaster_secret, premaster_secret_len);
- OPENSSL_free(premaster_secret);
- }
- OPENSSL_free(decrypt_buf);
-
- return ret;
-
+ return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_read_client_certificate_verify(SSL_HANDSHAKE *hs) {
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index d5500bb..13e6655 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -146,6 +146,7 @@
#include <stdlib.h>
+#include <limits>
#include <new>
#include <type_traits>
#include <utility>
@@ -154,8 +155,11 @@
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/ssl.h>
+#include <openssl/span.h>
#include <openssl/stack.h>
+#include "../crypto/internal.h"
+
#if defined(OPENSSL_WINDOWS)
// Windows defines struct timeval in winsock2.h.
@@ -233,6 +237,103 @@
#define PURE_VIRTUAL { abort(); }
#endif
+// Array<T> is an owning array of elements of |T|.
+template <typename T>
+class Array {
+ public:
+ // Array's default constructor creates an empty array.
+ Array() {}
+ Array(const Array &) = delete;
+ Array(Array &&other) { *this = std::move(other); }
+
+ ~Array() { Reset(); }
+
+ Array &operator=(const Array &) = delete;
+ Array &operator=(Array &&other) {
+ Reset();
+ other.Release(&data_, &size_);
+ return *this;
+ }
+
+ const T *data() const { return data_; }
+ T *data() { return data_; }
+ size_t size() const { return size_; }
+
+ const T &operator[](size_t i) const { return data_[i]; }
+ T &operator[](size_t i) { return data_[i]; }
+
+ T *begin() { return data_; }
+ const T *cbegin() const { return data_; }
+ T *end() { return data_ + size_; }
+ const T *cend() const { return data_ + size_; }
+
+ void Reset() { Reset(nullptr, 0); }
+
+ // Reset releases the current contents of the array and takes ownership of the
+ // raw pointer supplied by the caller.
+ void Reset(T *new_data, size_t new_size) {
+ for (size_t i = 0; i < size_; i++) {
+ data_[i].~T();
+ }
+ OPENSSL_free(data_);
+ data_ = new_data;
+ size_ = new_size;
+ }
+
+ // Release releases ownership of the array to a raw pointer supplied by the
+ // caller.
+ void Release(T **out, size_t *out_size) {
+ *out = data_;
+ *out_size = size_;
+ data_ = nullptr;
+ size_ = 0;
+ }
+
+ // Init replaces the array with a newly-allocated array of |new_size|
+ // default-constructed copies of |T|. It returns true on success and false on
+ // error.
+ //
+ // Note that if |T| is a primitive type like |uint8_t|, it is uninitialized.
+ bool Init(size_t new_size) {
+ Reset();
+ if (new_size == 0) {
+ return true;
+ }
+
+ if (new_size > std::numeric_limits<size_t>::max() / sizeof(T)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+ return false;
+ }
+ data_ = reinterpret_cast<T*>(OPENSSL_malloc(new_size * sizeof(T)));
+ if (data_ == nullptr) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ return false;
+ }
+ size_ = new_size;
+ for (size_t i = 0; i < size_; i++) {
+ new (&data_[i]) T;
+ }
+ return true;
+ }
+
+ // CopyFrom replaces the array with a newly-allocated copy of |in|. It returns
+ // true on success and false on error.
+ bool CopyFrom(Span<const uint8_t> in) {
+ if (!Init(in.size())) {
+ return false;
+ }
+ OPENSSL_memcpy(data_, in.data(), in.size());
+ return true;
+ }
+
+ private:
+ T *data_ = nullptr;
+ size_t size_ = 0;
+};
+
+// CBBFinishArray behaves like |CBB_finish| but stores the result in an Array.
+bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
+
// Protocol versions.
//
@@ -839,30 +940,20 @@
// Accept performs a key exchange against the |peer_key| generated by |offer|.
// On success, it returns true, writes the public value to |out_public_key|,
- // and sets |*out_secret| and |*out_secret_len| to a newly-allocated buffer
- // containing the shared secret. The caller must release this buffer with
- // |OPENSSL_free|. On failure, it returns false and sets |*out_alert| to an
- // alert to send to the peer.
+ // and sets |*out_secret| the shared secret. On failure, it returns false and
+ // sets |*out_alert| to an alert to send to the peer.
//
// The default implementation calls |Offer| and then |Finish|, assuming a key
// exchange protocol where the peers are symmetric.
- //
- // TODO(davidben): out_secret should be a smart pointer.
- virtual bool Accept(CBB *out_public_key, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len);
+ virtual bool Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+ uint8_t *out_alert, Span<const uint8_t> peer_key);
// Finish performs a key exchange against the |peer_key| generated by
- // |Accept|. On success, it returns true and sets |*out_secret| and
- // |*out_secret_len| to a newly-allocated buffer containing the shared
- // secret. The caller must release this buffer with |OPENSSL_free|. On
- // failure, it returns zero and sets |*out_alert| to an alert to send to the
- // peer.
- //
- // TODO(davidben): out_secret should be a smart pointer.
- virtual bool Finish(uint8_t **out_secret, size_t *out_secret_len,
- uint8_t *out_alert, const uint8_t *peer_key,
- size_t peer_key_len) PURE_VIRTUAL;
+ // |Accept|. On success, it returns true and sets |*out_secret| to the shared
+ // secret. On failure, it returns zero and sets |*out_alert| to an alert to
+ // send to the peer.
+ virtual bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+ Span<const uint8_t> peer_key) PURE_VIRTUAL;
};
// ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
@@ -1208,41 +1299,33 @@
SSLTranscript transcript;
// cookie is the value of the cookie received from the server, if any.
- uint8_t *cookie = nullptr;
- size_t cookie_len = 0;
+ Array<uint8_t> cookie;
// key_share_bytes is the value of the previously sent KeyShare extension by
// the client in TLS 1.3.
- uint8_t *key_share_bytes = nullptr;
- size_t key_share_bytes_len = 0;
+ Array<uint8_t> key_share_bytes;
// ecdh_public_key, for servers, is the key share to be sent to the client in
// TLS 1.3.
- uint8_t *ecdh_public_key = nullptr;
- size_t ecdh_public_key_len = 0;
+ Array<uint8_t> ecdh_public_key;
// peer_sigalgs are the signature algorithms that the peer supports. These are
// taken from the contents of the signature algorithms extension for a server
// or from the CertificateRequest for a client.
- uint16_t *peer_sigalgs = nullptr;
- // num_peer_sigalgs is the number of entries in |peer_sigalgs|.
- size_t num_peer_sigalgs = 0;
+ Array<uint16_t> peer_sigalgs;
// peer_supported_group_list contains the supported group IDs advertised by
// the peer. This is only set on the server's end. The server does not
// advertise this extension to the client.
- uint16_t *peer_supported_group_list = nullptr;
- size_t peer_supported_group_list_len = 0;
+ Array<uint16_t> peer_supported_group_list;
// peer_key is the peer's ECDH key for a TLS 1.2 client.
- uint8_t *peer_key = nullptr;
- size_t peer_key_len = 0;
+ Array<uint8_t> peer_key;
// server_params, in a TLS 1.2 server, stores the ServerKeyExchange
// parameters. It has client and server randoms prepended for signing
// convenience.
- uint8_t *server_params = nullptr;
- size_t server_params_len = 0;
+ Array<uint8_t> server_params;
// peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
// server when using a TLS 1.2 PSK key exchange.
@@ -1258,8 +1341,7 @@
// certificate_types, on the client, contains the set of certificate types
// received in a CertificateRequest message.
- uint8_t *certificate_types = nullptr;
- size_t num_certificate_types = 0;
+ Array<uint8_t> certificate_types;
// local_pubkey is the public key we are authenticating as.
UniquePtr<EVP_PKEY> local_pubkey;
@@ -1414,12 +1496,11 @@
int tls13_add_finished(SSL_HANDSHAKE *hs);
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,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
+ Array<uint8_t> *out_secret,
uint8_t *out_alert, CBS *contents);
int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
- uint8_t **out_secret,
- size_t *out_secret_len,
+ Array<uint8_t> *out_secret,
uint8_t *out_alert, CBS *contents);
int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
@@ -1436,10 +1517,6 @@
int ssl_write_client_hello(SSL_HANDSHAKE *hs);
-// ssl_clear_tls13_state releases client state only needed for TLS 1.3. It
-// should be called once the version is known to be TLS 1.2 or earlier.
-void ssl_clear_tls13_state(SSL_HANDSHAKE *hs);
-
enum ssl_cert_verify_context_t {
ssl_cert_verify_server,
ssl_cert_verify_client,
@@ -1490,11 +1567,8 @@
// ClientHello functions.
-// ssl_client_hello_init parses |msg| as a ClientHello and writes the result to
-// |*out|. It returns one on success and zero on error. This function is
-// exported for unit tests.
-OPENSSL_EXPORT int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
- const SSLMessage &msg);
+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);
@@ -1502,10 +1576,6 @@
int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
uint16_t id);
-// ssl_is_probably_java returns true if |client_hello| looks like a Java
-// ClientHello and false otherwise. This function is exported for tests.
-OPENSSL_EXPORT bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello);
-
// GREASE.
@@ -2234,16 +2304,15 @@
void ssl3_free(SSL *ssl);
int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
-int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
-int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int ssl3_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg);
+int ssl3_add_message(SSL *ssl, Array<uint8_t> msg);
int ssl3_add_change_cipher_spec(SSL *ssl);
int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
int ssl3_flush_flight(SSL *ssl);
int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
-int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
- size_t *out_len);
-int dtls1_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int dtls1_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg);
+int dtls1_add_message(SSL *ssl, Array<uint8_t> msg);
int dtls1_add_change_cipher_spec(SSL *ssl);
int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
int dtls1_flush_flight(SSL *ssl);
@@ -2301,14 +2370,12 @@
int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
const uint8_t *premaster, size_t premaster_len);
-// tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
-// locally-configured group preference list.
-void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
- size_t *out_group_ids_len);
+// tls1_get_grouplist returns the locally-configured group preference list.
+Span<const uint16_t> tls1_get_grouplist(const SSL *ssl);
// tls1_check_group_id returns one if |group_id| is consistent with
// locally-configured group preferences.
-int tls1_check_group_id(SSL *ssl, uint16_t group_id);
+int tls1_check_group_id(const SSL *ssl, uint16_t group_id);
// tls1_get_shared_group sets |*out_group_id| to the first preferred shared
// group between client and server preferences and returns one. If none may be
@@ -2452,15 +2519,12 @@
// root CBB to be passed into |finish_message|. |*body| is set to a child CBB
// the caller should write to. It returns one on success and zero on error.
int (*init_message)(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
- // finish_message finishes a handshake message. It sets |*out_msg| to a
- // newly-allocated buffer with the serialized message. The caller must
- // release it with |OPENSSL_free| when done. It returns one on success and
- // zero on error.
- int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
+ // finish_message finishes a handshake message. It sets |*out_msg| to the
+ // serialized message. It returns one on success and zero on error.
+ int (*finish_message)(SSL *ssl, CBB *cbb, bssl::Array<uint8_t> *out_msg);
// add_message adds a handshake message to the pending flight. It returns one
- // on success and zero on error. In either case, it takes ownership of |msg|
- // and releases it with |OPENSSL_free| when done.
- int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
+ // on success and zero on error.
+ int (*add_message)(SSL *ssl, bssl::Array<uint8_t> msg);
// add_change_cipher_spec adds a ChangeCipherSpec record to the pending
// flight. It returns one on success and zero on error.
int (*add_change_cipher_spec)(SSL *ssl);
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index dfa8bfa..f63ed26 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -176,23 +176,16 @@
return 1;
}
-int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
- size_t *out_len) {
- if (!CBB_finish(cbb, out_msg, out_len)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- return 1;
+int ssl3_finish_message(SSL *ssl, CBB *cbb, Array<uint8_t> *out_msg) {
+ return CBBFinishArray(cbb, out_msg);
}
-int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
+int ssl3_add_message(SSL *ssl, Array<uint8_t> msg) {
// Add the message to the current flight, splitting into several records if
// needed.
- int ret = 0;
size_t added = 0;
do {
- size_t todo = len - added;
+ size_t todo = msg.size() - added;
if (todo > ssl->max_send_fragment) {
todo = ssl->max_send_fragment;
}
@@ -205,24 +198,21 @@
type = SSL3_RT_PLAINTEXT_HANDSHAKE;
}
- if (!add_record_to_flight(ssl, type, msg + added, todo)) {
- goto err;
+ if (!add_record_to_flight(ssl, type, msg.data() + added, todo)) {
+ return 0;
}
added += todo;
- } while (added < len);
+ } while (added < msg.size());
- ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
+ ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg.data(),
+ msg.size());
// TODO(svaldez): Move this up a layer to fix abstraction for SSLTranscript on
// hs.
if (ssl->s3->hs != NULL &&
- !ssl->s3->hs->transcript.Update(msg, len)) {
- goto err;
+ !ssl->s3->hs->transcript.Update(msg.data(), msg.size())) {
+ return 0;
}
- ret = 1;
-
-err:
- OPENSSL_free(msg);
- return ret;
+ return 1;
}
int ssl3_add_change_cipher_spec(SSL *ssl) {
diff --git a/src/ssl/ssl_file.cc b/src/ssl/ssl_file.cc
index 1bdc14f..bafa64a 100644
--- a/src/ssl/ssl_file.cc
+++ b/src/ssl/ssl_file.cc
@@ -570,6 +570,14 @@
ctx->default_passwd_callback = cb;
}
+pem_password_cb *SSL_CTX_get_default_passwd_cb(const SSL_CTX *ctx) {
+ return ctx->default_passwd_callback;
+}
+
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
ctx->default_passwd_callback_userdata = data;
}
+
+void *SSL_CTX_get_default_passwd_cb_userdata(const SSL_CTX *ctx) {
+ return ctx->default_passwd_callback_userdata;
+}
diff --git a/src/ssl/ssl_key_share.cc b/src/ssl/ssl_key_share.cc
index 207f11e..3ceb180 100644
--- a/src/ssl/ssl_key_share.cc
+++ b/src/ssl/ssl_key_share.cc
@@ -17,6 +17,8 @@
#include <assert.h>
#include <string.h>
+#include <utility>
+
#include <openssl/bn.h>
#include <openssl/bytestring.h>
#include <openssl/curve25519.h>
@@ -71,8 +73,8 @@
return true;
}
- bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) override {
+ bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+ Span<const uint8_t> peer_key) override {
assert(private_key_);
*out_alert = SSL_AD_INTERNAL_ERROR;
@@ -95,8 +97,8 @@
return false;
}
- if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key,
- peer_key_len, bn_ctx.get())) {
+ if (!EC_POINT_oct2point(group.get(), peer_point.get(), peer_key.data(),
+ peer_key.size(), bn_ctx.get())) {
*out_alert = SSL_AD_DECODE_ERROR;
return false;
}
@@ -110,14 +112,13 @@
}
// Encode the x-coordinate left-padded with zeros.
- size_t secret_len = (EC_GROUP_get_degree(group.get()) + 7) / 8;
- UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(secret_len));
- if (!secret || !BN_bn2bin_padded(secret.get(), secret_len, x)) {
+ Array<uint8_t> secret;
+ if (!secret.Init((EC_GROUP_get_degree(group.get()) + 7) / 8) ||
+ !BN_bn2bin_padded(secret.data(), secret.size(), x)) {
return false;
}
- *out_secret = secret.release();
- *out_secret_len = secret_len;
+ *out_secret = std::move(secret);
return true;
}
@@ -142,24 +143,24 @@
return !!CBB_add_bytes(out, public_key, sizeof(public_key));
}
- bool Finish(uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) override {
+ bool Finish(Array<uint8_t> *out_secret, uint8_t *out_alert,
+ Span<const uint8_t> peer_key) override {
*out_alert = SSL_AD_INTERNAL_ERROR;
- UniquePtr<uint8_t> secret((uint8_t *)OPENSSL_malloc(32));
- if (!secret) {
+ Array<uint8_t> secret;
+ if (!secret.Init(32)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return false;
}
- if (peer_key_len != 32 || !X25519(secret.get(), private_key_, peer_key)) {
+ if (peer_key.size() != 32 ||
+ !X25519(secret.data(), private_key_, peer_key.data())) {
*out_alert = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECPOINT);
return false;
}
- *out_secret = secret.release();
- *out_secret_len = 32;
+ *out_secret = std::move(secret);
return true;
}
@@ -202,12 +203,11 @@
}
}
-bool SSLKeyShare::Accept(CBB *out_public_key, uint8_t **out_secret,
- size_t *out_secret_len, uint8_t *out_alert,
- const uint8_t *peer_key, size_t peer_key_len) {
+bool SSLKeyShare::Accept(CBB *out_public_key, Array<uint8_t> *out_secret,
+ uint8_t *out_alert, Span<const uint8_t> peer_key) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return Offer(out_public_key) &&
- Finish(out_secret, out_secret_len, out_alert, peer_key, peer_key_len);
+ Finish(out_secret, out_alert, peer_key);
}
int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 7a75776..b864f8d 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -187,6 +187,17 @@
static CRYPTO_EX_DATA_CLASS g_ex_data_class_ssl_ctx =
CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
+bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out) {
+ uint8_t *ptr;
+ size_t len;
+ if (!CBB_finish(cbb, &ptr, &len)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return false;
+ }
+ out->Reset(ptr, len);
+ return true;
+}
+
void ssl_reset_error_state(SSL *ssl) {
// Functions which use |SSL_get_error| must reset I/O and error state on
// entry.
@@ -418,6 +429,11 @@
return 1;
}
+int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) {
+ CRYPTO_library_init();
+ return 1;
+}
+
static uint32_t ssl_session_hash(const SSL_SESSION *sess) {
const uint8_t *session_id = sess->session_id;
@@ -1555,9 +1571,8 @@
ssl->s3->send_connection_binding;
}
-LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; }
-
size_t SSL_CTX_sess_number(const SSL_CTX *ctx) {
+ MutexReadLock lock(const_cast<CRYPTO_MUTEX *>(&ctx->lock));
return lh_SSL_SESSION_num_items(ctx->sessions);
}
@@ -2022,8 +2037,8 @@
*out_types = NULL;
return 0;
}
- *out_types = ssl->s3->hs->certificate_types;
- return ssl->s3->hs->num_certificate_types;
+ *out_types = ssl->s3->hs->certificate_types.data();
+ return ssl->s3->hs->certificate_types.size();
}
EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 0e6c66c..ed4c779 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -672,21 +672,26 @@
data.session_id_length = session_id_len;
OPENSSL_memcpy(data.session_id, session_id, session_id_len);
- CRYPTO_MUTEX_lock_read(&ssl->session_ctx->lock);
+ MutexReadLock lock(&ssl->session_ctx->lock);
session.reset(lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data));
if (session) {
// |lh_SSL_SESSION_retrieve| returns a non-owning pointer.
SSL_SESSION_up_ref(session.get());
}
// TODO(davidben): This should probably move it to the front of the list.
- CRYPTO_MUTEX_unlock_read(&ssl->session_ctx->lock);
}
// Fall back to the external cache, if it exists.
- if (!session && ssl->session_ctx->get_session_cb != NULL) {
+ if (!session && (ssl->session_ctx->get_session_cb != nullptr ||
+ ssl->session_ctx->get_session_cb_legacy != nullptr)) {
int copy = 1;
- session.reset(ssl->session_ctx->get_session_cb(ssl, (uint8_t *)session_id,
- session_id_len, ©));
+ if (ssl->session_ctx->get_session_cb != nullptr) {
+ session.reset(ssl->session_ctx->get_session_cb(ssl, session_id,
+ session_id_len, ©));
+ } else {
+ session.reset(ssl->session_ctx->get_session_cb_legacy(
+ ssl, const_cast<uint8_t *>(session_id), session_id_len, ©));
+ }
if (!session) {
return ssl_hs_ok;
@@ -722,72 +727,6 @@
return ssl_hs_ok;
}
-bool ssl_is_probably_java(const SSL_CLIENT_HELLO *client_hello) {
- CBS extension, groups;
- if (SSL_is_dtls(client_hello->ssl) ||
- !ssl_client_hello_get_extension(client_hello, &extension,
- TLSEXT_TYPE_supported_groups) ||
- !CBS_get_u16_length_prefixed(&extension, &groups) ||
- CBS_len(&extension) != 0) {
- return false;
- }
-
- // Original Java curve list.
- static const uint8_t kCurveList1[] = {
- 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00, 0x15,
- 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18,
- 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e,
- 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12,
- 0x00, 0x04, 0x00, 0x05, 0x00, 0x14, 0x00, 0x08, 0x00, 0x16};
-
- // Newer Java curve list.
- static const uint8_t kCurveList2[] = {
- 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a,
- 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16};
-
- // IcedTea curve list.
- static const uint8_t kCurveList3[] = {0x00, 0x17, 0x00, 0x18, 0x00, 0x19};
-
- auto groups_span = MakeConstSpan(CBS_data(&groups), CBS_len(&groups));
- if (groups_span != kCurveList1 && groups_span != kCurveList2 &&
- groups_span != kCurveList3) {
- return false;
- }
-
- // Java has a very distinctive curve list, but IcedTea patches it to a more
- // standard [P-256, P-384, P-521]. Additionally check the extension
- // order. This may still flag other clients, but false positives only mean a
- // loss of resumption. Any client new enough to support one of X25519,
- // extended master secret, session tickets, or TLS 1.3 will be unaffected.
- //
- // Java sends different extensions depending on configuration and version, but
- // those which are present are always in the same order. Check if the
- // extensions are an ordered subset of |kJavaExtensions|.
- static const uint16_t kJavaExtensions[] = {
- TLSEXT_TYPE_supported_groups,
- TLSEXT_TYPE_ec_point_formats,
- TLSEXT_TYPE_signature_algorithms,
- TLSEXT_TYPE_server_name,
- 17 /* status_request_v2 */,
- TLSEXT_TYPE_status_request,
- TLSEXT_TYPE_application_layer_protocol_negotiation,
- TLSEXT_TYPE_renegotiate,
- };
- CBS extensions;
- CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
- for (uint16_t expected : kJavaExtensions) {
- CBS extensions_copy = extensions, body;
- uint16_t type;
- // Peek at the next extension.
- if (CBS_get_u16(&extensions_copy, &type) &&
- CBS_get_u16_length_prefixed(&extensions_copy, &body) &&
- type == expected) {
- extensions = extensions_copy;
- }
- }
- return CBS_len(&extensions) == 0;
-}
-
enum ssl_hs_wait_t ssl_get_prev_session(SSL *ssl,
UniquePtr<SSL_SESSION> *out_session,
bool *out_tickets_supported,
@@ -795,6 +734,8 @@
const SSL_CLIENT_HELLO *client_hello) {
// This is used only by servers.
assert(ssl->server);
+ UniquePtr<SSL_SESSION> session;
+ bool renew_ticket = false;
// If tickets are disabled, always behave as if no tickets are present.
const uint8_t *ticket = NULL;
@@ -804,37 +745,6 @@
ssl->version > SSL3_VERSION &&
SSL_early_callback_ctx_extension_get(
client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
-
- if (ssl_is_probably_java(client_hello)) {
- // The Java client implementation of the 3SHAKE mitigation incorrectly
- // rejects initial handshakes when all of the following are true:
- //
- // 1. The ClientHello offered a session.
- // 2. The session was successfully resumed previously.
- // 3. The server declines the session.
- // 4. The server sends a certificate with a different (see below) SAN list
- // than in the previous session.
- //
- // (Note the 3SHAKE mitigation is to reject certificates changes on
- // renegotiation, while Java's logic applies to initial handshakes as well.)
- //
- // The end result is long-lived Java clients break on certificate rotations
- // where the SAN list changes too much. Older versions of Java break if the
- // first DNS name of the two certificates is different. Newer ones will
- // break if there is no intersection. The new logic mostly mitigates this,
- // but this can still cause problems if switching to or from wildcards.
- //
- // Thus, fingerprint Java clients and decline all offered sessions. This
- // avoids (2) while still introducing new sessions to clear any existing
- // problematic sessions.
- *out_session = nullptr;
- *out_tickets_supported = tickets_supported;
- *out_renew_ticket = false;
- return ssl_hs_ok;
- }
-
- UniquePtr<SSL_SESSION> session;
- bool renew_ticket = false;
if (tickets_supported && ticket_len > 0) {
switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
client_hello->session_id,
@@ -1056,6 +966,30 @@
return 1;
}
+int SSL_SESSION_should_be_single_use(const SSL_SESSION *session) {
+ return SSL_SESSION_protocol_version(session) >= TLS1_3_VERSION;
+}
+
+int SSL_SESSION_is_resumable(const SSL_SESSION *session) {
+ return !session->not_resumable;
+}
+
+int SSL_SESSION_has_ticket(const SSL_SESSION *session) {
+ return session->tlsext_ticklen > 0;
+}
+
+void SSL_SESSION_get0_ticket(const SSL_SESSION *session,
+ const uint8_t **out_ticket, size_t *out_len) {
+ if (out_ticket != nullptr) {
+ *out_ticket = session->tlsext_tick;
+ }
+ *out_len = session->tlsext_ticklen;
+}
+
+uint32_t SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session) {
+ return session->tlsext_tick_lifetime_hint;
+}
+
SSL_SESSION *SSL_magic_pending_session_ptr(void) {
return (SSL_SESSION *)&g_pending_session_magic;
}
@@ -1109,41 +1043,44 @@
// Although |session| is inserted into two structures (a doubly-linked list
// and the hash table), |ctx| only takes one reference.
SSL_SESSION_up_ref(session);
+ UniquePtr<SSL_SESSION> owned_session(session);
SSL_SESSION *old_session;
- CRYPTO_MUTEX_lock_write(&ctx->lock);
+ MutexWriteLock lock(&ctx->lock);
if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
- SSL_SESSION_free(session);
return 0;
}
+ // |ctx->sessions| took ownership of |session| and gave us back a reference to
+ // |old_session|. (|old_session| may be the same as |session|, in which case
+ // we traded identical references with |ctx->sessions|.)
+ owned_session.release();
+ owned_session.reset(old_session);
if (old_session != NULL) {
if (old_session == session) {
- // |session| was already in the cache.
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
- SSL_SESSION_free(old_session);
+ // |session| was already in the cache. There are no linked list pointers
+ // to update.
return 0;
}
- // There was a session ID collision. |old_session| must be removed from
- // the linked list and released.
+ // There was a session ID collision. |old_session| was replaced with
+ // |session| in the hash table, so |old_session| must be removed from the
+ // linked list to match.
SSL_SESSION_list_remove(ctx, old_session);
- SSL_SESSION_free(old_session);
}
SSL_SESSION_list_add(ctx, session);
// Enforce any cache size limits.
if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
- while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
+ while (lh_SSL_SESSION_num_items(ctx->sessions) >
+ SSL_CTX_sess_get_cache_size(ctx)) {
if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
break;
}
}
}
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
return 1;
}
@@ -1222,9 +1159,8 @@
return;
}
tp.time = time;
- CRYPTO_MUTEX_lock_write(&ctx->lock);
+ MutexWriteLock lock(&ctx->lock);
lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
- CRYPTO_MUTEX_unlock_write(&ctx->lock);
}
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
@@ -1247,14 +1183,21 @@
}
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
- SSL_SESSION *(*cb)(SSL *ssl,
- uint8_t *id, int id_len,
- int *out_copy)) {
+ SSL_SESSION *(*cb)(SSL *ssl, const uint8_t *id,
+ int id_len, int *out_copy)) {
ctx->get_session_cb = cb;
}
-SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(
- SSL *ssl, uint8_t *id, int id_len, int *out_copy) {
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+ SSL_SESSION *(*cb)(SSL *ssl, uint8_t *id,
+ int id_len, int *out_copy)) {
+ ctx->get_session_cb_legacy = cb;
+}
+
+SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
+ const uint8_t *id,
+ int id_len,
+ int *out_copy) {
return ctx->get_session_cb;
}
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 10bc215..4653f73 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1399,7 +1399,7 @@
// Check the hash table.
std::vector<SSL_SESSION*> actual, expected_copy;
- lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
+ lh_SSL_SESSION_doall_arg(ctx->sessions, AppendSession, &actual);
expected_copy = expected;
std::sort(actual.begin(), actual.end());
@@ -1941,197 +1941,106 @@
EXPECT_EQ(Bytes(cert_sha256), Bytes(session->peer_sha256));
}
-static bool ClientHelloMatches(uint16_t version, const uint8_t *expected,
- size_t expected_len) {
- bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- // Our default cipher list varies by CPU capabilities, so manually place the
- // ChaCha20 ciphers in front.
- const char* cipher_list = "CHACHA20:ALL";
- if (!ctx ||
- // SSLv3 is off by default.
- !SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION) ||
- !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
- !SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list)) {
- return false;
- }
-
- bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
- if (!ssl) {
- return false;
- }
- std::vector<uint8_t> client_hello;
- if (!GetClientHello(ssl.get(), &client_hello)) {
- return false;
- }
-
- // Zero the client_random.
- constexpr size_t kRandomOffset = 1 + 2 + 2 + // record header
- 1 + 3 + // handshake message header
- 2; // client_version
- if (client_hello.size() < kRandomOffset + SSL3_RANDOM_SIZE) {
- fprintf(stderr, "ClientHello for version %04x too short.\n", version);
- return false;
- }
- OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
-
- if (client_hello.size() != expected_len ||
- OPENSSL_memcmp(client_hello.data(), expected, expected_len) != 0) {
- fprintf(stderr, "ClientHello for version %04x did not match:\n", version);
- fprintf(stderr, "Got:\n\t");
- for (size_t i = 0; i < client_hello.size(); i++) {
- fprintf(stderr, "0x%02x, ", client_hello[i]);
- }
- fprintf(stderr, "\nWanted:\n\t");
- for (size_t i = 0; i < expected_len; i++) {
- fprintf(stderr, "0x%02x, ", expected[i]);
- }
- fprintf(stderr, "\n");
- return false;
- }
-
- return true;
-}
-
-// Tests that our ClientHellos do not change unexpectedly.
-static bool TestClientHello() {
- static const uint8_t kSSL3ClientHello[] = {
- 0x16,
- 0x03, 0x00,
- 0x00, 0x3b,
- 0x01,
- 0x00, 0x00, 0x37,
- 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- 0x00, 0x10,
- 0xc0, 0x09,
- 0xc0, 0x13,
- 0xc0, 0x0a,
- 0xc0, 0x14,
- 0x00, 0x2f,
- 0x00, 0x35,
- 0x00, 0x0a,
- 0x00, 0xff, 0x01, 0x00,
- };
- if (!ClientHelloMatches(SSL3_VERSION, kSSL3ClientHello,
- sizeof(kSSL3ClientHello))) {
- return false;
- }
-
- static const uint8_t kTLS1ClientHello[] = {
- 0x16,
- 0x03, 0x01,
- 0x00, 0x5a,
- 0x01,
- 0x00, 0x00, 0x56,
- 0x03, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- 0x00, 0x0e,
- 0xc0, 0x09,
- 0xc0, 0x13,
- 0xc0, 0x0a,
- 0xc0, 0x14,
- 0x00, 0x2f,
- 0x00, 0x35,
- 0x00, 0x0a,
+// Tests that our ClientHellos do not change unexpectedly. These are purely
+// change detection tests. If they fail as part of an intentional ClientHello
+// change, update the test vector.
+TEST(SSLTest, ClientHello) {
+ struct {
+ uint16_t max_version;
+ std::vector<uint8_t> expected;
+ } kTests[] = {
+ {SSL3_VERSION,
+ {0x16, 0x03, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x37, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
+ 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00}},
+ {TLS1_VERSION,
+ {0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x56, 0x03, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xc0, 0x09,
+ 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
- 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
- };
- if (!ClientHelloMatches(TLS1_VERSION, kTLS1ClientHello,
- sizeof(kTLS1ClientHello))) {
- return false;
- }
-
- static const uint8_t kTLS11ClientHello[] = {
- 0x16,
- 0x03, 0x01,
- 0x00, 0x5a,
- 0x01,
- 0x00, 0x00, 0x56,
- 0x03, 0x02,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- 0x00, 0x0e,
- 0xc0, 0x09,
- 0xc0, 0x13,
- 0xc0, 0x0a,
- 0xc0, 0x14,
- 0x00, 0x2f,
- 0x00, 0x35,
- 0x00, 0x0a,
+ 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18}},
+ {TLS1_1_VERSION,
+ {0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x56, 0x03, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0xc0, 0x09,
+ 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
- 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
- };
- if (!ClientHelloMatches(TLS1_1_VERSION, kTLS11ClientHello,
- sizeof(kTLS11ClientHello))) {
- return false;
- }
-
- // kTLS12ClientHello assumes RSA-PSS, which is disabled for Android system
- // builds.
-#if defined(BORINGSSL_ANDROID_SYSTEM)
- return true;
+ 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18}},
+ // This test assumes RSA-PSS, which is disabled for Android system builds.
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+ {TLS1_2_VERSION,
+ {0x16, 0x03, 0x01, 0x00, 0x8e, 0x01, 0x00, 0x00, 0x8a, 0x03, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0xcc, 0xa9,
+ 0xcc, 0xa8, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xc0, 0x09,
+ 0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x27, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14,
+ 0xc0, 0x28, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x35,
+ 0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01,
+ 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00,
+ 0x14, 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08,
+ 0x05, 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00,
+ 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00,
+ 0x17, 0x00, 0x18}},
#endif
-
- static const uint8_t kTLS12ClientHello[] = {
- 0x16,
- 0x03, 0x01,
- 0x00, 0x8e,
- 0x01,
- 0x00, 0x00, 0x8a,
- 0x03, 0x03,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x2a,
- 0xcc, 0xa9,
- 0xcc, 0xa8,
- 0xc0, 0x2b,
- 0xc0, 0x2f,
- 0xc0, 0x2c,
- 0xc0, 0x30,
- 0xc0, 0x09,
- 0xc0, 0x23,
- 0xc0, 0x13,
- 0xc0, 0x27,
- 0xc0, 0x0a,
- 0xc0, 0x24,
- 0xc0, 0x14,
- 0xc0, 0x28,
- 0x00, 0x9c,
- 0x00, 0x9d,
- 0x00, 0x2f,
- 0x00, 0x3c,
- 0x00, 0x35,
- 0x00, 0x3d,
- 0x00, 0x0a,
- 0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
- 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04,
- 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08,
- 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
- 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+ // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
+ // implementation has settled enough that it won't change.
};
- if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
- sizeof(kTLS12ClientHello))) {
- return false;
+
+ for (const auto &t : kTests) {
+ SCOPED_TRACE(t.max_version);
+
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+ ASSERT_TRUE(ctx);
+ // Our default cipher list varies by CPU capabilities, so manually place the
+ // ChaCha20 ciphers in front.
+ const char *cipher_list = "CHACHA20:ALL";
+ // SSLv3 is off by default.
+ ASSERT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION));
+ ASSERT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), t.max_version));
+ ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list));
+
+ bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+ ASSERT_TRUE(ssl);
+ std::vector<uint8_t> client_hello;
+ ASSERT_TRUE(GetClientHello(ssl.get(), &client_hello));
+
+ // Zero the client_random.
+ constexpr size_t kRandomOffset = 1 + 2 + 2 + // record header
+ 1 + 3 + // handshake message header
+ 2; // client_version
+ ASSERT_GE(client_hello.size(), kRandomOffset + SSL3_RANDOM_SIZE);
+ OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
+
+ if (client_hello != t.expected) {
+ ADD_FAILURE() << "ClientHellos did not match.";
+ // Print the value manually so it is easier to update the test vector.
+ for (size_t i = 0; i < client_hello.size(); i += 12) {
+ printf(" %c", i == 0 ? '{' : ' ');
+ for (size_t j = i; j < client_hello.size() && j < i + 12; j++) {
+ if (j > i) {
+ printf(" ");
+ }
+ printf("0x%02x", client_hello[j]);
+ if (j < client_hello.size() - 1) {
+ printf(",");
+ }
+ }
+ if (i + 12 >= client_hello.size()) {
+ printf("}}");
+ }
+ printf("\n");
+ }
+ }
}
-
- // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
- // implementation has settled enough that it won't change.
-
- return true;
}
static bssl::UniquePtr<SSL_SESSION> g_last_session;
@@ -3831,179 +3740,6 @@
EXPECT_EQ(SSL_R_NO_CIPHERS_AVAILABLE, ERR_GET_REASON(err));
}
-TEST(SSLTest, IsProbablyJava) {
- bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
- ASSERT_TRUE(ctx);
- bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
- ASSERT_TRUE(ssl);
-
- const struct {
- const char *name;
- std::vector<uint8_t> in;
- bool is_probably_java;
- } kTests[] = {
- {"JDK 6 with IcedTea curve list",
- {0x03, 0x01, 0x59, 0xb3, 0x10, 0xea, 0x17, 0xfe, 0x9e, 0x69, 0x7e, 0x79,
- 0xc7, 0x33, 0x10, 0x81, 0x73, 0x9e, 0xe7, 0xbf, 0x78, 0x4a, 0x33, 0x76,
- 0x12, 0x1f, 0xc5, 0x6d, 0x28, 0x8d, 0xd7, 0x60, 0xf0, 0x5e, 0x00, 0x00,
- 0x2c, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00,
- 0x39, 0x00, 0x38, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0,
- 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0,
- 0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00,
- 0x12, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x17, 0x00, 0x18, 0x00,
- 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00},
- true},
- {"JDK 7 with IcedTea curve list",
- {0x03, 0x03, 0x59, 0xb3, 0x10, 0xc8, 0x03, 0x7d, 0x10, 0x5a, 0x6b, 0x6e,
- 0x84, 0xa5, 0xbe, 0x6e, 0xe2, 0xd0, 0xb4, 0xb5, 0xcf, 0x6d, 0xa1, 0x58,
- 0xb5, 0xc0, 0x05, 0x63, 0xf6, 0x81, 0xda, 0xc2, 0xa0, 0xb0, 0x00, 0x00,
- 0x48, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
- 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
- 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
- 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
- 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x08, 0xc0,
- 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00, 0x16, 0x00, 0x13, 0x00,
- 0xff, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00,
- 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
- 0x0d, 0x00, 0x18, 0x00, 0x16, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
- 0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
- 0x01, 0x02, 0x02},
- true},
- {"JDK 8",
- {0x03, 0x03, 0x59, 0xb3, 0x10, 0xfc, 0xc7, 0xcb, 0x36, 0x85, 0x8c, 0x00,
- 0xd6, 0xa7, 0x5b, 0xfb, 0x98, 0xbe, 0xf9, 0xa3, 0xa0, 0x01, 0xff, 0x35,
- 0xb9, 0x1a, 0xc1, 0x72, 0xf1, 0x51, 0x4b, 0x49, 0x96, 0x1a, 0x00, 0x00,
- 0x70, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0, 0x26, 0xc0, 0x2a, 0x00,
- 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x35, 0xc0, 0x05, 0xc0,
- 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0, 0x27, 0x00, 0x3c, 0xc0,
- 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0, 0x09, 0xc0, 0x13, 0x00,
- 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00, 0x32, 0xc0, 0x2c, 0xc0,
- 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0, 0x32, 0x00, 0x9f, 0x00,
- 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0, 0x31, 0x00, 0x9e, 0x00,
- 0xa2, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
- 0x16, 0x00, 0x13, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x05, 0xc0, 0x02, 0xc0,
- 0x0c, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5c, 0x00, 0x0a, 0x00,
- 0x34, 0x00, 0x32, 0x00, 0x17, 0x00, 0x01, 0x00, 0x03, 0x00, 0x13, 0x00,
- 0x15, 0x00, 0x06, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x18, 0x00,
- 0x0b, 0x00, 0x0c, 0x00, 0x19, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00,
- 0x10, 0x00, 0x11, 0x00, 0x02, 0x00, 0x12, 0x00, 0x04, 0x00, 0x05, 0x00,
- 0x14, 0x00, 0x08, 0x00, 0x16, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
- 0x0d, 0x00, 0x1a, 0x00, 0x18, 0x06, 0x03, 0x06, 0x01, 0x05, 0x03, 0x05,
- 0x01, 0x04, 0x03, 0x04, 0x01, 0x03, 0x03, 0x03, 0x01, 0x02, 0x03, 0x02,
- 0x01, 0x02, 0x02, 0x01, 0x01},
- true},
- {"JDK 9",
- {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
- 0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
- 0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
- 0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
- 0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
- 0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
- 0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
- 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
- 0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
- 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
- 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
- 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x5d, 0x00, 0x0a, 0x00,
- 0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
- 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
- 0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
- 0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
- 0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x05, 0x01, 0x00, 0x00, 0x00, 0x00},
- true},
- {"JDK 9 with SNI and ALPN enabled and no SCSV cipher",
- {0x03, 0x03, 0x37, 0xa6, 0x4b, 0x58, 0x02, 0xd0, 0x77, 0xe4, 0x48, 0xaf,
- 0x90, 0x50, 0x45, 0xd5, 0x2f, 0xe7, 0x98, 0x5d, 0x54, 0x93, 0x85, 0x3a,
- 0xde, 0xb6, 0xaa, 0x47, 0xef, 0x7f, 0xb5, 0x52, 0xe6, 0xf8, 0x00, 0x00,
- 0x02, 0xc0, 0x24, 0x01, 0x00, 0x00, 0x87, 0x00, 0x0a, 0x00, 0x16, 0x00,
- 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00, 0x0a, 0x00,
- 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00, 0x0b, 0x00,
- 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06, 0x03, 0x06,
- 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04, 0x02, 0x03,
- 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02, 0x02, 0x00,
- 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d,
- 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x11, 0x00, 0x10, 0x00,
- 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x10, 0x00, 0x0d, 0x00, 0x0b, 0x07, 0x68, 0x74, 0x74, 0x70, 0x31,
- 0x2e, 0x31, 0x02, 0x68, 0x32, 0xff, 0x01, 0x00, 0x01, 0x00},
- true},
- {"JDK 9 with EMS extension appended",
- {0x03, 0x03, 0x0c, 0xe6, 0x06, 0xc6, 0x5d, 0x38, 0xb4, 0x5e, 0x3a, 0xd5,
- 0xb0, 0x5f, 0x5b, 0x84, 0x3b, 0xff, 0x86, 0x4f, 0xb0, 0x3f, 0xc1, 0xfd,
- 0x08, 0xf0, 0x97, 0xf3, 0x56, 0x44, 0x08, 0xe2, 0xdd, 0x2a, 0x00, 0x00,
- 0x64, 0xc0, 0x2c, 0xc0, 0x2b, 0xc0, 0x30, 0x00, 0x9d, 0xc0, 0x2e, 0xc0,
- 0x32, 0x00, 0x9f, 0x00, 0xa3, 0xc0, 0x2f, 0x00, 0x9c, 0xc0, 0x2d, 0xc0,
- 0x31, 0x00, 0x9e, 0x00, 0xa2, 0xc0, 0x24, 0xc0, 0x28, 0x00, 0x3d, 0xc0,
- 0x26, 0xc0, 0x2a, 0x00, 0x6b, 0x00, 0x6a, 0xc0, 0x0a, 0xc0, 0x14, 0x00,
- 0x35, 0xc0, 0x05, 0xc0, 0x0f, 0x00, 0x39, 0x00, 0x38, 0xc0, 0x23, 0xc0,
- 0x27, 0x00, 0x3c, 0xc0, 0x25, 0xc0, 0x29, 0x00, 0x67, 0x00, 0x40, 0xc0,
- 0x09, 0xc0, 0x13, 0x00, 0x2f, 0xc0, 0x04, 0xc0, 0x0e, 0x00, 0x33, 0x00,
- 0x32, 0xc0, 0x08, 0xc0, 0x12, 0x00, 0x0a, 0xc0, 0x03, 0xc0, 0x0d, 0x00,
- 0x16, 0x00, 0x13, 0x00, 0xff, 0x01, 0x00, 0x00, 0x61, 0x00, 0x0a, 0x00,
- 0x16, 0x00, 0x14, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, 0x09, 0x00,
- 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x16, 0x00,
- 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x1c, 0x00, 0x1a, 0x06,
- 0x03, 0x06, 0x01, 0x05, 0x03, 0x05, 0x01, 0x04, 0x03, 0x04, 0x01, 0x04,
- 0x02, 0x03, 0x03, 0x03, 0x01, 0x03, 0x02, 0x02, 0x03, 0x02, 0x01, 0x02,
- 0x02, 0x00, 0x11, 0x00, 0x10, 0x00, 0x0e, 0x02, 0x00, 0x04, 0x00, 0x00,
- 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00,
- 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00},
- false},
- {"Chrome 61",
- {0x03, 0x03, 0x33, 0x43, 0x8a, 0x6f, 0x76, 0xdd, 0x84, 0x3f, 0x8d, 0xaa,
- 0x43, 0xf1, 0x86, 0xee, 0xdd, 0x97, 0x96, 0x54, 0xf6, 0x17, 0x2c, 0xde,
- 0x69, 0xfe, 0x5e, 0x53, 0xaa, 0x47, 0xee, 0xad, 0xd7, 0x47, 0x00, 0x00,
- 0x1c, 0x3a, 0x3a, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc,
- 0xa9, 0xcc, 0xa8, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00,
- 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x77, 0x8a, 0x8a, 0x00,
- 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0c,
- 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
- 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14,
- 0x00, 0x12, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05,
- 0x05, 0x01, 0x08, 0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x05, 0x00, 0x05,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74, 0x74, 0x70, 0x2f,
- 0x31, 0x2e, 0x31, 0x75, 0x50, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01,
- 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x4a, 0x4a, 0x00, 0x1d, 0x00,
- 0x17, 0x00, 0x18, 0x6a, 0x6a, 0x00, 0x01, 0x00},
- false},
- {"Firefox 55",
- {0x03, 0x03, 0x06, 0x8e, 0xf8, 0xf7, 0x7a, 0xfd, 0xce, 0x45, 0xb0, 0x39,
- 0xbe, 0xa4, 0x55, 0x27, 0xe2, 0x80, 0xc4, 0x0a, 0xbd, 0xce, 0x56, 0x7a,
- 0xbc, 0x1f, 0x26, 0x2f, 0xfa, 0xb9, 0xa1, 0x7e, 0xe6, 0xde, 0x00, 0x00,
- 0x1e, 0xc0, 0x2b, 0xc0, 0x2f, 0xcc, 0xa9, 0xcc, 0xa8, 0xc0, 0x2c, 0xc0,
- 0x30, 0xc0, 0x0a, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x14, 0x00, 0x33, 0x00,
- 0x39, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x6a, 0x00,
- 0x00, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f, 0x63, 0x61,
- 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00,
- 0x01, 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17,
- 0x00, 0x18, 0x00, 0x19, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x23,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08,
- 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x04,
- 0x03, 0x05, 0x03, 0x06, 0x03, 0x08, 0x04, 0x08, 0x05, 0x08, 0x06, 0x04,
- 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x03, 0x02, 0x01},
- false},
- };
- for (const auto &t : kTests) {
- SCOPED_TRACE(t.name);
-
- bssl::SSLMessage msg;
- msg.is_v2_hello = false;
- msg.type = SSL3_MT_CLIENT_HELLO;
- CBS_init(&msg.body, t.in.data(), t.in.size());
- CBS_init(&msg.raw, nullptr, 0); // unused
-
- SSL_CLIENT_HELLO client_hello;
- ASSERT_TRUE(bssl::ssl_client_hello_init(ssl.get(), &client_hello, msg));
- EXPECT_EQ(t.is_probably_java, bssl::ssl_is_probably_java(&client_hello));
- }
-}
-
// TODO(davidben): Convert this file to GTest properly.
TEST(SSLTest, AllTests) {
if (!TestSSL_SESSIONEncoding(kOpenSSLSession) ||
@@ -4019,8 +3755,7 @@
!TestPaddingExtension(TLS1_3_VERSION, TLS1_2_VERSION) ||
// Test the padding extension at TLS 1.3 with a TLS 1.3 session, so there
// will be a PSK binder after the padding extension.
- !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION) ||
- !TestClientHello()) {
+ !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION)) {
ADD_FAILURE() << "Tests failed";
}
}
diff --git a/src/ssl/ssl_x509.cc b/src/ssl/ssl_x509.cc
index 7ff6a89..2b7ba83 100644
--- a/src/ssl/ssl_x509.cc
+++ b/src/ssl/ssl_x509.cc
@@ -835,10 +835,8 @@
X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
check_ssl_ctx_x509_method(ctx);
- CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
- X509 *ret = ssl_cert_get0_leaf(ctx->cert);
- CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
- return ret;
+ MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
+ return ssl_cert_get0_leaf(ctx->cert);
}
static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
@@ -994,11 +992,8 @@
int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
check_ssl_ctx_x509_method(ctx);
- CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
- const int ret = ssl_cert_cache_chain_certs(ctx->cert);
- CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
-
- if (!ret) {
+ MutexWriteLock lock(const_cast<CRYPTO_MUTEX*>(&ctx->lock));
+ if (!ssl_cert_cache_chain_certs(ctx->cert)) {
*out_chain = NULL;
return 0;
}
@@ -1165,11 +1160,10 @@
check_ssl_ctx_x509_method(ctx);
// This is a logically const operation that may be called on multiple threads,
// so it needs to lock around updating |cached_x509_client_CA|.
- CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
- STACK_OF(X509_NAME) *ret = buffer_names_to_x509(
- ctx->client_CA, (STACK_OF(X509_NAME) **)&ctx->cached_x509_client_CA);
- CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
- return ret;
+ MutexWriteLock lock(const_cast<CRYPTO_MUTEX *>(&ctx->lock));
+ return buffer_names_to_x509(
+ ctx->client_CA,
+ const_cast<STACK_OF(X509_NAME) **>(&ctx->cached_x509_client_CA));
}
static int add_client_CA(STACK_OF(CRYPTO_BUFFER) **names, X509 *x509,
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index ec70d27..1fe360b 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -113,6 +113,8 @@
#include <stdlib.h>
#include <string.h>
+#include <utility>
+
#include <openssl/bytestring.h>
#include <openssl/digest.h>
#include <openssl/err.h>
@@ -147,19 +149,16 @@
// This function does an initial scan over the extensions block to filter those
// out.
static int tls1_check_duplicate_extensions(const CBS *cbs) {
- CBS extensions = *cbs;
- size_t num_extensions = 0, i = 0;
- uint16_t *extension_types = NULL;
- int ret = 0;
-
// First pass: count the extensions.
+ size_t num_extensions = 0;
+ CBS extensions = *cbs;
while (CBS_len(&extensions) > 0) {
uint16_t type;
CBS extension;
if (!CBS_get_u16(&extensions, &type) ||
!CBS_get_u16_length_prefixed(&extensions, &extension)) {
- goto done;
+ return 0;
}
num_extensions++;
@@ -169,39 +168,34 @@
return 1;
}
- extension_types =
- (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions);
- if (extension_types == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto done;
+ Array<uint16_t> extension_types;
+ if (!extension_types.Init(num_extensions)) {
+ return 0;
}
// Second pass: gather the extension types.
extensions = *cbs;
- for (i = 0; i < num_extensions; i++) {
+ for (size_t i = 0; i < extension_types.size(); i++) {
CBS extension;
if (!CBS_get_u16(&extensions, &extension_types[i]) ||
!CBS_get_u16_length_prefixed(&extensions, &extension)) {
// This should not happen.
- goto done;
+ return 0;
}
}
assert(CBS_len(&extensions) == 0);
// Sort the extensions and make sure there are no duplicates.
- qsort(extension_types, num_extensions, sizeof(uint16_t), compare_uint16_t);
- for (i = 1; i < num_extensions; i++) {
+ qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t),
+ compare_uint16_t);
+ for (size_t i = 1; i < num_extensions; i++) {
if (extension_types[i - 1] == extension_types[i]) {
- goto done;
+ return 0;
}
}
- ret = 1;
-
-done:
- OPENSSL_free(extension_types);
- return ret;
+ return 1;
}
int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out,
@@ -297,24 +291,18 @@
SSL_CURVE_SECP384R1,
};
-void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
- size_t *out_group_ids_len) {
- *out_group_ids = ssl->supported_group_list;
- *out_group_ids_len = ssl->supported_group_list_len;
- if (!*out_group_ids) {
- *out_group_ids = kDefaultGroups;
- *out_group_ids_len = OPENSSL_ARRAY_SIZE(kDefaultGroups);
+Span<const uint16_t> tls1_get_grouplist(const SSL *ssl) {
+ if (ssl->supported_group_list != nullptr) {
+ return MakeConstSpan(ssl->supported_group_list,
+ ssl->supported_group_list_len);
}
+ return Span<const uint16_t>(kDefaultGroups);
}
int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
SSL *const ssl = hs->ssl;
assert(ssl->server);
- const uint16_t *groups, *pref, *supp;
- size_t groups_len, pref_len, supp_len;
- tls1_get_grouplist(ssl, &groups, &groups_len);
-
// Clients are not required to send a supported_groups extension. In this
// case, the server is free to pick any group it likes. See RFC 4492,
// section 4, paragraph 3.
@@ -324,22 +312,20 @@
// support our favoured group. Thus we do not special-case an emtpy
// |peer_supported_group_list|.
+ Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+ Span<const uint16_t> pref, supp;
if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
pref = groups;
- pref_len = groups_len;
supp = hs->peer_supported_group_list;
- supp_len = hs->peer_supported_group_list_len;
} else {
pref = hs->peer_supported_group_list;
- pref_len = hs->peer_supported_group_list_len;
supp = groups;
- supp_len = groups_len;
}
- for (size_t i = 0; i < pref_len; i++) {
- for (size_t j = 0; j < supp_len; j++) {
- if (pref[i] == supp[j]) {
- *out_group_id = pref[i];
+ for (uint16_t pref_group : pref) {
+ for (uint16_t supp_group : supp) {
+ if (pref_group == supp_group) {
+ *out_group_id = pref_group;
return 1;
}
}
@@ -412,12 +398,9 @@
return 0;
}
-int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
- const uint16_t *groups;
- size_t groups_len;
- tls1_get_grouplist(ssl, &groups, &groups_len);
- for (size_t i = 0; i < groups_len; i++) {
- if (groups[i] == group_id) {
+int tls1_check_group_id(const SSL *ssl, uint16_t group_id) {
+ for (uint16_t supported : tls1_get_grouplist(ssl)) {
+ if (supported == group_id) {
return 1;
}
}
@@ -1028,10 +1011,7 @@
static int ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
- OPENSSL_free(hs->peer_sigalgs);
- hs->peer_sigalgs = NULL;
- hs->num_peer_sigalgs = 0;
-
+ hs->peer_sigalgs.Reset();
if (contents == NULL) {
return 1;
}
@@ -2111,13 +2091,11 @@
// We received a HelloRetryRequest without a new curve, so there is no new
// share to append. Leave |hs->key_share| as-is.
if (group_id == 0 &&
- !CBB_add_bytes(&kse_bytes, hs->key_share_bytes,
- hs->key_share_bytes_len)) {
+ !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(),
+ hs->key_share_bytes.size())) {
return 0;
}
- OPENSSL_free(hs->key_share_bytes);
- hs->key_share_bytes = NULL;
- hs->key_share_bytes_len = 0;
+ hs->key_share_bytes.Reset();
if (group_id == 0) {
return CBB_flush(out);
}
@@ -2132,10 +2110,8 @@
}
// Predict the most preferred group.
- const uint16_t *groups;
- size_t groups_len;
- tls1_get_grouplist(ssl, &groups, &groups_len);
- if (groups_len == 0) {
+ Span<const uint16_t> groups = tls1_get_grouplist(ssl);
+ if (groups.size() == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
return 0;
}
@@ -2153,22 +2129,18 @@
return 0;
}
- if (!hs->received_hello_retry_request) {
- // Save the contents of the extension to repeat it in the second
- // ClientHello.
- hs->key_share_bytes_len = CBB_len(&kse_bytes);
- hs->key_share_bytes =
- (uint8_t *)BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes));
- if (hs->key_share_bytes == NULL) {
- return 0;
- }
+ // Save the contents of the extension to repeat it in the second ClientHello.
+ if (!hs->received_hello_retry_request &&
+ !hs->key_share_bytes.CopyFrom(
+ MakeConstSpan(CBB_data(&kse_bytes), CBB_len(&kse_bytes)))) {
+ return 0;
}
return CBB_flush(out);
}
-int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
- size_t *out_secret_len,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
+ Array<uint8_t> *out_secret,
uint8_t *out_alert, CBS *contents) {
CBS peer_key;
uint16_t group_id;
@@ -2185,8 +2157,7 @@
return 0;
}
- if (!hs->key_share->Finish(out_secret, out_secret_len, out_alert,
- CBS_data(&peer_key), CBS_len(&peer_key))) {
+ if (!hs->key_share->Finish(out_secret, out_alert, peer_key)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
@@ -2197,8 +2168,7 @@
}
int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found,
- uint8_t **out_secret,
- size_t *out_secret_len,
+ Array<uint8_t> *out_secret,
uint8_t *out_alert, CBS *contents) {
uint16_t group_id;
CBS key_shares;
@@ -2241,29 +2211,23 @@
if (!found) {
*out_found = false;
- *out_secret = NULL;
- *out_secret_len = 0;
+ out_secret->Reset();
return 1;
}
// Compute the DH secret.
- uint8_t *secret = NULL;
- size_t secret_len;
+ Array<uint8_t> secret;
ScopedCBB public_key;
UniquePtr<SSLKeyShare> key_share = SSLKeyShare::Create(group_id);
if (!key_share ||
!CBB_init(public_key.get(), 32) ||
- !key_share->Accept(public_key.get(), &secret, &secret_len, out_alert,
- CBS_data(&peer_key), CBS_len(&peer_key)) ||
- !CBB_finish(public_key.get(), &hs->ecdh_public_key,
- &hs->ecdh_public_key_len)) {
- OPENSSL_free(secret);
+ !key_share->Accept(public_key.get(), &secret, out_alert, peer_key) ||
+ !CBBFinishArray(public_key.get(), &hs->ecdh_public_key)) {
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
- *out_secret = secret;
- *out_secret_len = secret_len;
+ *out_secret = std::move(secret);
*out_found = true;
return 1;
}
@@ -2276,15 +2240,13 @@
!CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
- !CBB_add_bytes(&public_key, hs->ecdh_public_key,
- hs->ecdh_public_key_len) ||
+ !CBB_add_bytes(&public_key, hs->ecdh_public_key.data(),
+ hs->ecdh_public_key.size()) ||
!CBB_flush(out)) {
return 0;
}
- OPENSSL_free(hs->ecdh_public_key);
- hs->ecdh_public_key = NULL;
- hs->ecdh_public_key_len = 0;
+ hs->ecdh_public_key.Reset();
hs->new_session->group_id = group_id;
return 1;
@@ -2328,7 +2290,7 @@
// https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.2
static int ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- if (hs->cookie == NULL) {
+ if (hs->cookie.size() == 0) {
return 1;
}
@@ -2336,15 +2298,13 @@
if (!CBB_add_u16(out, TLSEXT_TYPE_cookie) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &cookie) ||
- !CBB_add_bytes(&cookie, hs->cookie, hs->cookie_len) ||
+ !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) ||
!CBB_flush(out)) {
return 0;
}
// The cookie is no longer needed in memory.
- OPENSSL_free(hs->cookie);
- hs->cookie = NULL;
- hs->cookie_len = 0;
+ hs->cookie.Reset();
return 1;
}
@@ -2370,12 +2330,8 @@
return 0;
}
- const uint16_t *groups;
- size_t groups_len;
- tls1_get_grouplist(ssl, &groups, &groups_len);
-
- for (size_t i = 0; i < groups_len; i++) {
- if (!CBB_add_u16(&groups_bytes, groups[i])) {
+ for (uint16_t group : tls1_get_grouplist(ssl)) {
+ if (!CBB_add_u16(&groups_bytes, group)) {
return 0;
}
}
@@ -2391,6 +2347,29 @@
return 1;
}
+static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) {
+ CBS copy = *cbs;
+ if ((CBS_len(©) & 1) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ return false;
+ }
+
+ Array<uint16_t> ret;
+ if (!ret.Init(CBS_len(©) / 2)) {
+ return false;
+ }
+ for (size_t i = 0; i < ret.size(); i++) {
+ if (!CBS_get_u16(©, &ret[i])) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return false;
+ }
+ }
+
+ assert(CBS_len(©) == 0);
+ *out = std::move(ret);
+ return 1;
+}
+
static int ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
@@ -2401,36 +2380,12 @@
CBS supported_group_list;
if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
CBS_len(&supported_group_list) == 0 ||
- (CBS_len(&supported_group_list) & 1) != 0 ||
- CBS_len(contents) != 0) {
+ CBS_len(contents) != 0 ||
+ !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) {
return 0;
}
- hs->peer_supported_group_list =
- (uint16_t *)OPENSSL_malloc(CBS_len(&supported_group_list));
- if (hs->peer_supported_group_list == NULL) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
-
- const size_t num_groups = CBS_len(&supported_group_list) / 2;
- for (size_t i = 0; i < num_groups; i++) {
- if (!CBS_get_u16(&supported_group_list,
- &hs->peer_supported_group_list[i])) {
- goto err;
- }
- }
-
- assert(CBS_len(&supported_group_list) == 0);
- hs->peer_supported_group_list_len = num_groups;
-
return 1;
-
-err:
- OPENSSL_free(hs->peer_supported_group_list);
- hs->peer_supported_group_list = NULL;
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return 0;
}
static int ext_supported_groups_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
@@ -3193,39 +3148,7 @@
return 1;
}
- OPENSSL_free(hs->peer_sigalgs);
- hs->peer_sigalgs = NULL;
- hs->num_peer_sigalgs = 0;
-
- size_t num_sigalgs = CBS_len(in_sigalgs);
- if (num_sigalgs % 2 != 0) {
- return 0;
- }
- num_sigalgs /= 2;
-
- // supported_signature_algorithms in the certificate request is
- // allowed to be empty.
- if (num_sigalgs == 0) {
- return 1;
- }
-
- // This multiplication doesn't overflow because sizeof(uint16_t) is two
- // and we just divided |num_sigalgs| by two.
- hs->peer_sigalgs = (uint16_t *)OPENSSL_malloc(num_sigalgs * sizeof(uint16_t));
- if (hs->peer_sigalgs == NULL) {
- return 0;
- }
- hs->num_peer_sigalgs = num_sigalgs;
-
- CBS sigalgs;
- CBS_init(&sigalgs, CBS_data(in_sigalgs), CBS_len(in_sigalgs));
- for (size_t i = 0; i < num_sigalgs; i++) {
- if (!CBS_get_u16(&sigalgs, &hs->peer_sigalgs[i])) {
- return 0;
- }
- }
-
- return 1;
+ return parse_u16_array(in_sigalgs, &hs->peer_sigalgs);
}
int tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) {
@@ -3255,36 +3178,31 @@
return 1;
}
- const uint16_t *sigalgs = cert->sigalgs;
- size_t num_sigalgs = cert->num_sigalgs;
- if (sigalgs == NULL) {
- sigalgs = kSignSignatureAlgorithms;
- num_sigalgs = OPENSSL_ARRAY_SIZE(kSignSignatureAlgorithms);
+ Span<const uint16_t> sigalgs = kSignSignatureAlgorithms;
+ if (cert->sigalgs != nullptr) {
+ sigalgs = MakeConstSpan(cert->sigalgs, cert->num_sigalgs);
}
- const uint16_t *peer_sigalgs = hs->peer_sigalgs;
- size_t num_peer_sigalgs = hs->num_peer_sigalgs;
- if (num_peer_sigalgs == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+ Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs;
+ if (peer_sigalgs.size() == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
// If the client didn't specify any signature_algorithms extension then
// we can assume that it supports SHA1. See
// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
SSL_SIGN_ECDSA_SHA1};
peer_sigalgs = kDefaultPeerAlgorithms;
- num_peer_sigalgs = OPENSSL_ARRAY_SIZE(kDefaultPeerAlgorithms);
}
- for (size_t i = 0; i < num_sigalgs; i++) {
- uint16_t sigalg = sigalgs[i];
+ for (uint16_t sigalg : sigalgs) {
// SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal value and should never be
// negotiated.
if (sigalg == SSL_SIGN_RSA_PKCS1_MD5_SHA1 ||
- !ssl_private_key_supports_signature_algorithm(hs, sigalgs[i])) {
+ !ssl_private_key_supports_signature_algorithm(hs, sigalg)) {
continue;
}
- for (size_t j = 0; j < num_peer_sigalgs; j++) {
- if (sigalg == peer_sigalgs[j]) {
+ for (uint16_t peer_sigalg : peer_sigalgs) {
+ if (sigalg == peer_sigalg) {
*out = sigalg;
return 1;
}
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 316ae01..5f83910 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -854,7 +854,7 @@
*out_pkey = GetTestState(ssl)->channel_id.release();
}
-static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len,
+static SSL_SESSION *GetSessionCallback(SSL *ssl, const uint8_t *data, int len,
int *copy) {
TestState *async_state = GetTestState(ssl);
if (async_state->session) {
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 19edb7f..8404d52 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -1446,11 +1446,6 @@
// PadClientHello, if non-zero, pads the ClientHello to a multiple of
// that many bytes.
PadClientHello int
-
- // SendOnlyECExtensions omits all extensions except supported_groups and
- // ec_point_formats, in order to trigger the Java ClientHello
- // fingerprint.
- SendOnlyECExtensions bool
}
func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index a04ffd0..0c23793 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -97,7 +97,6 @@
pskBinderFirst: c.config.Bugs.PSKBinderFirst,
omitExtensions: c.config.Bugs.OmitExtensions,
emptyExtensions: c.config.Bugs.EmptyExtensions,
- sendOnlyECExtensions: c.config.Bugs.SendOnlyECExtensions,
}
if maxVersion >= VersionTLS13 {
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 2e6d286..5dbcab9 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -176,7 +176,6 @@
omitExtensions bool
emptyExtensions bool
pad int
- sendOnlyECExtensions bool
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -225,8 +224,7 @@
m.pskBinderFirst == m1.pskBinderFirst &&
m.omitExtensions == m1.omitExtensions &&
m.emptyExtensions == m1.emptyExtensions &&
- m.pad == m1.pad &&
- m.sendOnlyECExtensions == m1.sendOnlyECExtensions
+ m.pad == m1.pad
}
func (m *clientHelloMsg) marshal() []byte {
@@ -314,6 +312,22 @@
certificateStatusRequest.addU16(0) // ResponderID length
certificateStatusRequest.addU16(0) // Extensions length
}
+ if len(m.supportedCurves) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.1.1
+ extensions.addU16(extensionSupportedCurves)
+ supportedCurvesList := extensions.addU16LengthPrefixed()
+ supportedCurves := supportedCurvesList.addU16LengthPrefixed()
+ for _, curve := range m.supportedCurves {
+ supportedCurves.addU16(uint16(curve))
+ }
+ }
+ if len(m.supportedPoints) > 0 {
+ // http://tools.ietf.org/html/rfc4492#section-5.1.2
+ extensions.addU16(extensionSupportedPoints)
+ supportedPointsList := extensions.addU16LengthPrefixed()
+ supportedPoints := supportedPointsList.addU8LengthPrefixed()
+ supportedPoints.addBytes(m.supportedPoints)
+ }
if m.hasKeyShares {
extensions.addU16(extensionKeyShare)
keyShareList := extensions.addU16LengthPrefixed()
@@ -426,30 +440,6 @@
customExt := extensions.addU16LengthPrefixed()
customExt.addBytes([]byte(m.customExtension))
}
-
- // Discard all extensions but the curve-related ones to trigger the Java
- // fingerprinter.
- if m.sendOnlyECExtensions {
- hello.discardChild()
- extensions = hello.addU16LengthPrefixed()
- }
- if len(m.supportedCurves) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.1.1
- extensions.addU16(extensionSupportedCurves)
- supportedCurvesList := extensions.addU16LengthPrefixed()
- supportedCurves := supportedCurvesList.addU16LengthPrefixed()
- for _, curve := range m.supportedCurves {
- supportedCurves.addU16(uint16(curve))
- }
- }
- if len(m.supportedPoints) > 0 {
- // http://tools.ietf.org/html/rfc4492#section-5.1.2
- extensions.addU16(extensionSupportedPoints)
- supportedPointsList := extensions.addU16LengthPrefixed()
- supportedPoints := supportedPointsList.addU8LengthPrefixed()
- supportedPoints.addBytes(m.supportedPoints)
- }
-
// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
extensions.addU16(extensionPreSharedKey)
@@ -466,8 +456,6 @@
}
}
- // This must be swapped with PSK (with some length computation) if we
- // ever need to support PadClientHello and TLS 1.3.
if m.pad != 0 && hello.len()%m.pad != 0 {
extensions.addU16(extensionPadding)
padding := extensions.addU16LengthPrefixed()
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index ee72c2e..5415aa5 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -2797,25 +2797,6 @@
shouldFail: true,
expectedLocalError: "local error: record overflow",
},
- {
- // Test that Java-like ClientHellos are provided session
- // IDs but resumption is always declined. This is to
- // workaround a bug that causes connection failures when
- // certificates rotate.
- testType: serverTest,
- name: "JavaWorkaround",
- config: Config{
- MaxVersion: VersionTLS12,
- CurvePreferences: []CurveID{CurveP256, CurveP384, CurveP521},
- SessionTicketsDisabled: true,
- Bugs: ProtocolBugs{
- SendOnlyECExtensions: true,
- },
- },
- flags: []string{"-expect-session-id"},
- resumeSession: true,
- expectResumeRejected: true,
- },
}
testCases = append(testCases, basicTests...)
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index f50b077..7ed9fad 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -99,7 +99,7 @@
return ssl_hs_error;
}
- if (!CBS_stow(&cookie_value, &hs->cookie, &hs->cookie_len)) {
+ if (!hs->cookie.CopyFrom(cookie_value)) {
return ssl_hs_error;
}
}
@@ -113,18 +113,7 @@
}
// The group must be supported.
- const uint16_t *groups;
- size_t groups_len;
- tls1_get_grouplist(ssl, &groups, &groups_len);
- int found = 0;
- for (size_t i = 0; i < groups_len; i++) {
- if (groups[i] == group_id) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
+ if (!tls1_check_group_id(ssl, group_id)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return ssl_hs_error;
@@ -336,22 +325,16 @@
}
// Resolve ECDHE and incorporate it into the secret.
- uint8_t *dhe_secret;
- size_t dhe_secret_len;
+ Array<uint8_t> dhe_secret;
alert = SSL_AD_DECODE_ERROR;
- if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &dhe_secret_len,
- &alert, &key_share)) {
+ if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &alert,
+ &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
- if (!tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len)) {
- OPENSSL_free(dhe_secret);
- return ssl_hs_error;
- }
- OPENSSL_free(dhe_secret);
-
- if (!ssl_hash_message(hs, msg) ||
+ if (!tls13_advance_key_schedule(hs, dhe_secret.data(), dhe_secret.size()) ||
+ !ssl_hash_message(hs, msg) ||
!tls13_derive_handshake_secrets(hs)) {
return ssl_hs_error;
}
@@ -856,12 +839,4 @@
return 1;
}
-void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
- hs->key_share.reset();
-
- OPENSSL_free(hs->key_share_bytes);
- hs->key_share_bytes = NULL;
- hs->key_share_bytes_len = 0;
-}
-
} // namespace bssl
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 550f3b5..ea1beae 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -74,12 +74,10 @@
}
bool found_key_share;
- uint8_t *dhe_secret;
- size_t dhe_secret_len;
+ Array<uint8_t> dhe_secret;
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
- &dhe_secret_len, &alert,
- &key_share)) {
+ &alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
}
@@ -89,9 +87,7 @@
return 0;
}
- int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
- OPENSSL_free(dhe_secret);
- return ok;
+ return tls13_advance_key_schedule(hs, dhe_secret.data(), dhe_secret.size());
}
static int ssl_ext_supported_versions_add_serverhello(SSL_HANDSHAKE *hs,
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index ef23080..d5794fc 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -48,7 +48,8 @@
)
type test struct {
- args []string
+ args []string
+ shard, numShards int
// cpu, if not empty, contains an Intel CPU code to simulate. Run
// `sde64 -help` to get a list of these codes.
cpu string
@@ -259,19 +260,6 @@
}
}
-// shortTestName returns the short name of a test. Except for evp_test and
-// cipher_test, it assumes that any argument which ends in .txt is a path to a
-// data file and not relevant to the test's uniqueness.
-func shortTestName(test test) string {
- var args []string
- for _, arg := range test.args {
- if test.args[0] == "crypto/evp/evp_test" || test.args[0] == "crypto/cipher_extra/cipher_test" || test.args[0] == "crypto/cipher_extra/aead_test" || !strings.HasSuffix(arg, ".txt") || strings.HasPrefix(arg, "--gtest_filter=") {
- args = append(args, arg)
- }
- }
- return strings.Join(args, " ") + test.cpuMsg()
-}
-
// setWorkingDirectory walks up directories as needed until the current working
// directory is the top of a BoringSSL checkout.
func setWorkingDirectory() {
@@ -313,6 +301,22 @@
}
}
+func (t test) shortName() string {
+ return t.args[0] + t.shardMsg() + t.cpuMsg()
+}
+
+func (t test) longName() string {
+ return strings.Join(t.args, " ") + t.cpuMsg()
+}
+
+func (t test) shardMsg() string {
+ if t.numShards == 0 {
+ return ""
+ }
+
+ return fmt.Sprintf(" [shard %d/%d]", t.shard+1, t.numShards)
+}
+
func (t test) cpuMsg() string {
if len(t.cpu) == 0 {
return ""
@@ -389,9 +393,14 @@
}
shard := t
shard.args = []string{shard.args[0], "--gtest_filter=" + strings.Join(shuffled[i:i+n], ":")}
+ shard.shard = len(shards)
shards = append(shards, shard)
}
+ for i := range shards {
+ shards[i].numShards = len(shards)
+ }
+
return shards, nil
}
@@ -447,18 +456,19 @@
test := testResult.Test
args := test.args
- fmt.Printf("%s%s\n", strings.Join(args, " "), test.cpuMsg())
- name := shortTestName(test)
if testResult.Error != nil {
+ fmt.Printf("%s\n", test.longName())
fmt.Printf("%s failed to complete: %s\n", args[0], testResult.Error)
failed = append(failed, test)
- testOutput.addResult(name, "CRASHED")
+ testOutput.addResult(test.longName(), "CRASHED")
} else if !testResult.Passed {
+ fmt.Printf("%s\n", test.longName())
fmt.Printf("%s failed to print PASS on the last line.\n", args[0])
failed = append(failed, test)
- testOutput.addResult(name, "FAIL")
+ testOutput.addResult(test.longName(), "FAIL")
} else {
- testOutput.addResult(name, "PASS")
+ fmt.Printf("%s\n", test.shortName())
+ testOutput.addResult(test.longName(), "PASS")
}
}