/*
- * Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2014-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2014, Intel Corporation. All Rights Reserved.
* Copyright (c) 2015, CloudFlare, Inc.
*
* 256 Bit Primes"
*/
+/*
+ * ECDSA low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
#include <string.h>
#include "internal/cryptlib.h"
-#include "internal/bn_int.h"
-#include "ec_lcl.h"
+#include "crypto/bn.h"
+#include "ec_local.h"
#include "internal/refcount.h"
#if BN_BITS2 != 64
ecp_nistz256_sub(H, U2, U1); /* H = U2 - U1 */
/*
- * This should not happen during sign/ecdh, so no constant time violation
+ * The formulae are incorrect if the points are equal so we check for
+ * this and do doubling if this happens.
+ *
+ * Points here are in Jacobian projective coordinates (Xi, Yi, Zi)
+ * that are bound to the affine coordinates (xi, yi) by the following
+ * equations:
+ * - xi = Xi / (Zi)^2
+ * - y1 = Yi / (Zi)^3
+ *
+ * For the sake of optimization, the algorithm operates over
+ * intermediate variables U1, U2 and S1, S2 that are derived from
+ * the projective coordinates:
+ * - U1 = X1 * (Z2)^2 ; U2 = X2 * (Z1)^2
+ * - S1 = Y1 * (Z2)^3 ; S2 = Y2 * (Z1)^3
+ *
+ * It is easy to prove that is_equal(U1, U2) implies that the affine
+ * x-coordinates are equal, or either point is at infinity.
+ * Likewise is_equal(S1, S2) implies that the affine y-coordinates are
+ * equal, or either point is at infinity.
+ *
+ * The special case of either point being the point at infinity (Z1 or Z2
+ * is zero), is handled separately later on in this function, so we avoid
+ * jumping to point_double here in those special cases.
+ *
+ * When both points are inverse of each other, we know that the affine
+ * x-coordinates are equal, and the y-coordinates have different sign.
+ * Therefore since U1 = U2, we know H = 0, and therefore Z3 = H*Z1*Z2
+ * will equal 0, thus the result is infinity, if we simply let this
+ * function continue normally.
+ *
+ * We use bitwise operations to avoid potential side-channels introduced by
+ * the short-circuiting behaviour of boolean operators.
*/
- if (is_equal(U1, U2) && !in1infty && !in2infty) {
- if (is_equal(S1, S2)) {
- ecp_nistz256_point_double(r, a);
- return;
- } else {
- memset(r, 0, sizeof(*r));
- return;
- }
+ if (is_equal(U1, U2) & ~in1infty & ~in2infty & is_equal(S1, S2)) {
+ /*
+ * This is obviously not constant-time but it should never happen during
+ * single point multiplication, so there is no timing leak for ECDH or
+ * ECDSA signing.
+ */
+ ecp_nistz256_point_double(r, a);
+ return;
}
ecp_nistz256_sqr_mont(Rsqr, R); /* R^2 */
return 0;
if (ctx == NULL) {
- ctx = new_ctx = BN_CTX_new();
+ ctx = new_ctx = BN_CTX_new_ex(group->libctx);
if (ctx == NULL)
goto err;
}
* It would be faster to use EC_POINTs_make_affine and
* make multiple points affine at the same time.
*/
- if (!EC_POINT_make_affine(group, P, ctx))
+ if (group->meth->make_affine == NULL
+ || !group->meth->make_affine(group, P, ctx))
goto err;
if (!ecp_nistz256_bignum_to_field_elem(temp.X, P->X) ||
!ecp_nistz256_bignum_to_field_elem(temp.Y, P->Y)) {
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_nistz256_pre_comp_free(pre_comp);
return;
CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
- REF_PRINT_COUNT("EC_nistz256", x);
+ REF_PRINT_COUNT("EC_nistz256", pre);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
const BN_ULONG b[P256_LIMBS]);
void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
- int rep);
+ BN_ULONG rep);
static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
ec_GFp_simple_point_clear_finish,
ec_GFp_simple_point_copy,
ec_GFp_simple_point_set_to_infinity,
- ec_GFp_simple_set_Jprojective_coordinates_GFp,
- ec_GFp_simple_get_Jprojective_coordinates_GFp,
ec_GFp_simple_point_set_affine_coordinates,
ecp_nistz256_get_affine,
0, 0, 0,
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
0, /* field_div */
+ ec_GFp_mont_field_inv,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
ec_GFp_mont_field_set_to_one,
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
+ ecdsa_simple_sign_setup,
+ ecdsa_simple_sign_sig,
+ ecdsa_simple_verify_sig,
ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
0, /* blind_coordinates */
0, /* ladder_pre */