external/boringssl: Sync to ba94746eb2b4b59a0eb72047e4ca2d2d54454c87.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/7f8c553d7f4db0a6ce727f2986d41bf8fe8ec4bf..ba94746eb2b4b59a0eb72047e4ca2d2d54454c87
Test: BoringSSL CTS Presubmits
Change-Id: I5283ca8ec80f4abbc2543fece2ecf2b33240c6e4
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1814b13..1f2f6ba 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -72,6 +72,9 @@
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+ if(APPLE)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
+ endif()
if(NOT BORINGSSL_ALLOW_CXX_RUNTIME)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
endif()
@@ -307,7 +310,7 @@
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR}")
endif()
-if (${ARCH} STREQUAL "x86" AND APPLE)
+if (${ARCH} STREQUAL "x86" AND APPLE AND ${CMAKE_VERSION} VERSION_LESS "3.0")
# With CMake 2.8.x, ${CMAKE_SYSTEM_PROCESSOR} evalutes to i386 on OS X,
# but clang defaults to 64-bit builds on OS X unless otherwise told.
# Set ARCH to x86_64 so clang and CMake agree. This is fixed in CMake 3.
diff --git a/src/crypto/asn1/a_enum.c b/src/crypto/asn1/a_enum.c
index cc46905..4a77971 100644
--- a/src/crypto/asn1/a_enum.c
+++ b/src/crypto/asn1/a_enum.c
@@ -56,6 +56,7 @@
#include <openssl/asn1.h>
+#include <limits.h>
#include <string.h>
#include <openssl/err.h>
@@ -110,7 +111,6 @@
long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
{
int neg = 0, i;
- long r = 0;
if (a == NULL)
return (0L);
@@ -120,20 +120,31 @@
else if (i != V_ASN1_ENUMERATED)
return -1;
- if (a->length > (int)sizeof(long)) {
- /* hmm... a bit ugly */
- return (0xffffffffL);
- }
- if (a->data == NULL)
- return 0;
+ OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
+ long_larger_than_uint64_t);
- for (i = 0; i < a->length; i++) {
- r <<= 8;
- r |= (unsigned char)a->data[i];
+ if (a->length > (int)sizeof(uint64_t)) {
+ /* hmm... a bit ugly */
+ return -1;
}
+
+ uint64_t r64 = 0;
+ if (a->data != NULL) {
+ for (i = 0; i < a->length; i++) {
+ r64 <<= 8;
+ r64 |= (unsigned char)a->data[i];
+ }
+
+ if (r64 > LONG_MAX) {
+ return -1;
+ }
+ }
+
+ long r = (long) r64;
if (neg)
r = -r;
- return (r);
+
+ return r;
}
ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
index 617ba96..8a4edd6 100644
--- a/src/crypto/asn1/a_int.c
+++ b/src/crypto/asn1/a_int.c
@@ -57,6 +57,7 @@
#include <openssl/asn1.h>
#include <string.h>
+#include <limits.h>
#include <openssl/err.h>
#include <openssl/mem.h>
@@ -385,7 +386,6 @@
long ASN1_INTEGER_get(const ASN1_INTEGER *a)
{
int neg = 0, i;
- long r = 0;
if (a == NULL)
return (0L);
@@ -395,20 +395,31 @@
else if (i != V_ASN1_INTEGER)
return -1;
- if (a->length > (int)sizeof(long)) {
+ OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) >= sizeof(long),
+ long_larger_than_uint64_t);
+
+ if (a->length > (int)sizeof(uint64_t)) {
/* hmm... a bit ugly, return all ones */
return -1;
}
- if (a->data == NULL)
- return 0;
- for (i = 0; i < a->length; i++) {
- r <<= 8;
- r |= (unsigned char)a->data[i];
+ uint64_t r64 = 0;
+ if (a->data != NULL) {
+ for (i = 0; i < a->length; i++) {
+ r64 <<= 8;
+ r64 |= (unsigned char)a->data[i];
+ }
+
+ if (r64 > LONG_MAX) {
+ return -1;
+ }
}
+
+ long r = (long) r64;
if (neg)
r = -r;
- return (r);
+
+ return r;
}
ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
diff --git a/src/crypto/asn1/asn1_locl.h b/src/crypto/asn1/asn1_locl.h
index fef00ac..10a832c 100644
--- a/src/crypto/asn1/asn1_locl.h
+++ b/src/crypto/asn1/asn1_locl.h
@@ -90,6 +90,9 @@
int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
+void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
+ int combine);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/crypto/asn1/tasn_fre.c b/src/crypto/asn1/tasn_fre.c
index 609cb9f..eabc0fb 100644
--- a/src/crypto/asn1/tasn_fre.c
+++ b/src/crypto/asn1/tasn_fre.c
@@ -59,8 +59,7 @@
#include <openssl/asn1t.h>
#include <openssl/mem.h>
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
- int combine);
+#include "asn1_locl.h"
/* Free up an ASN1 structure */
@@ -74,8 +73,7 @@
asn1_item_combine_free(pval, it, 0);
}
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
- int combine)
+void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
{
const ASN1_TEMPLATE *tt = NULL, *seqtt;
const ASN1_EXTERN_FUNCS *ef;
diff --git a/src/crypto/asn1/tasn_new.c b/src/crypto/asn1/tasn_new.c
index 10cf954..5db38be 100644
--- a/src/crypto/asn1/tasn_new.c
+++ b/src/crypto/asn1/tasn_new.c
@@ -63,6 +63,7 @@
#include <openssl/mem.h>
#include <openssl/obj.h>
+#include "asn1_locl.h"
#include "../internal.h"
@@ -201,7 +202,7 @@
return 1;
memerr2:
- ASN1_item_ex_free(pval, it);
+ asn1_item_combine_free(pval, it, combine);
memerr:
OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
#ifdef CRYPTO_MDEBUG
@@ -211,7 +212,7 @@
return 0;
auxerr2:
- ASN1_item_ex_free(pval, it);
+ asn1_item_combine_free(pval, it, combine);
auxerr:
OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
#ifdef CRYPTO_MDEBUG
diff --git a/src/crypto/bn_extra/bn_asn1.c b/src/crypto/bn_extra/bn_asn1.c
index 8b939da..0d96573 100644
--- a/src/crypto/bn_extra/bn_asn1.c
+++ b/src/crypto/bn_extra/bn_asn1.c
@@ -42,22 +42,6 @@
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
}
-int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
- CBS child;
- if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
- CBS_len(&child) == 0) {
- OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
- return 0;
- }
-
- // This function intentionally does not reject negative numbers or non-minimal
- // encodings. Estonian IDs issued between September 2014 to September 2015 are
- // broken. See https://crbug.com/532048 and https://crbug.com/534766.
- //
- // TODO(davidben): Remove this code and callers in March 2016.
- return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
-}
-
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
// Negative numbers are unsupported.
if (BN_is_negative(bn)) {
diff --git a/src/crypto/cpu-intel.c b/src/crypto/cpu-intel.c
index 127fa57..1ac280c 100644
--- a/src/crypto/cpu-intel.c
+++ b/src/crypto/cpu-intel.c
@@ -164,7 +164,7 @@
uint32_t num_extended_ids = eax;
if (num_extended_ids >= 0x80000001) {
OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 0x80000001);
- if (ecx & (1 << 11)) {
+ if (ecx & (1u << 11)) {
has_amd_xop = 1;
}
}
@@ -193,68 +193,68 @@
OPENSSL_cpuid(&eax, &ebx, &ecx, &edx, 1);
// Adjust the hyper-threading bit.
- if (edx & (1 << 28)) {
+ if (edx & (1u << 28)) {
uint32_t num_logical_cores = (ebx >> 16) & 0xff;
if (cores_per_cache == 1 || num_logical_cores <= 1) {
- edx &= ~(1 << 28);
+ edx &= ~(1u << 28);
}
}
// Reserved bit #20 was historically repurposed to control the in-memory
// representation of RC4 state. Always set it to zero.
- edx &= ~(1 << 20);
+ edx &= ~(1u << 20);
// Reserved bit #30 is repurposed to signal an Intel CPU.
if (is_intel) {
- edx |= (1 << 30);
+ edx |= (1u << 30);
// Clear the XSAVE bit on Knights Landing to mimic Silvermont. This enables
// some Silvermont-specific codepaths which perform better. See OpenSSL
// commit 64d92d74985ebb3d0be58a9718f9e080a14a8e7f.
if ((eax & 0x0fff0ff0) == 0x00050670 /* Knights Landing */ ||
(eax & 0x0fff0ff0) == 0x00080650 /* Knights Mill (per SDE) */) {
- ecx &= ~(1 << 26);
+ ecx &= ~(1u << 26);
}
} else {
- edx &= ~(1 << 30);
+ edx &= ~(1u << 30);
}
// The SDBG bit is repurposed to denote AMD XOP support.
if (has_amd_xop) {
- ecx |= (1 << 11);
+ ecx |= (1u << 11);
} else {
- ecx &= ~(1 << 11);
+ ecx &= ~(1u << 11);
}
uint64_t xcr0 = 0;
- if (ecx & (1 << 27)) {
+ if (ecx & (1u << 27)) {
// XCR0 may only be queried if the OSXSAVE bit is set.
xcr0 = OPENSSL_xgetbv(0);
}
// See Intel manual, volume 1, section 14.3.
if ((xcr0 & 6) != 6) {
// YMM registers cannot be used.
- ecx &= ~(1 << 28); // AVX
- ecx &= ~(1 << 12); // FMA
- ecx &= ~(1 << 11); // AMD XOP
+ ecx &= ~(1u << 28); // AVX
+ ecx &= ~(1u << 12); // FMA
+ ecx &= ~(1u << 11); // AMD XOP
// Clear AVX2 and AVX512* bits.
//
// TODO(davidben): Should bits 17 and 26-28 also be cleared? Upstream
// doesn't clear those.
extended_features &=
- ~((1 << 5) | (1 << 16) | (1 << 21) | (1 << 30) | (1 << 31));
+ ~((1u << 5) | (1u << 16) | (1u << 21) | (1u << 30) | (1u << 31));
}
// See Intel manual, volume 1, section 15.2.
if ((xcr0 & 0xe6) != 0xe6) {
// Clear AVX512F. Note we don't touch other AVX512 extensions because they
// can be used with YMM.
- extended_features &= ~(1 << 16);
+ extended_features &= ~(1u << 16);
}
// Disable ADX instructions on Knights Landing. See OpenSSL commit
// 64d92d74985ebb3d0be58a9718f9e080a14a8e7f.
- if ((ecx & (1 << 26)) == 0) {
- extended_features &= ~(1 << 19);
+ if ((ecx & (1u << 26)) == 0) {
+ extended_features &= ~(1u << 19);
}
OPENSSL_ia32cap_P[0] = edx;
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index 390cd8b..9f4639f 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -40,6 +40,18 @@
OPENSSL_ARM || OPENSSL_AARCH64) */
+// Our assembly does not use the GOT to reference symbols, which means
+// references to visible symbols will often require a TEXTREL. This is
+// undesirable, so all assembly-referenced symbols should be hidden. CPU
+// capabilities are the only such symbols defined in C. Explicitly hide them,
+// rather than rely on being built with -fvisibility=hidden.
+#if defined(OPENSSL_WINDOWS)
+#define HIDDEN
+#else
+#define HIDDEN __attribute__((visibility("hidden")))
+#endif
+
+
// The capability variables are defined in this file in order to work around a
// linker bug. When linking with a .a, if no symbols in a .o are referenced
// then the .o is discarded, even if it has constructor functions.
@@ -57,11 +69,11 @@
// archive, linking on OS X will fail to resolve common symbols. By
// initialising it to zero, it becomes a "data symbol", which isn't so
// affected.
-uint32_t OPENSSL_ia32cap_P[4] = {0};
+HIDDEN uint32_t OPENSSL_ia32cap_P[4] = {0};
#elif defined(OPENSSL_PPC64LE)
-unsigned long OPENSSL_ppc64le_hwcap2 = 0;
+HIDDEN unsigned long OPENSSL_ppc64le_hwcap2 = 0;
#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
@@ -69,7 +81,7 @@
#if defined(OPENSSL_STATIC_ARMCAP)
-uint32_t OPENSSL_armcap_P =
+HIDDEN uint32_t OPENSSL_armcap_P =
#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
ARMV7_NEON |
#endif
@@ -88,7 +100,7 @@
0;
#else
-uint32_t OPENSSL_armcap_P = 0;
+HIDDEN uint32_t OPENSSL_armcap_P = 0;
#endif
#endif
diff --git a/src/crypto/ecdh/ecdh_test.cc b/src/crypto/ecdh/ecdh_test.cc
index b311445..6d48408 100644
--- a/src/crypto/ecdh/ecdh_test.cc
+++ b/src/crypto/ecdh/ecdh_test.cc
@@ -14,6 +14,7 @@
#include <stdio.h>
+#include <utility>
#include <vector>
#include <gtest/gtest.h>
@@ -23,6 +24,7 @@
#include <openssl/ec.h>
#include <openssl/ec_key.h>
#include <openssl/ecdh.h>
+#include <openssl/err.h>
#include <openssl/nid.h>
#include "../test/file_test.h"
@@ -112,3 +114,98 @@
Bytes(actual_z.data(), static_cast<size_t>(ret)));
});
}
+
+// MakeCustomGroup returns an |EC_GROUP| containing a non-standard group. (P-256
+// with the wrong generator.)
+static bssl::UniquePtr<EC_GROUP> MakeCustomGroup() {
+ static const uint8_t kP[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ };
+ static const uint8_t kA[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ };
+ static const uint8_t kB[] = {
+ 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
+ 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+ 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
+ };
+ static const uint8_t kX[] = {
+ 0xe6, 0x2b, 0x69, 0xe2, 0xbf, 0x65, 0x9f, 0x97, 0xbe, 0x2f, 0x1e,
+ 0x0d, 0x94, 0x8a, 0x4c, 0xd5, 0x97, 0x6b, 0xb7, 0xa9, 0x1e, 0x0d,
+ 0x46, 0xfb, 0xdd, 0xa9, 0xa9, 0x1e, 0x9d, 0xdc, 0xba, 0x5a,
+ };
+ static const uint8_t kY[] = {
+ 0x01, 0xe7, 0xd6, 0x97, 0xa8, 0x0a, 0x18, 0xf9, 0xc3, 0xc4, 0xa3,
+ 0x1e, 0x56, 0xe2, 0x7c, 0x83, 0x48, 0xdb, 0x16, 0x1a, 0x1c, 0xf5,
+ 0x1d, 0x7e, 0xf1, 0x94, 0x2d, 0x4b, 0xcf, 0x72, 0x22, 0xc1,
+ };
+ static const uint8_t kOrder[] = {
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
+ 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
+ };
+ bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+ bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
+ bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
+ bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
+ bssl::UniquePtr<BIGNUM> x(BN_bin2bn(kX, sizeof(kX), nullptr));
+ bssl::UniquePtr<BIGNUM> y(BN_bin2bn(kY, sizeof(kY), nullptr));
+ bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
+ if (!ctx || !p || !a || !b || !x || !y || !order) {
+ return nullptr;
+ }
+ bssl::UniquePtr<EC_GROUP> group(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
+ if (!group) {
+ return nullptr;
+ }
+ bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
+ if (!generator ||
+ !EC_POINT_set_affine_coordinates_GFp(group.get(), generator.get(),
+ x.get(), y.get(), ctx.get()) ||
+ !EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
+ BN_value_one())) {
+ return nullptr;
+ }
+ return group;
+}
+
+TEST(ECDHTest, GroupMismatch) {
+ const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
+ std::vector<EC_builtin_curve> curves(num_curves);
+ EC_get_builtin_curves(curves.data(), num_curves);
+
+ // Instantiate all the built-in curves.
+ std::vector<bssl::UniquePtr<EC_GROUP>> groups;
+ for (const auto &curve : curves) {
+ groups.emplace_back(EC_GROUP_new_by_curve_name(curve.nid));
+ ASSERT_TRUE(groups.back());
+ }
+
+ // Also create some arbitrary group. (This is P-256 with the wrong generator.)
+ groups.push_back(MakeCustomGroup());
+ ASSERT_TRUE(groups.back());
+
+ for (const auto &a : groups) {
+ for (const auto &b : groups) {
+ if (a.get() == b.get()) {
+ continue;
+ }
+
+ bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
+ ASSERT_TRUE(EC_KEY_set_group(key.get(), a.get()));
+ ASSERT_TRUE(EC_KEY_generate_key(key.get()));
+
+ // ECDH across the groups should not work.
+ char out[64];
+ const EC_POINT *peer = EC_GROUP_get0_generator(b.get());
+ EXPECT_EQ(-1,
+ ECDH_compute_key(out, sizeof(out), peer, key.get(), nullptr));
+ ERR_clear_error();
+ }
+ }
+}
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
index 5157a89..a188538 100644
--- a/src/crypto/evp/p_rsa_asn1.c
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -63,19 +63,9 @@
#include <openssl/rsa.h>
#include "../fipsmodule/rsa/internal.h"
-#include "../internal.h"
#include "internal.h"
-static struct CRYPTO_STATIC_MUTEX g_buggy_lock = CRYPTO_STATIC_MUTEX_INIT;
-static int g_buggy = 0;
-
-void EVP_set_buggy_rsa_parser(int buggy) {
- CRYPTO_STATIC_MUTEX_lock_write(&g_buggy_lock);
- g_buggy = buggy;
- CRYPTO_STATIC_MUTEX_unlock_write(&g_buggy_lock);
-}
-
static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
// See RFC 3279, section 2.3.1.
CBB spki, algorithm, oid, null, key_bitstring;
@@ -96,11 +86,6 @@
}
static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
- int buggy;
- CRYPTO_STATIC_MUTEX_lock_read(&g_buggy_lock);
- buggy = g_buggy;
- CRYPTO_STATIC_MUTEX_unlock_read(&g_buggy_lock);
-
// See RFC 3279, section 2.3.1.
// The parameters must be NULL.
@@ -112,13 +97,7 @@
return 0;
}
- // Estonian IDs issued between September 2014 to September 2015 are
- // broken. See https://crbug.com/532048 and https://crbug.com/534766.
- //
- // TODO(davidben): Switch this to the strict version in March 2016 or when
- // Chromium can force client certificates down a different codepath, whichever
- // comes first.
- RSA *rsa = buggy ? RSA_parse_public_key_buggy(key) : RSA_parse_public_key(key);
+ RSA *rsa = RSA_parse_public_key(key);
if (rsa == NULL || CBS_len(key) != 0) {
OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
RSA_free(rsa);
diff --git a/src/crypto/ex_data.c b/src/crypto/ex_data.c
index af7e7e2..71d60a5 100644
--- a/src/crypto/ex_data.c
+++ b/src/crypto/ex_data.c
@@ -113,7 +113,6 @@
#include <openssl/crypto.h>
#include <openssl/err.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/stack.h>
#include <openssl/thread.h>
diff --git a/src/crypto/fipsmodule/bn/add.c b/src/crypto/fipsmodule/bn/add.c
index bbe275e..201c526 100644
--- a/src/crypto/fipsmodule/bn/add.c
+++ b/src/crypto/fipsmodule/bn/add.c
@@ -133,7 +133,7 @@
while (dif) {
dif--;
t1 = *(ap++);
- t2 = (t1 + 1) & BN_MASK2;
+ t2 = t1 + 1;
*(rp++) = t2;
if (t2) {
carry = 0;
@@ -162,8 +162,6 @@
BN_ULONG l;
int i;
- w &= BN_MASK2;
-
// degenerate case: w is zero
if (!w) {
return 1;
@@ -185,7 +183,7 @@
}
for (i = 0; w != 0 && i < a->top; i++) {
- a->d[i] = l = (a->d[i] + w) & BN_MASK2;
+ a->d[i] = l = a->d[i] + w;
w = (w > l) ? 1 : 0;
}
@@ -285,12 +283,12 @@
t2 = *(bp++);
if (carry) {
carry = (t1 <= t2);
- t1 = (t1 - t2 - 1) & BN_MASK2;
+ t1 -= t2 + 1;
} else {
carry = (t1 < t2);
- t1 = (t1 - t2) & BN_MASK2;
+ t1 -= t2;
}
- *(rp++) = t1 & BN_MASK2;
+ *(rp++) = t1;
}
if (carry) // subtracted
@@ -303,7 +301,7 @@
while (dif) {
dif--;
t1 = *(ap++);
- t2 = (t1 - 1) & BN_MASK2;
+ t2 = t1 - 1;
*(rp++) = t2;
if (t1) {
break;
@@ -325,8 +323,6 @@
int BN_sub_word(BIGNUM *a, BN_ULONG w) {
int i;
- w &= BN_MASK2;
-
// degenerate case: w is zero
if (!w) {
return 1;
@@ -361,7 +357,7 @@
a->d[i] -= w;
break;
} else {
- a->d[i] = (a->d[i] - w) & BN_MASK2;
+ a->d[i] -= w;
i++;
w = 1;
}
diff --git a/src/crypto/fipsmodule/bn/bn_test.cc b/src/crypto/fipsmodule/bn/bn_test.cc
index fe03e5f..975264e 100644
--- a/src/crypto/fipsmodule/bn/bn_test.cc
+++ b/src/crypto/fipsmodule/bn/bn_test.cc
@@ -778,27 +778,27 @@
TEST_F(BNTest, Dec2BN) {
bssl::UniquePtr<BIGNUM> bn;
int ret = DecimalToBIGNUM(&bn, "0");
- EXPECT_EQ(1, ret);
+ ASSERT_EQ(1, ret);
EXPECT_TRUE(BN_is_zero(bn.get()));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = DecimalToBIGNUM(&bn, "256");
- EXPECT_EQ(3, ret);
+ ASSERT_EQ(3, ret);
EXPECT_TRUE(BN_is_word(bn.get(), 256));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = DecimalToBIGNUM(&bn, "-42");
- EXPECT_EQ(3, ret);
+ ASSERT_EQ(3, ret);
EXPECT_TRUE(BN_abs_is_word(bn.get(), 42));
EXPECT_TRUE(BN_is_negative(bn.get()));
ret = DecimalToBIGNUM(&bn, "-0");
- EXPECT_EQ(2, ret);
+ ASSERT_EQ(2, ret);
EXPECT_TRUE(BN_is_zero(bn.get()));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = DecimalToBIGNUM(&bn, "42trailing garbage is ignored");
- EXPECT_EQ(2, ret);
+ ASSERT_EQ(2, ret);
EXPECT_TRUE(BN_abs_is_word(bn.get(), 42));
EXPECT_FALSE(BN_is_negative(bn.get()));
}
@@ -806,27 +806,27 @@
TEST_F(BNTest, Hex2BN) {
bssl::UniquePtr<BIGNUM> bn;
int ret = HexToBIGNUM(&bn, "0");
- EXPECT_EQ(1, ret);
+ ASSERT_EQ(1, ret);
EXPECT_TRUE(BN_is_zero(bn.get()));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = HexToBIGNUM(&bn, "256");
- EXPECT_EQ(3, ret);
+ ASSERT_EQ(3, ret);
EXPECT_TRUE(BN_is_word(bn.get(), 0x256));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = HexToBIGNUM(&bn, "-42");
- EXPECT_EQ(3, ret);
+ ASSERT_EQ(3, ret);
EXPECT_TRUE(BN_abs_is_word(bn.get(), 0x42));
EXPECT_TRUE(BN_is_negative(bn.get()));
ret = HexToBIGNUM(&bn, "-0");
- EXPECT_EQ(2, ret);
+ ASSERT_EQ(2, ret);
EXPECT_TRUE(BN_is_zero(bn.get()));
EXPECT_FALSE(BN_is_negative(bn.get()));
ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored");
- EXPECT_EQ(3, ret);
+ ASSERT_EQ(3, ret);
EXPECT_TRUE(BN_is_word(bn.get(), 0xabc));
EXPECT_FALSE(BN_is_negative(bn.get()));
}
@@ -1000,16 +1000,11 @@
{"\x03\x01\x00", 3},
// Empty contents.
{"\x02\x00", 2},
-};
-
-// kASN1BuggyTests contains incorrect encodings and the corresponding, expected
-// results of |BN_parse_asn1_unsigned_buggy| given that input.
-static const ASN1Test kASN1BuggyTests[] = {
// Negative numbers.
- {"128", "\x02\x01\x80", 3},
- {"255", "\x02\x01\xff", 3},
+ {"\x02\x01\x80", 3},
+ {"\x02\x01\xff", 3},
// Unnecessary leading zeros.
- {"1", "\x02\x02\x00\x01", 4},
+ {"\x02\x02\x00\x01", 4},
};
TEST_F(BNTest, ASN1) {
@@ -1036,12 +1031,6 @@
ASSERT_TRUE(CBB_finish(cbb.get(), &der, &der_len));
bssl::UniquePtr<uint8_t> delete_der(der);
EXPECT_EQ(Bytes(test.der, test.der_len), Bytes(der, der_len));
-
- // |BN_parse_asn1_unsigned_buggy| parses all valid input.
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- ASSERT_TRUE(BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()));
- EXPECT_EQ(0u, CBS_len(&cbs));
- EXPECT_BIGNUMS_EQUAL("decode ASN.1 buggy", bn.get(), bn2.get());
}
for (const ASN1InvalidTest &test : kASN1InvalidTests) {
@@ -1053,35 +1042,6 @@
EXPECT_FALSE(BN_parse_asn1_unsigned(&cbs, bn.get()))
<< "Parsed invalid input.";
ERR_clear_error();
-
- // All tests in kASN1InvalidTests are also rejected by
- // |BN_parse_asn1_unsigned_buggy|.
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- EXPECT_FALSE(BN_parse_asn1_unsigned_buggy(&cbs, bn.get()))
- << "Parsed invalid input.";
- ERR_clear_error();
- }
-
- for (const ASN1Test &test : kASN1BuggyTests) {
- SCOPED_TRACE(Bytes(test.der, test.der_len));
-
- // These broken encodings are rejected by |BN_parse_asn1_unsigned|.
- bssl::UniquePtr<BIGNUM> bn(BN_new());
- ASSERT_TRUE(bn);
- CBS cbs;
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- EXPECT_FALSE(BN_parse_asn1_unsigned(&cbs, bn.get()))
- << "Parsed invalid input.";
- ERR_clear_error();
-
- // However |BN_parse_asn1_unsigned_buggy| accepts them.
- bssl::UniquePtr<BIGNUM> bn2 = ASCIIToBIGNUM(test.value_ascii);
- ASSERT_TRUE(bn2);
-
- CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
- ASSERT_TRUE(BN_parse_asn1_unsigned_buggy(&cbs, bn.get()));
- EXPECT_EQ(0u, CBS_len(&cbs));
- EXPECT_BIGNUMS_EQUAL("decode ASN.1 buggy", bn2.get(), bn.get());
}
// Serializing negative numbers is not supported.
diff --git a/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go b/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go
new file mode 100644
index 0000000..d1ee734
--- /dev/null
+++ b/src/crypto/fipsmodule/bn/bn_test_to_fuzzer.go
@@ -0,0 +1,234 @@
+// 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.
+
+package main
+
+import (
+ "bufio"
+ "crypto/sha1"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math/big"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+type test struct {
+ LineNumber int
+ Type string
+ Values map[string]*big.Int
+}
+
+type testScanner struct {
+ scanner *bufio.Scanner
+ lineNo int
+ err error
+ test test
+}
+
+func newTestScanner(r io.Reader) *testScanner {
+ return &testScanner{scanner: bufio.NewScanner(r)}
+}
+
+func (s *testScanner) scanLine() bool {
+ if !s.scanner.Scan() {
+ return false
+ }
+ s.lineNo++
+ return true
+}
+
+func (s *testScanner) addAttribute(line string) (key string, ok bool) {
+ fields := strings.SplitN(line, "=", 2)
+ if len(fields) != 2 {
+ s.setError(errors.New("invalid syntax"))
+ return "", false
+ }
+
+ key = strings.TrimSpace(fields[0])
+ value := strings.TrimSpace(fields[1])
+
+ valueInt, ok := new(big.Int).SetString(value, 16)
+ if !ok {
+ s.setError(fmt.Errorf("could not parse %q", value))
+ return "", false
+ }
+ if _, dup := s.test.Values[key]; dup {
+ s.setError(fmt.Errorf("duplicate key %q", key))
+ return "", false
+ }
+ s.test.Values[key] = valueInt
+ return key, true
+}
+
+func (s *testScanner) Scan() bool {
+ s.test = test{
+ Values: make(map[string]*big.Int),
+ }
+
+ // Scan until the first attribute.
+ for {
+ if !s.scanLine() {
+ return false
+ }
+ if len(s.scanner.Text()) != 0 && s.scanner.Text()[0] != '#' {
+ break
+ }
+ }
+
+ var ok bool
+ s.test.Type, ok = s.addAttribute(s.scanner.Text())
+ if !ok {
+ return false
+ }
+ s.test.LineNumber = s.lineNo
+
+ for s.scanLine() {
+ if len(s.scanner.Text()) == 0 {
+ break
+ }
+
+ if s.scanner.Text()[0] == '#' {
+ continue
+ }
+
+ if _, ok := s.addAttribute(s.scanner.Text()); !ok {
+ return false
+ }
+ }
+ return s.scanner.Err() == nil
+}
+
+func (s *testScanner) Test() test {
+ return s.test
+}
+
+func (s *testScanner) Err() error {
+ if s.err != nil {
+ return s.err
+ }
+ return s.scanner.Err()
+}
+
+func (s *testScanner) setError(err error) {
+ s.err = fmt.Errorf("line %d: %s", s.lineNo, err)
+}
+
+func checkKeys(t test, keys ...string) bool {
+ var foundErrors bool
+
+ for _, k := range keys {
+ if _, ok := t.Values[k]; !ok {
+ fmt.Fprintf(os.Stderr, "Line %d: missing key %q.\n", t.LineNumber, k)
+ foundErrors = true
+ }
+ }
+
+ for k, _ := range t.Values {
+ var found bool
+ for _, k2 := range keys {
+ if k == k2 {
+ found = true
+ break
+ }
+ }
+ if !found {
+ fmt.Fprintf(os.Stderr, "Line %d: unexpected key %q.\n", t.LineNumber, k)
+ foundErrors = true
+ }
+ }
+
+ return !foundErrors
+}
+
+func appendLengthPrefixed(ret, b []byte) []byte {
+ ret = append(ret, byte(len(b)>>8), byte(len(b)))
+ ret = append(ret, b...)
+ return ret
+}
+
+func appendUnsigned(ret []byte, n *big.Int) []byte {
+ b := n.Bytes()
+ if n.Sign() == 0 {
+ b = []byte{0}
+ }
+ return appendLengthPrefixed(ret, b)
+}
+
+func appendSigned(ret []byte, n *big.Int) []byte {
+ var sign byte
+ if n.Sign() < 0 {
+ sign = 1
+ }
+ b := []byte{sign}
+ b = append(b, n.Bytes()...)
+ if n.Sign() == 0 {
+ b = append(b, 0)
+ }
+ return appendLengthPrefixed(ret, b)
+}
+
+func main() {
+ if len(os.Args) != 3 {
+ fmt.Fprintf(os.Stderr, "Usage: %s TESTS FUZZ_DIR\n", os.Args[0])
+ os.Exit(1)
+ }
+
+ in, err := os.Open(os.Args[1])
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Error opening %s: %s.\n", os.Args[0], err)
+ os.Exit(1)
+ }
+ defer in.Close()
+
+ fuzzerDir := os.Args[2]
+
+ scanner := newTestScanner(in)
+ for scanner.Scan() {
+ var fuzzer string
+ var b []byte
+ test := scanner.Test()
+ switch test.Type {
+ case "Quotient":
+ if checkKeys(test, "A", "B", "Quotient", "Remainder") {
+ fuzzer = "bn_div"
+ b = appendSigned(b, test.Values["A"])
+ b = appendSigned(b, test.Values["B"])
+ }
+ case "ModExp":
+ if checkKeys(test, "A", "E", "M", "ModExp") {
+ fuzzer = "bn_mod_exp"
+ b = appendSigned(b, test.Values["A"])
+ b = appendUnsigned(b, test.Values["E"])
+ b = appendUnsigned(b, test.Values["M"])
+ }
+ }
+
+ if len(fuzzer) != 0 {
+ hash := sha1.Sum(b)
+ path := filepath.Join(fuzzerDir, fuzzer + "_corpus", hex.EncodeToString(hash[:]))
+ if err := ioutil.WriteFile(path, b, 0666); err != nil {
+ fmt.Fprintf(os.Stderr, "Error writing to %s: %s.\n", path, err)
+ os.Exit(1)
+ }
+ }
+ }
+ if scanner.Err() != nil {
+ fmt.Fprintf(os.Stderr, "Error reading tests: %s.\n", scanner.Err())
+ }
+}
diff --git a/src/crypto/fipsmodule/bn/div.c b/src/crypto/fipsmodule/bn/div.c
index 1bcff50..0b8b9b9 100644
--- a/src/crypto/fipsmodule/bn/div.c
+++ b/src/crypto/fipsmodule/bn/div.c
@@ -128,7 +128,7 @@
}
ret = q << BN_BITS4;
- h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
+ h = (h << BN_BITS4) | (l >> BN_BITS4);
l = (l & BN_MASK2l) << BN_BITS4;
}
@@ -569,8 +569,6 @@
BN_ULONG ret = 0;
int i, j;
- w &= BN_MASK2;
-
if (!w) {
// actually this an error (division by zero)
return (BN_ULONG) - 1;
@@ -592,7 +590,7 @@
BN_ULONG d;
BN_ULONG unused_rem;
bn_div_rem_words(&d, &unused_rem, ret, l, w);
- ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
+ ret = l - (d * w);
a->d[i] = d;
}
@@ -634,7 +632,6 @@
}
#endif
- w &= BN_MASK2;
for (i = a->top - 1; i >= 0; i--) {
#ifndef BN_ULLONG
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
diff --git a/src/crypto/fipsmodule/bn/exponentiation.c b/src/crypto/fipsmodule/bn/exponentiation.c
index f4e028b..b6b7fa9 100644
--- a/src/crypto/fipsmodule/bn/exponentiation.c
+++ b/src/crypto/fipsmodule/bn/exponentiation.c
@@ -655,9 +655,9 @@
goto err;
}
// 2^(top*BN_BITS2) - m
- r->d[0] = (0 - m->d[0]) & BN_MASK2;
+ r->d[0] = 0 - m->d[0];
for (i = 1; i < j; i++) {
- r->d[i] = (~m->d[i]) & BN_MASK2;
+ r->d[i] = ~m->d[i];
}
r->top = j;
// Upper words will be zero if the corresponding words of 'm'
@@ -963,9 +963,9 @@
// by Shay Gueron's suggestion
if (m->d[top - 1] & (((BN_ULONG)1) << (BN_BITS2 - 1))) {
// 2^(top*BN_BITS2) - m
- tmp.d[0] = (0 - m->d[0]) & BN_MASK2;
+ tmp.d[0] = 0 - m->d[0];
for (i = 1; i < top; i++) {
- tmp.d[i] = (~m->d[i]) & BN_MASK2;
+ tmp.d[i] = ~m->d[i];
}
tmp.top = top;
} else if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) {
diff --git a/src/crypto/fipsmodule/bn/generic.c b/src/crypto/fipsmodule/bn/generic.c
index b70080f..11c377c 100644
--- a/src/crypto/fipsmodule/bn/generic.c
+++ b/src/crypto/fipsmodule/bn/generic.c
@@ -209,21 +209,21 @@
assert(n >= 0);
if (n <= 0) {
- return (BN_ULONG)0;
+ return 0;
}
while (n & ~3) {
ll += (BN_ULLONG)a[0] + b[0];
- r[0] = (BN_ULONG)ll & BN_MASK2;
+ r[0] = (BN_ULONG)ll;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[1] + b[1];
- r[1] = (BN_ULONG)ll & BN_MASK2;
+ r[1] = (BN_ULONG)ll;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[2] + b[2];
- r[2] = (BN_ULONG)ll & BN_MASK2;
+ r[2] = (BN_ULONG)ll;
ll >>= BN_BITS2;
ll += (BN_ULLONG)a[3] + b[3];
- r[3] = (BN_ULONG)ll & BN_MASK2;
+ r[3] = (BN_ULONG)ll;
ll >>= BN_BITS2;
a += 4;
b += 4;
@@ -232,7 +232,7 @@
}
while (n) {
ll += (BN_ULLONG)a[0] + b[0];
- r[0] = (BN_ULONG)ll & BN_MASK2;
+ r[0] = (BN_ULONG)ll;
ll >>= BN_BITS2;
a++;
b++;
@@ -256,27 +256,27 @@
c = 0;
while (n & ~3) {
t = a[0];
- t = (t + c) & BN_MASK2;
+ t += c;
c = (t < c);
- l = (t + b[0]) & BN_MASK2;
+ l = t + b[0];
c += (l < t);
r[0] = l;
t = a[1];
- t = (t + c) & BN_MASK2;
+ t += c;
c = (t < c);
- l = (t + b[1]) & BN_MASK2;
+ l = t + b[1];
c += (l < t);
r[1] = l;
t = a[2];
- t = (t + c) & BN_MASK2;
+ t += c;
c = (t < c);
- l = (t + b[2]) & BN_MASK2;
+ l = t + b[2];
c += (l < t);
r[2] = l;
t = a[3];
- t = (t + c) & BN_MASK2;
+ t += c;
c = (t < c);
- l = (t + b[3]) & BN_MASK2;
+ l = t + b[3];
c += (l < t);
r[3] = l;
a += 4;
@@ -286,9 +286,9 @@
}
while (n) {
t = a[0];
- t = (t + c) & BN_MASK2;
+ t += c;
c = (t < c);
- l = (t + b[0]) & BN_MASK2;
+ l = t + b[0];
c += (l < t);
r[0] = l;
a++;
@@ -314,25 +314,25 @@
while (n & ~3) {
t1 = a[0];
t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
+ r[0] = t1 - t2 - c;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[1];
t2 = b[1];
- r[1] = (t1 - t2 - c) & BN_MASK2;
+ r[1] = t1 - t2 - c;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[2];
t2 = b[2];
- r[2] = (t1 - t2 - c) & BN_MASK2;
+ r[2] = t1 - t2 - c;
if (t1 != t2) {
c = (t1 < t2);
}
t1 = a[3];
t2 = b[3];
- r[3] = (t1 - t2 - c) & BN_MASK2;
+ r[3] = t1 - t2 - c;
if (t1 != t2) {
c = (t1 < t2);
}
@@ -344,7 +344,7 @@
while (n) {
t1 = a[0];
t2 = b[0];
- r[0] = (t1 - t2 - c) & BN_MASK2;
+ r[0] = t1 - t2 - c;
if (t1 != t2) {
c = (t1 < t2);
}
@@ -372,7 +372,7 @@
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- (c1) = ((c1) + (hi)) & BN_MASK2; \
+ (c1) += (hi); \
if ((c1) < hi) { \
(c2)++; \
} \
@@ -385,14 +385,14 @@
BN_ULLONG tt = t + (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(tt); \
hi = (BN_ULONG)Hw(tt); \
- (c1) = ((c1) + hi) & BN_MASK2; \
+ (c1) += hi; \
if ((c1) < hi) { \
(c2)++; \
} \
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- (c1) = ((c1) + hi) & BN_MASK2; \
+ (c1) += hi; \
if ((c1) < hi) { \
(c2)++; \
} \
@@ -405,7 +405,7 @@
t += (c0); /* no carry */ \
(c0) = (BN_ULONG)Lw(t); \
hi = (BN_ULONG)Hw(t); \
- (c1) = ((c1) + hi) & BN_MASK2; \
+ (c1) += hi; \
if ((c1) < hi) { \
(c2)++; \
} \
diff --git a/src/crypto/fipsmodule/bn/internal.h b/src/crypto/fipsmodule/bn/internal.h
index ecd7d6c..b1e0b0d 100644
--- a/src/crypto/fipsmodule/bn/internal.h
+++ b/src/crypto/fipsmodule/bn/internal.h
@@ -191,8 +191,8 @@
}
#if defined(BN_ULLONG)
-#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
-#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
+#define Lw(t) ((BN_ULONG)(t))
+#define Hw(t) ((BN_ULONG)((t) >> BN_BITS2))
#endif
// bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
diff --git a/src/crypto/fipsmodule/bn/montgomery.c b/src/crypto/fipsmodule/bn/montgomery.c
index 8024e27..5219187 100644
--- a/src/crypto/fipsmodule/bn/montgomery.c
+++ b/src/crypto/fipsmodule/bn/montgomery.c
@@ -290,8 +290,8 @@
n0 = mont->n0[0];
for (carry = 0, i = 0; i < nl; i++, rp++) {
- v = bn_mul_add_words(rp, np, nl, (rp[0] * n0) & BN_MASK2);
- v = (v + carry + rp[nl]) & BN_MASK2;
+ v = bn_mul_add_words(rp, np, nl, rp[0] * n0);
+ v += carry + rp[nl];
carry |= (v != rp[nl]);
carry &= (v <= rp[nl]);
rp[nl] = v;
diff --git a/src/crypto/fipsmodule/bn/mul.c b/src/crypto/fipsmodule/bn/mul.c
index a4e27f2..b6f3ff1 100644
--- a/src/crypto/fipsmodule/bn/mul.c
+++ b/src/crypto/fipsmodule/bn/mul.c
@@ -141,7 +141,7 @@
if (dl < 0) {
for (;;) {
t = b[0];
- r[0] = (0 - t - c) & BN_MASK2;
+ r[0] = 0 - t - c;
if (t != 0) {
c = 1;
}
@@ -150,7 +150,7 @@
}
t = b[1];
- r[1] = (0 - t - c) & BN_MASK2;
+ r[1] = 0 - t - c;
if (t != 0) {
c = 1;
}
@@ -159,7 +159,7 @@
}
t = b[2];
- r[2] = (0 - t - c) & BN_MASK2;
+ r[2] = 0 - t - c;
if (t != 0) {
c = 1;
}
@@ -168,7 +168,7 @@
}
t = b[3];
- r[3] = (0 - t - c) & BN_MASK2;
+ r[3] = 0 - t - c;
if (t != 0) {
c = 1;
}
@@ -183,7 +183,7 @@
int save_dl = dl;
while (c) {
t = a[0];
- r[0] = (t - c) & BN_MASK2;
+ r[0] = t - c;
if (t != 0) {
c = 0;
}
@@ -192,7 +192,7 @@
}
t = a[1];
- r[1] = (t - c) & BN_MASK2;
+ r[1] = t - c;
if (t != 0) {
c = 0;
}
@@ -201,7 +201,7 @@
}
t = a[2];
- r[2] = (t - c) & BN_MASK2;
+ r[2] = t - c;
if (t != 0) {
c = 0;
}
@@ -210,7 +210,7 @@
}
t = a[3];
- r[3] = (t - c) & BN_MASK2;
+ r[3] = t - c;
if (t != 0) {
c = 0;
}
@@ -407,7 +407,7 @@
if (c1) {
p = &(r[n + n2]);
lo = *p;
- ln = (lo + c1) & BN_MASK2;
+ ln = lo + c1;
*p = ln;
// The overflow will stop before we over write
@@ -416,7 +416,7 @@
do {
p++;
lo = *p;
- ln = (lo + 1) & BN_MASK2;
+ ln = lo + 1;
*p = ln;
} while (ln == 0);
}
@@ -544,7 +544,7 @@
if (c1) {
p = &(r[n + n2]);
lo = *p;
- ln = (lo + c1) & BN_MASK2;
+ ln = lo + c1;
*p = ln;
// The overflow will stop before we over write
@@ -553,7 +553,7 @@
do {
p++;
lo = *p;
- ln = (lo + 1) & BN_MASK2;
+ ln = lo + 1;
*p = ln;
} while (ln == 0);
}
@@ -757,7 +757,7 @@
if (c1) {
p = &(r[n + n2]);
lo = *p;
- ln = (lo + c1) & BN_MASK2;
+ ln = lo + c1;
*p = ln;
// The overflow will stop before we over write
@@ -766,7 +766,7 @@
do {
p++;
lo = *p;
- ln = (lo + 1) & BN_MASK2;
+ ln = lo + 1;
*p = ln;
} while (ln == 0);
}
@@ -774,9 +774,6 @@
}
int BN_mul_word(BIGNUM *bn, BN_ULONG w) {
- BN_ULONG ll;
-
- w &= BN_MASK2;
if (!bn->top) {
return 1;
}
@@ -786,7 +783,7 @@
return 1;
}
- ll = bn_mul_words(bn->d, bn->d, bn->top, w);
+ BN_ULONG ll = bn_mul_words(bn->d, bn->d, bn->top, w);
if (ll) {
if (!bn_wexpand(bn, bn->top + 1)) {
return 0;
diff --git a/src/crypto/fipsmodule/bn/shift.c b/src/crypto/fipsmodule/bn/shift.c
index d3fcf39..64afa78 100644
--- a/src/crypto/fipsmodule/bn/shift.c
+++ b/src/crypto/fipsmodule/bn/shift.c
@@ -90,8 +90,8 @@
} else {
for (i = a->top - 1; i >= 0; i--) {
l = f[i];
- t[nw + i + 1] |= (l >> rb) & BN_MASK2;
- t[nw + i] = (l << lb) & BN_MASK2;
+ t[nw + i + 1] |= l >> rb;
+ t[nw + i] = l << lb;
}
}
OPENSSL_memset(t, 0, nw * sizeof(t[0]));
@@ -121,7 +121,7 @@
c = 0;
for (i = 0; i < a->top; i++) {
t = *(ap++);
- *(rp++) = ((t << 1) | c) & BN_MASK2;
+ *(rp++) = (t << 1) | c;
c = (t & BN_TBIT) ? 1 : 0;
}
if (c) {
@@ -173,11 +173,12 @@
} else {
l = *(f++);
for (i = j - 1; i != 0; i--) {
- tmp = (l >> rb) & BN_MASK2;
+ tmp = l >> rb;
l = *(f++);
- *(t++) = (tmp | (l << lb)) & BN_MASK2;
+ *(t++) = tmp | (l << lb);
}
- if ((l = (l >> rb) & BN_MASK2)) {
+ l >>= rb;
+ if (l) {
*(t) = l;
}
}
@@ -214,7 +215,7 @@
}
while (i > 0) {
t = ap[--i];
- rp[i] = ((t >> 1) & BN_MASK2) | c;
+ rp[i] = (t >> 1) | c;
c = (t & 1) ? BN_TBIT : 0;
}
r->top = j;
@@ -227,19 +228,17 @@
}
int BN_set_bit(BIGNUM *a, int n) {
- int i, j, k;
-
if (n < 0) {
return 0;
}
- i = n / BN_BITS2;
- j = n % BN_BITS2;
+ int i = n / BN_BITS2;
+ int j = n % BN_BITS2;
if (a->top <= i) {
if (!bn_wexpand(a, i + 1)) {
return 0;
}
- for (k = a->top; k < i + 1; k++) {
+ for (int k = a->top; k < i + 1; k++) {
a->d[k] = 0;
}
a->top = i + 1;
@@ -269,13 +268,11 @@
}
int BN_is_bit_set(const BIGNUM *a, int n) {
- int i, j;
-
if (n < 0) {
return 0;
}
- i = n / BN_BITS2;
- j = n % BN_BITS2;
+ int i = n / BN_BITS2;
+ int j = n % BN_BITS2;
if (a->top <= i) {
return 0;
}
@@ -284,14 +281,12 @@
}
int BN_mask_bits(BIGNUM *a, int n) {
- int b, w;
-
if (n < 0) {
return 0;
}
- w = n / BN_BITS2;
- b = n % BN_BITS2;
+ int w = n / BN_BITS2;
+ int b = n % BN_BITS2;
if (w >= a->top) {
return 0;
}
diff --git a/src/crypto/fipsmodule/ec/ec.c b/src/crypto/fipsmodule/ec/ec.c
index a39ca59..600aedc 100644
--- a/src/crypto/fipsmodule/ec/ec.c
+++ b/src/crypto/fipsmodule/ec/ec.c
@@ -80,6 +80,8 @@
#include "../delocate.h"
+static void ec_point_free(EC_POINT *point, int free_group);
+
static const uint8_t kP224Params[6 * 28] = {
// p
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -354,6 +356,7 @@
}
OPENSSL_memset(ret, 0, sizeof(EC_GROUP));
+ ret->references = 1;
ret->meth = meth;
BN_init(&ret->order);
@@ -365,6 +368,19 @@
return ret;
}
+static void ec_group_set0_generator(EC_GROUP *group, EC_POINT *generator) {
+ assert(group->generator == NULL);
+ assert(group == generator->group);
+
+ // Avoid a reference cycle. |group->generator| does not maintain an owning
+ // pointer to |group|.
+ group->generator = generator;
+ int is_zero = CRYPTO_refcount_dec_and_test_zero(&group->references);
+
+ assert(!is_zero);
+ (void)is_zero;
+}
+
EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx) {
EC_GROUP *ret = ec_group_new(EC_GFp_mont_method());
@@ -372,9 +388,10 @@
return NULL;
}
- if (ret->meth->group_set_curve == 0) {
+ if (ret->meth->group_set_curve == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
+ EC_GROUP_free(ret);
+ return NULL;
}
if (!ret->meth->group_set_curve(ret, p, a, b, ctx)) {
EC_GROUP_free(ret);
@@ -385,9 +402,13 @@
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor) {
- if (group->curve_name != NID_undef || group->generator != NULL) {
+ if (group->curve_name != NID_undef || group->generator != NULL ||
+ generator->group != group) {
// |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
// |EC_GROUP_new_curve_GFp| and may only used once on each group.
+ // Additionally, |generator| must been created from
+ // |EC_GROUP_new_curve_GFp|, not a copy, so that
+ // |generator->group->generator| is set correctly.
return 0;
}
@@ -397,10 +418,16 @@
return 0;
}
- group->generator = EC_POINT_new(group);
- return group->generator != NULL &&
- EC_POINT_copy(group->generator, generator) &&
- BN_copy(&group->order, order);
+ EC_POINT *copy = EC_POINT_new(group);
+ if (copy == NULL ||
+ !EC_POINT_copy(copy, generator) ||
+ !BN_copy(&group->order, order)) {
+ EC_POINT_free(copy);
+ return 0;
+ }
+
+ ec_group_set0_generator(group, copy);
+ return 1;
}
static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) {
@@ -459,7 +486,7 @@
group->order_mont = monts[built_in_index];
}
- group->generator = P;
+ ec_group_set0_generator(group, P);
P = NULL;
ok = 1;
@@ -500,15 +527,16 @@
}
void EC_GROUP_free(EC_GROUP *group) {
- if (!group) {
+ if (group == NULL ||
+ !CRYPTO_refcount_dec_and_test_zero(&group->references)) {
return;
}
- if (group->meth->group_finish != 0) {
+ if (group->meth->group_finish != NULL) {
group->meth->group_finish(group);
}
- EC_POINT_free(group->generator);
+ ec_point_free(group->generator, 0 /* don't free group */);
BN_free(&group->order);
OPENSSL_free(group);
@@ -523,42 +551,37 @@
return NULL;
}
- if (a->meth->group_copy == NULL) {
- OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return NULL;
- }
-
- EC_GROUP *ret = ec_group_new(a->meth);
- if (ret == NULL) {
- return NULL;
- }
-
- ret->order_mont = a->order_mont;
- ret->curve_name = a->curve_name;
-
- if (a->generator != NULL) {
- ret->generator = EC_POINT_dup(a->generator, ret);
- if (ret->generator == NULL) {
- goto err;
- }
- }
-
- if (!BN_copy(&ret->order, &a->order) ||
- !ret->meth->group_copy(ret, a)) {
- goto err;
- }
-
- return ret;
-
-err:
- EC_GROUP_free(ret);
- return NULL;
+ // Groups are logically immutable (but for |EC_GROUP_set_generator| which must
+ // be called early on), so we simply take a reference.
+ EC_GROUP *group = (EC_GROUP *)a;
+ CRYPTO_refcount_inc(&group->references);
+ return group;
}
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
- return a->curve_name == NID_undef ||
- b->curve_name == NID_undef ||
- a->curve_name != b->curve_name;
+ // Note this function returns 0 if equal and non-zero otherwise.
+ if (a == b) {
+ return 0;
+ }
+ if (a->curve_name != b->curve_name) {
+ return 1;
+ }
+ if (a->curve_name != NID_undef) {
+ // Built-in curves may be compared by curve name alone.
+ return 0;
+ }
+
+ // |a| and |b| are both custom curves. We compare the entire curve
+ // structure. If |a| or |b| is incomplete (due to legacy OpenSSL mistakes,
+ // custom curve construction is sadly done in two parts) but otherwise not the
+ // same object, we consider them always unequal.
+ return a->generator == NULL ||
+ b->generator == NULL ||
+ BN_cmp(&a->order, &b->order) != 0 ||
+ BN_cmp(&a->field, &b->field) != 0 ||
+ BN_cmp(&a->a, &b->a) != 0 ||
+ BN_cmp(&a->b, &b->b) != 0 ||
+ ec_GFp_simple_cmp(a, a->generator, b->generator, NULL) != 0;
}
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group) {
@@ -608,9 +631,9 @@
return NULL;
}
- ret->meth = group->meth;
-
- if (!ec_GFp_simple_point_init(ret)) {
+ ret->group = EC_GROUP_dup(group);
+ if (ret->group == NULL ||
+ !ec_GFp_simple_point_init(ret)) {
OPENSSL_free(ret);
return NULL;
}
@@ -618,28 +641,25 @@
return ret;
}
-void EC_POINT_free(EC_POINT *point) {
+static void ec_point_free(EC_POINT *point, int free_group) {
if (!point) {
return;
}
-
ec_GFp_simple_point_finish(point);
-
- OPENSSL_free(point);
-}
-
-void EC_POINT_clear_free(EC_POINT *point) {
- if (!point) {
- return;
+ if (free_group) {
+ EC_GROUP_free(point->group);
}
-
- ec_GFp_simple_point_clear_finish(point);
-
OPENSSL_free(point);
}
+void EC_POINT_free(EC_POINT *point) {
+ ec_point_free(point, 1 /* free group */);
+}
+
+void EC_POINT_clear_free(EC_POINT *point) { EC_POINT_free(point); }
+
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src) {
- if (dest->meth != src->meth) {
+ if (EC_GROUP_cmp(dest->group, src->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -665,7 +685,7 @@
}
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -673,7 +693,7 @@
}
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -682,7 +702,7 @@
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -691,7 +711,8 @@
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx) {
- if ((group->meth != a->meth) || (a->meth != b->meth)) {
+ if (EC_GROUP_cmp(group, a->group, NULL) != 0 ||
+ EC_GROUP_cmp(group, b->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return -1;
}
@@ -699,7 +720,7 @@
}
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -709,7 +730,7 @@
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
BN_CTX *ctx) {
for (size_t i = 0; i < num; i++) {
- if (group->meth != points[i]->meth) {
+ if (EC_GROUP_cmp(group, points[i]->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -724,7 +745,7 @@
OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -734,7 +755,7 @@
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -752,8 +773,9 @@
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx) {
- if ((group->meth != r->meth) || (r->meth != a->meth) ||
- (a->meth != b->meth)) {
+ if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
+ EC_GROUP_cmp(group, a->group, NULL) != 0 ||
+ EC_GROUP_cmp(group, b->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -763,7 +785,8 @@
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx) {
- if ((group->meth != r->meth) || (r->meth != a->meth)) {
+ if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
+ EC_GROUP_cmp(group, a->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -772,7 +795,7 @@
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx) {
- if (group->meth != a->meth) {
+ if (EC_GROUP_cmp(group, a->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -790,8 +813,8 @@
return 0;
}
- if (group->meth != r->meth ||
- (p != NULL && group->meth != p->meth)) {
+ if (EC_GROUP_cmp(group, r->group, NULL) != 0 ||
+ (p != NULL && EC_GROUP_cmp(group, p->group, NULL) != 0)) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -803,7 +826,7 @@
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
diff --git a/src/crypto/fipsmodule/ec/ec_montgomery.c b/src/crypto/fipsmodule/ec/ec_montgomery.c
index c5f240b..6670b84 100644
--- a/src/crypto/fipsmodule/ec/ec_montgomery.c
+++ b/src/crypto/fipsmodule/ec/ec_montgomery.c
@@ -90,32 +90,6 @@
ec_GFp_simple_group_finish(group);
}
-int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
- BN_MONT_CTX_free(dest->mont);
- dest->mont = NULL;
-
- if (!ec_GFp_simple_group_copy(dest, src)) {
- return 0;
- }
-
- if (src->mont != NULL) {
- dest->mont = BN_MONT_CTX_new();
- if (dest->mont == NULL) {
- return 0;
- }
- if (!BN_MONT_CTX_copy(dest->mont, src->mont)) {
- goto err;
- }
- }
-
- return 1;
-
-err:
- BN_MONT_CTX_free(dest->mont);
- dest->mont = NULL;
- return 0;
-}
-
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
BN_CTX *new_ctx = NULL;
@@ -293,7 +267,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) {
out->group_init = ec_GFp_mont_group_init;
out->group_finish = ec_GFp_mont_group_finish;
- out->group_copy = ec_GFp_mont_group_copy;
out->group_set_curve = ec_GFp_mont_group_set_curve;
out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates;
out->mul = ec_wNAF_mul /* XXX: Not constant time. */;
diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc
index 48b60ee..0ee7378 100644
--- a/src/crypto/fipsmodule/ec/ec_test.cc
+++ b/src/crypto/fipsmodule/ec/ec_test.cc
@@ -276,6 +276,33 @@
// The key must be valid according to the new group too.
EXPECT_TRUE(EC_KEY_check_key(key2.get()));
+
+ // Make a second instance of |group|.
+ bssl::UniquePtr<EC_GROUP> group2(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
+ ASSERT_TRUE(group2);
+ bssl::UniquePtr<EC_POINT> generator2(EC_POINT_new(group2.get()));
+ ASSERT_TRUE(generator2);
+ ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
+ group2.get(), generator2.get(), gx.get(), gy.get(), ctx.get()));
+ ASSERT_TRUE(EC_GROUP_set_generator(group2.get(), generator2.get(),
+ order.get(), BN_value_one()));
+
+ EXPECT_EQ(0, EC_GROUP_cmp(group.get(), group.get(), NULL));
+ EXPECT_EQ(0, EC_GROUP_cmp(group2.get(), group.get(), NULL));
+
+ // group3 uses the wrong generator.
+ bssl::UniquePtr<EC_GROUP> group3(
+ EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
+ ASSERT_TRUE(group3);
+ bssl::UniquePtr<EC_POINT> generator3(EC_POINT_new(group3.get()));
+ ASSERT_TRUE(generator3);
+ ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
+ group3.get(), generator3.get(), x.get(), y.get(), ctx.get()));
+ ASSERT_TRUE(EC_GROUP_set_generator(group3.get(), generator3.get(),
+ order.get(), BN_value_one()));
+
+ EXPECT_NE(0, EC_GROUP_cmp(group.get(), group3.get(), NULL));
}
class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
diff --git a/src/crypto/fipsmodule/ec/internal.h b/src/crypto/fipsmodule/ec/internal.h
index 39c9349..f065744 100644
--- a/src/crypto/fipsmodule/ec/internal.h
+++ b/src/crypto/fipsmodule/ec/internal.h
@@ -82,7 +82,6 @@
struct ec_method_st {
int (*group_init)(EC_GROUP *);
void (*group_finish)(EC_GROUP *);
- int (*group_copy)(EC_GROUP *, const EC_GROUP *);
int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
@@ -114,6 +113,8 @@
struct ec_group_st {
const EC_METHOD *meth;
+ // Unlike all other |EC_POINT|s, |generator| does not own |generator->group|
+ // to avoid a reference cycle.
EC_POINT *generator;
BIGNUM order;
@@ -130,13 +131,17 @@
int a_is_minus3; // enable optimized point arithmetics for special case
+ CRYPTO_refcount_t references;
+
BN_MONT_CTX *mont; // Montgomery structure.
BIGNUM one; // The value one.
} /* EC_GROUP */;
struct ec_point_st {
- const EC_METHOD *meth;
+ // group is an owning reference to |group|, unless this is
+ // |group->generator|.
+ EC_GROUP *group;
BIGNUM X;
BIGNUM Y;
@@ -145,7 +150,6 @@
} /* EC_POINT */;
EC_GROUP *ec_group_new(const EC_METHOD *meth);
-int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src);
// ec_group_get_order_mont returns a Montgomery context for operations modulo
// |group|'s order. It may return NULL in the case that |group| is not a
@@ -158,7 +162,6 @@
// method functions in simple.c
int ec_GFp_simple_group_init(EC_GROUP *);
void ec_GFp_simple_group_finish(EC_GROUP *);
-int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
@@ -166,7 +169,6 @@
unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *);
int ec_GFp_simple_point_init(EC_POINT *);
void ec_GFp_simple_point_finish(EC_POINT *);
-void ec_GFp_simple_point_clear_finish(EC_POINT *);
int ec_GFp_simple_point_copy(EC_POINT *, const EC_POINT *);
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *, EC_POINT *);
int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *, EC_POINT *,
@@ -205,7 +207,6 @@
int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
void ec_GFp_mont_group_finish(EC_GROUP *);
-int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_mont_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
diff --git a/src/crypto/fipsmodule/ec/oct.c b/src/crypto/fipsmodule/ec/oct.c
index cf51e4b..7d62395 100644
--- a/src/crypto/fipsmodule/ec/oct.c
+++ b/src/crypto/fipsmodule/ec/oct.c
@@ -251,7 +251,7 @@
int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
const uint8_t *buf, size_t len, BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -261,7 +261,7 @@
size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form, uint8_t *buf,
size_t len, BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
@@ -396,7 +396,7 @@
int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx) {
- if (group->meth != point->meth) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
diff --git a/src/crypto/fipsmodule/ec/p224-64.c b/src/crypto/fipsmodule/ec/p224-64.c
index ec5a93d..26a94b9 100644
--- a/src/crypto/fipsmodule/ec/p224-64.c
+++ b/src/crypto/fipsmodule/ec/p224-64.c
@@ -1151,7 +1151,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
out->group_init = ec_GFp_simple_group_init;
out->group_finish = ec_GFp_simple_group_finish;
- out->group_copy = ec_GFp_simple_group_copy;
out->group_set_curve = ec_GFp_simple_group_set_curve;
out->point_get_affine_coordinates =
ec_GFp_nistp224_point_get_affine_coordinates;
diff --git a/src/crypto/fipsmodule/ec/p256-64.c b/src/crypto/fipsmodule/ec/p256-64.c
index f7d1ff1..04ae56b 100644
--- a/src/crypto/fipsmodule/ec/p256-64.c
+++ b/src/crypto/fipsmodule/ec/p256-64.c
@@ -1694,7 +1694,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) {
out->group_init = ec_GFp_simple_group_init;
out->group_finish = ec_GFp_simple_group_finish;
- out->group_copy = ec_GFp_simple_group_copy;
out->group_set_curve = ec_GFp_simple_group_set_curve;
out->point_get_affine_coordinates =
ec_GFp_nistp256_point_get_affine_coordinates;
diff --git a/src/crypto/fipsmodule/ec/p256-x86_64.c b/src/crypto/fipsmodule/ec/p256-x86_64.c
index 8b51677..0004add 100644
--- a/src/crypto/fipsmodule/ec/p256-x86_64.c
+++ b/src/crypto/fipsmodule/ec/p256-x86_64.c
@@ -547,7 +547,6 @@
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) {
out->group_init = ec_GFp_mont_group_init;
out->group_finish = ec_GFp_mont_group_finish;
- out->group_copy = ec_GFp_mont_group_copy;
out->group_set_curve = ec_GFp_mont_group_set_curve;
out->point_get_affine_coordinates = ecp_nistz256_get_affine;
out->mul = ecp_nistz256_points_mul;
diff --git a/src/crypto/fipsmodule/ec/simple.c b/src/crypto/fipsmodule/ec/simple.c
index 75c06da..f7faa45 100644
--- a/src/crypto/fipsmodule/ec/simple.c
+++ b/src/crypto/fipsmodule/ec/simple.c
@@ -104,18 +104,6 @@
BN_free(&group->one);
}
-int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
- if (!BN_copy(&dest->field, &src->field) ||
- !BN_copy(&dest->a, &src->a) ||
- !BN_copy(&dest->b, &src->b) ||
- !BN_copy(&dest->one, &src->one)) {
- return 0;
- }
-
- dest->a_is_minus3 = src->a_is_minus3;
- return 1;
-}
-
int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx) {
@@ -249,12 +237,6 @@
BN_free(&point->Z);
}
-void ec_GFp_simple_point_clear_finish(EC_POINT *point) {
- BN_clear_free(&point->X);
- BN_clear_free(&point->Y);
- BN_clear_free(&point->Z);
-}
-
int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
if (!BN_copy(&dest->X, &src->X) ||
!BN_copy(&dest->Y, &src->Y) ||
@@ -814,11 +796,11 @@
const BIGNUM *tmp1_, *tmp2_;
int ret = -1;
- if (EC_POINT_is_at_infinity(group, a)) {
- return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
+ if (ec_GFp_simple_is_at_infinity(group, a)) {
+ return ec_GFp_simple_is_at_infinity(group, b) ? 0 : 1;
}
- if (EC_POINT_is_at_infinity(group, b)) {
+ if (ec_GFp_simple_is_at_infinity(group, b)) {
return 1;
}
diff --git a/src/crypto/fipsmodule/ec/wnaf.c b/src/crypto/fipsmodule/ec/wnaf.c
index 0e3ee13..842a8fb 100644
--- a/src/crypto/fipsmodule/ec/wnaf.c
+++ b/src/crypto/fipsmodule/ec/wnaf.c
@@ -446,7 +446,7 @@
}
if (val != NULL) {
for (i = 0; i < num_val; i++) {
- EC_POINT_clear_free(val[i]);
+ EC_POINT_free(val[i]);
}
OPENSSL_free(val);
diff --git a/src/crypto/lhash/lhash.c b/src/crypto/lhash/lhash.c
index 5054529..7bfd289 100644
--- a/src/crypto/lhash/lhash.c
+++ b/src/crypto/lhash/lhash.c
@@ -73,6 +73,25 @@
static const size_t kMaxAverageChainLength = 2;
static const size_t kMinAverageChainLength = 1;
+struct lhash_st {
+ // num_items contains the total number of items in the hash table.
+ size_t num_items;
+ // buckets is an array of |num_buckets| pointers. Each points to the head of
+ // a chain of LHASH_ITEM objects that have the same hash value, mod
+ // |num_buckets|.
+ LHASH_ITEM **buckets;
+ // num_buckets contains the length of |buckets|. This value is always >=
+ // kMinNumBuckets.
+ size_t num_buckets;
+ // callback_depth contains the current depth of |lh_doall| or |lh_doall_arg|
+ // calls. If non-zero then this suppresses resizing of the |buckets| array,
+ // which would otherwise disrupt the iteration.
+ unsigned callback_depth;
+
+ lhash_cmp_func comp;
+ lhash_hash_func hash;
+};
+
_LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp) {
_LHASH *ret = OPENSSL_malloc(sizeof(_LHASH));
if (ret == NULL) {
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index afa39d7..8f89096 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -764,13 +764,13 @@
int PEM_def_callback(char *buf, int size, int rwflag, void *userdata)
{
- if (!buf || !userdata) {
+ if (!buf || !userdata || size < 0) {
return 0;
}
size_t len = strlen((char *)userdata);
if (len >= (size_t)size) {
return 0;
}
- strcpy(buf, (char *)userdata);
+ BUF_strlcpy(buf, userdata, (size_t)size);
return len;
}
diff --git a/src/crypto/rsa_extra/rsa_asn1.c b/src/crypto/rsa_extra/rsa_asn1.c
index 23c91bd..3cc6a9c 100644
--- a/src/crypto/rsa_extra/rsa_asn1.c
+++ b/src/crypto/rsa_extra/rsa_asn1.c
@@ -69,22 +69,15 @@
#include "../internal.h"
-static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) {
+static int parse_integer(CBS *cbs, BIGNUM **out) {
assert(*out == NULL);
*out = BN_new();
if (*out == NULL) {
return 0;
}
- if (buggy) {
- return BN_parse_asn1_unsigned_buggy(cbs, *out);
- }
return BN_parse_asn1_unsigned(cbs, *out);
}
-static int parse_integer(CBS *cbs, BIGNUM **out) {
- return parse_integer_buggy(cbs, out, 0 /* not buggy */);
-}
-
static int marshal_integer(CBB *cbb, BIGNUM *bn) {
if (bn == NULL) {
// An RSA object may be missing some components.
@@ -94,14 +87,14 @@
return BN_marshal_asn1(cbb, bn);
}
-static RSA *parse_public_key(CBS *cbs, int buggy) {
+RSA *RSA_parse_public_key(CBS *cbs) {
RSA *ret = RSA_new();
if (ret == NULL) {
return NULL;
}
CBS child;
if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
- !parse_integer_buggy(&child, &ret->n, buggy) ||
+ !parse_integer(&child, &ret->n) ||
!parse_integer(&child, &ret->e) ||
CBS_len(&child) != 0) {
OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_ENCODING);
@@ -119,18 +112,6 @@
return ret;
}
-RSA *RSA_parse_public_key(CBS *cbs) {
- return parse_public_key(cbs, 0 /* not buggy */);
-}
-
-RSA *RSA_parse_public_key_buggy(CBS *cbs) {
- // Estonian IDs issued between September 2014 to September 2015 are
- // broken. See https://crbug.com/532048 and https://crbug.com/534766.
- //
- // TODO(davidben): Remove this code and callers in March 2016.
- return parse_public_key(cbs, 1 /* buggy */);
-}
-
RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len) {
CBS cbs;
CBS_init(&cbs, in, in_len);
diff --git a/src/crypto/rsa_extra/rsa_test.cc b/src/crypto/rsa_extra/rsa_test.cc
index 1cc71ea..23e8c67 100644
--- a/src/crypto/rsa_extra/rsa_test.cc
+++ b/src/crypto/rsa_extra/rsa_test.cc
@@ -622,13 +622,6 @@
sizeof(kEstonianRSAKey)));
EXPECT_FALSE(rsa);
ERR_clear_error();
-
- // But |RSA_parse_public_key_buggy| will accept it.
- CBS cbs;
- CBS_init(&cbs, kEstonianRSAKey, sizeof(kEstonianRSAKey));
- rsa.reset(RSA_parse_public_key_buggy(&cbs));
- EXPECT_TRUE(rsa);
- EXPECT_EQ(0u, CBS_len(&cbs));
}
TEST(RSATest, BadExponent) {
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
index d72f9ec..635b851 100644
--- a/src/crypto/x509/by_dir.c
+++ b/src/crypto/x509/by_dir.c
@@ -61,7 +61,6 @@
#include <openssl/buf.h>
#include <openssl/err.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include <openssl/x509.h>
@@ -235,8 +234,7 @@
by_dir_entry_free(ent);
return 0;
}
- strncpy(ent->dir, ss, len);
- ent->dir[len] = '\0';
+ BUF_strlcpy(ent->dir, ss, len + 1);
if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
by_dir_entry_free(ent);
return 0;
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 2bec572..555cb85 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -59,7 +59,6 @@
#include <openssl/buf.h>
#include <openssl/err.h>
-#include <openssl/lhash.h>
#include <openssl/pem.h>
#include <openssl/thread.h>
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index 1014a05..1a841db 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -58,7 +58,6 @@
#include <string.h>
#include <openssl/err.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/thread.h>
#include <openssl/x509.h>
diff --git a/src/crypto/x509/x509_obj.c b/src/crypto/x509/x509_obj.c
index 33eafc4..65b1bfb 100644
--- a/src/crypto/x509/x509_obj.c
+++ b/src/crypto/x509/x509_obj.c
@@ -59,7 +59,6 @@
#include <openssl/buf.h>
#include <openssl/err.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/x509.h>
@@ -102,8 +101,7 @@
buf = b->data;
OPENSSL_free(b);
}
- strncpy(buf, "NO X509_NAME", len);
- buf[len - 1] = '\0';
+ BUF_strlcpy(buf, "NO X509_NAME", len);
return buf;
}
diff --git a/src/crypto/x509/x509_txt.c b/src/crypto/x509/x509_txt.c
index 17e6cdb..753e720 100644
--- a/src/crypto/x509/x509_txt.c
+++ b/src/crypto/x509/x509_txt.c
@@ -54,13 +54,7 @@
* copied and put under another distribution licence
* [including the GNU Public Licence.] */
-#include <openssl/asn1.h>
-#include <openssl/buf.h>
-#include <openssl/cipher.h>
-#include <openssl/evp.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
-#include <openssl/obj.h>
#include <openssl/x509.h>
const char *X509_verify_cert_error_string(long n)
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index 8e258fe..aff2ee9 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -61,7 +61,6 @@
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/evp.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/thread.h>
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
index 2317214..d0f8f79 100644
--- a/src/crypto/x509/x509_vpm.c
+++ b/src/crypto/x509/x509_vpm.c
@@ -57,7 +57,6 @@
#include <string.h>
#include <openssl/buf.h>
-#include <openssl/lhash.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
index 6280651..b78a410 100644
--- a/src/crypto/x509v3/v3_alt.c
+++ b/src/crypto/x509v3/v3_alt.c
@@ -166,9 +166,9 @@
for (i = 0; i < 8; i++) {
BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]);
p += 2;
- strcat(oline, htmp);
+ BUF_strlcat(oline, htmp, sizeof(oline));
if (i != 7)
- strcat(oline, ":");
+ BUF_strlcat(oline, ":", sizeof(oline));
}
} else {
if (!X509V3_add_value("IP Address", "<invalid>", &ret))
@@ -588,8 +588,7 @@
objtmp = OPENSSL_malloc(objlen + 1);
if (objtmp == NULL)
return 0;
- strncpy(objtmp, value, objlen);
- objtmp[objlen] = 0;
+ BUF_strlcpy(objtmp, value, objlen + 1);
gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
OPENSSL_free(objtmp);
if (!gen->d.otherName->type_id)
diff --git a/src/crypto/x509v3/v3_genn.c b/src/crypto/x509v3/v3_genn.c
index 2331cd4..8c92687 100644
--- a/src/crypto/x509v3/v3_genn.c
+++ b/src/crypto/x509v3/v3_genn.c
@@ -231,6 +231,7 @@
oth = OTHERNAME_new();
if (!oth)
return 0;
+ ASN1_TYPE_free(oth->value);
oth->type_id = oid;
oth->value = value;
GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
diff --git a/src/crypto/x509v3/v3_info.c b/src/crypto/x509v3/v3_info.c
index 40f451f..ff96489 100644
--- a/src/crypto/x509v3/v3_info.c
+++ b/src/crypto/x509v3/v3_info.c
@@ -192,8 +192,7 @@
OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
goto err;
}
- strncpy(objtmp, cnf->name, objlen);
- objtmp[objlen] = 0;
+ BUF_strlcpy(objtmp, cnf->name, objlen + 1);
acc->method = OBJ_txt2obj(objtmp, 0);
if (!acc->method) {
OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index 52333ac..9960b75 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -317,10 +317,6 @@
// the result to |ret|. It returns one on success and zero on failure.
OPENSSL_EXPORT int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret);
-// BN_parse_asn1_unsigned_buggy acts like |BN_parse_asn1_unsigned| but tolerates
-// some invalid encodings. Do not use this function.
-OPENSSL_EXPORT int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret);
-
// BN_marshal_asn1 marshals |bn| as a non-negative DER INTEGER and appends the
// result to |cbb|. It returns one on success and zero on failure.
OPENSSL_EXPORT int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn);
diff --git a/src/include/openssl/ec.h b/src/include/openssl/ec.h
index 4a08a9b..dee41b7 100644
--- a/src/include/openssl/ec.h
+++ b/src/include/openssl/ec.h
@@ -162,10 +162,6 @@
// EC_POINT_free frees |point| and the data that it points to.
OPENSSL_EXPORT void EC_POINT_free(EC_POINT *point);
-// EC_POINT_clear_free clears the data that |point| points to, frees it and
-// then frees |point| itself.
-OPENSSL_EXPORT void EC_POINT_clear_free(EC_POINT *point);
-
// EC_POINT_copy sets |*dest| equal to |*src|. It returns one on success and
// zero otherwise.
OPENSSL_EXPORT int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src);
@@ -306,7 +302,7 @@
// EC_GROUP_set_generator sets the generator for |group| to |generator|, which
// must have the given order and cofactor. It may only be used with |EC_GROUP|
// objects returned by |EC_GROUP_new_curve_GFp| and may only be used once on
-// each group.
+// each group. |generator| must have been created using |group|.
OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group,
const EC_POINT *generator,
const BIGNUM *order,
@@ -350,6 +346,9 @@
OPENSSL_EXPORT size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
size_t max_num_curves);
+// EC_POINT_clear_free calls |EC_POINT_free|.
+OPENSSL_EXPORT void EC_POINT_clear_free(EC_POINT *point);
+
// Old code expects to get EC_KEY from ec.h.
#include <openssl/ec_key.h>
diff --git a/src/include/openssl/evp.h b/src/include/openssl/evp.h
index c57d7c7..f5eb200 100644
--- a/src/include/openssl/evp.h
+++ b/src/include/openssl/evp.h
@@ -225,10 +225,6 @@
// success and zero on error.
OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key);
-// EVP_set_buggy_rsa_parser configures whether |RSA_parse_public_key_buggy| is
-// used by |EVP_parse_public_key|. By default, it is not used.
-OPENSSL_EXPORT void EVP_set_buggy_rsa_parser(int buggy);
-
// Signing
diff --git a/src/include/openssl/lhash.h b/src/include/openssl/lhash.h
index 7525c08..1ceeb69 100644
--- a/src/include/openssl/lhash.h
+++ b/src/include/openssl/lhash.h
@@ -125,24 +125,7 @@
// uint32_t.
typedef uint32_t (*lhash_hash_func)(const void *a);
-typedef struct lhash_st {
- // num_items contains the total number of items in the hash table.
- size_t num_items;
- // buckets is an array of |num_buckets| pointers. Each points to the head of
- // a chain of LHASH_ITEM objects that have the same hash value, mod
- // |num_buckets|.
- LHASH_ITEM **buckets;
- // num_buckets contains the length of |buckets|. This value is always >=
- // kMinNumBuckets.
- size_t num_buckets;
- // callback_depth contains the current depth of |lh_doall| or |lh_doall_arg|
- // calls. If non-zero then this suppresses resizing of the |buckets| array,
- // which would otherwise disrupt the iteration.
- unsigned callback_depth;
-
- lhash_cmp_func comp;
- lhash_hash_func hash;
-} _LHASH;
+typedef struct lhash_st _LHASH;
// lh_new returns a new, empty hash table or NULL on error.
OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp);
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index 3f45318..74268cf 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -428,10 +428,6 @@
// error.
OPENSSL_EXPORT RSA *RSA_parse_public_key(CBS *cbs);
-// RSA_parse_public_key_buggy behaves like |RSA_parse_public_key|, but it
-// tolerates some invalid encodings. Do not use this function.
-OPENSSL_EXPORT RSA *RSA_parse_public_key_buggy(CBS *cbs);
-
// RSA_public_key_from_bytes parses |in| as a DER-encoded RSAPublicKey structure
// (RFC 3447). It returns a newly-allocated |RSA| or NULL on error.
OPENSSL_EXPORT RSA *RSA_public_key_from_bytes(const uint8_t *in, size_t in_len);
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
index 991cbda..208a380 100644
--- a/src/include/openssl/x509_vfy.h
+++ b/src/include/openssl/x509_vfy.h
@@ -64,8 +64,6 @@
#ifndef HEADER_X509_VFY_H
#define HEADER_X509_VFY_H
-#include <openssl/bio.h>
-#include <openssl/lhash.h>
#include <openssl/thread.h>
#ifdef __cplusplus
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index dd56bbc..abd52c0 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -57,6 +57,7 @@
#include <openssl/bio.h>
#include <openssl/conf.h>
+#include <openssl/lhash.h>
#include <openssl/x509.h>
#ifdef __cplusplus
diff --git a/src/ssl/d1_both.cc b/src/ssl/d1_both.cc
index 798deb0..c219f5a 100644
--- a/src/ssl/d1_both.cc
+++ b/src/ssl/d1_both.cc
@@ -144,23 +144,18 @@
// Receiving handshake messages.
-static void dtls1_hm_fragment_free(hm_fragment *frag) {
- if (frag == NULL) {
- return;
- }
- OPENSSL_free(frag->data);
- OPENSSL_free(frag->reassembly);
- OPENSSL_free(frag);
+hm_fragment::~hm_fragment() {
+ OPENSSL_free(data);
+ OPENSSL_free(reassembly);
}
-static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) {
+static UniquePtr<hm_fragment> dtls1_hm_fragment_new(
+ const struct hm_header_st *msg_hdr) {
ScopedCBB cbb;
- hm_fragment *frag = (hm_fragment *)OPENSSL_malloc(sizeof(hm_fragment));
- if (frag == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return NULL;
+ UniquePtr<hm_fragment> frag = MakeUnique<hm_fragment>();
+ if (!frag) {
+ return nullptr;
}
- OPENSSL_memset(frag, 0, sizeof(hm_fragment));
frag->type = msg_hdr->type;
frag->seq = msg_hdr->seq;
frag->msg_len = msg_hdr->msg_len;
@@ -170,7 +165,7 @@
(uint8_t *)OPENSSL_malloc(DTLS1_HM_HEADER_LENGTH + msg_hdr->msg_len);
if (frag->data == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
if (!CBB_init_fixed(cbb.get(), frag->data, DTLS1_HM_HEADER_LENGTH) ||
@@ -181,7 +176,7 @@
!CBB_add_u24(cbb.get(), msg_hdr->msg_len) ||
!CBB_finish(cbb.get(), NULL, NULL)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
// If the handshake message is empty, |frag->reassembly| is NULL.
@@ -189,22 +184,18 @@
// Initialize reassembly bitmask.
if (msg_hdr->msg_len + 7 < msg_hdr->msg_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
- goto err;
+ return nullptr;
}
size_t bitmask_len = (msg_hdr->msg_len + 7) / 8;
frag->reassembly = (uint8_t *)OPENSSL_malloc(bitmask_len);
if (frag->reassembly == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
+ return nullptr;
}
OPENSSL_memset(frag->reassembly, 0, bitmask_len);
}
return frag;
-
-err:
- dtls1_hm_fragment_free(frag);
- return NULL;
}
// bit_range returns a |uint8_t| with bits |start|, inclusive, to |end|,
@@ -262,8 +253,8 @@
// dtls1_is_current_message_complete returns whether the current handshake
// message is complete.
static bool dtls1_is_current_message_complete(const SSL *ssl) {
- hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
- SSL_MAX_HANDSHAKE_FLIGHT];
+ size_t idx = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
+ hm_fragment *frag = ssl->d1->incoming_messages[idx].get();
return frag != NULL && frag->reassembly == NULL;
}
@@ -280,7 +271,7 @@
}
size_t idx = msg_hdr->seq % SSL_MAX_HANDSHAKE_FLIGHT;
- hm_fragment *frag = ssl->d1->incoming_messages[idx];
+ hm_fragment *frag = ssl->d1->incoming_messages[idx].get();
if (frag != NULL) {
assert(frag->seq == msg_hdr->seq);
// The new fragment must be compatible with the previous fragments from this
@@ -295,13 +286,12 @@
}
// This is the first fragment from this message.
- frag = dtls1_hm_fragment_new(msg_hdr);
- if (frag == NULL) {
+ ssl->d1->incoming_messages[idx] = dtls1_hm_fragment_new(msg_hdr);
+ if (!ssl->d1->incoming_messages[idx]) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return NULL;
}
- ssl->d1->incoming_messages[idx] = frag;
- return frag;
+ return ssl->d1->incoming_messages[idx].get();
}
ssl_open_record_t dtls1_open_handshake(SSL *ssl, size_t *out_consumed,
@@ -420,8 +410,8 @@
return false;
}
- hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
- SSL_MAX_HANDSHAKE_FLIGHT];
+ size_t idx = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
+ hm_fragment *frag = ssl->d1->incoming_messages[idx].get();
out->type = frag->type;
CBS_init(&out->body, frag->data + DTLS1_HM_HEADER_LENGTH, frag->msg_len);
CBS_init(&out->raw, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len);
@@ -437,8 +427,7 @@
assert(ssl->s3->has_message);
assert(dtls1_is_current_message_complete(ssl));
size_t index = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
- dtls1_hm_fragment_free(ssl->d1->incoming_messages[index]);
- ssl->d1->incoming_messages[index] = NULL;
+ ssl->d1->incoming_messages[index].reset();
ssl->d1->handshake_read_seq++;
ssl->s3->has_message = false;
// If we previously sent a flight, mark it as having a reply, so
@@ -448,13 +437,6 @@
}
}
-void dtls_clear_incoming_messages(SSL *ssl) {
- for (size_t i = 0; i < SSL_MAX_HANDSHAKE_FLIGHT; i++) {
- dtls1_hm_fragment_free(ssl->d1->incoming_messages[i]);
- ssl->d1->incoming_messages[i] = NULL;
- }
-}
-
bool dtls_has_unprocessed_handshake_data(const SSL *ssl) {
if (ssl->d1->has_change_cipher_spec) {
return true;
@@ -467,7 +449,7 @@
assert(dtls1_is_current_message_complete(ssl));
continue;
}
- if (ssl->d1->incoming_messages[i] != NULL) {
+ if (ssl->d1->incoming_messages[i] != nullptr) {
return true;
}
}
@@ -510,10 +492,14 @@
// Sending handshake messages.
+void DTLS_OUTGOING_MESSAGE::Clear() {
+ OPENSSL_free(data);
+ data = nullptr;
+}
+
void dtls_clear_outgoing_messages(SSL *ssl) {
for (size_t i = 0; i < ssl->d1->outgoing_messages_len; i++) {
- OPENSSL_free(ssl->d1->outgoing_messages[i].data);
- ssl->d1->outgoing_messages[i].data = NULL;
+ ssl->d1->outgoing_messages[i].Clear();
}
ssl->d1->outgoing_messages_len = 0;
ssl->d1->outgoing_written = 0;
@@ -552,7 +538,7 @@
// add_outgoing adds a new handshake message or ChangeCipherSpec to the current
// outgoing flight. It returns true on success and false on error.
-static bool add_outgoing(SSL *ssl, int is_ccs, Array<uint8_t> data) {
+static bool add_outgoing(SSL *ssl, bool 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.
@@ -594,11 +580,11 @@
}
bool dtls1_add_message(SSL *ssl, Array<uint8_t> data) {
- return add_outgoing(ssl, 0 /* handshake */, std::move(data));
+ return add_outgoing(ssl, false /* handshake */, std::move(data));
}
bool dtls1_add_change_cipher_spec(SSL *ssl) {
- return add_outgoing(ssl, 1 /* ChangeCipherSpec */, Array<uint8_t>());
+ return add_outgoing(ssl, true /* ChangeCipherSpec */, Array<uint8_t>());
}
bool dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
@@ -808,14 +794,14 @@
// Retry this packet the next time around.
ssl->d1->outgoing_written = old_written;
ssl->d1->outgoing_offset = old_offset;
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
ret = bio_ret;
goto err;
}
}
if (BIO_flush(ssl->wbio) <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
goto err;
}
diff --git a/src/ssl/d1_lib.cc b/src/ssl/d1_lib.cc
index 38bc5be..eff06ee 100644
--- a/src/ssl/d1_lib.cc
+++ b/src/ssl/d1_lib.cc
@@ -78,18 +78,24 @@
// before failing the DTLS handshake.
#define DTLS1_MAX_TIMEOUTS 12
+DTLS1_STATE::DTLS1_STATE()
+ : has_change_cipher_spec(false),
+ outgoing_messages_complete(false),
+ flight_has_reply(false) {}
+
+DTLS1_STATE::~DTLS1_STATE() {}
+
bool dtls1_new(SSL *ssl) {
if (!ssl3_new(ssl)) {
return false;
}
- DTLS1_STATE *d1 = (DTLS1_STATE *)OPENSSL_malloc(sizeof *d1);
- if (d1 == NULL) {
+ UniquePtr<DTLS1_STATE> d1 = MakeUnique<DTLS1_STATE>();
+ if (!d1) {
ssl3_free(ssl);
return false;
}
- OPENSSL_memset(d1, 0, sizeof *d1);
- ssl->d1 = d1;
+ ssl->d1 = d1.release();
// Set the version to the highest supported version.
//
@@ -103,15 +109,11 @@
void dtls1_free(SSL *ssl) {
ssl3_free(ssl);
- if (ssl == NULL || ssl->d1 == NULL) {
+ if (ssl == NULL) {
return;
}
- dtls_clear_incoming_messages(ssl);
- dtls_clear_outgoing_messages(ssl);
- Delete(ssl->d1->last_aead_write_ctx);
-
- OPENSSL_free(ssl->d1);
+ Delete(ssl->d1);
ssl->d1 = NULL;
}
diff --git a/src/ssl/d1_pkt.cc b/src/ssl/d1_pkt.cc
index c6be93d..d29a5c2 100644
--- a/src/ssl/d1_pkt.cc
+++ b/src/ssl/d1_pkt.cc
@@ -187,8 +187,8 @@
return ssl_open_record_success;
}
-int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake,
- const uint8_t *buf, int len) {
+int dtls1_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in,
+ int len) {
assert(!SSL_in_init(ssl));
*out_needs_handshake = false;
@@ -211,7 +211,7 @@
return 0;
}
- int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf, (size_t)len,
+ int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, in, (size_t)len,
dtls1_use_current_epoch);
if (ret <= 0) {
return ret;
@@ -219,29 +219,29 @@
return len;
}
-int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
+int dtls1_write_record(SSL *ssl, int type, const uint8_t *in, size_t len,
enum dtls1_use_epoch_t use_epoch) {
+ SSLBuffer *buf = &ssl->s3->write_buffer;
assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
// There should never be a pending write buffer in DTLS. One can't write half
// a datagram, so the write buffer is always dropped in
// |ssl_write_buffer_flush|.
- assert(!ssl_write_buffer_is_pending(ssl));
+ assert(buf->empty());
if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
- size_t max_out = len + SSL_max_seal_overhead(ssl);
- uint8_t *out;
size_t ciphertext_len;
- if (!ssl_write_buffer_init(ssl, &out, max_out) ||
- !dtls_seal_record(ssl, out, &ciphertext_len, max_out, type, buf, len,
- use_epoch)) {
- ssl_write_buffer_clear(ssl);
+ if (!buf->EnsureCap(ssl_seal_align_prefix_len(ssl),
+ len + SSL_max_seal_overhead(ssl)) ||
+ !dtls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
+ buf->remaining().size(), type, in, len, use_epoch)) {
+ buf->Clear();
return -1;
}
- ssl_write_buffer_set_len(ssl, ciphertext_len);
+ buf->DidWrite(ciphertext_len);
int ret = ssl_write_buffer_flush(ssl);
if (ret <= 0) {
diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc
index fab19be..91a955f 100644
--- a/src/ssl/dtls_method.cc
+++ b/src/ssl/dtls_method.cc
@@ -94,8 +94,7 @@
OPENSSL_memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
- Delete(ssl->s3->aead_read_ctx);
- ssl->s3->aead_read_ctx = aead_ctx.release();
+ ssl->s3->aead_read_ctx = std::move(aead_ctx);
return true;
}
@@ -106,9 +105,8 @@
sizeof(ssl->s3->write_sequence));
OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
- Delete(ssl->d1->last_aead_write_ctx);
- ssl->d1->last_aead_write_ctx = ssl->s3->aead_write_ctx;
- ssl->s3->aead_write_ctx = aead_ctx.release();
+ ssl->d1->last_aead_write_ctx = std::move(ssl->s3->aead_write_ctx);
+ ssl->s3->aead_write_ctx = std::move(aead_ctx);
return true;
}
diff --git a/src/ssl/dtls_record.cc b/src/ssl/dtls_record.cc
index a746640..5e795fa 100644
--- a/src/ssl/dtls_record.cc
+++ b/src/ssl/dtls_record.cc
@@ -275,10 +275,10 @@
enum dtls1_use_epoch_t use_epoch) {
if (use_epoch == dtls1_use_previous_epoch) {
assert(ssl->d1->w_epoch >= 1);
- return ssl->d1->last_aead_write_ctx;
+ return ssl->d1->last_aead_write_ctx.get();
}
- return ssl->s3->aead_write_ctx;
+ return ssl->s3->aead_write_ctx.get();
}
size_t dtls_max_seal_overhead(const SSL *ssl,
@@ -303,12 +303,12 @@
// Determine the parameters for the current epoch.
uint16_t epoch = ssl->d1->w_epoch;
- SSLAEADContext *aead = ssl->s3->aead_write_ctx;
+ SSLAEADContext *aead = ssl->s3->aead_write_ctx.get();
uint8_t *seq = ssl->s3->write_sequence;
if (use_epoch == dtls1_use_previous_epoch) {
assert(ssl->d1->w_epoch >= 1);
epoch = ssl->d1->w_epoch - 1;
- aead = ssl->d1->last_aead_write_ctx;
+ aead = ssl->d1->last_aead_write_ctx.get();
seq = ssl->d1->last_write_sequence;
}
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 8531ca4..ed11484 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -149,17 +149,15 @@
ssl->ctx->x509_method->hs_flush_cached_ca_names(this);
}
-SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
+UniquePtr<SSL_HANDSHAKE> ssl_handshake_new(SSL *ssl) {
UniquePtr<SSL_HANDSHAKE> hs = MakeUnique<SSL_HANDSHAKE>(ssl);
if (!hs ||
!hs->transcript.Init()) {
return nullptr;
}
- return hs.release();
+ return hs;
}
-void ssl_handshake_free(SSL_HANDSHAKE *hs) { Delete(hs); }
-
bool ssl_check_message_type(SSL *ssl, const SSLMessage &msg, int type) {
if (msg.type != type) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
@@ -282,7 +280,7 @@
enum ssl_verify_result_t ssl_verify_peer_cert(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- const SSL_SESSION *prev_session = ssl->s3->established_session;
+ const SSL_SESSION *prev_session = ssl->s3->established_session.get();
if (prev_session != NULL) {
// If renegotiating, the server must not change the server certificate. See
// https://mitls.org/pages/attacks/3SHAKE. We never resume on renegotiation,
@@ -505,10 +503,10 @@
ssl_open_record_t ret;
if (hs->wait == ssl_hs_read_change_cipher_spec) {
ret = ssl_open_change_cipher_spec(ssl, &consumed, &alert,
- ssl_read_buffer(ssl));
+ ssl->s3->read_buffer.span());
} else {
- ret =
- ssl_open_handshake(ssl, &consumed, &alert, ssl_read_buffer(ssl));
+ ret = ssl_open_handshake(ssl, &consumed, &alert,
+ ssl->s3->read_buffer.span());
}
if (ret == ssl_open_record_error &&
hs->wait == ssl_hs_read_server_hello) {
@@ -533,7 +531,7 @@
if (retry) {
continue;
}
- ssl_read_buffer_discard(ssl);
+ ssl->s3->read_buffer.DiscardConsumed();
break;
}
@@ -548,42 +546,42 @@
}
case ssl_hs_certificate_selection_pending:
- ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
+ ssl->s3->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_x509_lookup:
- ssl->rwstate = SSL_X509_LOOKUP;
+ ssl->s3->rwstate = SSL_X509_LOOKUP;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_channel_id_lookup:
- ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
+ ssl->s3->rwstate = SSL_CHANNEL_ID_LOOKUP;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_private_key_operation:
- ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+ ssl->s3->rwstate = SSL_PRIVATE_KEY_OPERATION;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_pending_session:
- ssl->rwstate = SSL_PENDING_SESSION;
+ ssl->s3->rwstate = SSL_PENDING_SESSION;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_pending_ticket:
- ssl->rwstate = SSL_PENDING_TICKET;
+ ssl->s3->rwstate = SSL_PENDING_TICKET;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_certificate_verify:
- ssl->rwstate = SSL_CERTIFICATE_VERIFY;
+ ssl->s3->rwstate = SSL_CERTIFICATE_VERIFY;
hs->wait = ssl_hs_ok;
return -1;
case ssl_hs_early_data_rejected:
- ssl->rwstate = SSL_EARLY_DATA_REJECTED;
+ ssl->s3->rwstate = SSL_EARLY_DATA_REJECTED;
// Cause |SSL_write| to start failing immediately.
hs->can_early_write = false;
return -1;
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index 5466b56..ff8ebd8 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -1476,14 +1476,15 @@
if (hs->next_proto_neg_seen) {
static const uint8_t kZero[32] = {0};
- size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
+ size_t padding_len =
+ 32 - ((ssl->s3->next_proto_negotiated.size() + 2) % 32);
ScopedCBB cbb;
CBB body, child;
if (!ssl->method->init_message(ssl, cbb.get(), &body, SSL3_MT_NEXT_PROTO) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
- !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
- ssl->s3->next_proto_negotiated_len) ||
+ !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated.data(),
+ ssl->s3->next_proto_negotiated.size()) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
!CBB_add_bytes(&child, kZero, padding_len) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
@@ -1517,8 +1518,8 @@
// False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN.
return !SSL_is_dtls(ssl) &&
SSL_version(ssl) == TLS1_2_VERSION &&
- (ssl->s3->alpn_selected != NULL ||
- ssl->s3->next_proto_negotiated != NULL) &&
+ (!ssl->s3->alpn_selected.empty() ||
+ !ssl->s3->next_proto_negotiated.empty()) &&
hs->new_cipher->algorithm_mkey == SSL_kECDHE &&
hs->new_cipher->algorithm_mac == SSL_AEAD;
}
@@ -1664,18 +1665,16 @@
ssl->method->on_handshake_complete(ssl);
- SSL_SESSION_free(ssl->s3->established_session);
if (ssl->session != NULL) {
SSL_SESSION_up_ref(ssl->session);
- ssl->s3->established_session = ssl->session;
+ ssl->s3->established_session.reset(ssl->session);
} else {
// We make a copy of the session in order to maintain the immutability
// of the new established_session due to False Start. The caller may
// have taken a reference to the temporary session.
ssl->s3->established_session =
- SSL_SESSION_dup(hs->new_session.get(), SSL_SESSION_DUP_ALL)
- .release();
- if (ssl->s3->established_session == NULL) {
+ SSL_SESSION_dup(hs->new_session.get(), SSL_SESSION_DUP_ALL);
+ if (!ssl->s3->established_session) {
return ssl_hs_error;
}
// Renegotiations do not participate in session resumption.
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 7b282d8..d346875 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -1392,8 +1392,7 @@
return ssl_hs_error;
}
- if (!CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
- &ssl->s3->next_proto_negotiated_len)) {
+ if (!ssl->s3->next_proto_negotiated.CopyFrom(selected_protocol)) {
return ssl_hs_error;
}
@@ -1510,12 +1509,11 @@
ssl->ctx->x509_method->session_clear(hs->new_session.get());
}
- SSL_SESSION_free(ssl->s3->established_session);
if (ssl->session != NULL) {
SSL_SESSION_up_ref(ssl->session);
- ssl->s3->established_session = ssl->session;
+ ssl->s3->established_session.reset(ssl->session);
} else {
- ssl->s3->established_session = hs->new_session.release();
+ ssl->s3->established_session = std::move(hs->new_session);
ssl->s3->established_session->not_resumable = 0;
}
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 174445a..7e1801a 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -746,10 +746,10 @@
struct DTLS1_BITMAP {
// map is a bit mask of the last 64 sequence numbers. Bit
// |1<<i| corresponds to |max_seq_num - i|.
- uint64_t map;
+ uint64_t map = 0;
// max_seq_num is the largest sequence number seen so far as a 64-bit
// integer.
- uint64_t max_seq_num;
+ uint64_t max_seq_num = 0;
};
@@ -998,9 +998,6 @@
// in a handshake message for |ssl|.
size_t ssl_max_handshake_message_len(const SSL *ssl);
-// dtls_clear_incoming_messages releases all buffered incoming messages.
-void dtls_clear_incoming_messages(SSL *ssl);
-
// tls_can_accept_handshake_data returns whether |ssl| is able to accept more
// data into handshake buffer.
bool tls_can_accept_handshake_data(const SSL *ssl, uint8_t *out_alert);
@@ -1014,10 +1011,17 @@
bool dtls_has_unprocessed_handshake_data(const SSL *ssl);
struct DTLS_OUTGOING_MESSAGE {
- uint8_t *data;
- uint32_t len;
- uint16_t epoch;
- char is_ccs;
+ DTLS_OUTGOING_MESSAGE() {}
+ DTLS_OUTGOING_MESSAGE(const DTLS_OUTGOING_MESSAGE &) = delete;
+ DTLS_OUTGOING_MESSAGE &operator=(const DTLS_OUTGOING_MESSAGE &) = delete;
+ ~DTLS_OUTGOING_MESSAGE() { Clear(); }
+
+ void Clear();
+
+ uint8_t *data = nullptr;
+ uint32_t len = 0;
+ uint16_t epoch = 0;
+ bool is_ccs = false;
};
// dtls_clear_outgoing_messages releases all buffered outgoing messages.
@@ -1036,8 +1040,57 @@
// Transport buffers.
-// ssl_read_buffer returns the current read buffer.
-Span<uint8_t> ssl_read_buffer(SSL *ssl);
+class SSLBuffer {
+ public:
+ SSLBuffer() {}
+ ~SSLBuffer() { Clear(); }
+
+ SSLBuffer(const SSLBuffer &) = delete;
+ SSLBuffer &operator=(const SSLBuffer &) = delete;
+
+ uint8_t *data() { return buf_ + offset_; }
+ size_t size() const { return size_; }
+ bool empty() const { return size_ == 0; }
+ size_t cap() const { return cap_; }
+
+ Span<uint8_t> span() { return MakeSpan(data(), size()); }
+
+ Span<uint8_t> remaining() {
+ return MakeSpan(data() + size(), cap() - size());
+ }
+
+ // Clear releases the buffer.
+ void Clear();
+
+ // EnsureCap ensures the buffer has capacity at least |new_cap|, aligned such
+ // that data written after |header_len| is aligned to a
+ // |SSL3_ALIGN_PAYLOAD|-byte boundary. It returns true on success and false
+ // on error.
+ bool EnsureCap(size_t header_len, size_t new_cap);
+
+ // DidWrite extends the buffer by |len|. The caller must have filled in to
+ // this point.
+ void DidWrite(size_t len);
+
+ // Consume consumes |len| bytes from the front of the buffer. The memory
+ // consumed will remain valid until the next call to |DiscardConsumed| or
+ // |Clear|.
+ void Consume(size_t len);
+
+ // DiscardConsumed discards the consumed bytes from the buffer. If the buffer
+ // is now empty, it releases memory used by it.
+ void DiscardConsumed();
+
+ private:
+ // buf_ is the memory allocated for this buffer.
+ uint8_t *buf_ = nullptr;
+ // offset_ is the offset into |buf_| which the buffer contents start at.
+ uint16_t offset_ = 0;
+ // size_ is the size of the buffer contents from |buf_| + |offset_|.
+ uint16_t size_ = 0;
+ // cap_ is how much memory beyond |buf_| + |offset_| is available.
+ uint16_t cap_ = 0;
+};
// ssl_read_buffer_extend_to extends the read buffer to the desired length. For
// TLS, it reads to the end of the buffer until the buffer is |len| bytes
@@ -1048,49 +1101,18 @@
// non-empty.
int ssl_read_buffer_extend_to(SSL *ssl, size_t len);
-// ssl_read_buffer_consume consumes |len| bytes from the read buffer. It
-// advances the data pointer and decrements the length. The memory consumed will
-// remain valid until the next call to |ssl_read_buffer_extend| or it is
-// discarded with |ssl_read_buffer_discard|.
-void ssl_read_buffer_consume(SSL *ssl, size_t len);
-
-// ssl_read_buffer_discard discards the consumed bytes from the read buffer. If
-// the buffer is now empty, it releases memory used by it.
-void ssl_read_buffer_discard(SSL *ssl);
-
-// ssl_read_buffer_clear releases all memory associated with the read buffer and
-// zero-initializes it.
-void ssl_read_buffer_clear(SSL *ssl);
-
-// ssl_handle_open_record handles the result of passing |ssl_read_buffer| to a
-// record-processing function. If |ret| is a success or if the caller should
-// retry, it returns one and sets |*out_retry|. Otherwise, it returns <= 0.
+// ssl_handle_open_record handles the result of passing |ssl->s3->read_buffer|
+// to a record-processing function. If |ret| is a success or if the caller
+// should retry, it returns one and sets |*out_retry|. Otherwise, it returns <=
+// 0.
int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret,
size_t consumed, uint8_t alert);
-// ssl_write_buffer_is_pending returns one if the write buffer has pending data
-// and zero if is empty.
-int ssl_write_buffer_is_pending(const SSL *ssl);
-
-// ssl_write_buffer_init initializes the write buffer. On success, it sets
-// |*out_ptr| to the start of the write buffer with space for up to |max_len|
-// bytes. It returns one on success and zero on failure. Call
-// |ssl_write_buffer_set_len| to complete initialization.
-int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len);
-
-// ssl_write_buffer_set_len is called after |ssl_write_buffer_init| to complete
-// initialization after |len| bytes are written to the buffer.
-void ssl_write_buffer_set_len(SSL *ssl, size_t len);
-
// ssl_write_buffer_flush flushes the write buffer to the transport. It returns
// one on success and <= 0 on error. For DTLS, whether or not the write
// succeeds, the write buffer will be cleared.
int ssl_write_buffer_flush(SSL *ssl);
-// ssl_write_buffer_clear releases all memory associated with the write buffer
-// and zero-initializes it.
-void ssl_write_buffer_clear(SSL *ssl);
-
// Certificate functions.
@@ -1468,10 +1490,7 @@
uint16_t early_data_written = 0;
};
-SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
-
-// ssl_handshake_free releases all memory associated with |hs|.
-void ssl_handshake_free(SSL_HANDSHAKE *hs);
+UniquePtr<SSL_HANDSHAKE> ssl_handshake_new(SSL *ssl);
// ssl_check_message_type checks if |msg| has type |type|. If so it returns
// one. Otherwise, it sends an alert and returns zero.
@@ -1556,6 +1575,10 @@
SSL_HANDSHAKE *hs, Array<uint8_t> *out,
enum ssl_cert_verify_context_t cert_verify_context);
+// ssl_is_alpn_protocol_allowed returns whether |protocol| is a valid server
+// selection for |ssl|'s client preferences.
+bool ssl_is_alpn_protocol_allowed(const SSL *ssl, Span<const uint8_t> protocol);
+
// ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
// true on successful negotiation or if nothing was negotiated. It returns false
// and sets |*out_alert| to an alert on error.
@@ -2134,17 +2157,6 @@
bool ed25519_enabled:1;
};
-struct SSL3_BUFFER {
- // buf is the memory allocated for this buffer.
- uint8_t *buf;
- // offset is the offset into |buf| which the buffer contents start at.
- uint16_t offset;
- // len is the length of the buffer contents from |buf| + |offset|.
- uint16_t len;
- // cap is how much memory beyond |buf| + |offset| is available.
- uint16_t cap;
-};
-
// An ssl_shutdown_t describes the shutdown state of one end of the connection,
// whether it is alive or has been shutdown via close_notify or fatal alert.
enum ssl_shutdown_t {
@@ -2154,55 +2166,65 @@
};
struct SSL3_STATE {
- uint8_t read_sequence[8];
- uint8_t write_sequence[8];
+ static constexpr bool kAllowUniquePtr = true;
- uint8_t server_random[SSL3_RANDOM_SIZE];
- uint8_t client_random[SSL3_RANDOM_SIZE];
+ SSL3_STATE();
+ ~SSL3_STATE();
+
+ uint8_t read_sequence[8] = {0};
+ uint8_t write_sequence[8] = {0};
+
+ uint8_t server_random[SSL3_RANDOM_SIZE] = {0};
+ uint8_t client_random[SSL3_RANDOM_SIZE] = {0};
// read_buffer holds data from the transport to be processed.
- SSL3_BUFFER read_buffer;
+ SSLBuffer read_buffer;
// write_buffer holds data to be written to the transport.
- SSL3_BUFFER write_buffer;
+ SSLBuffer write_buffer;
// pending_app_data is the unconsumed application data. It points into
// |read_buffer|.
Span<uint8_t> pending_app_data;
// partial write - check the numbers match
- unsigned int wnum; // number of bytes sent so far
- int wpend_tot; // number bytes written
- int wpend_type;
- int wpend_ret; // number of bytes submitted
- const uint8_t *wpend_buf;
+ unsigned int wnum = 0; // number of bytes sent so far
+ int wpend_tot = 0; // number bytes written
+ int wpend_type = 0;
+ int wpend_ret = 0; // number of bytes submitted
+ const uint8_t *wpend_buf = nullptr;
// read_shutdown is the shutdown state for the read half of the connection.
- enum ssl_shutdown_t read_shutdown;
+ enum ssl_shutdown_t read_shutdown = ssl_shutdown_none;
// write_shutdown is the shutdown state for the write half of the connection.
- enum ssl_shutdown_t write_shutdown;
+ enum ssl_shutdown_t write_shutdown = ssl_shutdown_none;
// read_error, if |read_shutdown| is |ssl_shutdown_error|, is the error for
// the receive half of the connection.
- ERR_SAVE_STATE *read_error;
+ UniquePtr<ERR_SAVE_STATE> read_error;
- int alert_dispatch;
+ int alert_dispatch = 0;
- int total_renegotiations;
+ int total_renegotiations = 0;
+
+ // This holds a variable that indicates what we were doing when a 0 or -1 is
+ // returned. This is needed for non-blocking IO so we know what request
+ // needs re-doing when in SSL_accept or SSL_connect
+ int rwstate = SSL_NOTHING;
// early_data_skipped is the amount of early data that has been skipped by the
// record layer.
- uint16_t early_data_skipped;
+ uint16_t early_data_skipped = 0;
// empty_record_count is the number of consecutive empty records received.
- uint8_t empty_record_count;
+ uint8_t empty_record_count = 0;
// warning_alert_count is the number of consecutive warning alerts
// received.
- uint8_t warning_alert_count;
+ uint8_t warning_alert_count = 0;
// key_update_count is the number of consecutive KeyUpdates received.
- uint8_t key_update_count;
+ uint8_t key_update_count = 0;
// skip_early_data instructs the record layer to skip unexpected early data
// messages when 0RTT is rejected.
@@ -2246,56 +2268,49 @@
// wpend_pending is true if we have a pending write outstanding.
bool wpend_pending:1;
- uint8_t send_alert[2];
+ uint8_t send_alert[2] = {0};
+
+ // hs_buf is the buffer of handshake data to process.
+ UniquePtr<BUF_MEM> hs_buf;
// pending_flight is the pending outgoing flight. This is used to flush each
// handshake flight in a single write. |write_buffer| must be written out
// before this data.
- BUF_MEM *pending_flight;
+ UniquePtr<BUF_MEM> pending_flight;
// pending_flight_offset is the number of bytes of |pending_flight| which have
// been successfully written.
- uint32_t pending_flight_offset;
+ uint32_t pending_flight_offset = 0;
// aead_read_ctx is the current read cipher state.
- SSLAEADContext *aead_read_ctx;
+ UniquePtr<SSLAEADContext> aead_read_ctx;
// aead_write_ctx is the current write cipher state.
- SSLAEADContext *aead_write_ctx;
+ UniquePtr<SSLAEADContext> aead_write_ctx;
// hs is the handshake state for the current handshake or NULL if there isn't
// one.
- SSL_HANDSHAKE *hs;
+ UniquePtr<SSL_HANDSHAKE> hs;
- uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
- uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
- uint8_t exporter_secret[EVP_MAX_MD_SIZE];
- uint8_t early_exporter_secret[EVP_MAX_MD_SIZE];
- uint8_t write_traffic_secret_len;
- uint8_t read_traffic_secret_len;
- uint8_t exporter_secret_len;
- uint8_t early_exporter_secret_len;
+ uint8_t write_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t read_traffic_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t exporter_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t early_exporter_secret[EVP_MAX_MD_SIZE] = {0};
+ uint8_t write_traffic_secret_len = 0;
+ uint8_t read_traffic_secret_len = 0;
+ uint8_t exporter_secret_len = 0;
+ uint8_t early_exporter_secret_len = 0;
// Connection binding to prevent renegotiation attacks
- uint8_t previous_client_finished[12];
- uint8_t previous_client_finished_len;
- uint8_t previous_server_finished_len;
- uint8_t previous_server_finished[12];
-
- // State pertaining to the pending handshake.
- //
- // TODO(davidben): Move everything not needed after the handshake completes to
- // |hs| and remove this.
- struct {
- uint8_t new_mac_secret_len;
- uint8_t new_key_len;
- uint8_t new_fixed_iv_len;
- } tmp;
+ uint8_t previous_client_finished[12] = {0};
+ uint8_t previous_client_finished_len = 0;
+ uint8_t previous_server_finished_len = 0;
+ uint8_t previous_server_finished[12] = {0};
// established_session is the session established by the connection. This
// session is only filled upon the completion of the handshake and is
// immutable.
- SSL_SESSION *established_session;
+ UniquePtr<SSL_SESSION> established_session;
// Next protocol negotiation. For the client, this is the protocol that we
// sent in NextProtocol and is set when handling ServerHello extensions.
@@ -2303,8 +2318,7 @@
// For a server, this is the client's selected_protocol from NextProtocol and
// is set when handling the NextProtocol message, before the Finished
// message.
- uint8_t *next_proto_negotiated;
- size_t next_proto_negotiated_len;
+ Array<uint8_t> next_proto_negotiated;
// ALPN information
// (we are in the process of transitioning from NPN to ALPN.)
@@ -2312,22 +2326,21 @@
// In a server these point to the selected ALPN protocol after the
// ClientHello has been processed. In a client these contain the protocol
// that the server selected once the ServerHello has been processed.
- uint8_t *alpn_selected;
- size_t alpn_selected_len;
+ Array<uint8_t> alpn_selected;
// hostname, on the server, is the value of the SNI extension.
- char *hostname;
+ UniquePtr<char> hostname;
// For a server:
// If |tlsext_channel_id_valid| is true, then this contains the
// verified Channel ID from the client: a P256 point, (x,y), where
// each are big-endian values.
- uint8_t tlsext_channel_id[64];
+ uint8_t tlsext_channel_id[64] = {0};
// ticket_age_skew is the difference, in seconds, between the client-sent
// ticket age and the server-computed value in TLS 1.3 server connections
// which resumed a session.
- int32_t ticket_age_skew;
+ int32_t ticket_age_skew = 0;
};
// lengths of messages
@@ -2351,18 +2364,26 @@
// An hm_fragment is an incoming DTLS message, possibly not yet assembled.
struct hm_fragment {
+ static constexpr bool kAllowUniquePtr = true;
+
+ hm_fragment() {}
+ hm_fragment(const hm_fragment &) = delete;
+ hm_fragment &operator=(const hm_fragment &) = delete;
+
+ ~hm_fragment();
+
// type is the type of the message.
- uint8_t type;
+ uint8_t type = 0;
// seq is the sequence number of this message.
- uint16_t seq;
+ uint16_t seq = 0;
// msg_len is the length of the message body.
- uint32_t msg_len;
+ uint32_t msg_len = 0;
// data is a pointer to the message, including message header. It has length
// |DTLS1_HM_HEADER_LENGTH| + |msg_len|.
- uint8_t *data;
+ uint8_t *data = nullptr;
// reassembly is a bitmask of |msg_len| bits corresponding to which parts of
// the message have been received. It is NULL if the message is complete.
- uint8_t *reassembly;
+ uint8_t *reassembly = nullptr;
};
struct OPENSSL_timeval {
@@ -2371,6 +2392,11 @@
};
struct DTLS1_STATE {
+ static constexpr bool kAllowUniquePtr = true;
+
+ DTLS1_STATE();
+ ~DTLS1_STATE();
+
// has_change_cipher_spec is true if we have received a ChangeCipherSpec from
// the peer in this epoch.
bool has_change_cipher_spec:1;
@@ -2385,54 +2411,54 @@
// peer sent the final flight.
bool flight_has_reply:1;
- uint8_t cookie[DTLS1_COOKIE_LENGTH];
- size_t cookie_len;
+ uint8_t cookie[DTLS1_COOKIE_LENGTH] = {0};
+ size_t cookie_len = 0;
// The current data and handshake epoch. This is initially undefined, and
// starts at zero once the initial handshake is completed.
- uint16_t r_epoch;
- uint16_t w_epoch;
+ uint16_t r_epoch = 0;
+ uint16_t w_epoch = 0;
// records being received in the current epoch
DTLS1_BITMAP bitmap;
- uint16_t handshake_write_seq;
- uint16_t handshake_read_seq;
+ uint16_t handshake_write_seq = 0;
+ uint16_t handshake_read_seq = 0;
// save last sequence number for retransmissions
- uint8_t last_write_sequence[8];
- SSLAEADContext *last_aead_write_ctx;
+ uint8_t last_write_sequence[8] = {0};
+ UniquePtr<SSLAEADContext> last_aead_write_ctx;
// incoming_messages is a ring buffer of incoming handshake messages that have
// yet to be processed. The front of the ring buffer is message number
// |handshake_read_seq|, at position |handshake_read_seq| %
// |SSL_MAX_HANDSHAKE_FLIGHT|.
- hm_fragment *incoming_messages[SSL_MAX_HANDSHAKE_FLIGHT];
+ UniquePtr<hm_fragment> incoming_messages[SSL_MAX_HANDSHAKE_FLIGHT];
// outgoing_messages is the queue of outgoing messages from the last handshake
// flight.
DTLS_OUTGOING_MESSAGE outgoing_messages[SSL_MAX_HANDSHAKE_FLIGHT];
- uint8_t outgoing_messages_len;
+ uint8_t outgoing_messages_len = 0;
// outgoing_written is the number of outgoing messages that have been
// written.
- uint8_t outgoing_written;
+ uint8_t outgoing_written = 0;
// outgoing_offset is the number of bytes of the next outgoing message have
// been written.
- uint32_t outgoing_offset;
+ uint32_t outgoing_offset = 0;
- unsigned int mtu; // max DTLS packet size
+ unsigned mtu = 0; // max DTLS packet size
// num_timeouts is the number of times the retransmit timer has fired since
// the last time it was reset.
- unsigned int num_timeouts;
+ unsigned num_timeouts = 0;
// Indicates when the last handshake msg or heartbeat sent will
// timeout.
- struct OPENSSL_timeval next_timeout;
+ struct OPENSSL_timeval next_timeout = {0, 0};
// timeout_duration_ms is the timeout duration in milliseconds.
- unsigned timeout_duration_ms;
+ unsigned timeout_duration_ms = 0;
};
// SSLConnection backs the public |SSL| type. Due to compatibility constraints,
@@ -2472,8 +2498,6 @@
// progress.
enum ssl_hs_wait_t (*do_handshake)(SSL_HANDSHAKE *hs);
- BUF_MEM *init_buf; // buffer used during init
-
SSL3_STATE *s3; // SSLv3 variables
DTLS1_STATE *d1; // DTLSv1 variables
@@ -2493,11 +2517,6 @@
// This is used to hold the server certificate used
CERT *cert;
- // This holds a variable that indicates what we were doing when a 0 or -1 is
- // returned. This is needed for non-blocking IO so we know what request
- // needs re-doing when in SSL_accept or SSL_connect
- int rwstate;
-
// initial_timeout_duration_ms is the default DTLS timeout duration in
// milliseconds. It's used to initialize the timer any time it's restarted.
unsigned initial_timeout_duration_ms;
@@ -2601,7 +2620,6 @@
};
// From draft-ietf-tls-tls13-18, used in determining PSK modes.
-#define SSL_PSK_KE 0x0
#define SSL_PSK_DHE_KE 0x1
// From draft-ietf-tls-tls13-16, used in determining whether to respond with a
diff --git a/src/ssl/s3_both.cc b/src/ssl/s3_both.cc
index 1459085..ede4ba7 100644
--- a/src/ssl/s3_both.cc
+++ b/src/ssl/s3_both.cc
@@ -137,9 +137,9 @@
// We'll never add a flight while in the process of writing it out.
assert(ssl->s3->pending_flight_offset == 0);
- if (ssl->s3->pending_flight == NULL) {
- ssl->s3->pending_flight = BUF_MEM_new();
- if (ssl->s3->pending_flight == NULL) {
+ if (ssl->s3->pending_flight == nullptr) {
+ ssl->s3->pending_flight.reset(BUF_MEM_new());
+ if (ssl->s3->pending_flight == nullptr) {
return false;
}
}
@@ -152,7 +152,7 @@
}
size_t len;
- if (!BUF_MEM_reserve(ssl->s3->pending_flight, new_cap) ||
+ if (!BUF_MEM_reserve(ssl->s3->pending_flight.get(), new_cap) ||
!tls_seal_record(ssl,
(uint8_t *)ssl->s3->pending_flight->data +
ssl->s3->pending_flight->length,
@@ -229,7 +229,7 @@
}
int ssl3_flush_flight(SSL *ssl) {
- if (ssl->s3->pending_flight == NULL) {
+ if (ssl->s3->pending_flight == nullptr) {
return 1;
}
@@ -246,10 +246,10 @@
// If there is pending data in the write buffer, it must be flushed out before
// any new data in pending_flight.
- if (ssl_write_buffer_is_pending(ssl)) {
+ if (!ssl->s3->write_buffer.empty()) {
int ret = ssl_write_buffer_flush(ssl);
if (ret <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
return ret;
}
}
@@ -261,7 +261,7 @@
ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset);
if (ret <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
return ret;
}
@@ -269,12 +269,11 @@
}
if (BIO_flush(ssl->wbio) <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
return -1;
}
- BUF_MEM_free(ssl->s3->pending_flight);
- ssl->s3->pending_flight = NULL;
+ ssl->s3->pending_flight.reset();
ssl->s3->pending_flight_offset = 0;
return 1;
}
@@ -303,7 +302,7 @@
return ssl_open_record_partial;
}
- CBS v2_client_hello = CBS(ssl_read_buffer(ssl).subspan(2, msg_length));
+ CBS v2_client_hello = CBS(ssl->s3->read_buffer.span().subspan(2, msg_length));
// The V2ClientHello without the length is incorporated into the handshake
// hash. This is only ever called at the start of the handshake, so hs is
// guaranteed to be non-NULL.
@@ -352,9 +351,9 @@
1 /* compression length */ + 1 /* compression */;
ScopedCBB client_hello;
CBB hello_body, cipher_suites;
- if (!BUF_MEM_reserve(ssl->init_buf, max_v3_client_hello) ||
- !CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->init_buf->data,
- ssl->init_buf->max) ||
+ if (!BUF_MEM_reserve(ssl->s3->hs_buf.get(), max_v3_client_hello) ||
+ !CBB_init_fixed(client_hello.get(), (uint8_t *)ssl->s3->hs_buf->data,
+ ssl->s3->hs_buf->max) ||
!CBB_add_u8(client_hello.get(), SSL3_MT_CLIENT_HELLO) ||
!CBB_add_u24_length_prefixed(client_hello.get(), &hello_body) ||
!CBB_add_u16(&hello_body, version) ||
@@ -387,7 +386,7 @@
// Add the null compression scheme and finish.
if (!CBB_add_u8(&hello_body, 1) ||
!CBB_add_u8(&hello_body, 0) ||
- !CBB_finish(client_hello.get(), NULL, &ssl->init_buf->length)) {
+ !CBB_finish(client_hello.get(), NULL, &ssl->s3->hs_buf->length)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return ssl_open_record_error;
}
@@ -399,15 +398,15 @@
static bool parse_message(const SSL *ssl, SSLMessage *out,
size_t *out_bytes_needed) {
- if (ssl->init_buf == NULL) {
+ if (!ssl->s3->hs_buf) {
*out_bytes_needed = 4;
return false;
}
CBS cbs;
uint32_t len;
- CBS_init(&cbs, reinterpret_cast<const uint8_t *>(ssl->init_buf->data),
- ssl->init_buf->length);
+ CBS_init(&cbs, reinterpret_cast<const uint8_t *>(ssl->s3->hs_buf->data),
+ ssl->s3->hs_buf->length);
if (!CBS_get_u8(&cbs, &out->type) ||
!CBS_get_u24(&cbs, &len)) {
*out_bytes_needed = 4;
@@ -419,7 +418,7 @@
return false;
}
- CBS_init(&out->raw, reinterpret_cast<const uint8_t *>(ssl->init_buf->data),
+ CBS_init(&out->raw, reinterpret_cast<const uint8_t *>(ssl->s3->hs_buf->data),
4 + len);
out->is_v2_hello = ssl->s3->is_v2_hello;
return true;
@@ -469,16 +468,16 @@
}
}
- return ssl->init_buf != NULL && ssl->init_buf->length > msg_len;
+ return ssl->s3->hs_buf && ssl->s3->hs_buf->length > msg_len;
}
ssl_open_record_t ssl3_open_handshake(SSL *ssl, size_t *out_consumed,
uint8_t *out_alert, Span<uint8_t> in) {
*out_consumed = 0;
// Re-create the handshake buffer if needed.
- if (ssl->init_buf == NULL) {
- ssl->init_buf = BUF_MEM_new();
- if (ssl->init_buf == NULL) {
+ if (!ssl->s3->hs_buf) {
+ ssl->s3->hs_buf.reset(BUF_MEM_new());
+ if (!ssl->s3->hs_buf) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
@@ -552,7 +551,7 @@
}
// Append the entire handshake record to the buffer.
- if (!BUF_MEM_append(ssl->init_buf, body.data(), body.size())) {
+ if (!BUF_MEM_append(ssl->s3->hs_buf.get(), body.data(), body.size())) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
@@ -563,23 +562,23 @@
void ssl3_next_message(SSL *ssl) {
SSLMessage msg;
if (!ssl3_get_message(ssl, &msg) ||
- ssl->init_buf == NULL ||
- ssl->init_buf->length < CBS_len(&msg.raw)) {
+ !ssl->s3->hs_buf ||
+ ssl->s3->hs_buf->length < CBS_len(&msg.raw)) {
assert(0);
return;
}
- OPENSSL_memmove(ssl->init_buf->data, ssl->init_buf->data + CBS_len(&msg.raw),
- ssl->init_buf->length - CBS_len(&msg.raw));
- ssl->init_buf->length -= CBS_len(&msg.raw);
+ OPENSSL_memmove(ssl->s3->hs_buf->data,
+ ssl->s3->hs_buf->data + CBS_len(&msg.raw),
+ ssl->s3->hs_buf->length - CBS_len(&msg.raw));
+ ssl->s3->hs_buf->length -= CBS_len(&msg.raw);
ssl->s3->is_v2_hello = false;
ssl->s3->has_message = false;
// Post-handshake messages are rare, so release the buffer after every
// message. During the handshake, |on_handshake_complete| will release it.
- if (!SSL_in_init(ssl) && ssl->init_buf->length == 0) {
- BUF_MEM_free(ssl->init_buf);
- ssl->init_buf = NULL;
+ if (!SSL_in_init(ssl) && ssl->s3->hs_buf->length == 0) {
+ ssl->s3->hs_buf.reset();
}
}
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index f3f99fa..b925cd7 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -164,30 +164,35 @@
namespace bssl {
+SSL3_STATE::SSL3_STATE()
+ : skip_early_data(false),
+ have_version(false),
+ v2_hello_done(false),
+ is_v2_hello(false),
+ has_message(false),
+ initial_handshake_complete(false),
+ session_reused(false),
+ send_connection_binding(false),
+ tlsext_channel_id_valid(false),
+ key_update_pending(false),
+ wpend_pending(false) {}
+
+SSL3_STATE::~SSL3_STATE() {}
+
bool ssl3_new(SSL *ssl) {
- UniquePtr<SSLAEADContext> aead_read_ctx =
- SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
- UniquePtr<SSLAEADContext> aead_write_ctx =
- SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
- if (!aead_read_ctx || !aead_write_ctx) {
+ UniquePtr<SSL3_STATE> s3 = MakeUnique<SSL3_STATE>();
+ if (!s3) {
return false;
}
- SSL3_STATE *s3 = (SSL3_STATE *)OPENSSL_malloc(sizeof *s3);
- if (s3 == NULL) {
- return false;
- }
- OPENSSL_memset(s3, 0, sizeof *s3);
-
+ s3->aead_read_ctx = SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
+ s3->aead_write_ctx = SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
s3->hs = ssl_handshake_new(ssl);
- if (s3->hs == NULL) {
- OPENSSL_free(s3);
+ if (!s3->aead_read_ctx || !s3->aead_write_ctx || !s3->hs) {
return false;
}
- s3->aead_read_ctx = aead_read_ctx.release();
- s3->aead_write_ctx = aead_write_ctx.release();
- ssl->s3 = s3;
+ ssl->s3 = s3.release();
// Set the version to the highest supported version.
//
@@ -203,20 +208,7 @@
return;
}
- ssl_read_buffer_clear(ssl);
- ssl_write_buffer_clear(ssl);
-
- ERR_SAVE_STATE_free(ssl->s3->read_error);
- SSL_SESSION_free(ssl->s3->established_session);
- ssl_handshake_free(ssl->s3->hs);
- OPENSSL_free(ssl->s3->next_proto_negotiated);
- OPENSSL_free(ssl->s3->alpn_selected);
- OPENSSL_free(ssl->s3->hostname);
- Delete(ssl->s3->aead_read_ctx);
- Delete(ssl->s3->aead_write_ctx);
- BUF_MEM_free(ssl->s3->pending_flight);
-
- OPENSSL_free(ssl->s3);
+ Delete(ssl->s3);
ssl->s3 = NULL;
}
diff --git a/src/ssl/s3_pkt.cc b/src/ssl/s3_pkt.cc
index 7966e6f..285abb3 100644
--- a/src/ssl/s3_pkt.cc
+++ b/src/ssl/s3_pkt.cc
@@ -124,9 +124,9 @@
namespace bssl {
-static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
+static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len);
-int ssl3_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *buf,
+int ssl3_write_app_data(SSL *ssl, bool *out_needs_handshake, const uint8_t *in,
int len) {
assert(ssl_can_write(ssl));
assert(!ssl->s3->aead_write_ctx->is_null_cipher());
@@ -180,7 +180,7 @@
nw = n;
}
- int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &buf[tot], nw);
+ int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &in[tot], nw);
if (ret <= 0) {
ssl->s3->wnum = tot;
return ret;
@@ -199,11 +199,11 @@
}
}
-static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf,
+static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *in,
unsigned int len) {
if (ssl->s3->wpend_tot > (int)len ||
(!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) &&
- ssl->s3->wpend_buf != buf) ||
+ ssl->s3->wpend_buf != in) ||
ssl->s3->wpend_type != type) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY);
return -1;
@@ -218,13 +218,14 @@
}
// do_ssl3_write writes an SSL record of the given type.
-static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
+static int do_ssl3_write(SSL *ssl, int type, const uint8_t *in, unsigned len) {
// If there is still data from the previous record, flush it.
if (ssl->s3->wpend_pending) {
- return ssl3_write_pending(ssl, type, buf, len);
+ return ssl3_write_pending(ssl, type, in, len);
}
- if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+ SSLBuffer *buf = &ssl->s3->write_buffer;
+ if (len > SSL3_RT_MAX_PLAIN_LENGTH || buf->size() > 0) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
@@ -234,7 +235,7 @@
}
size_t flight_len = 0;
- if (ssl->s3->pending_flight != NULL) {
+ if (ssl->s3->pending_flight != nullptr) {
flight_len =
ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset;
}
@@ -246,9 +247,7 @@
}
max_out += flight_len;
- uint8_t *out;
- size_t ciphertext_len;
- if (!ssl_write_buffer_init(ssl, &out, max_out)) {
+ if (!buf->EnsureCap(flight_len + ssl_seal_align_prefix_len(ssl), max_out)) {
return -1;
}
@@ -256,20 +255,22 @@
// acknowledgment or 0-RTT key change messages. |pending_flight| must be clear
// when data is added to |write_buffer| or it will be written in the wrong
// order.
- if (ssl->s3->pending_flight != NULL) {
+ if (ssl->s3->pending_flight != nullptr) {
OPENSSL_memcpy(
- out, ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
+ buf->remaining().data(),
+ ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
flight_len);
- BUF_MEM_free(ssl->s3->pending_flight);
- ssl->s3->pending_flight = NULL;
+ ssl->s3->pending_flight.reset();
ssl->s3->pending_flight_offset = 0;
+ buf->DidWrite(flight_len);
}
- if (!tls_seal_record(ssl, out + flight_len, &ciphertext_len,
- max_out - flight_len, type, buf, len)) {
+ size_t ciphertext_len;
+ if (!tls_seal_record(ssl, buf->remaining().data(), &ciphertext_len,
+ buf->remaining().size(), type, in, len)) {
return -1;
}
- ssl_write_buffer_set_len(ssl, flight_len + ciphertext_len);
+ buf->DidWrite(ciphertext_len);
// Now that we've made progress on the connection, uncork KeyUpdate
// acknowledgments.
@@ -278,13 +279,13 @@
// Memorize arguments so that ssl3_write_pending can detect bad write retries
// later.
ssl->s3->wpend_tot = len;
- ssl->s3->wpend_buf = buf;
+ ssl->s3->wpend_buf = in;
ssl->s3->wpend_type = type;
ssl->s3->wpend_ret = len;
ssl->s3->wpend_pending = true;
// We now just need to write the buffer.
- return ssl3_write_pending(ssl, type, buf, len);
+ return ssl3_write_pending(ssl, type, in, len);
}
ssl_open_record_t ssl3_open_app_data(SSL *ssl, Span<uint8_t> *out,
@@ -320,11 +321,11 @@
return ssl_open_record_error;
}
- if (ssl->init_buf == NULL) {
- ssl->init_buf = BUF_MEM_new();
+ if (!ssl->s3->hs_buf) {
+ ssl->s3->hs_buf.reset(BUF_MEM_new());
}
- if (ssl->init_buf == NULL ||
- !BUF_MEM_append(ssl->init_buf, body.data(), body.size())) {
+ if (!ssl->s3->hs_buf ||
+ !BUF_MEM_append(ssl->s3->hs_buf.get(), body.data(), body.size())) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return ssl_open_record_error;
}
@@ -408,7 +409,7 @@
ssl->s3->alert_dispatch = 1;
ssl->s3->send_alert[0] = level;
ssl->s3->send_alert[1] = desc;
- if (!ssl_write_buffer_is_pending(ssl)) {
+ if (ssl->s3->write_buffer.empty()) {
// Nothing is being written out, so the alert may be dispatched
// immediately.
return ssl->method->dispatch_alert(ssl);
diff --git a/src/ssl/ssl_buffer.cc b/src/ssl/ssl_buffer.cc
index 412df73..da1de93 100644
--- a/src/ssl/ssl_buffer.cc
+++ b/src/ssl/ssl_buffer.cc
@@ -36,17 +36,22 @@
static_assert((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0,
"SSL3_ALIGN_PAYLOAD must be a power of 2");
-// ensure_buffer ensures |buf| has capacity at least |cap|, aligned such that
-// data written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte
-// boundary. It returns one on success and zero on error.
-static int ensure_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) {
- if (cap > 0xffff) {
+void SSLBuffer::Clear() {
+ free(buf_); // Allocated with malloc().
+ buf_ = nullptr;
+ offset_ = 0;
+ size_ = 0;
+ cap_ = 0;
+}
+
+bool SSLBuffer::EnsureCap(size_t header_len, size_t new_cap) {
+ if (new_cap > 0xffff) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
- if (buf->cap >= cap) {
- return 1;
+ if (cap_ >= new_cap) {
+ return true;
}
// Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment.
@@ -54,88 +59,88 @@
// Since this buffer gets allocated quite frequently and doesn't contain any
// sensitive data, we allocate with malloc rather than |OPENSSL_malloc| and
// avoid zeroing on free.
- uint8_t *new_buf = (uint8_t *)malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
+ uint8_t *new_buf = (uint8_t *)malloc(new_cap + SSL3_ALIGN_PAYLOAD - 1);
if (new_buf == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- return 0;
+ return false;
}
// Offset the buffer such that the record body is aligned.
size_t new_offset =
(0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1);
- if (buf->buf != NULL) {
- OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len);
- free(buf->buf); // Allocated with malloc().
+ if (buf_ != NULL) {
+ OPENSSL_memcpy(new_buf + new_offset, buf_ + offset_, size_);
+ free(buf_); // Allocated with malloc().
}
- buf->buf = new_buf;
- buf->offset = new_offset;
- buf->cap = cap;
- return 1;
+ buf_ = new_buf;
+ offset_ = new_offset;
+ cap_ = new_cap;
+ return true;
}
-static void consume_buffer(SSL3_BUFFER *buf, size_t len) {
- if (len > buf->len) {
+void SSLBuffer::DidWrite(size_t new_size) {
+ if (new_size > cap() - size()) {
abort();
}
- buf->offset += (uint16_t)len;
- buf->len -= (uint16_t)len;
- buf->cap -= (uint16_t)len;
+ size_ += new_size;
}
-static void clear_buffer(SSL3_BUFFER *buf) {
- free(buf->buf); // Allocated with malloc().
- OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
+void SSLBuffer::Consume(size_t len) {
+ if (len > size_) {
+ abort();
+ }
+ offset_ += (uint16_t)len;
+ size_ -= (uint16_t)len;
+ cap_ -= (uint16_t)len;
}
-Span<uint8_t> ssl_read_buffer(SSL *ssl) {
- return MakeSpan(ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset,
- ssl->s3->read_buffer.len);
+void SSLBuffer::DiscardConsumed() {
+ if (size_ == 0) {
+ Clear();
+ }
}
static int dtls_read_buffer_next_packet(SSL *ssl) {
- SSL3_BUFFER *buf = &ssl->s3->read_buffer;
+ SSLBuffer *buf = &ssl->s3->read_buffer;
- if (buf->len > 0) {
+ if (!buf->empty()) {
// It is an error to call |dtls_read_buffer_extend| when the read buffer is
// not empty.
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return -1;
}
- // Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int.
- int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap);
+ // Read a single packet from |ssl->rbio|. |buf->cap()| must fit in an int.
+ int ret = BIO_read(ssl->rbio, buf->data(), static_cast<int>(buf->cap()));
if (ret <= 0) {
- ssl->rwstate = SSL_READING;
+ ssl->s3->rwstate = SSL_READING;
return ret;
}
- // |BIO_read| was bound by |buf->cap|, so this cannot overflow.
- buf->len = (uint16_t)ret;
+ buf->DidWrite(static_cast<size_t>(ret));
return 1;
}
static int tls_read_buffer_extend_to(SSL *ssl, size_t len) {
- SSL3_BUFFER *buf = &ssl->s3->read_buffer;
+ SSLBuffer *buf = &ssl->s3->read_buffer;
- if (len > buf->cap) {
+ if (len > buf->cap()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
return -1;
}
// Read until the target length is reached.
- while (buf->len < len) {
+ while (buf->size() < len) {
// The amount of data to read is bounded by |buf->cap|, which must fit in an
// int.
- int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len,
- (int)(len - buf->len));
+ int ret = BIO_read(ssl->rbio, buf->data() + buf->size(),
+ static_cast<int>(len - buf->size()));
if (ret <= 0) {
- ssl->rwstate = SSL_READING;
+ ssl->s3->rwstate = SSL_READING;
return ret;
}
- // |BIO_read| was bound by |buf->cap - buf->len|, so this cannot
- // overflow.
- buf->len += (uint16_t)ret;
+ buf->DidWrite(static_cast<size_t>(ret));
}
return 1;
@@ -143,7 +148,7 @@
int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
// |ssl_read_buffer_extend_to| implicitly discards any consumed data.
- ssl_read_buffer_discard(ssl);
+ ssl->s3->read_buffer.DiscardConsumed();
if (SSL_is_dtls(ssl)) {
static_assert(
@@ -154,7 +159,7 @@
len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
}
- if (!ensure_buffer(&ssl->s3->read_buffer, ssl_record_prefix_len(ssl), len)) {
+ if (!ssl->s3->read_buffer.EnsureCap(ssl_record_prefix_len(ssl), len)) {
return -1;
}
@@ -174,43 +179,20 @@
if (ret <= 0) {
// If the buffer was empty originally and remained empty after attempting to
// extend it, release the buffer until the next attempt.
- ssl_read_buffer_discard(ssl);
+ ssl->s3->read_buffer.DiscardConsumed();
}
return ret;
}
-void ssl_read_buffer_consume(SSL *ssl, size_t len) {
- SSL3_BUFFER *buf = &ssl->s3->read_buffer;
-
- consume_buffer(buf, len);
-
- // The TLS stack never reads beyond the current record, so there will never be
- // unconsumed data. If read-ahead is ever reimplemented,
- // |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back
- // to the front of the buffer, to ensure there is enough space for the next
- // record.
- assert(SSL_is_dtls(ssl) || len == 0 || buf->len == 0);
-}
-
-void ssl_read_buffer_discard(SSL *ssl) {
- if (ssl->s3->read_buffer.len == 0) {
- ssl_read_buffer_clear(ssl);
- }
-}
-
-void ssl_read_buffer_clear(SSL *ssl) {
- clear_buffer(&ssl->s3->read_buffer);
-}
-
int ssl_handle_open_record(SSL *ssl, bool *out_retry, ssl_open_record_t ret,
size_t consumed, uint8_t alert) {
*out_retry = false;
if (ret != ssl_open_record_partial) {
- ssl_read_buffer_consume(ssl, consumed);
+ ssl->s3->read_buffer.Consume(consumed);
}
if (ret != ssl_open_record_success) {
// Nothing was returned to the caller, so discard anything marked consumed.
- ssl_read_buffer_discard(ssl);
+ ssl->s3->read_buffer.DiscardConsumed();
}
switch (ret) {
case ssl_open_record_success:
@@ -243,10 +225,6 @@
}
-int ssl_write_buffer_is_pending(const SSL *ssl) {
- return ssl->s3->write_buffer.len > 0;
-}
-
static_assert(SSL3_RT_HEADER_LENGTH * 2 +
SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD * 2 +
SSL3_RT_MAX_PLAIN_LENGTH <=
@@ -258,61 +236,37 @@
0xffff,
"maximum DTLS write buffer is too large");
-int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) {
- SSL3_BUFFER *buf = &ssl->s3->write_buffer;
-
- if (buf->buf != NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!ensure_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) {
- return 0;
- }
- *out_ptr = buf->buf + buf->offset;
- return 1;
-}
-
-void ssl_write_buffer_set_len(SSL *ssl, size_t len) {
- SSL3_BUFFER *buf = &ssl->s3->write_buffer;
-
- if (len > buf->cap) {
- abort();
- }
- buf->len = len;
-}
-
static int tls_write_buffer_flush(SSL *ssl) {
- SSL3_BUFFER *buf = &ssl->s3->write_buffer;
+ SSLBuffer *buf = &ssl->s3->write_buffer;
- while (buf->len > 0) {
- int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
+ while (!buf->empty()) {
+ int ret = BIO_write(ssl->wbio, buf->data(), buf->size());
if (ret <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
return ret;
}
- consume_buffer(buf, (size_t)ret);
+ buf->Consume(static_cast<size_t>(ret));
}
- ssl_write_buffer_clear(ssl);
+ buf->Clear();
return 1;
}
static int dtls_write_buffer_flush(SSL *ssl) {
- SSL3_BUFFER *buf = &ssl->s3->write_buffer;
- if (buf->len == 0) {
+ SSLBuffer *buf = &ssl->s3->write_buffer;
+ if (buf->empty()) {
return 1;
}
- int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
+ int ret = BIO_write(ssl->wbio, buf->data(), buf->size());
if (ret <= 0) {
- ssl->rwstate = SSL_WRITING;
+ ssl->s3->rwstate = SSL_WRITING;
// If the write failed, drop the write buffer anyway. Datagram transports
// can't write half a packet, so the caller is expected to retry from the
// top.
- ssl_write_buffer_clear(ssl);
+ buf->Clear();
return ret;
}
- ssl_write_buffer_clear(ssl);
+ buf->Clear();
return 1;
}
@@ -329,8 +283,4 @@
}
}
-void ssl_write_buffer_clear(SSL *ssl) {
- clear_buffer(&ssl->s3->write_buffer);
-}
-
} // namespace bssl
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index e3f8a88..2fc6ffd 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -201,20 +201,19 @@
void ssl_reset_error_state(SSL *ssl) {
// Functions which use |SSL_get_error| must reset I/O and error state on
// entry.
- ssl->rwstate = SSL_NOTHING;
+ ssl->s3->rwstate = SSL_NOTHING;
ERR_clear_error();
ERR_clear_system_error();
}
void ssl_set_read_error(SSL* ssl) {
ssl->s3->read_shutdown = ssl_shutdown_error;
- ERR_SAVE_STATE_free(ssl->s3->read_error);
- ssl->s3->read_error = ERR_save_state();
+ ssl->s3->read_error.reset(ERR_save_state());
}
static bool check_read_error(const SSL *ssl) {
if (ssl->s3->read_shutdown == ssl_shutdown_error) {
- ERR_restore_state(ssl->s3->read_error);
+ ERR_restore_state(ssl->s3->read_error.get());
return false;
}
return true;
@@ -300,16 +299,16 @@
// A client may see new sessions on abbreviated handshakes if the server
// decides to renew the ticket. Once the handshake is completed, it should be
// inserted into the cache.
- if (ssl->s3->established_session != ssl->session ||
+ if (ssl->s3->established_session.get() != ssl->session ||
(!ssl->server && hs->ticket_expected)) {
if (use_internal_cache) {
- SSL_CTX_add_session(ctx, ssl->s3->established_session);
+ SSL_CTX_add_session(ctx, ssl->s3->established_session.get());
}
if (ctx->new_session_cb != NULL) {
- SSL_SESSION_up_ref(ssl->s3->established_session);
- if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
+ SSL_SESSION_up_ref(ssl->s3->established_session.get());
+ if (!ctx->new_session_cb(ssl, ssl->s3->established_session.get())) {
// |new_session_cb|'s return value signals whether it took ownership.
- SSL_SESSION_free(ssl->s3->established_session);
+ SSL_SESSION_free(ssl->s3->established_session.get());
}
}
}
@@ -717,8 +716,6 @@
goto err;
}
- ssl->rwstate = SSL_NOTHING;
-
CRYPTO_new_ex_data(&ssl->ex_data);
ssl->psk_identity_hint = NULL;
@@ -763,8 +760,6 @@
BIO_free_all(ssl->rbio);
BIO_free_all(ssl->wbio);
- BUF_MEM_free(ssl->init_buf);
-
// add extra stuff
ssl_cipher_preference_list_free(ssl->cipher_list);
@@ -860,7 +855,7 @@
}
// Run the handshake.
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL_HANDSHAKE *hs = ssl->s3->hs.get();
bool early_return = false;
int ret = ssl_run_handshake(hs, &early_return);
@@ -872,8 +867,7 @@
// Destroy the handshake object if the handshake has completely finished.
if (!early_return) {
- ssl_handshake_free(ssl->s3->hs);
- ssl->s3->hs = NULL;
+ ssl->s3->hs.reset();
}
return 1;
@@ -937,18 +931,18 @@
// protocol, namely in HTTPS, just before reading the HTTP response. Require
// the record-layer be idle and avoid complexities of sending a handshake
// record while an application_data record is being written.
- if (ssl_write_buffer_is_pending(ssl) ||
+ if (!ssl->s3->write_buffer.empty() ||
ssl->s3->write_shutdown != ssl_shutdown_none) {
goto no_renegotiation;
}
// Begin a new handshake.
- if (ssl->s3->hs != NULL) {
+ if (ssl->s3->hs != nullptr) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
ssl->s3->hs = ssl_handshake_new(ssl);
- if (ssl->s3->hs == NULL) {
+ if (ssl->s3->hs == nullptr) {
return 0;
}
@@ -1004,7 +998,7 @@
uint8_t alert = SSL_AD_DECODE_ERROR;
size_t consumed = 0;
auto ret = ssl_open_app_data(ssl, &ssl->s3->pending_app_data, &consumed,
- &alert, ssl_read_buffer(ssl));
+ &alert, ssl->s3->read_buffer.span());
bool retry;
int bio_ret = ssl_handle_open_record(ssl, &retry, ret, consumed, alert);
if (bio_ret <= 0) {
@@ -1029,7 +1023,7 @@
ssl->s3->pending_app_data =
ssl->s3->pending_app_data.subspan(static_cast<size_t>(ret));
if (ssl->s3->pending_app_data.empty()) {
- ssl_read_buffer_discard(ssl);
+ ssl->s3->read_buffer.DiscardConsumed();
}
return ret;
}
@@ -1125,7 +1119,7 @@
// time out because the peer never received our close_notify. Report to
// the caller that the channel has fully shut down.
if (ssl->s3->read_shutdown == ssl_shutdown_error) {
- ERR_restore_state(ssl->s3->read_error);
+ ERR_restore_state(ssl->s3->read_error.get());
return -1;
}
ssl->s3->read_shutdown = ssl_shutdown_close_notify;
@@ -1190,7 +1184,7 @@
}
void SSL_reset_early_data_reject(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL_HANDSHAKE *hs = ssl->s3->hs.get();
if (hs == NULL ||
hs->wait != ssl_hs_early_data_rejected) {
abort();
@@ -1242,7 +1236,7 @@
return SSL_ERROR_SYSCALL;
}
- switch (ssl->rwstate) {
+ switch (ssl->s3->rwstate) {
case SSL_PENDING_SESSION:
return SSL_ERROR_PENDING_SESSION;
@@ -1863,7 +1857,7 @@
return ssl->tlsext_hostname;
}
- return ssl->s3->hostname;
+ return ssl->s3->hostname.get();
}
int SSL_get_servername_type(const SSL *ssl) {
@@ -1996,8 +1990,8 @@
void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data,
unsigned *out_len) {
- *out_data = ssl->s3->next_proto_negotiated;
- *out_len = ssl->s3->next_proto_negotiated_len;
+ *out_data = ssl->s3->next_proto_negotiated.data();
+ *out_len = ssl->s3->next_proto_negotiated.size();
}
void SSL_CTX_set_next_protos_advertised_cb(
@@ -2054,8 +2048,8 @@
*out_data = ssl->s3->hs->early_session->early_alpn;
*out_len = ssl->s3->hs->early_session->early_alpn_len;
} else {
- *out_data = ssl->s3->alpn_selected;
- *out_len = ssl->s3->alpn_selected_len;
+ *out_data = ssl->s3->alpn_selected.data();
+ *out_len = ssl->s3->alpn_selected.size();
}
}
@@ -2296,7 +2290,7 @@
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
-int SSL_want(const SSL *ssl) { return ssl->rwstate; }
+int SSL_want(const SSL *ssl) { return ssl->s3->rwstate; }
void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
RSA *(*cb)(SSL *ssl, int is_export,
@@ -2434,7 +2428,7 @@
// This returns false once all the handshake state has been finalized, to
// allow callbacks and getters based on SSL_in_init to return the correct
// values.
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL_HANDSHAKE *hs = ssl->s3->hs.get();
return hs != nullptr && !hs->handshake_finalized;
}
@@ -2547,7 +2541,7 @@
}
const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL_HANDSHAKE *hs = ssl->s3->hs.get();
if (hs == NULL) {
return NULL;
}
@@ -2574,23 +2568,12 @@
// In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously
// established session to be offered the next time around. wpa_supplicant
// depends on this behavior, so emulate it.
- SSL_SESSION *session = NULL;
+ UniquePtr<SSL_SESSION> session;
if (!ssl->server && ssl->s3->established_session != NULL) {
- session = ssl->s3->established_session;
- SSL_SESSION_up_ref(session);
+ session.reset(ssl->s3->established_session.get());
+ SSL_SESSION_up_ref(session.get());
}
- // TODO(davidben): Some state on |ssl| is reset both in |SSL_new| and
- // |SSL_clear| because it is per-connection state rather than configuration
- // state. Per-connection state should be on |ssl->s3| and |ssl->d1| so it is
- // naturally reset at the right points between |SSL_new|, |SSL_clear|, and
- // |ssl3_new|.
-
- ssl->rwstate = SSL_NOTHING;
-
- BUF_MEM_free(ssl->init_buf);
- ssl->init_buf = NULL;
-
// The ssl->d1->mtu is simultaneously configuration (preserved across
// clear) and connection-specific state (gets reset).
//
@@ -2602,7 +2585,6 @@
ssl->method->ssl_free(ssl);
if (!ssl->method->ssl_new(ssl)) {
- SSL_SESSION_free(session);
return 0;
}
@@ -2610,9 +2592,8 @@
ssl->d1->mtu = mtu;
}
- if (session != NULL) {
- SSL_set_session(ssl, session);
- SSL_SESSION_free(session);
+ if (session != nullptr) {
+ SSL_set_session(ssl, session.get());
}
return 1;
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index ea3c53f..34e7b31 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -999,9 +999,9 @@
// we return the intermediate session, either |session| (for resumption) or
// |new_session| if doing a full handshake.
if (!SSL_in_init(ssl)) {
- return ssl->s3->established_session;
+ return ssl->s3->established_session.get();
}
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL_HANDSHAKE *hs = ssl->s3->hs.get();
if (hs->early_session) {
return hs->early_session.get();
}
diff --git a/src/ssl/ssl_stat.cc b/src/ssl/ssl_stat.cc
index 37e0324..01153e9 100644
--- a/src/ssl/ssl_stat.cc
+++ b/src/ssl/ssl_stat.cc
@@ -89,12 +89,12 @@
const char *SSL_state_string_long(const SSL *ssl) {
- if (ssl->s3->hs == NULL) {
+ if (ssl->s3->hs == nullptr) {
return "SSL negotiation finished successfully";
}
- return ssl->server ? ssl_server_handshake_state(ssl->s3->hs)
- : ssl_client_handshake_state(ssl->s3->hs);
+ return ssl->server ? ssl_server_handshake_state(ssl->s3->hs.get())
+ : ssl_client_handshake_state(ssl->s3->hs.get());
}
const char *SSL_state_string(const SSL *ssl) {
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 5e9cde1..ab50a57 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -75,10 +75,7 @@
{TLS1_VERSION, VersionParam::is_tls, "TLS1"},
{TLS1_1_VERSION, VersionParam::is_tls, "TLS1_1"},
{TLS1_2_VERSION, VersionParam::is_tls, "TLS1_2"},
-// TLS 1.3 requires RSA-PSS, which is disabled for Android system builds.
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
{TLS1_3_VERSION, VersionParam::is_tls, "TLS1_3"},
-#endif
{DTLS1_VERSION, VersionParam::is_dtls, "DTLS1"},
{DTLS1_2_VERSION, VersionParam::is_dtls, "DTLS1_2"},
};
@@ -1974,8 +1971,6 @@
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}},
- // 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,
@@ -1990,7 +1985,6 @@
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
// TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
// implementation has settled enough that it won't change.
};
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index e1578bd..1298a10 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -316,68 +316,65 @@
return 1;
}
-static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- if (!hs->key_block.empty()) {
- return 1;
- }
-
- SSL_SESSION *session = ssl->session;
- if (hs->new_session) {
- session = hs->new_session.get();
- }
-
+static bool get_key_block_lengths(const SSL *ssl, size_t *out_mac_secret_len,
+ size_t *out_key_len, size_t *out_iv_len,
+ const SSL_CIPHER *cipher) {
const EVP_AEAD *aead = NULL;
- size_t mac_secret_len, fixed_iv_len;
- if (session->cipher == NULL ||
- !ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
- session->cipher, ssl_protocol_version(ssl),
- SSL_is_dtls(ssl))) {
+ if (!ssl_cipher_get_evp_aead(&aead, out_mac_secret_len, out_iv_len, cipher,
+ ssl_protocol_version(ssl), SSL_is_dtls(ssl))) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
- return 0;
+ return false;
}
- size_t key_len = EVP_AEAD_key_length(aead);
- if (mac_secret_len > 0) {
+
+ *out_key_len = EVP_AEAD_key_length(aead);
+ if (*out_mac_secret_len > 0) {
// For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
// key length reported by |EVP_AEAD_key_length| will include the MAC key
// bytes and initial implicit IV.
- if (key_len < mac_secret_len + fixed_iv_len) {
+ if (*out_key_len < *out_mac_secret_len + *out_iv_len) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return 0;
+ return false;
}
- key_len -= mac_secret_len + fixed_iv_len;
+ *out_key_len -= *out_mac_secret_len + *out_iv_len;
}
- assert(mac_secret_len < 256);
- assert(key_len < 256);
- assert(fixed_iv_len < 256);
+ return true;
+}
- ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
- ssl->s3->tmp.new_key_len = (uint8_t)key_len;
- ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
+static bool setup_key_block(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (!hs->key_block.empty()) {
+ return true;
+ }
+ size_t mac_secret_len, key_len, fixed_iv_len;
Array<uint8_t> key_block;
- if (!key_block.Init(SSL_get_key_block_len(ssl)) ||
+ if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &fixed_iv_len,
+ hs->new_cipher) ||
+ !key_block.Init(2 * (mac_secret_len + key_len + fixed_iv_len)) ||
!SSL_generate_key_block(ssl, key_block.data(), key_block.size())) {
- return 0;
+ return false;
}
hs->key_block = std::move(key_block);
- return 1;
+ return true;
}
int tls1_change_cipher_state(SSL_HANDSHAKE *hs,
evp_aead_direction_t direction) {
SSL *const ssl = hs->ssl;
// Ensure the key block is set up.
- if (!tls1_setup_key_block(hs)) {
+ size_t mac_secret_len, key_len, iv_len;
+ if (!setup_key_block(hs) ||
+ !get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len,
+ hs->new_cipher)) {
return 0;
}
- size_t mac_secret_len = ssl->s3->tmp.new_mac_secret_len;
- size_t key_len = ssl->s3->tmp.new_key_len;
- size_t iv_len = ssl->s3->tmp.new_fixed_iv_len;
- assert((mac_secret_len + key_len + iv_len) * 2 == hs->key_block.size());
+ if ((mac_secret_len + key_len + iv_len) * 2 != hs->key_block.size()) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
Span<const uint8_t> key_block = hs->key_block;
Span<const uint8_t> mac_secret, key, iv;
@@ -448,9 +445,14 @@
using namespace bssl;
size_t SSL_get_key_block_len(const SSL *ssl) {
- return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
- (size_t)ssl->s3->tmp.new_key_len +
- (size_t)ssl->s3->tmp.new_fixed_iv_len);
+ size_t mac_secret_len, key_len, fixed_iv_len;
+ if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &fixed_iv_len,
+ SSL_get_current_cipher(ssl))) {
+ ERR_clear_error();
+ return 0;
+ }
+
+ return 2 * (mac_secret_len + key_len + fixed_iv_len);
}
int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 5d85cb0..31b51c9 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -418,25 +418,15 @@
// List our preferred algorithms first.
SSL_SIGN_ED25519,
SSL_SIGN_ECDSA_SECP256R1_SHA256,
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA256,
-#endif
SSL_SIGN_RSA_PKCS1_SHA256,
// Larger hashes are acceptable.
SSL_SIGN_ECDSA_SECP384R1_SHA384,
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA384,
-#endif
SSL_SIGN_RSA_PKCS1_SHA384,
- // TODO(davidben): Remove this.
-#if defined(BORINGSSL_ANDROID_SYSTEM)
- SSL_SIGN_ECDSA_SECP521R1_SHA512,
-#endif
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA512,
-#endif
SSL_SIGN_RSA_PKCS1_SHA512,
// For now, SHA-1 is still accepted but least preferable.
@@ -454,24 +444,18 @@
// List our preferred algorithms first.
SSL_SIGN_ED25519,
SSL_SIGN_ECDSA_SECP256R1_SHA256,
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA256,
-#endif
SSL_SIGN_RSA_PKCS1_SHA256,
// If needed, sign larger hashes.
//
// TODO(davidben): Determine which of these may be pruned.
SSL_SIGN_ECDSA_SECP384R1_SHA384,
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA384,
-#endif
SSL_SIGN_RSA_PKCS1_SHA384,
SSL_SIGN_ECDSA_SECP521R1_SHA512,
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
SSL_SIGN_RSA_PSS_SHA512,
-#endif
SSL_SIGN_RSA_PKCS1_SHA512,
// If the peer supports nothing else, sign with SHA-1.
@@ -640,10 +624,12 @@
}
// Copy the hostname as a string.
- if (!CBS_strdup(&host_name, &ssl->s3->hostname)) {
+ char *raw = nullptr;
+ if (!CBS_strdup(&host_name, &raw)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return false;
}
+ ssl->s3->hostname.reset(raw);
hs->should_ack_sni = true;
return true;
@@ -862,7 +848,7 @@
}
// Whether EMS is negotiated may not change on renegotiation.
- if (ssl->s3->established_session != NULL &&
+ if (ssl->s3->established_session != nullptr &&
hs->extended_master_secret !=
!!ssl->s3->established_session->extended_master_secret) {
OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
@@ -1150,7 +1136,7 @@
assert(!SSL_is_dtls(ssl));
assert(ssl->ctx->next_proto_select_cb != NULL);
- if (ssl->s3->alpn_selected != NULL) {
+ if (!ssl->s3->alpn_selected.empty()) {
// NPN and ALPN may not be negotiated in the same connection.
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
@@ -1172,22 +1158,14 @@
uint8_t selected_len;
if (ssl->ctx->next_proto_select_cb(
ssl, &selected, &selected_len, orig_contents, orig_len,
- ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK) {
+ ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK ||
+ !ssl->s3->next_proto_negotiated.CopyFrom(
+ MakeConstSpan(selected, selected_len))) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return false;
}
- OPENSSL_free(ssl->s3->next_proto_negotiated);
- ssl->s3->next_proto_negotiated =
- (uint8_t *)BUF_memdup(selected, selected_len);
- if (ssl->s3->next_proto_negotiated == NULL) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return false;
- }
-
- ssl->s3->next_proto_negotiated_len = selected_len;
hs->next_proto_neg_seen = true;
-
return true;
}
@@ -1388,37 +1366,13 @@
return false;
}
- if (!ssl->ctx->allow_unknown_alpn_protos) {
- // Check that the protocol name is one of the ones we advertised.
- bool protocol_ok = false;
- CBS client_protocol_name_list, client_protocol_name;
- CBS_init(&client_protocol_name_list, ssl->alpn_client_proto_list,
- ssl->alpn_client_proto_list_len);
- while (CBS_len(&client_protocol_name_list) > 0) {
- if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
- &client_protocol_name)) {
- *out_alert = SSL_AD_INTERNAL_ERROR;
- return false;
- }
-
- if (CBS_len(&client_protocol_name) == CBS_len(&protocol_name) &&
- OPENSSL_memcmp(CBS_data(&client_protocol_name),
- CBS_data(&protocol_name),
- CBS_len(&protocol_name)) == 0) {
- protocol_ok = true;
- break;
- }
- }
-
- if (!protocol_ok) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
- *out_alert = SSL_AD_ILLEGAL_PARAMETER;
- return false;
- }
+ if (!ssl_is_alpn_protocol_allowed(ssl, protocol_name)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+ return false;
}
- if (!CBS_stow(&protocol_name, &ssl->s3->alpn_selected,
- &ssl->s3->alpn_selected_len)) {
+ if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return false;
}
@@ -1426,6 +1380,34 @@
return true;
}
+bool ssl_is_alpn_protocol_allowed(const SSL *ssl,
+ Span<const uint8_t> protocol) {
+ if (ssl->alpn_client_proto_list == nullptr) {
+ return false;
+ }
+
+ if (ssl->ctx->allow_unknown_alpn_protos) {
+ return true;
+ }
+
+ // Check that the protocol name is one of the ones we advertised.
+ CBS client_protocol_name_list, client_protocol_name;
+ CBS_init(&client_protocol_name_list, ssl->alpn_client_proto_list,
+ ssl->alpn_client_proto_list_len);
+ while (CBS_len(&client_protocol_name_list) > 0) {
+ if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
+ &client_protocol_name)) {
+ return false;
+ }
+
+ if (client_protocol_name == protocol) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
const SSL_CLIENT_HELLO *client_hello) {
SSL *const ssl = hs->ssl;
@@ -1470,13 +1452,11 @@
ssl, &selected, &selected_len, CBS_data(&protocol_name_list),
CBS_len(&protocol_name_list),
ssl->ctx->alpn_select_cb_arg) == SSL_TLSEXT_ERR_OK) {
- OPENSSL_free(ssl->s3->alpn_selected);
- ssl->s3->alpn_selected = (uint8_t *)BUF_memdup(selected, selected_len);
- if (ssl->s3->alpn_selected == NULL) {
+ if (!ssl->s3->alpn_selected.CopyFrom(
+ MakeConstSpan(selected, selected_len))) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return false;
}
- ssl->s3->alpn_selected_len = selected_len;
}
return true;
@@ -1484,7 +1464,7 @@
static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (ssl->s3->alpn_selected == NULL) {
+ if (ssl->s3->alpn_selected.empty()) {
return true;
}
@@ -1493,8 +1473,8 @@
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &proto_list) ||
!CBB_add_u8_length_prefixed(&proto_list, &proto) ||
- !CBB_add_bytes(&proto, ssl->s3->alpn_selected,
- ssl->s3->alpn_selected_len) ||
+ !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(),
+ ssl->s3->alpn_selected.size()) ||
!CBB_flush(out)) {
return false;
}
@@ -1998,11 +1978,19 @@
static bool ext_early_data_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
SSL *const ssl = hs->ssl;
- if (ssl->session == NULL ||
+ if (!ssl->cert->enable_early_data ||
+ // Session must be 0-RTT capable.
+ ssl->session == NULL ||
ssl_session_protocol_version(ssl->session) < TLS1_3_VERSION ||
ssl->session->ticket_max_early_data == 0 ||
+ // The second ClientHello never offers early data.
hs->received_hello_retry_request ||
- !ssl->cert->enable_early_data) {
+ // In case ALPN preferences changed since this session was established,
+ // avoid reporting a confusing value in |SSL_get0_alpn_selected|.
+ (ssl->session->early_alpn_len != 0 &&
+ !ssl_is_alpn_protocol_allowed(
+ ssl, MakeConstSpan(ssl->session->early_alpn,
+ ssl->session->early_alpn_len)))) {
return true;
}
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 1d7b996..d439cb5 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -1101,7 +1101,6 @@
// Connect returns a new socket connected to localhost on |port| or -1 on
// error.
static int Connect(uint16_t port) {
- time_t start_time = time(nullptr);
for (int af : { AF_INET6, AF_INET }) {
int sock = socket(af, SOCK_STREAM, 0);
if (sock == -1) {
@@ -1148,11 +1147,6 @@
}
PrintSocketError("connect");
- // TODO(davidben): Remove this logging when https://crbug.com/boringssl/199 is
- // resolved.
- fprintf(stderr, "start_time = %lld, end_time = %lld\n",
- static_cast<long long>(start_time),
- static_cast<long long>(time(nullptr)));
return -1;
}
@@ -2201,6 +2195,12 @@
return false;
}
+ if (is_resume && !is_retry && !config->is_server &&
+ config->expect_no_offer_early_data && SSL_in_early_data(ssl)) {
+ fprintf(stderr, "Client unexpectedly offered early data.\n");
+ return false;
+ }
+
if (config->handshake_twice) {
do {
ret = SSL_do_handshake(ssl);
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 0edbe5c..71b52f2 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -244,14 +244,6 @@
hc.incEpoch()
}
-func (hc *halfConn) doKeyUpdate(c *Conn, isOutgoing bool) {
- side := serverWrite
- if c.isClient == isOutgoing {
- side = clientWrite
- }
- hc.useTrafficSecret(hc.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), side)
-}
-
// incSeq increments the sequence number.
func (hc *halfConn) incSeq(isOutgoing bool) {
limit := 0
@@ -737,6 +729,26 @@
return b, bb
}
+func (c *Conn) useInTrafficSecret(version uint16, suite *cipherSuite, secret []byte) error {
+ if c.hand.Len() != 0 {
+ return c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change"))
+ }
+ side := serverWrite
+ if !c.isClient {
+ side = clientWrite
+ }
+ c.in.useTrafficSecret(version, suite, secret, side)
+ return nil
+}
+
+func (c *Conn) useOutTrafficSecret(version uint16, suite *cipherSuite, secret []byte) {
+ side := serverWrite
+ if c.isClient {
+ side = clientWrite
+ }
+ c.out.useTrafficSecret(version, suite, secret, side)
+}
+
func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
RestartReadRecord:
if c.isDTLS {
@@ -940,8 +952,11 @@
break
}
if !isResumptionExperiment(c.wireVersion) {
- err := c.in.changeCipherSpec(c.config)
- if err != nil {
+ if c.hand.Len() != 0 {
+ c.in.setErrorLocked(errors.New("tls: buffered handshake messages on cipher change"))
+ break
+ }
+ if err := c.in.changeCipherSpec(c.config); err != nil {
c.in.setErrorLocked(c.sendAlert(err.(alert)))
}
}
@@ -1522,7 +1537,9 @@
if c.config.Bugs.RejectUnsolicitedKeyUpdate {
return errors.New("tls: unexpected KeyUpdate message")
}
- c.in.doKeyUpdate(c, false)
+ if err := c.useInTrafficSecret(c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.in.trafficSecret)); err != nil {
+ return err
+ }
if keyUpdate.keyUpdateRequest == keyUpdateRequested {
c.keyUpdateRequested = true
}
@@ -1554,8 +1571,7 @@
return errors.New("tls: received invalid KeyUpdate message")
}
- c.in.doKeyUpdate(c, false)
- return nil
+ return c.useInTrafficSecret(c.in.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.in.trafficSecret))
}
func (c *Conn) Renegotiate() error {
@@ -1885,7 +1901,7 @@
if err := c.flushHandshake(); err != nil {
return err
}
- c.out.doKeyUpdate(c, true)
+ c.useOutTrafficSecret(c.out.wireVersion, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), c.out.trafficSecret))
return nil
}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index ef6a464..30105a5 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -411,7 +411,7 @@
finishedHash.addEntropy(session.masterSecret)
finishedHash.Write(helloBytes)
earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
- c.out.useTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret, clientWrite)
+ c.useOutTrafficSecret(session.wireVersion, pskCipherSuite, earlyTrafficSecret)
for _, earlyData := range c.config.Bugs.SendEarlyData {
if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
return err
@@ -754,7 +754,9 @@
// traffic key.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
- c.in.useTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+ if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret); err != nil {
+ return err
+ }
msg, err := c.readHandshake()
if err != nil {
@@ -888,7 +890,9 @@
// Switch to application data keys on read. In particular, any alerts
// from the client certificate are read over these keys.
- c.in.useTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret, serverWrite)
+ if err := c.useInTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret); err != nil {
+ return err
+ }
// If we're expecting 0.5-RTT messages from the server, read them
// now.
@@ -934,7 +938,7 @@
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
- c.out.useTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+ c.useOutTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret)
if certReq != nil && !c.config.Bugs.SkipClientCertificate {
certMsg := &certificateMsg{
@@ -1020,7 +1024,7 @@
c.flushHandshake()
// Switch to application data keys.
- c.out.useTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret, clientWrite)
+ c.useOutTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret)
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
return nil
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 0ffb72c..f50772e 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -648,8 +648,7 @@
// AcceptAnyBinder is set. See https://crbug.com/115.
if hs.sessionState != nil && !config.Bugs.AcceptAnySession {
binderToVerify := newClientHello.pskBinders[pskIndex]
- err := verifyPSKBinder(newClientHello, hs.sessionState, binderToVerify, append(oldClientHelloBytes, helloRetryRequest.marshal()...))
- if err != nil {
+ if err := verifyPSKBinder(newClientHello, hs.sessionState, binderToVerify, append(oldClientHelloBytes, helloRetryRequest.marshal()...)); err != nil {
return err
}
}
@@ -664,7 +663,9 @@
}
if encryptedExtensions.extensions.hasEarlyData {
earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
- c.in.useTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret, clientWrite)
+ if err := c.useInTrafficSecret(c.wireVersion, hs.suite, earlyTrafficSecret); err != nil {
+ return err
+ }
for _, expectedMsg := range config.Bugs.ExpectEarlyData {
if err := c.readRecord(recordTypeApplicationData); err != nil {
@@ -761,7 +762,7 @@
// Switch to handshake traffic keys.
serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
- c.out.useTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+ c.useOutTrafficSecret(c.wireVersion, hs.suite, serverHandshakeTrafficSecret)
// Derive handshake traffic read key, but don't switch yet.
clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
@@ -902,7 +903,7 @@
// Switch to application data keys on write. In particular, any alerts
// from the client certificate are sent over these keys.
- c.out.useTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret, serverWrite)
+ c.useOutTrafficSecret(c.wireVersion, hs.suite, serverTrafficSecret)
// Send 0.5-RTT messages.
for _, halfRTTMsg := range config.Bugs.SendHalfRTTData {
@@ -928,7 +929,9 @@
}
// Switch input stream to handshake traffic keys.
- c.in.useTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+ if err := c.useInTrafficSecret(c.wireVersion, hs.suite, clientHandshakeTrafficSecret); err != nil {
+ return err
+ }
// If we requested a client certificate, then the client must send a
// certificate message, even if it's empty.
@@ -1032,7 +1035,9 @@
hs.writeClientHash(clientFinished.marshal())
// Switch to application data keys on read.
- c.in.useTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret, clientWrite)
+ if err := c.useInTrafficSecret(c.wireVersion, hs.suite, clientTrafficSecret); err != nil {
+ return err
+ }
c.cipherSuite = hs.suite
c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index e666404..d34eaa6 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -901,28 +901,20 @@
// exit first.
func acceptOrWait(listener *net.TCPListener, waitChan chan error) (net.Conn, error) {
type connOrError struct {
- conn net.Conn
- err error
- startTime, endTime time.Time
+ conn net.Conn
+ err error
}
connChan := make(chan connOrError, 1)
go func() {
- startTime := time.Now()
if !*useGDB {
listener.SetDeadline(time.Now().Add(*idleTimeout))
}
conn, err := listener.Accept()
- endTime := time.Now()
- connChan <- connOrError{conn, err, startTime, endTime}
+ connChan <- connOrError{conn, err}
close(connChan)
}()
select {
case result := <-connChan:
- if result.err != nil {
- // TODO(davidben): Remove this logging when
- // https://crbug.com/boringssl/199 is resolved.
- fmt.Fprintf(os.Stderr, "acceptOrWait failed, startTime=%v, endTime=%v\n", result.startTime, result.endTime)
- }
return result.conn, result.err
case childErr := <-waitChan:
waitChan <- childErr
@@ -2761,11 +2753,12 @@
},
},
{
- // Test the server so there is a large certificate as
- // well as application data.
+ // Test the TLS 1.2 server so there is a large
+ // unencrypted certificate as well as application data.
testType: serverTest,
- name: "MaxSendFragment",
+ name: "MaxSendFragment-TLS12",
config: Config{
+ MaxVersion: VersionTLS12,
Bugs: ProtocolBugs{
MaxReceivePlaintext: 512,
},
@@ -2777,11 +2770,50 @@
},
},
{
- // Test the server so there is a large certificate as
- // well as application data.
+ // Test the TLS 1.2 server so there is a large
+ // unencrypted certificate as well as application data.
testType: serverTest,
- name: "MaxSendFragment-TooLarge",
+ name: "MaxSendFragment-TLS12-TooLarge",
config: Config{
+ MaxVersion: VersionTLS12,
+ Bugs: ProtocolBugs{
+ // Ensure that some of the records are
+ // 512.
+ MaxReceivePlaintext: 511,
+ },
+ },
+ messageLen: 1024,
+ flags: []string{
+ "-max-send-fragment", "512",
+ "-read-size", "1024",
+ },
+ shouldFail: true,
+ expectedLocalError: "local error: record overflow",
+ },
+ {
+ // Test the TLS 1.3 server so there is a large encrypted
+ // certificate as well as application data.
+ testType: serverTest,
+ name: "MaxSendFragment-TLS13",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ MaxReceivePlaintext: 512,
+ },
+ },
+ messageLen: 1024,
+ flags: []string{
+ "-max-send-fragment", "512",
+ "-read-size", "1024",
+ },
+ },
+ {
+ // Test the TLS 1.3 server so there is a large encrypted
+ // certificate as well as application data.
+ testType: serverTest,
+ name: "MaxSendFragment-TLS13-TooLarge",
+ config: Config{
+ MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
// Ensure that some of the records are
// 512.
@@ -11726,6 +11758,28 @@
expectedError: ":ALPN_MISMATCH_ON_EARLY_DATA:",
})
+ // Test that the client does not offer early data if it is incompatible
+ // with ALPN preferences.
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-ALPNPreferenceChanged",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ NextProtos: []string{"foo", "bar"},
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-no-offer-early-data",
+ "-on-initial-advertise-alpn", "\x03foo",
+ "-on-resume-advertise-alpn", "\x03bar",
+ "-on-initial-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "bar",
+ },
+ })
+
// Test that the server correctly rejects 0-RTT when the previous
// session did not allow early data on resumption.
testCases = append(testCases, testCase{
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 6df8d2a..3354851 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -121,6 +121,7 @@
{ "-expect-no-session-id", &TestConfig::expect_no_session_id },
{ "-expect-accept-early-data", &TestConfig::expect_accept_early_data },
{ "-expect-reject-early-data", &TestConfig::expect_reject_early_data },
+ { "-expect-no-offer-early-data", &TestConfig::expect_no_offer_early_data },
{ "-no-op-extra-handshake", &TestConfig::no_op_extra_handshake },
{ "-handshake-twice", &TestConfig::handshake_twice },
{ "-allow-unknown-alpn-protos", &TestConfig::allow_unknown_alpn_protos },
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 9af64bc..b96d9e5 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -90,6 +90,7 @@
bool expect_early_data_info = false;
bool expect_accept_early_data = false;
bool expect_reject_early_data = false;
+ bool expect_no_offer_early_data = false;
bool use_ticket_callback = false;
bool renew_ticket = false;
bool enable_early_data = false;
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index a03c581..b6307ee 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -390,21 +390,21 @@
}
// Store the negotiated ALPN in the session.
- if (ssl->s3->alpn_selected != NULL) {
+ if (!ssl->s3->alpn_selected.empty()) {
hs->new_session->early_alpn = (uint8_t *)BUF_memdup(
- ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
+ ssl->s3->alpn_selected.data(), ssl->s3->alpn_selected.size());
if (hs->new_session->early_alpn == NULL) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
- hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
+ hs->new_session->early_alpn_len = ssl->s3->alpn_selected.size();
}
if (ssl->early_data_accepted) {
if (hs->early_session->cipher != hs->new_session->cipher ||
- hs->early_session->early_alpn_len != ssl->s3->alpn_selected_len ||
- OPENSSL_memcmp(hs->early_session->early_alpn, ssl->s3->alpn_selected,
- ssl->s3->alpn_selected_len) != 0) {
+ MakeConstSpan(hs->early_session->early_alpn,
+ hs->early_session->early_alpn_len) !=
+ ssl->s3->alpn_selected) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ALPN_MISMATCH_ON_EARLY_DATA);
return ssl_hs_error;
}
@@ -781,8 +781,8 @@
return 1;
}
- UniquePtr<SSL_SESSION> session(SSL_SESSION_dup(ssl->s3->established_session,
- SSL_SESSION_INCLUDE_NONAUTH));
+ UniquePtr<SSL_SESSION> session = SSL_SESSION_dup(
+ ssl->s3->established_session.get(), SSL_SESSION_INCLUDE_NONAUTH);
if (!session) {
return 0;
}
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 09437a5..89c9d46 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -371,8 +371,8 @@
hs->new_session =
SSL_SESSION_dup(session.get(), SSL_SESSION_DUP_AUTH_ONLY);
- if (// Early data must be acceptable for this ticket.
- ssl->cert->enable_early_data &&
+ if (ssl->cert->enable_early_data &&
+ // Early data must be acceptable for this ticket.
session->ticket_max_early_data != 0 &&
// The client must have offered early data.
hs->early_data_offered &&
@@ -381,9 +381,8 @@
// Custom extensions is incompatible with 0-RTT.
hs->custom_extensions.received == 0 &&
// The negotiated ALPN must match the one in the ticket.
- ssl->s3->alpn_selected_len == session->early_alpn_len &&
- OPENSSL_memcmp(ssl->s3->alpn_selected, session->early_alpn,
- ssl->s3->alpn_selected_len) == 0) {
+ ssl->s3->alpn_selected ==
+ MakeConstSpan(session->early_alpn, session->early_alpn_len)) {
ssl->early_data_accepted = true;
}
@@ -412,14 +411,14 @@
hs->new_session->cipher = hs->new_cipher;
// Store the initial negotiated ALPN in the session.
- if (ssl->s3->alpn_selected != NULL) {
+ if (!ssl->s3->alpn_selected.empty()) {
hs->new_session->early_alpn = (uint8_t *)BUF_memdup(
- ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
+ ssl->s3->alpn_selected.data(), ssl->s3->alpn_selected.size());
if (hs->new_session->early_alpn == NULL) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
- hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
+ hs->new_session->early_alpn_len = ssl->s3->alpn_selected.size();
}
if (ssl->ctx->dos_protection_cb != NULL &&
diff --git a/src/ssl/tls_method.cc b/src/ssl/tls_method.cc
index 94b9e20..c5b0178 100644
--- a/src/ssl/tls_method.cc
+++ b/src/ssl/tls_method.cc
@@ -73,14 +73,13 @@
// The handshake should have released its final message.
assert(!ssl->s3->has_message);
- // During the handshake, |init_buf| is retained. Release if it there is no
+ // During the handshake, |hs_buf| is retained. Release if it there is no
// excess in it. There may be excess left if there server sent Finished and
// HelloRequest in the same record.
//
// TODO(davidben): SChannel does not support this. Reject this case.
- if (ssl->init_buf != NULL && ssl->init_buf->length == 0) {
- BUF_MEM_free(ssl->init_buf);
- ssl->init_buf = NULL;
+ if (ssl->s3->hs_buf && ssl->s3->hs_buf->length == 0) {
+ ssl->s3->hs_buf.reset();
}
}
@@ -93,17 +92,13 @@
}
OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
-
- Delete(ssl->s3->aead_read_ctx);
- ssl->s3->aead_read_ctx = aead_ctx.release();
+ ssl->s3->aead_read_ctx = std::move(aead_ctx);
return true;
}
static bool ssl3_set_write_state(SSL *ssl, UniquePtr<SSLAEADContext> aead_ctx) {
OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
-
- Delete(ssl->s3->aead_write_ctx);
- ssl->s3->aead_write_ctx = aead_ctx.release();
+ ssl->s3->aead_write_ctx = std::move(aead_ctx);
return true;
}
diff --git a/src/util/BUILD.toplevel b/src/util/BUILD.toplevel
index af7bd30..6e569ec 100644
--- a/src/util/BUILD.toplevel
+++ b/src/util/BUILD.toplevel
@@ -46,6 +46,11 @@
values = {"cpu": "x64_windows"},
)
+config_setting(
+ name = "android",
+ values = {"crosstool_top": "//external:android/crosstool"}
+)
+
posix_copts = [
# Assembler option --noexecstack adds .note.GNU-stack to each object to
# ensure that binaries can be built with non-executable stack.
@@ -120,6 +125,9 @@
includes = ["src/include"],
linkopts = select({
":mac_x86_64": [],
+ # Android supports pthreads, but does not provide a libpthread
+ # to link against.
+ ":android": [],
"//conditions:default": ["-lpthread"],
}),
visibility = ["//visibility:public"],