diff options
author | Robert Sloan <varomodt@google.com> | 2018-01-19 11:01:41 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-01-19 11:01:41 +0000 |
commit | 7375becf5eb38f8e7cc10f10bb52186e559688f1 (patch) | |
tree | 3586ad210d439fd1afb10f66782babac5af5fe64 | |
parent | b7ace47a0bc07de8c61176ba2909751acc2a4a17 (diff) | |
parent | bbd53e043de3f98f94c25727af15a50a9e10e2f6 (diff) | |
download | boringssl-7375becf5eb38f8e7cc10f10bb52186e559688f1.tar.gz |
NO PARTIAL RERUN external/boringssl: Sync to 37c6eb4284bea36be9fa41d35b582008f2023dcf. am: 0db7f543e9
am: bbd53e043d
Change-Id: If8c3b62c84171fec7be3baf9d002927a7dfa49de
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 |