summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2018-01-19 11:01:41 +0000
committerandroid-build-merger <android-build-merger@google.com>2018-01-19 11:01:41 +0000
commit7375becf5eb38f8e7cc10f10bb52186e559688f1 (patch)
tree3586ad210d439fd1afb10f66782babac5af5fe64
parentb7ace47a0bc07de8c61176ba2909751acc2a4a17 (diff)
parentbbd53e043de3f98f94c25727af15a50a9e10e2f6 (diff)
downloadboringssl-7375becf5eb38f8e7cc10f10bb52186e559688f1.tar.gz
NO PARTIAL RERUN external/boringssl: Sync to 37c6eb4284bea36be9fa41d35b582008f2023dcf. am: 0db7f543e9
am: bbd53e043d Change-Id: If8c3b62c84171fec7be3baf9d002927a7dfa49de
-rw-r--r--BORINGSSL_REVISION2
-rw-r--r--src/crypto/fipsmodule/bcm.c1
-rw-r--r--src/crypto/fipsmodule/ec/ec.c12
-rw-r--r--src/crypto/fipsmodule/ec/ec_key.c43
-rw-r--r--src/crypto/fipsmodule/ec/ec_test.cc13
-rw-r--r--src/crypto/fipsmodule/ec/internal.h12
-rw-r--r--src/crypto/fipsmodule/ec/oct.c73
-rw-r--r--src/crypto/fipsmodule/ec/p224-64.c69
-rw-r--r--src/crypto/fipsmodule/ec/simple.c26
-rw-r--r--src/crypto/fipsmodule/tls/internal.h39
-rw-r--r--src/crypto/fipsmodule/tls/kdf.c160
-rw-r--r--src/crypto/test/file_test.cc39
-rw-r--r--src/crypto/test/file_test.h9
-rw-r--r--src/crypto/test/file_test_gtest.cc2
-rw-r--r--src/fipstools/CMakeLists.txt2
-rw-r--r--src/fipstools/cavp_kas_test.cc160
-rw-r--r--src/fipstools/cavp_main.cc2
-rw-r--r--src/fipstools/cavp_test_util.h2
-rw-r--r--src/fipstools/cavp_tlskdf_test.cc111
-rw-r--r--src/fipstools/run_cavp.go118
-rw-r--r--src/include/openssl/base.h5
-rw-r--r--src/include/openssl/bio.h2
-rw-r--r--src/include/openssl/ssl.h17
-rw-r--r--src/include/openssl/stack.h2
-rw-r--r--src/include/openssl/tls1.h6
-rw-r--r--src/ssl/internal.h28
-rw-r--r--src/ssl/ssl_lib.cc9
-rw-r--r--src/ssl/ssl_test.cc2
-rw-r--r--src/ssl/ssl_versions.cc19
-rw-r--r--src/ssl/t1_enc.cc92
-rw-r--r--src/ssl/t1_lib.cc73
-rw-r--r--src/ssl/test/bssl_shim.cc4
-rw-r--r--src/ssl/test/runner/common.go23
-rw-r--r--src/ssl/test/runner/handshake_client.go5
-rw-r--r--src/ssl/test/runner/handshake_messages.go61
-rw-r--r--src/ssl/test/runner/handshake_server.go12
-rw-r--r--src/ssl/test/runner/runner.go53
-rw-r--r--src/ssl/test/test_config.cc1
-rw-r--r--src/ssl/test/test_config.h1
-rw-r--r--src/ssl/tls13_client.cc12
-rw-r--r--src/ssl/tls13_server.cc13
-rw-r--r--src/third_party/fiat/BUILD.gn4
-rw-r--r--src/third_party/fiat/README.chromium10
-rw-r--r--src/third_party/fiat/p256.c25
-rw-r--r--src/tool/client.cc2
-rw-r--r--src/util/bot/UPDATING6
-rw-r--r--src/util/bot/cmake-win32.zip.sha12
47 files changed, 1014 insertions, 370 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 509a8a9e..76dfcd61 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-9770532afa91dd1441ba0d3e9d4bb86d7e501f19
+37c6eb4284bea36be9fa41d35b582008f2023dcf
diff --git a/src/crypto/fipsmodule/bcm.c b/src/crypto/fipsmodule/bcm.c
index fb16215f..1e5742b1 100644
--- a/src/crypto/fipsmodule/bcm.c
+++ b/src/crypto/fipsmodule/bcm.c
@@ -87,6 +87,7 @@
#include "rsa/blinding.c"
#include "rsa/padding.c"
#include "rsa/rsa.c"
+#include "tls/kdf.c"
#include "rsa/rsa_impl.c"
#include "sha/sha1-altivec.c"
#include "sha/sha1.c"
diff --git a/src/crypto/fipsmodule/ec/ec.c b/src/crypto/fipsmodule/ec/ec.c
index 47a90ce4..c9687a61 100644
--- a/src/crypto/fipsmodule/ec/ec.c
+++ b/src/crypto/fipsmodule/ec/ec.c
@@ -908,18 +908,6 @@ int ec_point_mul_scalar(const EC_GROUP *group, EC_POINT *r,
return group->meth->mul(group, r, g_scalar, p, p_scalar, ctx);
}
-int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- const BIGNUM *y, const BIGNUM *z,
- BN_CTX *ctx) {
- if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- return ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, x, y, z,
- ctx);
-}
-
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag) {}
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group) {
diff --git a/src/crypto/fipsmodule/ec/ec_key.c b/src/crypto/fipsmodule/ec/ec_key.c
index 4e0bcb22..084d33b7 100644
--- a/src/crypto/fipsmodule/ec/ec_key.c
+++ b/src/crypto/fipsmodule/ec/ec_key.c
@@ -390,8 +390,6 @@ int EC_KEY_check_fips(const EC_KEY *key) {
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
BIGNUM *y) {
- BN_CTX *ctx = NULL;
- BIGNUM *tx, *ty;
EC_POINT *point = NULL;
int ok = 0;
@@ -399,51 +397,18 @@ int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
- ctx = BN_CTX_new();
-
- if (ctx == NULL) {
- return 0;
- }
- BN_CTX_start(ctx);
point = EC_POINT_new(key->group);
-
- if (point == NULL) {
- goto err;
- }
-
- tx = BN_CTX_get(ctx);
- ty = BN_CTX_get(ctx);
- if (tx == NULL ||
- ty == NULL) {
- goto err;
- }
-
- if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
- !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) {
- goto err;
- }
-
- // Check if retrieved coordinates match originals: if not values
- // are out of range.
- if (BN_cmp(x, tx) || BN_cmp(y, ty)) {
- OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
- goto err;
- }
-
- if (!EC_KEY_set_public_key(key, point)) {
- goto err;
- }
-
- if (EC_KEY_check_key(key) == 0) {
+ if (point == NULL ||
+ !EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, NULL) ||
+ !EC_KEY_set_public_key(key, point) ||
+ !EC_KEY_check_key(key)) {
goto err;
}
ok = 1;
err:
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
}
diff --git a/src/crypto/fipsmodule/ec/ec_test.cc b/src/crypto/fipsmodule/ec/ec_test.cc
index d2cd2afb..e69f8d72 100644
--- a/src/crypto/fipsmodule/ec/ec_test.cc
+++ b/src/crypto/fipsmodule/ec/ec_test.cc
@@ -352,8 +352,12 @@ TEST_P(ECCurveTest, SetAffine) {
ASSERT_TRUE(x);
bssl::UniquePtr<BIGNUM> y(BN_new());
ASSERT_TRUE(y);
+ bssl::UniquePtr<BIGNUM> p(BN_new());
+ ASSERT_TRUE(p);
EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
+ EXPECT_TRUE(
+ EC_GROUP_get_curve_GFp(group, p.get(), nullptr, nullptr, nullptr));
// Points on the curve should be accepted.
auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
@@ -369,6 +373,15 @@ TEST_P(ECCurveTest, SetAffine) {
ASSERT_TRUE(invalid_point);
EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
x.get(), y.get(), nullptr));
+
+ // Coordinates out of range should be rejected.
+ EXPECT_TRUE(BN_add(y.get(), y.get(), BN_value_one()));
+ EXPECT_TRUE(BN_add(y.get(), y.get(), p.get()));
+
+ EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
+ x.get(), y.get(), nullptr));
+ EXPECT_FALSE(
+ EC_KEY_set_public_key_affine_coordinates(key.get(), x.get(), y.get()));
}
TEST_P(ECCurveTest, GenerateFIPS) {
diff --git a/src/crypto/fipsmodule/ec/internal.h b/src/crypto/fipsmodule/ec/internal.h
index 145c5c40..06fa3711 100644
--- a/src/crypto/fipsmodule/ec/internal.h
+++ b/src/crypto/fipsmodule/ec/internal.h
@@ -223,16 +223,9 @@ int ec_GFp_simple_point_init(EC_POINT *);
void ec_GFp_simple_point_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 *,
- const BIGNUM *x,
- const BIGNUM *y,
- const BIGNUM *z, BN_CTX *);
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *);
-int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
- const BIGNUM *x, int y_bit,
- BN_CTX *);
int ec_GFp_simple_add(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *);
int ec_GFp_simple_dbl(const EC_GROUP *, EC_POINT *r, const EC_POINT *a,
@@ -264,11 +257,6 @@ int ec_GFp_mont_field_encode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
-int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- const BIGNUM *y, const BIGNUM *z,
- BN_CTX *ctx);
-
void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
const EC_METHOD *EC_GFp_nistp224_method(void);
diff --git a/src/crypto/fipsmodule/ec/oct.c b/src/crypto/fipsmodule/ec/oct.c
index 7d623956..96c138a1 100644
--- a/src/crypto/fipsmodule/ec/oct.c
+++ b/src/crypto/fipsmodule/ec/oct.c
@@ -268,16 +268,20 @@ size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
}
-int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- int y_bit, BN_CTX *ctx) {
+int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x,
+ int y_bit, BN_CTX *ctx) {
+ if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
+ OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
+ return 0;
+ }
+
if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
return 0;
}
BN_CTX *new_ctx = NULL;
- BIGNUM *tmp1, *tmp2, *y;
int ret = 0;
ERR_clear_error();
@@ -292,10 +296,13 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
y_bit = (y_bit != 0);
BN_CTX_start(ctx);
- tmp1 = BN_CTX_get(ctx);
- tmp2 = BN_CTX_get(ctx);
- y = BN_CTX_get(ctx);
- if (y == NULL) {
+ BIGNUM *tmp1 = BN_CTX_get(ctx);
+ BIGNUM *tmp2 = BN_CTX_get(ctx);
+ BIGNUM *a = BN_CTX_get(ctx);
+ BIGNUM *b = BN_CTX_get(ctx);
+ BIGNUM *y = BN_CTX_get(ctx);
+ if (y == NULL ||
+ !EC_GROUP_get_curve_GFp(group, NULL, a, b, ctx)) {
goto err;
}
@@ -304,17 +311,9 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
// so y is one of the square roots of x^3 + a*x + b.
// tmp1 := x^3
- if (group->meth->field_decode == 0) {
- // field_{sqr,mul} work on standard representation
- if (!group->meth->field_sqr(group, tmp2, x, ctx) ||
- !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) {
- goto err;
- }
- } else {
- if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
- !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
- goto err;
- }
+ if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
+ !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
+ goto err;
}
// tmp1 := tmp1 + a*x
@@ -325,33 +324,15 @@ int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
goto err;
}
} else {
- if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, tmp2, &group->a, ctx) ||
- !BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) {
- goto err;
- }
- } else {
- // field_mul works on standard representation
- if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) {
- goto err;
- }
- }
-
- if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) {
+ if (!BN_mod_mul(tmp2, a, x, &group->field, ctx) ||
+ !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) {
goto err;
}
}
// tmp1 := tmp1 + b
- if (group->meth->field_decode) {
- if (!group->meth->field_decode(group, tmp2, &group->b, ctx) ||
- !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) {
- goto err;
- }
- } else {
- if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) {
- goto err;
- }
+ if (!BN_mod_add_quick(tmp1, tmp1, b, &group->field)) {
+ goto err;
}
if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) {
@@ -392,13 +373,3 @@ err:
BN_CTX_free(new_ctx);
return ret;
}
-
-int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- int y_bit, BN_CTX *ctx) {
- if (EC_GROUP_cmp(group, point->group, NULL) != 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
- return 0;
- }
- return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx);
-}
diff --git a/src/crypto/fipsmodule/ec/p224-64.c b/src/crypto/fipsmodule/ec/p224-64.c
index 00972097..71a8af0a 100644
--- a/src/crypto/fipsmodule/ec/p224-64.c
+++ b/src/crypto/fipsmodule/ec/p224-64.c
@@ -1015,22 +1015,27 @@ static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
p224_felem_inv(z2, z1);
p224_felem_square(tmp, z2);
p224_felem_reduce(z1, tmp);
- p224_felem_mul(tmp, x_in, z1);
- p224_felem_reduce(x_in, tmp);
- p224_felem_contract(x_out, x_in);
- if (x != NULL && !p224_felem_to_BN(x, x_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+
+ if (x != NULL) {
+ p224_felem_mul(tmp, x_in, z1);
+ p224_felem_reduce(x_in, tmp);
+ p224_felem_contract(x_out, x_in);
+ if (!p224_felem_to_BN(x, x_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
- p224_felem_mul(tmp, z1, z2);
- p224_felem_reduce(z1, tmp);
- p224_felem_mul(tmp, y_in, z1);
- p224_felem_reduce(y_in, tmp);
- p224_felem_contract(y_out, y_in);
- if (y != NULL && !p224_felem_to_BN(y, y_out)) {
- OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- return 0;
+ if (y != NULL) {
+ p224_felem_mul(tmp, z1, z2);
+ p224_felem_reduce(z1, tmp);
+ p224_felem_mul(tmp, y_in, z1);
+ p224_felem_reduce(y_in, tmp);
+ p224_felem_contract(y_out, y_in);
+ if (!p224_felem_to_BN(y, y_out)) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+ return 0;
+ }
}
return 1;
@@ -1040,28 +1045,9 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
const EC_SCALAR *g_scalar,
const EC_POINT *p,
const EC_SCALAR *p_scalar, BN_CTX *ctx) {
- int ret = 0;
- BN_CTX *new_ctx = NULL;
- BIGNUM *x, *y, *z, *tmp_scalar;
p224_felem p_pre_comp[17][3];
p224_felem x_in, y_in, z_in, x_out, y_out, z_out;
- if (ctx == NULL) {
- ctx = BN_CTX_new();
- new_ctx = ctx;
- if (ctx == NULL) {
- return 0;
- }
- }
-
- BN_CTX_start(ctx);
- if ((x = BN_CTX_get(ctx)) == NULL ||
- (y = BN_CTX_get(ctx)) == NULL ||
- (z = BN_CTX_get(ctx)) == NULL ||
- (tmp_scalar = BN_CTX_get(ctx)) == NULL) {
- goto err;
- }
-
if (p != NULL && p_scalar != NULL) {
// We treat NULL scalars as 0, and NULL points as points at infinity, i.e.,
// they contribute nothing to the linear combination.
@@ -1070,7 +1056,7 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
if (!p224_BN_to_felem(x_out, &p->X) ||
!p224_BN_to_felem(y_out, &p->Y) ||
!p224_BN_to_felem(z_out, &p->Z)) {
- goto err;
+ return 0;
}
p224_felem_assign(p_pre_comp[1][0], x_out);
@@ -1100,18 +1086,13 @@ static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
p224_felem_contract(x_in, x_out);
p224_felem_contract(y_in, y_out);
p224_felem_contract(z_in, z_out);
- if (!p224_felem_to_BN(x, x_in) ||
- !p224_felem_to_BN(y, y_in) ||
- !p224_felem_to_BN(z, z_in)) {
+ if (!p224_felem_to_BN(&r->X, x_in) ||
+ !p224_felem_to_BN(&r->Y, y_in) ||
+ !p224_felem_to_BN(&r->Z, z_in)) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
- goto err;
+ return 0;
}
- ret = ec_point_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
-
-err:
- BN_CTX_end(ctx);
- BN_CTX_free(new_ctx);
- return ret;
+ return 1;
}
DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) {
diff --git a/src/crypto/fipsmodule/ec/simple.c b/src/crypto/fipsmodule/ec/simple.c
index bc395252..ab011ca3 100644
--- a/src/crypto/fipsmodule/ec/simple.c
+++ b/src/crypto/fipsmodule/ec/simple.c
@@ -269,9 +269,14 @@ static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out,
return BN_copy(out, in) != NULL;
}
-int ec_GFp_simple_set_Jprojective_coordinates_GFp(
- const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y,
- const BIGNUM *z, BN_CTX *ctx) {
+int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
+ EC_POINT *point, const BIGNUM *x,
+ const BIGNUM *y, BN_CTX *ctx) {
+ if (x == NULL || y == NULL) {
+ OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
BN_CTX *new_ctx = NULL;
int ret = 0;
@@ -284,7 +289,7 @@ int ec_GFp_simple_set_Jprojective_coordinates_GFp(
if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) ||
!set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) ||
- !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) {
+ !BN_copy(&point->Z, &group->one)) {
goto err;
}
@@ -295,19 +300,6 @@ err:
return ret;
}
-int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
- EC_POINT *point, const BIGNUM *x,
- const BIGNUM *y, BN_CTX *ctx) {
- if (x == NULL || y == NULL) {
- // unlike for projective coordinates, we do not tolerate this
- OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
- return 0;
- }
-
- return ec_point_set_Jprojective_coordinates_GFp(group, point, x, y,
- BN_value_one(), ctx);
-}
-
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx) {
int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
diff --git a/src/crypto/fipsmodule/tls/internal.h b/src/crypto/fipsmodule/tls/internal.h
new file mode 100644
index 00000000..ef642a6c
--- /dev/null
+++ b/src/crypto/fipsmodule/tls/internal.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2018, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H
+#define OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// tls1_prf calculates |out_len| bytes of the TLS PDF, using |digest|, and
+// writes them to |out|. It returns one on success and zero on error.
+OPENSSL_EXPORT int CRYPTO_tls1_prf(const EVP_MD *digest,
+ uint8_t *out, size_t out_len,
+ const uint8_t *secret, size_t secret_len,
+ const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_TLS_INTERNAL_H
diff --git a/src/crypto/fipsmodule/tls/kdf.c b/src/crypto/fipsmodule/tls/kdf.c
new file mode 100644
index 00000000..120553f9
--- /dev/null
+++ b/src/crypto/fipsmodule/tls/kdf.c
@@ -0,0 +1,160 @@
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/hmac.h>
+
+#include "internal.h"
+
+
+// tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
+// section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and
+// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to
+// form the seed parameter. It returns true on success and false on failure.
+static int tls1_P_hash(uint8_t *out, size_t out_len,
+ const EVP_MD *md,
+ const uint8_t *secret, size_t secret_len,
+ const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
+ HMAC_CTX ctx, ctx_tmp, ctx_init;
+ uint8_t A1[EVP_MAX_MD_SIZE];
+ unsigned A1_len;
+ int ret = 0;
+
+ const size_t chunk = EVP_MD_size(md);
+ HMAC_CTX_init(&ctx);
+ HMAC_CTX_init(&ctx_tmp);
+ HMAC_CTX_init(&ctx_init);
+
+ if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) ||
+ !HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
+ !HMAC_Update(&ctx, (const uint8_t *) label, label_len) ||
+ !HMAC_Update(&ctx, seed1, seed1_len) ||
+ !HMAC_Update(&ctx, seed2, seed2_len) ||
+ !HMAC_Final(&ctx, A1, &A1_len)) {
+ goto err;
+ }
+
+ for (;;) {
+ unsigned len;
+ uint8_t hmac[EVP_MAX_MD_SIZE];
+ if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
+ !HMAC_Update(&ctx, A1, A1_len) ||
+ // Save a copy of |ctx| to compute the next A1 value below.
+ (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) ||
+ !HMAC_Update(&ctx, (const uint8_t *) label, label_len) ||
+ !HMAC_Update(&ctx, seed1, seed1_len) ||
+ !HMAC_Update(&ctx, seed2, seed2_len) ||
+ !HMAC_Final(&ctx, hmac, &len)) {
+ goto err;
+ }
+ assert(len == chunk);
+
+ // XOR the result into |out|.
+ if (len > out_len) {
+ len = out_len;
+ }
+ for (unsigned i = 0; i < len; i++) {
+ out[i] ^= hmac[i];
+ }
+ out += len;
+ out_len -= len;
+
+ if (out_len == 0) {
+ break;
+ }
+
+ // Calculate the next A1 value.
+ if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) {
+ goto err;
+ }
+ }
+
+ ret = 1;
+
+err:
+ OPENSSL_cleanse(A1, sizeof(A1));
+ HMAC_CTX_cleanup(&ctx);
+ HMAC_CTX_cleanup(&ctx_tmp);
+ HMAC_CTX_cleanup(&ctx_init);
+ return ret;
+}
+
+int CRYPTO_tls1_prf(const EVP_MD *digest,
+ uint8_t *out, size_t out_len,
+ const uint8_t *secret, size_t secret_len,
+ const char *label, size_t label_len,
+ const uint8_t *seed1, size_t seed1_len,
+ const uint8_t *seed2, size_t seed2_len) {
+ if (out_len == 0) {
+ return 1;
+ }
+
+ OPENSSL_memset(out, 0, out_len);
+
+ if (digest == EVP_md5_sha1()) {
+ // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1.
+ size_t secret_half = secret_len - (secret_len / 2);
+ if (!tls1_P_hash(out, out_len, EVP_md5(), secret, secret_half, label,
+ label_len, seed1, seed1_len, seed2, seed2_len)) {
+ return 0;
+ }
+
+ // Note that, if |secret_len| is odd, the two halves share a byte.
+ secret += secret_len - secret_half;
+ secret_len = secret_half;
+ digest = EVP_sha1();
+ }
+
+ return tls1_P_hash(out, out_len, digest, secret, secret_len, label, label_len,
+ seed1, seed1_len, seed2, seed2_len);
+}
diff --git a/src/crypto/test/file_test.cc b/src/crypto/test/file_test.cc
index ea1fc3c5..cbb9f7f8 100644
--- a/src/crypto/test/file_test.cc
+++ b/src/crypto/test/file_test.cc
@@ -31,8 +31,10 @@
FileTest::FileTest(std::unique_ptr<FileTest::LineReader> reader,
- std::function<void(const std::string &)> comment_callback)
+ std::function<void(const std::string &)> comment_callback,
+ bool is_kas_test)
: reader_(std::move(reader)),
+ is_kas_test_(is_kas_test),
comment_callback_(std::move(comment_callback)) {}
FileTest::~FileTest() {}
@@ -122,9 +124,16 @@ FileTest::ReadResult FileTest::ReadNext() {
in_instruction_block = false;
// Delimit instruction block from test with a blank line.
current_test_ += "\r\n";
+ } else if (is_kas_test_) {
+ // KAS tests have random blank lines scattered around.
+ current_test_ += "\r\n";
}
} else if (buf[0] == '#') {
- if (comment_callback_) {
+ if (is_kas_test_ && seen_non_comment_) {
+ // KAS tests have comments after the initial comment block which need
+ // to be included in the corresponding place in the output.
+ current_test_ += std::string(buf.get());
+ } else if (comment_callback_) {
comment_callback_(buf.get());
}
// Otherwise ignore comments.
@@ -134,6 +143,7 @@ FileTest::ReadResult FileTest::ReadNext() {
// request files are hopelessly inconsistent.
} else if (buf[0] == '[') { // Inside an instruction block.
is_at_new_instruction_block_ = true;
+ seen_non_comment_ = true;
if (start_line_ != 0) {
// Instructions should be separate blocks.
fprintf(stderr, "Line %u is an instruction in a test case.\n", line_);
@@ -145,12 +155,25 @@ FileTest::ReadResult FileTest::ReadNext() {
}
// Parse the line as an instruction ("[key = value]" or "[key]").
- std::string kv = StripSpace(buf.get(), len);
- if (kv[kv.size() - 1] != ']') {
- fprintf(stderr, "Line %u, invalid instruction: %s\n", line_,
- kv.c_str());
- return kReadError;
+
+ // KAS tests contain invalid syntax.
+ std::string kv = buf.get();
+ const bool is_broken_kas_instruction =
+ is_kas_test_ &&
+ (kv == "[SHA(s) supported (Used for hashing Z): SHA512 \r\n");
+
+ if (!is_broken_kas_instruction) {
+ kv = StripSpace(buf.get(), len);
+ if (kv[kv.size() - 1] != ']') {
+ fprintf(stderr, "Line %u, invalid instruction: '%s'\n", line_,
+ kv.c_str());
+ return kReadError;
+ }
+ } else {
+ // Just remove the newline for the broken instruction.
+ kv = kv.substr(0, kv.size() - 2);
}
+
current_test_ += kv + "\r\n";
kv = std::string(kv.begin() + 1, kv.end() - 1);
@@ -422,7 +445,7 @@ int FileTestMain(const FileTest::Options &opts) {
return 1;
}
- FileTest t(std::move(reader), opts.comment_callback);
+ FileTest t(std::move(reader), opts.comment_callback, opts.is_kas_test);
bool failed = false;
while (true) {
diff --git a/src/crypto/test/file_test.h b/src/crypto/test/file_test.h
index 204ef9cb..002b350f 100644
--- a/src/crypto/test/file_test.h
+++ b/src/crypto/test/file_test.h
@@ -114,10 +114,15 @@ class FileTest {
bool silent = false;
// comment_callback is called after each comment in the input is parsed.
std::function<void(const std::string&)> comment_callback;
+ // is_kas_test is true if a NIST “KAS” test is being parsed. These tests
+ // are inconsistent with the other NIST files to such a degree that they
+ // need their own boolean.
+ bool is_kas_test = false;
};
explicit FileTest(std::unique_ptr<LineReader> reader,
- std::function<void(const std::string &)> comment_callback);
+ std::function<void(const std::string &)> comment_callback,
+ bool is_kas_test);
~FileTest();
// ReadNext reads the next test from the file. It returns |kReadSuccess| if
@@ -217,6 +222,8 @@ class FileTest {
std::string current_test_;
bool is_at_new_instruction_block_ = false;
+ bool seen_non_comment_ = false;
+ bool is_kas_test_ = false;
// comment_callback_, if set, is a callback function that is called with the
// contents of each comment as they are parsed.
diff --git a/src/crypto/test/file_test_gtest.cc b/src/crypto/test/file_test_gtest.cc
index bfa8d27d..8ff7a2bf 100644
--- a/src/crypto/test/file_test_gtest.cc
+++ b/src/crypto/test/file_test_gtest.cc
@@ -68,7 +68,7 @@ class StringLineReader : public FileTest::LineReader {
void FileTestGTest(const char *path, std::function<void(FileTest *)> run_test) {
std::unique_ptr<StringLineReader> reader(
new StringLineReader(GetTestData(path)));
- FileTest t(std::move(reader), nullptr);
+ FileTest t(std::move(reader), nullptr, false);
while (true) {
switch (t.ReadNext()) {
diff --git a/src/fipstools/CMakeLists.txt b/src/fipstools/CMakeLists.txt
index 8fd294fd..4831575b 100644
--- a/src/fipstools/CMakeLists.txt
+++ b/src/fipstools/CMakeLists.txt
@@ -14,6 +14,7 @@ if (FIPS)
cavp_ecdsa2_siggen_test.cc
cavp_ecdsa2_sigver_test.cc
cavp_hmac_test.cc
+ cavp_kas_test.cc
cavp_keywrap_test.cc
cavp_rsa2_keygen_test.cc
cavp_rsa2_siggen_test.cc
@@ -21,6 +22,7 @@ if (FIPS)
cavp_sha_monte_test.cc
cavp_sha_test.cc
cavp_tdes_test.cc
+ cavp_tlskdf_test.cc
cavp_test_util.cc
diff --git a/src/fipstools/cavp_kas_test.cc b/src/fipstools/cavp_kas_test.cc
new file mode 100644
index 00000000..a304a48c
--- /dev/null
+++ b/src/fipstools/cavp_kas_test.cc
@@ -0,0 +1,160 @@
+/* Copyright (c) 2018, 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. */
+
+// cavp_kas_test processes NIST CAVP ECC KAS test vector request files and
+// emits the corresponding response.
+
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/ecdh.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+#include <openssl/nid.h>
+
+#include "../crypto/internal.h"
+#include "../crypto/test/file_test.h"
+#include "cavp_test_util.h"
+
+
+static bool TestKAS(FileTest *t, void *arg) {
+ const bool validate = *reinterpret_cast<bool *>(arg);
+
+ int nid = NID_undef;
+ const EVP_MD *md = nullptr;
+
+ if (t->HasInstruction("EB - SHA224")) {
+ nid = NID_secp224r1;
+ md = EVP_sha224();
+ } else if (t->HasInstruction("EC - SHA256")) {
+ nid = NID_X9_62_prime256v1;
+ md = EVP_sha256();
+ } else if (t->HasInstruction("ED - SHA384")) {
+ nid = NID_secp384r1;
+ md = EVP_sha384();
+ } else if (t->HasInstruction("EE - SHA512")) {
+ nid = NID_secp521r1;
+ md = EVP_sha512();
+ } else {
+ return false;
+ }
+
+ if (!t->HasAttribute("COUNT")) {
+ return false;
+ }
+
+ bssl::UniquePtr<BIGNUM> their_x(GetBIGNUM(t, "QeCAVSx"));
+ bssl::UniquePtr<BIGNUM> their_y(GetBIGNUM(t, "QeCAVSy"));
+ bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(nid));
+ bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+ if (!their_x || !their_y || !ec_key || !ctx) {
+ return false;
+ }
+
+ const EC_GROUP *const group = EC_KEY_get0_group(ec_key.get());
+ bssl::UniquePtr<EC_POINT> their_point(EC_POINT_new(group));
+ if (!their_point ||
+ !EC_POINT_set_affine_coordinates_GFp(
+ group, their_point.get(), their_x.get(), their_y.get(), ctx.get())) {
+ return false;
+ }
+
+ if (validate) {
+ bssl::UniquePtr<BIGNUM> our_k(GetBIGNUM(t, "deIUT"));
+ if (!our_k ||
+ !EC_KEY_set_private_key(ec_key.get(), our_k.get()) ||
+ // These attributes are ignored.
+ !t->HasAttribute("QeIUTx") ||
+ !t->HasAttribute("QeIUTy")) {
+ return false;
+ }
+ } else if (!EC_KEY_generate_key(ec_key.get())) {
+ return false;
+ }
+
+ constexpr size_t kMaxCurveFieldBits = 521;
+ uint8_t shared_bytes[(kMaxCurveFieldBits + 7)/8];
+ const int shared_bytes_len =
+ ECDH_compute_key(shared_bytes, sizeof(shared_bytes), their_point.get(),
+ ec_key.get(), nullptr);
+
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ unsigned digest_len;
+ if (shared_bytes_len < 0 ||
+ !EVP_Digest(shared_bytes, shared_bytes_len, digest, &digest_len, md,
+ nullptr)) {
+ return false;
+ }
+
+ if (validate) {
+ std::vector<uint8_t> expected_shared_bytes;
+ if (!t->GetBytes(&expected_shared_bytes, "CAVSHashZZ")) {
+ return false;
+ }
+ const bool ok =
+ digest_len == expected_shared_bytes.size() &&
+ OPENSSL_memcmp(digest, expected_shared_bytes.data(), digest_len) == 0;
+
+ printf("%sIUTHashZZ = %s\r\nResult = %c\r\n\r\n\r\n",
+ t->CurrentTestToString().c_str(),
+ EncodeHex(digest, digest_len).c_str(), ok ? 'P' : 'F');
+ } else {
+ const EC_POINT *pub = EC_KEY_get0_public_key(ec_key.get());
+ bssl::UniquePtr<BIGNUM> x(BN_new());
+ bssl::UniquePtr<BIGNUM> y(BN_new());
+ if (!x || !y ||
+ !EC_POINT_get_affine_coordinates_GFp(group, pub, x.get(), y.get(),
+ ctx.get())) {
+ return false;
+ }
+ bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
+ bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
+
+ printf("%sQeIUTx = %s\r\nQeIUTy = %s\r\nHashZZ = %s\r\n",
+ t->CurrentTestToString().c_str(), x_hex.get(), y_hex.get(),
+ EncodeHex(digest, digest_len).c_str());
+ }
+
+ return true;
+}
+
+int cavp_kas_test_main(int argc, char **argv) {
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s (validity|function) <test file>\n",
+ argv[0]);
+ return 1;
+ }
+
+ bool validity;
+ if (strcmp(argv[1], "validity") == 0) {
+ validity = true;
+ } else if (strcmp(argv[1], "function") == 0) {
+ validity = false;
+ } else {
+ fprintf(stderr, "Unknown test type: %s\n", argv[1]);
+ return 1;
+ }
+
+ FileTest::Options opts;
+ opts.path = argv[2];
+ opts.arg = &validity;
+ opts.callback = TestKAS;
+ opts.silent = true;
+ opts.comment_callback = EchoComment;
+ opts.is_kas_test = true;
+ return FileTestMain(opts);
+}
diff --git a/src/fipstools/cavp_main.cc b/src/fipstools/cavp_main.cc
index e7bbfb41..64dbd69d 100644
--- a/src/fipstools/cavp_main.cc
+++ b/src/fipstools/cavp_main.cc
@@ -43,10 +43,12 @@ static TestSuite all_test_suites[] = {
{"ecdsa2_siggen", &cavp_ecdsa2_siggen_test_main},
{"ecdsa2_sigver", &cavp_ecdsa2_sigver_test_main},
{"hmac", &cavp_hmac_test_main},
+ {"kas", &cavp_kas_test_main},
{"keywrap", &cavp_keywrap_test_main},
{"rsa2_keygen", &cavp_rsa2_keygen_test_main},
{"rsa2_siggen", &cavp_rsa2_siggen_test_main},
{"rsa2_sigver", &cavp_rsa2_sigver_test_main},
+ {"tlskdf", &cavp_tlskdf_test_main},
{"sha", &cavp_sha_test_main},
{"sha_monte", &cavp_sha_monte_test_main},
{"tdes", &cavp_tdes_test_main}
diff --git a/src/fipstools/cavp_test_util.h b/src/fipstools/cavp_test_util.h
index 0cbd9a77..ca9e790c 100644
--- a/src/fipstools/cavp_test_util.h
+++ b/src/fipstools/cavp_test_util.h
@@ -64,6 +64,7 @@ int cavp_ecdsa2_pkv_test_main(int argc, char **argv);
int cavp_ecdsa2_siggen_test_main(int argc, char **argv);
int cavp_ecdsa2_sigver_test_main(int argc, char **argv);
int cavp_hmac_test_main(int argc, char **argv);
+int cavp_kas_test_main(int argc, char **argv);
int cavp_keywrap_test_main(int argc, char **argv);
int cavp_rsa2_keygen_test_main(int argc, char **argv);
int cavp_rsa2_siggen_test_main(int argc, char **argv);
@@ -71,6 +72,7 @@ int cavp_rsa2_sigver_test_main(int argc, char **argv);
int cavp_sha_monte_test_main(int argc, char **argv);
int cavp_sha_test_main(int argc, char **argv);
int cavp_tdes_test_main(int argc, char **argv);
+int cavp_tlskdf_test_main(int argc, char **argv);
#endif // OPENSSL_HEADER_CRYPTO_FIPSMODULE_CAVP_TEST_UTIL_H
diff --git a/src/fipstools/cavp_tlskdf_test.cc b/src/fipstools/cavp_tlskdf_test.cc
new file mode 100644
index 00000000..ac0f83f7
--- /dev/null
+++ b/src/fipstools/cavp_tlskdf_test.cc
@@ -0,0 +1,111 @@
+/* Copyright (c) 2018, 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. */
+
+// cavp_tlskdf_test processes NIST TLS KDF test vectors and emits the
+// corresponding response.
+// See https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/components/askdfvs.pdf, section 6.4.
+
+#include <vector>
+
+#include <openssl/digest.h>
+
+#include "cavp_test_util.h"
+#include "../crypto/fipsmodule/tls/internal.h"
+#include "../crypto/test/file_test.h"
+
+
+static bool TestTLSKDF(FileTest *t, void *arg) {
+ const EVP_MD *md = nullptr;
+
+ if (t->HasInstruction("TLS 1.0/1.1")) {
+ md = EVP_md5_sha1();
+ } else if (t->HasInstruction("TLS 1.2")) {
+ if (t->HasInstruction("SHA-256")) {
+ md = EVP_sha256();
+ } else if (t->HasInstruction("SHA-384")) {
+ md = EVP_sha384();
+ } else if (t->HasInstruction("SHA-512")) {
+ md = EVP_sha512();
+ }
+ }
+
+ if (md == nullptr) {
+ return false;
+ }
+
+ std::string key_block_len_str;
+ std::vector<uint8_t> premaster, server_random, client_random,
+ key_block_server_random, key_block_client_random;
+ if (!t->GetBytes(&premaster, "pre_master_secret") ||
+ !t->GetBytes(&server_random, "serverHello_random") ||
+ !t->GetBytes(&client_random, "clientHello_random") ||
+ // The NIST tests specify different client and server randoms for the
+ // expansion step from the master-secret step. This is impossible in TLS.
+ !t->GetBytes(&key_block_server_random, "server_random") ||
+ !t->GetBytes(&key_block_client_random, "client_random") ||
+ !t->GetInstruction(&key_block_len_str, "key block length") ||
+ // These are ignored.
+ !t->HasAttribute("COUNT") ||
+ !t->HasInstruction("pre-master secret length")) {
+ return false;
+ }
+
+ uint8_t master_secret[48];
+ static const char kMasterSecretLabel[] = "master secret";
+ if (!CRYPTO_tls1_prf(md, master_secret, sizeof(master_secret),
+ premaster.data(), premaster.size(), kMasterSecretLabel,
+ sizeof(kMasterSecretLabel) - 1, client_random.data(),
+ client_random.size(), server_random.data(),
+ server_random.size())) {
+ return false;
+ }
+
+ errno = 0;
+ const long int key_block_bits =
+ strtol(key_block_len_str.c_str(), nullptr, 10);
+ if (errno != 0 || key_block_bits <= 0 || (key_block_bits & 7) != 0) {
+ return false;
+ }
+ const size_t key_block_len = key_block_bits / 8;
+ std::vector<uint8_t> key_block(key_block_len);
+ static const char kLabel[] = "key expansion";
+ if (!CRYPTO_tls1_prf(
+ md, key_block.data(), key_block.size(), master_secret,
+ sizeof(master_secret), kLabel, sizeof(kLabel) - 1,
+ key_block_server_random.data(), key_block_server_random.size(),
+ key_block_client_random.data(), key_block_client_random.size())) {
+ return false;
+ }
+
+ printf("%smaster_secret = %s\r\nkey_block = %s\r\n\r\n",
+ t->CurrentTestToString().c_str(),
+ EncodeHex(master_secret, sizeof(master_secret)).c_str(),
+ EncodeHex(key_block.data(), key_block.size()).c_str());
+
+ return true;
+}
+
+int cavp_tlskdf_test_main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <test file>\n", argv[0]);
+ return 1;
+ }
+
+ FileTest::Options opts;
+ opts.path = argv[1];
+ opts.callback = TestTLSKDF;
+ opts.silent = true;
+ opts.comment_callback = EchoComment;
+ return FileTestMain(opts);
+}
diff --git a/src/fipstools/run_cavp.go b/src/fipstools/run_cavp.go
index e5c67c0c..2b1bf6d4 100644
--- a/src/fipstools/run_cavp.go
+++ b/src/fipstools/run_cavp.go
@@ -19,6 +19,7 @@ var (
oraclePath = flag.String("oracle-bin", "", "Path to the oracle binary")
suiteDir = flag.String("suite-dir", "", "Base directory containing the CAVP test suite")
noFAX = flag.Bool("no-fax", false, "Skip comparing against FAX files")
+ niap = flag.Bool("niap", false, "Perform NIAP tests rather than FIPS tests")
)
// test describes a single request file.
@@ -34,6 +35,12 @@ type test struct {
noFAX bool
}
+// nextLineState can be used by FAX next-line function to store state.
+type nextLineState struct {
+ // State used by the KAS test.
+ nextIsIUTHash bool
+}
+
// testSuite describes a series of tests that are handled by a single oracle
// binary.
type testSuite struct {
@@ -41,10 +48,13 @@ type testSuite struct {
directory string
// suite names the test suite to pass as the first command-line argument.
suite string
- // faxScanFunc, if not nil, is the function to use instead of
- // (*bufio.Scanner).Scan. This can be used to skip lines.
- faxScanFunc func(*bufio.Scanner) bool
- tests []test
+ // nextLineFunc, if not nil, is the function used to read the next line
+ // from the FAX file. This can be used to skip lines and/or mutate them
+ // as needed. The second argument can be used by the scanner to store
+ // state, if needed. If isWildcard is true on return then line is not
+ // meaningful and any line from the response file should be accepted.
+ nextLineFunc func(*bufio.Scanner, *nextLineState) (line string, isWildcard, ok bool)
+ tests []test
}
func (t *testSuite) getDirectory() string {
@@ -161,10 +171,10 @@ var rsa2SigGenTests = testSuite{
var rsa2SigVerTests = testSuite{
"RSA2",
"rsa2_sigver",
- func(s *bufio.Scanner) bool {
+ func(s *bufio.Scanner, state *nextLineState) (string, bool, bool) {
for {
if !s.Scan() {
- return false
+ return "", false, false
}
line := s.Text()
@@ -173,15 +183,13 @@ var rsa2SigVerTests = testSuite{
}
if strings.HasPrefix(line, "q = ") {
// Skip the "q = " line and an additional blank line.
- if !s.Scan() {
- return false
- }
- if len(strings.TrimSpace(s.Text())) > 0 {
- return false
+ if !s.Scan() ||
+ len(strings.TrimSpace(s.Text())) > 0 {
+ return "", false, false
}
continue
}
- return true
+ return line, false, true
}
},
[]test{
@@ -273,7 +281,51 @@ var keyWrapTests = testSuite{
},
}
-var allTestSuites = []*testSuite{
+var kasTests = testSuite{
+ "KAS",
+ "kas",
+ func(s *bufio.Scanner, state *nextLineState) (line string, isWildcard, ok bool) {
+ for {
+ // If the response file will include the IUT hash next,
+ // return a wildcard signal because this cannot be
+ // matched against the FAX file.
+ if state.nextIsIUTHash {
+ state.nextIsIUTHash = false
+ return "", true, true
+ }
+
+ if !s.Scan() {
+ return "", false, false
+ }
+
+ line := s.Text()
+ if strings.HasPrefix(line, "deCAVS = ") || strings.HasPrefix(line, "Z = ") {
+ continue
+ }
+ if strings.HasPrefix(line, "CAVSHashZZ = ") {
+ state.nextIsIUTHash = true
+ }
+ return line, false, true
+ }
+ },
+ []test{
+ {"KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_init", []string{"function"}, true},
+ {"KASFunctionTest_ECCEphemeralUnified_NOKC_ZZOnly_resp", []string{"function"}, true},
+ {"KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_init", []string{"validity"}, false},
+ {"KASValidityTest_ECCEphemeralUnified_NOKC_ZZOnly_resp", []string{"validity"}, false},
+ },
+}
+
+var tlsKDFTests = testSuite{
+ "KDF135",
+ "tlskdf",
+ nil,
+ []test{
+ {"tls", nil, false},
+ },
+}
+
+var fipsTestSuites = []*testSuite{
&aesGCMTests,
&aesTests,
&ctrDRBGTests,
@@ -291,6 +343,11 @@ var allTestSuites = []*testSuite{
&tdesTests,
}
+var niapTestSuites = []*testSuite{
+ &kasTests,
+ &tlsKDFTests,
+}
+
// testInstance represents a specific test in a testSuite.
type testInstance struct {
suite *testSuite
@@ -333,7 +390,12 @@ func main() {
go worker(&wg, work)
}
- for _, suite := range allTestSuites {
+ testSuites := fipsTestSuites
+ if *niap {
+ testSuites = niapTestSuites
+ }
+
+ for _, suite := range testSuites {
for i := range suite.tests {
work <- testInstance{suite, i}
}
@@ -385,9 +447,14 @@ func canonicalizeLine(in string) string {
}
func compareFAX(suite *testSuite, test test) error {
- faxScanFunc := suite.faxScanFunc
- if faxScanFunc == nil {
- faxScanFunc = (*bufio.Scanner).Scan
+ nextLineFunc := suite.nextLineFunc
+ if nextLineFunc == nil {
+ nextLineFunc = func(s *bufio.Scanner, state *nextLineState) (string, bool, bool) {
+ if !s.Scan() {
+ return "", false, false
+ }
+ return s.Text(), false, true
+ }
}
respPath := filepath.Join(suite.getDirectory(), "resp", test.inFile+".rsp")
@@ -406,6 +473,7 @@ func compareFAX(suite *testSuite, test test) error {
respScanner := bufio.NewScanner(respFile)
faxScanner := bufio.NewScanner(faxFile)
+ var nextLineState nextLineState
lineNo := 0
inHeader := true
@@ -414,6 +482,7 @@ func compareFAX(suite *testSuite, test test) error {
lineNo++
respLine := respScanner.Text()
var faxLine string
+ var isWildcard, ok bool
if inHeader && (len(respLine) == 0 || respLine[0] == '#') {
continue
@@ -423,8 +492,10 @@ func compareFAX(suite *testSuite, test test) error {
haveFaxLine := false
if inHeader {
- for faxScanFunc(faxScanner) {
- faxLine = faxScanner.Text()
+ for {
+ if faxLine, isWildcard, ok = nextLineFunc(faxScanner, &nextLineState); !ok {
+ break
+ }
if len(faxLine) != 0 && faxLine[0] != '#' {
haveFaxLine = true
break
@@ -433,10 +504,7 @@ func compareFAX(suite *testSuite, test test) error {
inHeader = false
} else {
- if faxScanFunc(faxScanner) {
- faxLine = faxScanner.Text()
- haveFaxLine = true
- }
+ faxLine, isWildcard, haveFaxLine = nextLineFunc(faxScanner, &nextLineState)
}
if !haveFaxLine {
@@ -454,14 +522,14 @@ func compareFAX(suite *testSuite, test test) error {
break
}
- if canonicalizeLine(faxLine) == canonicalizeLine(respLine) {
+ if isWildcard || canonicalizeLine(faxLine) == canonicalizeLine(respLine) {
continue
}
return fmt.Errorf("resp and fax differ at line %d for %q %q: %q vs %q", lineNo, suite.getDirectory(), test.inFile, respLine, faxLine)
}
- if faxScanFunc(faxScanner) {
+ if _, _, ok := nextLineFunc(faxScanner, &nextLineState); ok {
return fmt.Errorf("fax file is longer than resp for %q %q", suite.getDirectory(), test.inFile)
}
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index cc962f31..9edaa5ca 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -228,9 +228,10 @@ extern "C" {
#define OPENSSL_FALLTHROUGH [[fallthrough]]
#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__clang__)
#define OPENSSL_FALLTHROUGH [[clang::fallthrough]]
-#elif defined(__cplusplus) && __cplusplus >= 201103L && __GNUC__ >= 7
+#elif defined(__cplusplus) && __cplusplus >= 201103L && defined(__GNUC__) && \
+ __GNUC__ >= 7
#define OPENSSL_FALLTHROUGH [[gnu::fallthrough]]
-#elif __GNUC__ >= 7 // gcc 7
+#elif defined(__GNUC__) && __GNUC__ >= 7 // gcc 7
#define OPENSSL_FALLTHROUGH __attribute__ ((fallthrough))
#else // C++11 on gcc 6, and all other cases
#define OPENSSL_FALLTHROUGH
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index f87167ea..5e3e2ef2 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -347,7 +347,7 @@ OPENSSL_EXPORT int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len,
// Memory BIOs.
//
// Memory BIOs can be used as a read-only source (with |BIO_new_mem_buf|) or a
-// writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_get_mem_buf|). Data
+// writable sink (with |BIO_new|, |BIO_s_mem| and |BIO_mem_contents|). Data
// written to a writable, memory BIO can be recalled by reading from it.
//
// Calling |BIO_reset| on a read-only BIO resets it to the original contents.
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 6ab1682e..b868d3f2 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -592,6 +592,7 @@ OPENSSL_EXPORT int DTLSv1_handle_timeout(SSL *ssl);
#define DTLS1_2_VERSION 0xfefd
#define TLS1_3_DRAFT22_VERSION 0x7f16
+#define TLS1_3_DRAFT23_VERSION 0x7f17
#define TLS1_3_EXPERIMENT2_VERSION 0x7e02
// SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
@@ -2908,6 +2909,21 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity_hint(const SSL *ssl);
OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
+// Dummy post-quantum padding.
+//
+// Dummy post-quantum padding invovles the client (and later server) sending
+// useless, random-looking bytes in an extension in their ClientHello or
+// ServerHello. These extensions are sized to simulate a post-quantum
+// key-exchange and so enable measurement of the latency impact of the
+// additional bandwidth.
+
+// SSL_set_dummy_pq_padding_size enables the sending of a dummy PQ padding
+// extension and configures its size. This is only effective for a client: a
+// server will echo an extension with one of equal length when we get to that
+// phase of the experiment. It returns one for success and zero otherwise.
+OPENSSL_EXPORT int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes);
+
+
// Early data.
//
// WARNING: 0-RTT support in BoringSSL is currently experimental and not fully
@@ -3228,6 +3244,7 @@ OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
enum tls13_variant_t {
tls13_default = 0,
tls13_experiment2 = 1,
+ tls13_draft22 = 2,
};
// SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h
index 46f57a34..625f66e4 100644
--- a/src/include/openssl/stack.h
+++ b/src/include/openssl/stack.h
@@ -344,7 +344,7 @@ struct StackTraits {};
sk_##name##_deep_copy(const STACK_OF(name) *sk, \
ptrtype(*copy_func)(ptrtype), \
void (*free_func)(ptrtype)) { \
- return (STACK_OF(name) *)sk_deep_copy((_STACK *)sk, \
+ return (STACK_OF(name) *)sk_deep_copy((const _STACK *)sk, \
(void *(*)(void *))copy_func, \
(void (*)(void *))free_func); \
}
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index f62ee1fb..4b5d2262 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -207,7 +207,7 @@ extern "C" {
// ExtensionType values from draft-ietf-tls-tls13-18
#define TLSEXT_TYPE_supported_groups 10
-#define TLSEXT_TYPE_key_share 40
+#define TLSEXT_TYPE_old_key_share 40
#define TLSEXT_TYPE_pre_shared_key 41
#define TLSEXT_TYPE_early_data 42
#define TLSEXT_TYPE_supported_versions 43
@@ -215,6 +215,7 @@ extern "C" {
#define TLSEXT_TYPE_psk_key_exchange_modes 45
#define TLSEXT_TYPE_ticket_early_data_info 46
#define TLSEXT_TYPE_certificate_authorities 47
+#define TLSEXT_TYPE_new_key_share 51
// ExtensionType value from RFC5746
#define TLSEXT_TYPE_renegotiate 0xff01
@@ -228,6 +229,9 @@ extern "C" {
// This is not an IANA defined extension number
#define TLSEXT_TYPE_channel_id 30032
+// This is not an IANA defined extension number
+#define TLSEXT_TYPE_dummy_pq_padding 54537
+
// status request value from RFC 3546
#define TLSEXT_STATUSTYPE_ocsp 1
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index d59ecc47..91ca1f7e 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -392,32 +392,17 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
// call this function before the version is determined.
uint16_t ssl_protocol_version(const SSL *ssl);
-// ssl_is_draft21 returns whether the version corresponds to a draft21 TLS 1.3
-// variant.
-bool ssl_is_draft21(uint16_t version);
-
// ssl_is_draft22 returns whether the version corresponds to a draft22 TLS 1.3
// variant.
bool ssl_is_draft22(uint16_t version);
-// ssl_is_resumption_experiment returns whether the version corresponds to a
-// TLS 1.3 resumption experiment.
-bool ssl_is_resumption_experiment(uint16_t version);
-
-// ssl_is_resumption_variant returns whether the variant corresponds to a
-// TLS 1.3 resumption experiment.
-bool ssl_is_resumption_variant(uint16_t max_version,
- enum tls13_variant_t variant);
-
-// ssl_is_resumption_client_ccs_experiment returns whether the version
-// corresponds to a TLS 1.3 resumption experiment that sends a client CCS.
-bool ssl_is_resumption_client_ccs_experiment(uint16_t version);
-
-// ssl_is_resumption_record_version_experiment returns whether the version
-// corresponds to a TLS 1.3 resumption experiment that modifies the record
-// version.
-bool ssl_is_resumption_record_version_experiment(uint16_t version);
+// ssl_is_draft23 returns whether the version corresponds to a draft23 TLS 1.3
+// variant.
+bool ssl_is_draft23(uint16_t version);
+// ssl_is_draft23_variant returns whether the variant corresponds to a
+// draft23 TLS 1.3 variant.
+ bool ssl_is_draft23_variant(enum tls13_variant_t variant);
// Cipher suites.
@@ -2596,6 +2581,7 @@ struct SSLConnection {
uint32_t options; // protocol behaviour
uint32_t mode; // API behaviour
uint32_t max_cert_list;
+ uint16_t dummy_pq_padding_len;
char *tlsext_hostname;
size_t supported_group_list_len;
uint16_t *supported_group_list; // our list
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 5e420e89..8f53dcd5 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -2385,6 +2385,15 @@ void SSL_CTX_set_psk_server_callback(
ctx->psk_server_callback = cb;
}
+int SSL_set_dummy_pq_padding_size(SSL *ssl, size_t num_bytes) {
+ if (num_bytes > 0xffff) {
+ return 0;
+ }
+
+ ssl->dummy_pq_padding_len = num_bytes;
+ return 1;
+}
+
void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
void (*cb)(int write_p, int version,
int content_type, const void *buf,
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 5d37448a..a2a53f63 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -3861,7 +3861,7 @@ TEST(SSLTest, AllTests) {
!TestPaddingExtension(TLS1_3_VERSION, TLS1_2_VERSION) ||
// Test the padding extension at TLS 1.3 with a TLS 1.3 session, so there
// will be a PSK binder after the padding extension.
- !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT22_VERSION)) {
+ !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT23_VERSION)) {
ADD_FAILURE() << "Tests failed";
}
}
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index 4ef54da1..15012dc8 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -35,6 +35,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
return true;
case TLS1_3_DRAFT22_VERSION:
+ case TLS1_3_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
*out = TLS1_3_VERSION;
return true;
@@ -57,6 +58,7 @@ bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) {
// decreasing preference.
static const uint16_t kTLSVersions[] = {
+ TLS1_3_DRAFT23_VERSION,
TLS1_3_DRAFT22_VERSION,
TLS1_3_EXPERIMENT2_VERSION,
TLS1_2_VERSION,
@@ -102,6 +104,7 @@ static bool method_supports_version(const SSL_PROTOCOL_METHOD *method,
static const char *ssl_version_to_string(uint16_t version) {
switch (version) {
case TLS1_3_DRAFT22_VERSION:
+ case TLS1_3_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
return "TLSv1.3";
@@ -132,6 +135,7 @@ static uint16_t wire_version_to_api(uint16_t version) {
switch (version) {
// Report TLS 1.3 draft versions as TLS 1.3 in the public API.
case TLS1_3_DRAFT22_VERSION:
+ case TLS1_3_DRAFT23_VERSION:
case TLS1_3_EXPERIMENT2_VERSION:
return TLS1_3_VERSION;
default:
@@ -144,6 +148,7 @@ static uint16_t wire_version_to_api(uint16_t version) {
// used in context where that does not matter.
static bool api_version_to_wire(uint16_t *out, uint16_t version) {
if (version == TLS1_3_DRAFT22_VERSION ||
+ version == TLS1_3_DRAFT23_VERSION ||
version == TLS1_3_EXPERIMENT2_VERSION) {
return false;
}
@@ -303,8 +308,10 @@ bool ssl_supports_version(SSL_HANDSHAKE *hs, uint16_t version) {
if (protocol_version != TLS1_3_VERSION ||
(ssl->tls13_variant == tls13_experiment2 &&
version == TLS1_3_EXPERIMENT2_VERSION) ||
+ (ssl->tls13_variant == tls13_draft22 &&
+ version == TLS1_3_DRAFT22_VERSION) ||
(ssl->tls13_variant == tls13_default &&
- version == TLS1_3_DRAFT22_VERSION)) {
+ version == TLS1_3_DRAFT23_VERSION)) {
return true;
}
@@ -362,7 +369,15 @@ bool ssl_negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
}
bool ssl_is_draft22(uint16_t version) {
- return version == TLS1_3_DRAFT22_VERSION;
+ return version == TLS1_3_DRAFT22_VERSION || version == TLS1_3_DRAFT23_VERSION;
+}
+
+bool ssl_is_draft23(uint16_t version) {
+ return version == TLS1_3_DRAFT23_VERSION;
+}
+
+bool ssl_is_draft23_variant(tls13_variant_t variant) {
+ return variant == tls13_default;
}
} // namespace bssl
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index 6b5447d9..7f4f10b7 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -148,102 +148,20 @@
#include <openssl/nid.h>
#include <openssl/rand.h>
+#include "../crypto/fipsmodule/tls/internal.h"
#include "../crypto/internal.h"
#include "internal.h"
namespace bssl {
-// tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
-// section 5. It XORs |out.size()| bytes to |out|, using |md| as the hash and
-// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to
-// form the seed parameter. It returns true on success and false on failure.
-static bool tls1_P_hash(Span<uint8_t> out, const EVP_MD *md,
- Span<const uint8_t> secret, Span<const char> label,
- Span<const uint8_t> seed1, Span<const uint8_t> seed2) {
- ScopedHMAC_CTX ctx, ctx_tmp, ctx_init;
- uint8_t A1[EVP_MAX_MD_SIZE];
- unsigned A1_len;
- bool ret = false;
-
- size_t chunk = EVP_MD_size(md);
-
- if (!HMAC_Init_ex(ctx_init.get(), secret.data(), secret.size(), md,
- nullptr) ||
- !HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
- !HMAC_Update(ctx.get(), reinterpret_cast<const uint8_t *>(label.data()),
- label.size()) ||
- !HMAC_Update(ctx.get(), seed1.data(), seed1.size()) ||
- !HMAC_Update(ctx.get(), seed2.data(), seed2.size()) ||
- !HMAC_Final(ctx.get(), A1, &A1_len)) {
- goto err;
- }
-
- for (;;) {
- unsigned len;
- uint8_t hmac[EVP_MAX_MD_SIZE];
- if (!HMAC_CTX_copy_ex(ctx.get(), ctx_init.get()) ||
- !HMAC_Update(ctx.get(), A1, A1_len) ||
- // Save a copy of |ctx| to compute the next A1 value below.
- (out.size() > chunk && !HMAC_CTX_copy_ex(ctx_tmp.get(), ctx.get())) ||
- !HMAC_Update(ctx.get(), reinterpret_cast<const uint8_t *>(label.data()),
- label.size()) ||
- !HMAC_Update(ctx.get(), seed1.data(), seed1.size()) ||
- !HMAC_Update(ctx.get(), seed2.data(), seed2.size()) ||
- !HMAC_Final(ctx.get(), hmac, &len)) {
- goto err;
- }
- assert(len == chunk);
-
- // XOR the result into |out|.
- if (len > out.size()) {
- len = out.size();
- }
- for (unsigned i = 0; i < len; i++) {
- out[i] ^= hmac[i];
- }
- out = out.subspan(len);
-
- if (out.empty()) {
- break;
- }
-
- // Calculate the next A1 value.
- if (!HMAC_Final(ctx_tmp.get(), A1, &A1_len)) {
- goto err;
- }
- }
-
- ret = true;
-
-err:
- OPENSSL_cleanse(A1, sizeof(A1));
- return ret;
-}
-
bool tls1_prf(const EVP_MD *digest, Span<uint8_t> out,
Span<const uint8_t> secret, Span<const char> label,
Span<const uint8_t> seed1, Span<const uint8_t> seed2) {
- if (out.empty()) {
- return true;
- }
-
- OPENSSL_memset(out.data(), 0, out.size());
-
- if (digest == EVP_md5_sha1()) {
- // If using the MD5/SHA1 PRF, |secret| is partitioned between MD5 and SHA-1.
- size_t secret_half = secret.size() - (secret.size() / 2);
- if (!tls1_P_hash(out, EVP_md5(), secret.subspan(0, secret_half), label,
- seed1, seed2)) {
- return false;
- }
-
- // Note that, if |secret.size()| is odd, the two halves share a byte.
- secret = secret.subspan(secret.size() - secret_half);
- digest = EVP_sha1();
- }
-
- return tls1_P_hash(out, digest, secret, label, seed1, seed2);
+ return 1 == CRYPTO_tls1_prf(digest, out.data(), out.size(), secret.data(),
+ secret.size(), label.data(), label.size(),
+ seed1.data(), seed1.size(), seed2.data(),
+ seed2.size());
}
static bool ssl3_prf(Span<uint8_t> out, Span<const uint8_t> secret,
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 814cce1a..a8833e05 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -116,6 +116,7 @@
#include <utility>
#include <openssl/bytestring.h>
+#include <openssl/chacha.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
@@ -549,12 +550,21 @@ static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
return true;
}
+static bool dont_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ return true;
+}
+
static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
// This extension from the client is handled elsewhere.
return true;
}
+static bool ignore_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ CBS *contents) {
+ return true;
+}
+
static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
return true;
}
@@ -2080,7 +2090,9 @@ static bool ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
}
CBB contents, kse_bytes;
- if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
+ if (!CBB_add_u16(out, ssl_is_draft23_variant(ssl->tls13_variant)
+ ? TLSEXT_TYPE_new_key_share
+ : TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
!CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
return false;
@@ -2237,7 +2249,9 @@ bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t group_id;
CBB kse_bytes, public_key;
if (!tls1_get_shared_group(hs, &group_id) ||
- !CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(out, ssl_is_draft23(hs->ssl->version)
+ ? TLSEXT_TYPE_new_key_share
+ : TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
@@ -2310,6 +2324,42 @@ static bool ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
}
+// Dummy PQ Padding extension
+//
+// Dummy post-quantum padding invovles the client (and later server) sending
+// useless, random-looking bytes in an extension in their ClientHello or
+// ServerHello. These extensions are sized to simulate a post-quantum
+// key-exchange and so enable measurement of the latency impact of the
+// additional bandwidth.
+
+static bool ext_dummy_pq_padding_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ const size_t len = hs->ssl->dummy_pq_padding_len;
+ if (len == 0) {
+ return true;
+ }
+
+ CBB contents;
+ uint8_t *buffer;
+ if (!CBB_add_u16(out, TLSEXT_TYPE_dummy_pq_padding) ||
+ !CBB_add_u16_length_prefixed(out, &contents) ||
+ !CBB_add_space(&contents, &buffer, len)) {
+ return false;
+ }
+
+ // The length is used as the nonce so that different length extensions have
+ // different contents. There's no reason this has to be the case, it just
+ // makes things a little more obvious in a packet dump.
+ uint8_t nonce[12] = {0};
+ memcpy(nonce, &len, sizeof(len));
+
+ memset(buffer, 0, len);
+ static const uint8_t kZeroKey[32] = {0};
+ CRYPTO_chacha_20(buffer, buffer, len, kZeroKey, nonce, 0);
+
+ return CBB_flush(out);
+}
+
+
// Negotiated Groups
//
// https://tools.ietf.org/html/rfc4492#section-5.1.2
@@ -2491,7 +2541,16 @@ static const struct tls_extension kExtensions[] = {
ext_ec_point_add_serverhello,
},
{
- TLSEXT_TYPE_key_share,
+ TLSEXT_TYPE_old_key_share,
+ // This is added by TLSEXT_TYPE_new_key_share's callback.
+ NULL,
+ dont_add_clienthello,
+ forbid_parse_serverhello,
+ ignore_parse_clienthello,
+ dont_add_serverhello,
+ },
+ {
+ TLSEXT_TYPE_new_key_share,
NULL,
ext_key_share_add_clienthello,
forbid_parse_serverhello,
@@ -2530,6 +2589,14 @@ static const struct tls_extension kExtensions[] = {
ignore_parse_clienthello,
dont_add_serverhello,
},
+ {
+ TLSEXT_TYPE_dummy_pq_padding,
+ NULL,
+ ext_dummy_pq_padding_add_clienthello,
+ ignore_parse_serverhello,
+ ignore_parse_clienthello,
+ dont_add_serverhello,
+ },
// The final extension must be non-empty. WebSphere Application Server 7.0 is
// intolerant to the last extension being zero-length. See
// https://crbug.com/363583.
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 38e40778..0123df7a 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -2054,6 +2054,10 @@ static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
if (config->max_send_fragment > 0) {
SSL_set_max_send_fragment(ssl.get(), config->max_send_fragment);
}
+ if (config->dummy_pq_padding_len > 0 &&
+ !SSL_set_dummy_pq_padding_size(ssl.get(), config->dummy_pq_padding_len)) {
+ return false;
+ }
int sock = Connect(config->port);
if (sock == -1) {
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 51effed4..15e42ffe 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -35,14 +35,17 @@ const (
const (
tls13Experiment2Version = 0x7e02
tls13Draft22Version = 0x7f16
+ tls13Draft23Version = 0x7f17
)
const (
- TLS13Draft22 = 0
+ TLS13Draft23 = 0
TLS13Experiment2 = 1
+ TLS13Draft22 = 2
)
var allTLSWireVersions = []uint16{
+ tls13Draft23Version,
tls13Draft22Version,
tls13Experiment2Version,
VersionTLS12,
@@ -120,7 +123,7 @@ const (
extensionPadding uint16 = 21
extensionExtendedMasterSecret uint16 = 23
extensionSessionTicket uint16 = 35
- extensionKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
+ extensionOldKeyShare uint16 = 40 // draft-ietf-tls-tls13-16
extensionPreSharedKey uint16 = 41 // draft-ietf-tls-tls13-16
extensionEarlyData uint16 = 42 // draft-ietf-tls-tls13-16
extensionSupportedVersions uint16 = 43 // draft-ietf-tls-tls13-16
@@ -128,10 +131,12 @@ const (
extensionPSKKeyExchangeModes uint16 = 45 // draft-ietf-tls-tls13-18
extensionTicketEarlyDataInfo uint16 = 46 // draft-ietf-tls-tls13-18
extensionCertificateAuthorities uint16 = 47 // draft-ietf-tls-tls13-21
+ extensionNewKeyShare uint16 = 51 // draft-ietf-tls-tls13-23
extensionCustom uint16 = 1234 // not IANA assigned
extensionNextProtoNeg uint16 = 13172 // not IANA assigned
extensionRenegotiationInfo uint16 = 0xff01
extensionChannelID uint16 = 30032 // not IANA assigned
+ extensionDummyPQPadding uint16 = 54537 // not IANA assigned
)
// TLS signaling cipher suite values
@@ -1521,6 +1526,11 @@ type ProtocolBugs struct {
// ExpectDraftTLS13DowngradeRandom, if true, causes the client to
// require the server send the draft TLS 1.3 anti-downgrade signal.
ExpectDraftTLS13DowngradeRandom bool
+
+ // ExpectDummyPQPaddingLength, if not zero, causes the server to
+ // require that the client sent a dummy PQ padding extension of this
+ // length.
+ ExpectDummyPQPaddingLength int
}
func (c *Config) serverInit() {
@@ -1633,7 +1643,7 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
switch vers {
case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
return vers, true
- case tls13Draft22Version, tls13Experiment2Version:
+ case tls13Draft23Version, tls13Draft22Version, tls13Experiment2Version:
return VersionTLS13, true
}
}
@@ -1642,7 +1652,11 @@ func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
}
func isDraft22(vers uint16) bool {
- return vers == tls13Draft22Version
+ return vers == tls13Draft22Version || vers == tls13Draft23Version
+}
+
+func isDraft23(vers uint16) bool {
+ return vers == tls13Draft23Version
}
// isSupportedVersion checks if the specified wire version is acceptable. If so,
@@ -1650,6 +1664,7 @@ func isDraft22(vers uint16) bool {
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
if (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) ||
+ (c.TLS13Variant != TLS13Draft23 && wireVers == tls13Draft23Version) ||
(c.TLS13Variant != TLS13Draft22 && wireVers == tls13Draft22Version) {
return 0, false
}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 0f4a714e..e477edf9 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -159,6 +159,11 @@ func (c *Conn) clientHandshake() error {
if maxVersion >= VersionTLS13 {
keyShares = make(map[CurveID]ecdhCurve)
hello.hasKeyShares = true
+ if c.config.TLS13Variant == TLS13Draft23 {
+ hello.keyShareExtension = extensionNewKeyShare
+ } else {
+ hello.keyShareExtension = extensionOldKeyShare
+ }
hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
curvesToSend := c.config.defaultCurves()
for _, curveID := range hello.supportedCurves {
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index c4a6e162..16d858f5 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -265,6 +265,7 @@ type clientHelloMsg struct {
supportedCurves []CurveID
supportedPoints []uint8
hasKeyShares bool
+ keyShareExtension uint16
keyShares []keyShareEntry
trailingKeyShareData bool
pskIdentities []pskIdentity
@@ -291,6 +292,7 @@ type clientHelloMsg struct {
omitExtensions bool
emptyExtensions bool
pad int
+ dummyPQPaddingLen int
}
func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -339,7 +341,8 @@ func (m *clientHelloMsg) equal(i interface{}) bool {
m.pskBinderFirst == m1.pskBinderFirst &&
m.omitExtensions == m1.omitExtensions &&
m.emptyExtensions == m1.emptyExtensions &&
- m.pad == m1.pad
+ m.pad == m1.pad &&
+ m.dummyPQPaddingLen == m1.dummyPQPaddingLen
}
func (m *clientHelloMsg) marshal() []byte {
@@ -444,7 +447,7 @@ func (m *clientHelloMsg) marshal() []byte {
supportedPoints.addBytes(m.supportedPoints)
}
if m.hasKeyShares {
- extensions.addU16(extensionKeyShare)
+ extensions.addU16(m.keyShareExtension)
keyShareList := extensions.addU16LengthPrefixed()
keyShares := keyShareList.addU16LengthPrefixed()
@@ -719,7 +722,12 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
// http://tools.ietf.org/html/rfc5077#section-3.2
m.ticketSupported = true
m.sessionTicket = []byte(body)
- case extensionKeyShare:
+ case extensionOldKeyShare, extensionNewKeyShare:
+ // We assume the client only supports one of draft-22 or draft-23.
+ if m.keyShareExtension != 0 {
+ return false
+ }
+ m.keyShareExtension = extension
// draft-ietf-tls-tls13 section 6.3.2.3
var keyShares byteReader
if !body.readU16LengthPrefixed(&keyShares) || len(body) != 0 {
@@ -847,6 +855,11 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool {
m.sctListSupported = true
case extensionCustom:
m.customExtension = string(body)
+ case extensionDummyPQPadding:
+ if len(body) == 0 {
+ return false
+ }
+ m.dummyPQPaddingLen = len(body)
}
if isGREASEValue(extension) {
@@ -912,7 +925,11 @@ func (m *serverHelloMsg) marshal() []byte {
if vers >= VersionTLS13 {
if m.hasKeyShare {
- extensions.addU16(extensionKeyShare)
+ if isDraft23(m.vers) {
+ extensions.addU16(extensionNewKeyShare)
+ } else {
+ extensions.addU16(extensionOldKeyShare)
+ }
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
@@ -1015,6 +1032,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool {
}
if vers >= VersionTLS13 {
+ extensionKeyShare := extensionOldKeyShare
+ if isDraft23(m.vers) {
+ extensionKeyShare = extensionNewKeyShare
+ }
for len(extensions) > 0 {
var extension uint16
var body byteReader
@@ -1195,7 +1216,7 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) {
}
}
if m.hasKeyShare {
- extensions.addU16(extensionKeyShare)
+ extensions.addU16(extensionOldKeyShare)
keyShare := extensions.addU16LengthPrefixed()
keyShare.addU16(uint16(m.keyShare.group))
keyExchange := keyShare.addU16LengthPrefixed()
@@ -1388,7 +1409,11 @@ func (m *helloRetryRequestMsg) marshal() []byte {
extensions.addU16(m.vers)
}
if m.hasSelectedGroup {
- extensions.addU16(extensionKeyShare)
+ if isDraft23(m.vers) {
+ extensions.addU16(extensionNewKeyShare)
+ } else {
+ extensions.addU16(extensionOldKeyShare)
+ }
extensions.addU16(2) // length
extensions.addU16(uint16(m.selectedGroup))
}
@@ -1431,11 +1456,12 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
if !reader.readU16LengthPrefixed(&extensions) || len(reader) != 0 {
return false
}
- for len(extensions) > 0 {
+ extensionsCopy := extensions
+ for len(extensionsCopy) > 0 {
var extension uint16
var body byteReader
- if !extensions.readU16(&extension) ||
- !extensions.readU16LengthPrefixed(&body) {
+ if !extensionsCopy.readU16(&extension) ||
+ !extensionsCopy.readU16LengthPrefixed(&body) {
return false
}
switch extension {
@@ -1445,6 +1471,23 @@ func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
len(body) != 0 {
return false
}
+ default:
+ }
+ }
+ extensionKeyShare := extensionOldKeyShare
+ if isDraft23(m.vers) {
+ extensionKeyShare = extensionNewKeyShare
+ }
+ for len(extensions) > 0 {
+ var extension uint16
+ var body byteReader
+ if !extensions.readU16(&extension) ||
+ !extensions.readU16LengthPrefixed(&body) {
+ return false
+ }
+ switch extension {
+ case extensionSupportedVersions:
+ // Parsed above.
case extensionKeyShare:
var v uint16
if !body.readU16(&v) || len(body) != 0 {
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 6b7daee1..d317d016 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -280,6 +280,14 @@ func (hs *serverHandshakeState) readClientHello() error {
}
}
+ // Check that we received the expected version of the key_share extension.
+ if c.vers >= VersionTLS13 {
+ if (isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionNewKeyShare) ||
+ (!isDraft23(c.wireVersion) && hs.clientHello.keyShareExtension != extensionOldKeyShare) {
+ return fmt.Errorf("tls: client offered wrong key_share extension")
+ }
+ }
+
if config.Bugs.ExpectNoTLS12Session {
if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 {
return fmt.Errorf("tls: client offered an unexpected session ID")
@@ -337,6 +345,10 @@ func (hs *serverHandshakeState) readClientHello() error {
}
}
+ if expected := hs.clientHello.dummyPQPaddingLen; expected != config.Bugs.ExpectDummyPQPaddingLength {
+ return fmt.Errorf("tls: expected dummy PQ padding extension of length %d, but got one of length %d", expected, config.Bugs.ExpectDummyPQPaddingLength)
+ }
+
applyBugsToClientHello(hs.clientHello, config)
return nil
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 75062803..1f2a20a4 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -909,6 +909,17 @@ func lldbOf(path string, args ...string) *exec.Cmd {
return exec.Command("xterm", xtermArgs...)
}
+func removeFirstLineIfSuffix(s, suffix string) string {
+ idx := strings.IndexByte(s, '\n')
+ if idx < 0 {
+ return s
+ }
+ if strings.HasSuffix(s[:idx], suffix) {
+ return s[idx+1:]
+ }
+ return s
+}
+
var (
errMoreMallocs = errors.New("child process did not exhaust all allocation calls")
errUnimplemented = errors.New("child process does not implement needed flags")
@@ -1206,6 +1217,18 @@ func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
+ // Work around an NDK / Android bug. The NDK r16 sometimes generates
+ // binaries with the DF_1_PIE, which the runtime linker on Android N
+ // complains about. The next NDK revision should work around this but,
+ // in the meantime, strip its error out.
+ //
+ // https://github.com/android-ndk/ndk/issues/602
+ // https://android-review.googlesource.com/c/platform/bionic/+/259790
+ // https://android-review.googlesource.com/c/toolchain/binutils/+/571550
+ //
+ // Remove this after switching to the r17 NDK.
+ stderr = removeFirstLineIfSuffix(stderr, ": unsupported flags DT_FLAGS_1=0x8000001")
+
// Separate the errors from the shim and those from tools like
// AddressSanitizer.
var extraStderr string
@@ -5306,7 +5329,7 @@ func addVersionNegotiationTests() {
expectedClientVersion := expectedVersion
if expectedVersion == VersionTLS13 && runnerVers.tls13Variant != shimVers.tls13Variant {
expectedClientVersion = VersionTLS12
- if shimVers.tls13Variant == TLS13Draft22 {
+ if shimVers.tls13Variant == TLS13Draft23 {
expectedServerVersion = VersionTLS12
}
}
@@ -5516,7 +5539,7 @@ func addVersionNegotiationTests() {
name: "IgnoreClientVersionOrder",
config: Config{
Bugs: ProtocolBugs{
- SendSupportedVersions: []uint16{VersionTLS12, tls13Draft22Version},
+ SendSupportedVersions: []uint16{VersionTLS12, tls13Draft23Version},
},
},
expectedVersion: VersionTLS13,
@@ -6750,6 +6773,32 @@ func addExtensionTests() {
shouldFail: true,
expectedError: ":INVALID_SCT_LIST:",
})
+
+ for _, version := range allVersions(tls) {
+ if version.version < VersionTLS12 {
+ continue
+ }
+
+ for _, paddingLen := range []int{1, 9700} {
+ flags := []string{
+ "-max-version", version.shimFlag(tls),
+ "-dummy-pq-padding-len", strconv.Itoa(paddingLen),
+ }
+
+ testCases = append(testCases, testCase{
+ name: fmt.Sprintf("DummyPQPadding-%d-%s", paddingLen, version.name),
+ testType: clientTest,
+ tls13Variant: version.tls13Variant,
+ config: Config{
+ MaxVersion: version.version,
+ Bugs: ProtocolBugs{
+ ExpectDummyPQPaddingLength: paddingLen,
+ },
+ },
+ flags: flags,
+ })
+ }
+ }
}
func addResumptionVersionTests() {
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 6744a00a..0d11f900 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -194,6 +194,7 @@ const Flag<int> kIntFlags[] = {
{ "-read-size", &TestConfig::read_size },
{ "-expect-ticket-age-skew", &TestConfig::expect_ticket_age_skew },
{ "-tls13-variant", &TestConfig::tls13_variant },
+ { "-dummy-pq-padding-len", &TestConfig::dummy_pq_padding_len },
};
const Flag<std::vector<int>> kIntVectorFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index a459ae52..fe107bce 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -147,6 +147,7 @@ struct TestConfig {
std::string expect_msg_callback;
bool allow_false_start_without_alpn = false;
bool expect_draft_downgrade = false;
+ int dummy_pq_padding_len = 0;
};
bool ParseConfig(int argc, char **argv, TestConfig *out_initial,
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 8d46d9fa..f4375195 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -136,8 +136,10 @@ static enum ssl_hs_wait_t do_read_hello_retry_request(SSL_HANDSHAKE *hs) {
bool have_cookie, have_key_share, have_supported_versions;
CBS cookie, key_share, supported_versions;
- const SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
+ SSL_EXTENSION_TYPE ext_types[] = {
+ {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
+ : (uint16_t)TLSEXT_TYPE_old_key_share,
+ &have_key_share, &key_share},
{TLSEXT_TYPE_cookie, &have_cookie, &cookie},
{TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions},
@@ -305,8 +307,10 @@ static enum ssl_hs_wait_t do_read_server_hello(SSL_HANDSHAKE *hs) {
bool have_key_share = false, have_pre_shared_key = false,
have_supported_versions = false;
CBS key_share, pre_shared_key, supported_versions;
- const SSL_EXTENSION_TYPE ext_types[] = {
- {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
+ SSL_EXTENSION_TYPE ext_types[] = {
+ {ssl_is_draft23(ssl->version) ? (uint16_t)TLSEXT_TYPE_new_key_share
+ : (uint16_t)TLSEXT_TYPE_old_key_share,
+ &have_key_share, &key_share},
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
{TLSEXT_TYPE_supported_versions, &have_supported_versions,
&supported_versions},
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index 46514594..72273dae 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -63,10 +63,15 @@ static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, bool *out_need_retry,
SSL *const ssl = hs->ssl;
*out_need_retry = false;
+ uint16_t key_share_ext = TLSEXT_TYPE_old_key_share;
+ if (ssl_is_draft23(ssl->version)) {
+ key_share_ext = TLSEXT_TYPE_new_key_share;
+ }
+
// We only support connections that include an ECDHE key exchange.
CBS key_share;
if (!ssl_client_hello_get_extension(client_hello, &key_share,
- TLSEXT_TYPE_key_share)) {
+ key_share_ext)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return 0;
@@ -508,7 +513,9 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
!CBB_add_u16(&extensions, TLSEXT_TYPE_supported_versions) ||
!CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, ssl->version) ||
- !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(&extensions, ssl_is_draft23(ssl->version)
+ ? TLSEXT_TYPE_new_key_share
+ : TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, group_id) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
@@ -529,7 +536,7 @@ static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher))) ||
!tls1_get_shared_group(hs, &group_id) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
- !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+ !CBB_add_u16(&extensions, TLSEXT_TYPE_old_key_share) ||
!CBB_add_u16(&extensions, 2 /* length */) ||
!CBB_add_u16(&extensions, group_id) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
diff --git a/src/third_party/fiat/BUILD.gn b/src/third_party/fiat/BUILD.gn
new file mode 100644
index 00000000..1201e25e
--- /dev/null
+++ b/src/third_party/fiat/BUILD.gn
@@ -0,0 +1,4 @@
+# This is an dummy target so Chromium's tools/licenses.py script picks up the
+# extra README.chromium file. The script expects README.chromium files to be
+# associated with GN targets.
+source_set("fiat_license") { }
diff --git a/src/third_party/fiat/README.chromium b/src/third_party/fiat/README.chromium
new file mode 100644
index 00000000..73c5ba20
--- /dev/null
+++ b/src/third_party/fiat/README.chromium
@@ -0,0 +1,10 @@
+Name: Fiat-Crypto: Synthesizing Correct-by-Construction Code for Cryptographic Primitives
+Short Name: fiat-crypto
+URL: https://github.com/mit-plv/fiat-crypto
+Version: git (see METADATA)
+License: MIT
+License File: LICENSE
+Security Critical: yes
+
+Description:
+See README.md and METADATA.
diff --git a/src/third_party/fiat/p256.c b/src/third_party/fiat/p256.c
index 9c7de35e..f1d53165 100644
--- a/src/third_party/fiat/p256.c
+++ b/src/third_party/fiat/p256.c
@@ -1069,10 +1069,10 @@ static void point_add(fe x3, fe y3, fe z3, const fe x1,
fe u1, s1, two_z1z2;
if (!mixed) {
- // ftmp2 = z2z2 = z2**2
+ // z2z2 = z2**2
fe z2z2; fe_sqr(z2z2, z2);
- // u1 = ftmp3 = x1*z2z2
+ // u1 = x1*z2z2
fe_mul(u1, x1, z2z2);
// two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2
@@ -1081,24 +1081,24 @@ static void point_add(fe x3, fe y3, fe z3, const fe x1,
fe_sub(two_z1z2, two_z1z2, z1z1);
fe_sub(two_z1z2, two_z1z2, z2z2);
- // s1 = ftmp2 = y1 * z2**3
+ // s1 = y1 * z2**3
fe_mul(s1, z2, z2z2);
fe_mul(s1, s1, y1);
} else {
// We'll assume z2 = 1 (special case z2 = 0 is handled later).
- // u1 = ftmp3 = x1*z2z2
+ // u1 = x1*z2z2
fe_copy(u1, x1);
// two_z1z2 = 2z1z2
fe_add(two_z1z2, z1, z1);
- // s1 = ftmp2 = y1 * z2**3
+ // s1 = y1 * z2**3
fe_copy(s1, y1);
}
// u2 = x2*z1z1
fe u2; fe_mul(u2, x2, z1z1);
- // h = ftmp4 = u2 - u1
+ // h = u2 - u1
fe h; fe_sub(h, u2, u1);
limb_t xneq = fe_nz(h);
@@ -1109,7 +1109,7 @@ static void point_add(fe x3, fe y3, fe z3, const fe x1,
// z1z1z1 = z1 * z1z1
fe z1z1z1; fe_mul(z1z1z1, z1, z1z1);
- // s2 = tmp = y2 * z1**3
+ // s2 = y2 * z1**3
fe s2; fe_mul(s2, y2, z1z1z1);
// r = (s2 - s1)*2
@@ -1129,10 +1129,10 @@ static void point_add(fe x3, fe y3, fe z3, const fe x1,
fe_add(i, h, h);
fe_sqr(i, i);
- // J = ftmp2 = h * I
+ // J = h * I
fe j; fe_mul(j, h, i);
- // V = ftmp4 = U1 * I
+ // V = U1 * I
fe v; fe_mul(v, u1, i);
// x_out = r**2 - J - 2V
@@ -1645,9 +1645,13 @@ static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
fe_inv(z2, z1);
fe_sqr(z1, z2);
+ // Instead of using |fe_from_montgomery| to convert the |x| coordinate and
+ // then calling |fe_from_montgomery| again to convert the |y| coordinate
+ // below, convert the common factor |z1| once now, saving one reduction.
+ fe_from_montgomery(z1);
+
if (x_out != NULL) {
fe_mul(x, x, z1);
- fe_from_montgomery(x);
if (!fe_to_BN(x_out, x)) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
return 0;
@@ -1657,7 +1661,6 @@ static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
if (y_out != NULL) {
fe_mul(z1, z1, z2);
fe_mul(y, y, z1);
- fe_from_montgomery(y);
if (!fe_to_BN(y_out, y)) {
OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
return 0;
diff --git a/src/tool/client.cc b/src/tool/client.cc
index fc8f5e06..de1a8ca3 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -333,7 +333,7 @@ static bool DoConnection(SSL_CTX *ctx,
static bool GetTLS13Variant(tls13_variant_t *out, const std::string &in) {
if (in == "draft22") {
- *out = tls13_default;
+ *out = tls13_draft22;
return true;
}
if (in == "experiment2") {
diff --git a/src/util/bot/UPDATING b/src/util/bot/UPDATING
index 7162f945..f5a831b4 100644
--- a/src/util/bot/UPDATING
+++ b/src/util/bot/UPDATING
@@ -39,11 +39,7 @@ cmake-win32.zip: Update to the latest prebuilt release of CMake, found at
https://cmake.org/download/. Use the file labeled "Windows ZIP". The
download will be named cmake-VERSION-win32-x86.zip.
- The current revision is cmake-3.5.0-win32-x86.zip.
-
- TODO(davidben): The update to CMake 3.10 on Windows was rolled back due to a
- CMake bug. Update to 3.10.1 when that is released.
- https://github.com/Kitware/CMake/commit/f969f1a9ce1d0045b9d056fd08c4683c34c420fa
+ The current revision is cmake-3.10.1-win32-x86.zip.
perl-win32.zip: Update to the latest 32-bit prebuilt "Portable" edition of
Strawberry Perl, found at http://strawberryperl.com/releases.html. The
diff --git a/src/util/bot/cmake-win32.zip.sha1 b/src/util/bot/cmake-win32.zip.sha1
index 6bb460eb..22926a36 100644
--- a/src/util/bot/cmake-win32.zip.sha1
+++ b/src/util/bot/cmake-win32.zip.sha1
@@ -1 +1 @@
-ed4e1939d246374b0bae724a1a4200fd60e7efe8 \ No newline at end of file
+f3ba5a7d4be36d6eba1795011ba0926bb651f35f \ No newline at end of file