From: jsg Date: Sun, 15 Jul 2018 05:38:48 +0000 (+0000) Subject: back out ecc constant time changes X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c9077bbc46769536e336db5aa610db3786adb7fe;p=openbsd back out ecc constant time changes after the constant time commits various regress tests started failing on sparc64 ssh t9, libcrypto ec ecdh ecdsa and trying to ssh out resulted in 'invalid elliptic curve value' ok tb@ --- diff --git a/lib/libcrypto/ec/ec2_mult.c b/lib/libcrypto/ec/ec2_mult.c index 463802950d2..10191d7916b 100644 --- a/lib/libcrypto/ec/ec2_mult.c +++ b/lib/libcrypto/ec/ec2_mult.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec2_mult.c,v 1.10 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec2_mult.c,v 1.11 2018/07/15 05:38:48 jsg Exp $ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * @@ -111,7 +111,7 @@ gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z, BN_CTX *ctx) ret = 1; - err: +err: BN_CTX_end(ctx); return ret; } @@ -155,7 +155,7 @@ gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1, BIGNUM *z1, ret = 1; - err: +err: BN_CTX_end(ctx); return ret; } @@ -243,7 +243,7 @@ gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, ret = 2; - err: +err: BN_CTX_end(ctx); return ret; } @@ -356,7 +356,7 @@ ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, ret = 1; - err: +err: BN_CTX_end(ctx); return ret; } @@ -424,7 +424,7 @@ ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, ret = 1; - err: +err: EC_POINT_free(p); EC_POINT_free(acc); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ec2_oct.c b/lib/libcrypto/ec/ec2_oct.c index 1727f780a3c..bb480c5016a 100644 --- a/lib/libcrypto/ec/ec2_oct.c +++ b/lib/libcrypto/ec/ec2_oct.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec2_oct.c,v 1.9 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec2_oct.c,v 1.10 2018/07/15 05:38:48 jsg Exp $ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * @@ -157,7 +157,7 @@ ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -272,7 +272,7 @@ ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, BN_CTX_free(new_ctx); return ret; - err: +err: if (used_ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -374,7 +374,7 @@ ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, } ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; diff --git a/lib/libcrypto/ec/ec2_smpl.c b/lib/libcrypto/ec/ec2_smpl.c index f1cbd3f3c49..c3fff56c440 100644 --- a/lib/libcrypto/ec/ec2_smpl.c +++ b/lib/libcrypto/ec/ec2_smpl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec2_smpl.c,v 1.17 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec2_smpl.c,v 1.18 2018/07/15 05:38:48 jsg Exp $ */ /* ==================================================================== * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. * @@ -107,11 +107,15 @@ EC_GF2m_simple_method(void) .point_cmp = ec_GF2m_simple_cmp, .make_affine = ec_GF2m_simple_make_affine, .points_make_affine = ec_GF2m_simple_points_make_affine, - .mul_generator_ct = ec_GFp_simple_mul_generator_ct, - .mul_single_ct = ec_GFp_simple_mul_single_ct, - .mul_double_nonct = ec_GFp_simple_mul_double_nonct, + + /* + * the following three method functions are defined in + * ec2_mult.c + */ + .mul = ec_GF2m_simple_mul, .precompute_mult = ec_GF2m_precompute_mult, .have_precompute_mult = ec_GF2m_have_precompute_mult, + .field_mul = ec_GF2m_simple_field_mul, .field_sqr = ec_GF2m_simple_field_sqr, .field_div = ec_GF2m_simple_field_div, @@ -228,7 +232,7 @@ ec_GF2m_simple_group_set_curve(EC_GROUP * group, group->b.d[i] = 0; ret = 1; - err: +err: return ret; } @@ -256,7 +260,7 @@ ec_GF2m_simple_group_get_curve(const EC_GROUP *group, } ret = 1; - err: +err: return ret; } @@ -302,7 +306,7 @@ ec_GF2m_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) ret = 1; - err: +err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -394,7 +398,7 @@ ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * p point->Z_is_one = 1; ret = 1; - err: +err: return ret; } @@ -428,7 +432,7 @@ ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, } ret = 1; - err: +err: return ret; } @@ -545,7 +549,7 @@ ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -637,7 +641,7 @@ ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX if (!BN_GF2m_add(lh, lh, y2)) goto err; ret = BN_is_zero(lh); - err: +err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -689,7 +693,7 @@ ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a, goto err; ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1; - err: +err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -730,7 +734,7 @@ ec_GF2m_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ct ret = 1; - err: +err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ec_ameth.c b/lib/libcrypto/ec/ec_ameth.c index 21390aabd42..30f29ef5453 100644 --- a/lib/libcrypto/ec/ec_ameth.c +++ b/lib/libcrypto/ec/ec_ameth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_ameth.c,v 1.21 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_ameth.c,v 1.22 2018/07/15 05:38:48 jsg Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2006. */ @@ -126,7 +126,7 @@ eckey_pub_encode(X509_PUBKEY * pk, const EVP_PKEY * pkey) if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc, penclen)) return 1; - err: +err: if (ptype == V_ASN1_OBJECT) ASN1_OBJECT_free(pval); else @@ -177,7 +177,7 @@ eckey_type2param(int ptype, const void *pval) return eckey; - ecerr: +ecerr: if (eckey) EC_KEY_free(eckey); return NULL; @@ -210,7 +210,7 @@ eckey_pub_decode(EVP_PKEY * pkey, X509_PUBKEY * pubkey) EVP_PKEY_assign_EC_KEY(pkey, eckey); return 1; - ecerr: +ecerr: if (eckey) EC_KEY_free(eckey); return 0; @@ -290,9 +290,9 @@ eckey_priv_decode(EVP_PKEY * pkey, PKCS8_PRIV_KEY_INFO * p8) EVP_PKEY_assign_EC_KEY(pkey, eckey); return 1; - ecliberr: +ecliberr: ECerror(ERR_R_EC_LIB); - ecerr: +ecerr: if (eckey) EC_KEY_free(eckey); return 0; @@ -483,7 +483,7 @@ do_EC_KEY_print(BIO * bp, const EC_KEY * x, int off, int ktype) if (!ECPKParameters_print(bp, group, off)) goto err; ret = 1; - err: +err: if (!ret) ECerror(reason); BN_free(pub_key); diff --git a/lib/libcrypto/ec/ec_asn1.c b/lib/libcrypto/ec/ec_asn1.c index 1fb0670efe1..f5a1331ba3a 100644 --- a/lib/libcrypto/ec/ec_asn1.c +++ b/lib/libcrypto/ec/ec_asn1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_asn1.c,v 1.28 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_asn1.c,v 1.29 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -793,7 +793,7 @@ ec_asn1_group2fieldid(const EC_GROUP * group, X9_62_FIELDID * field) ok = 1; - err: +err: BN_free(tmp); return (ok); } @@ -896,7 +896,7 @@ ec_asn1_group2curve(const EC_GROUP * group, X9_62_CURVE * curve) ok = 1; - err: +err: free(buffer_1); free(buffer_2); BN_free(tmp_1); @@ -988,8 +988,7 @@ ec_asn1_group2parameters(const EC_GROUP * group, ECPARAMETERS * param) } ok = 1; - err: - if (!ok) { +err: if (!ok) { if (ret && !param) ECPARAMETERS_free(ret); ret = NULL; @@ -1245,8 +1244,7 @@ ec_asn1_parameters2group(const ECPARAMETERS * params) } ok = 1; - err: - if (!ok) { +err: if (!ok) { EC_GROUP_clear_free(ret); ret = NULL; } @@ -1314,7 +1312,7 @@ d2i_ECPKParameters(EC_GROUP ** a, const unsigned char **in, long len) *a = group; } - err: +err: ECPKPARAMETERS_free(params); return (group); } @@ -1427,7 +1425,7 @@ d2i_ECPrivateKey(EC_KEY ** a, const unsigned char **in, long len) *a = ret; return (ret); - err: +err: if (a == NULL || *a != ret) EC_KEY_free(ret); if (priv_key) @@ -1512,7 +1510,7 @@ i2d_ECPrivateKey(EC_KEY * a, unsigned char **out) goto err; } ok = 1; - err: +err: free(buffer); if (priv_key) EC_PRIVATEKEY_free(priv_key); diff --git a/lib/libcrypto/ec/ec_check.c b/lib/libcrypto/ec/ec_check.c index b0c63331c66..a76d21c1ff6 100644 --- a/lib/libcrypto/ec/ec_check.c +++ b/lib/libcrypto/ec/ec_check.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_check.c,v 1.7 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_check.c,v 1.8 2018/07/15 05:38:48 jsg Exp $ */ /* ==================================================================== * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * @@ -106,7 +106,7 @@ EC_GROUP_check(const EC_GROUP * group, BN_CTX * ctx) } ret = 1; - err: +err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ec_curve.c b/lib/libcrypto/ec/ec_curve.c index 7bf85835dc2..1808e7b65cf 100644 --- a/lib/libcrypto/ec/ec_curve.c +++ b/lib/libcrypto/ec/ec_curve.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_curve.c,v 1.17 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_curve.c,v 1.18 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -3235,7 +3235,7 @@ ec_group_new_from_data(const ec_list_element curve) } } ok = 1; - err: +err: if (!ok) { EC_GROUP_free(group); group = NULL; diff --git a/lib/libcrypto/ec/ec_key.c b/lib/libcrypto/ec/ec_key.c index 33c9acccd77..a9f03c4ac28 100644 --- a/lib/libcrypto/ec/ec_key.c +++ b/lib/libcrypto/ec/ec_key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_key.c,v 1.15 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_key.c,v 1.16 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -253,7 +253,7 @@ EC_KEY_generate_key(EC_KEY * eckey) ok = 1; - err: +err: BN_free(order); if (pub_key != NULL && eckey->pub_key == NULL) EC_POINT_free(pub_key); @@ -324,7 +324,7 @@ EC_KEY_check_key(const EC_KEY * eckey) } } ok = 1; - err: +err: BN_CTX_free(ctx); EC_POINT_free(point); return (ok); @@ -395,7 +395,7 @@ EC_KEY_set_public_key_affine_coordinates(EC_KEY * key, BIGNUM * x, BIGNUM * y) ok = 1; - err: +err: BN_CTX_free(ctx); EC_POINT_free(point); return ok; diff --git a/lib/libcrypto/ec/ec_lcl.h b/lib/libcrypto/ec/ec_lcl.h index 4916d3a14a2..bcfd817b703 100644 --- a/lib/libcrypto/ec/ec_lcl.h +++ b/lib/libcrypto/ec/ec_lcl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_lcl.h,v 1.8 2018/07/10 21:55:49 tb Exp $ */ +/* $OpenBSD: ec_lcl.h,v 1.9 2018/07/15 05:38:48 jsg Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -160,12 +160,10 @@ struct ec_method_st { int (*make_affine)(const EC_GROUP *, EC_POINT *, BN_CTX *); int (*points_make_affine)(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); - /* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, EC_POINT_have_precompute_mult */ - int (*mul_generator_ct)(const EC_GROUP *, EC_POINT *r, const BIGNUM *scalar, BN_CTX *); - int (*mul_single_ct)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - const EC_POINT *point, BN_CTX *); - int (*mul_double_nonct)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, - const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *); + /* used by EC_POINTs_mul, EC_POINT_mul, EC_POINT_precompute_mult, EC_POINT_have_precompute_mult + * (default implementations are used if the 'mul' pointer is 0): */ + int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, + size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *); int (*precompute_mult)(EC_GROUP *group, BN_CTX *); int (*have_precompute_mult)(const EC_GROUP *group); @@ -339,11 +337,6 @@ int ec_GFp_simple_make_affine(const EC_GROUP *, EC_POINT *, BN_CTX *); int ec_GFp_simple_points_make_affine(const EC_GROUP *, size_t num, EC_POINT *[], BN_CTX *); int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a, BN_CTX *); -int ec_GFp_simple_mul_generator_ct(const EC_GROUP *, EC_POINT *r, const BIGNUM *scalar, BN_CTX *); -int ec_GFp_simple_mul_single_ct(const EC_GROUP *, EC_POINT *r, const BIGNUM *scalar, - const EC_POINT *point, BN_CTX *); -int ec_GFp_simple_mul_double_nonct(const EC_GROUP *, EC_POINT *r, const BIGNUM *g_scalar, - const BIGNUM *p_scalar, const EC_POINT *point, BN_CTX *); /* method functions in ecp_mont.c */ diff --git a/lib/libcrypto/ec/ec_lib.c b/lib/libcrypto/ec/ec_lib.c index 1d1daca1663..29207d6b489 100644 --- a/lib/libcrypto/ec/ec_lib.c +++ b/lib/libcrypto/ec/ec_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_lib.c,v 1.26 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_lib.c,v 1.27 2018/07/15 05:38:48 jsg Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -526,7 +526,7 @@ EC_GROUP_cmp(const EC_GROUP * a, const EC_GROUP * b, BN_CTX * ctx) return r; - err: +err: BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); @@ -1026,88 +1026,47 @@ EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], } -/* Functions for point multiplication */ +/* Functions for point multiplication. + * + * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c; + * otherwise we dispatch through methods. + */ + int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx) { - /* - * The function pointers must be set, and only support num == 0 and - * num == 1. - */ - if (group->meth->mul_generator_ct == NULL || - group->meth->mul_single_ct == NULL || - group->meth->mul_double_nonct == NULL || - num > 1) { - ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - - /* Either bP or aG + bP, this is sane. */ - if (num == 1 && points != NULL && scalars != NULL) - return EC_POINT_mul(group, r, scalar, points[0], scalars[0], - ctx); - - /* aG, this is sane */ - if (scalar != NULL && points == NULL && scalars == NULL) - return EC_POINT_mul(group, r, scalar, NULL, NULL, ctx); - - /* anything else is an error */ - ECerror(ERR_R_EC_LIB); - return 0; + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx); + + return group->meth->mul(group, r, scalar, num, points, scalars, ctx); } int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx) { - if (group->meth->mul_generator_ct == NULL || - group->meth->mul_single_ct == NULL || - group->meth->mul_double_nonct == NULL) { - ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return 0; - } - if (g_scalar != NULL && point == NULL && p_scalar == NULL) { - /* - * In this case we want to compute g_scalar * GeneratorPoint: - * this codepath is reached most prominently by (ephemeral) key - * generation of EC cryptosystems (i.e. ECDSA keygen and sign - * setup, ECDH keygen/first half), where the scalar is always - * secret. This is why we ignore if BN_FLG_CONSTTIME is actually - * set and we always call the constant time version. - */ - return group->meth->mul_generator_ct(group, r, g_scalar, ctx); - } - if (g_scalar == NULL && point != NULL && p_scalar != NULL) { - /* In this case we want to compute p_scalar * GenericPoint: - * this codepath is reached most prominently by the second half - * of ECDH, where the secret scalar is multiplied by the peer's - * public point. To protect the secret scalar, we ignore if - * BN_FLG_CONSTTIME is actually set and we always call the - * constant time version. - */ - return group->meth->mul_single_ct(group, r, p_scalar, point, - ctx); - } - if (g_scalar != NULL && point != NULL && p_scalar != NULL) { - /* - * In this case we want to compute - * g_scalar * GeneratorPoint + p_scalar * GenericPoint: - * this codepath is reached most prominently by ECDSA signature - * verification. So we call the non-ct version. - */ - return group->meth->mul_double_nonct(group, r, g_scalar, - p_scalar, point, ctx); - } - - /* Anything else is an error. */ - ECerror(ERR_R_EC_LIB); - return 0; + /* just a convenient interface to EC_POINTs_mul() */ + + const EC_POINT *points[1]; + const BIGNUM *scalars[1]; + + points[0] = point; + scalars[0] = p_scalar; + + return EC_POINTs_mul(group, r, g_scalar, + (point != NULL && p_scalar != NULL), + points, scalars, ctx); } int EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx) { + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_precompute_mult(group, ctx); + if (group->meth->precompute_mult != 0) return group->meth->precompute_mult(group, ctx); else @@ -1117,6 +1076,10 @@ EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx) int EC_GROUP_have_precompute_mult(const EC_GROUP * group) { + if (group->meth->mul == 0) + /* use default */ + return ec_wNAF_have_precompute_mult(group); + if (group->meth->have_precompute_mult != 0) return group->meth->have_precompute_mult(group); else diff --git a/lib/libcrypto/ec/ec_mult.c b/lib/libcrypto/ec/ec_mult.c index 08bc8c380c9..4f321d3f55d 100644 --- a/lib/libcrypto/ec/ec_mult.c +++ b/lib/libcrypto/ec/ec_mult.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ec_mult.c,v 1.22 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ec_mult.c,v 1.23 2018/07/15 05:38:48 jsg Exp $ */ /* * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project. */ @@ -301,7 +301,7 @@ compute_wNAF(const BIGNUM * scalar, int w, size_t * ret_len) len = j; ok = 1; - err: +err: if (!ok) { free(r); r = NULL; @@ -678,7 +678,7 @@ ec_wNAF_mul(const EC_GROUP * group, EC_POINT * r, const BIGNUM * scalar, ret = 1; - err: +err: BN_CTX_free(new_ctx); EC_POINT_free(tmp); free(wsize); @@ -857,7 +857,7 @@ ec_wNAF_precompute_mult(EC_GROUP * group, BN_CTX * ctx) pre_comp = NULL; ret = 1; - err: +err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/eck_prn.c b/lib/libcrypto/ec/eck_prn.c index 0291de96136..7c0db42ef4e 100644 --- a/lib/libcrypto/ec/eck_prn.c +++ b/lib/libcrypto/ec/eck_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eck_prn.c,v 1.13 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: eck_prn.c,v 1.14 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -321,7 +321,7 @@ ECPKParameters_print(BIO * bp, const EC_GROUP * x, int off) goto err; } ret = 1; - err: +err: if (!ret) ECerror(reason); BN_free(p); diff --git a/lib/libcrypto/ec/ecp_mont.c b/lib/libcrypto/ec/ecp_mont.c index 302f8333062..03e594d38d2 100644 --- a/lib/libcrypto/ec/ecp_mont.c +++ b/lib/libcrypto/ec/ecp_mont.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_mont.c,v 1.13 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_mont.c,v 1.14 2018/07/15 05:38:48 jsg Exp $ */ /* * Originally written by Bodo Moeller for the OpenSSL project. */ @@ -102,9 +102,6 @@ EC_GFp_mont_method(void) .point_cmp = ec_GFp_simple_cmp, .make_affine = ec_GFp_simple_make_affine, .points_make_affine = ec_GFp_simple_points_make_affine, - .mul_generator_ct = ec_GFp_simple_mul_generator_ct, - .mul_single_ct = ec_GFp_simple_mul_single_ct, - .mul_double_nonct = ec_GFp_simple_mul_double_nonct, .field_mul = ec_GFp_mont_field_mul, .field_sqr = ec_GFp_mont_field_sqr, .field_encode = ec_GFp_mont_field_encode, @@ -175,7 +172,7 @@ ec_GFp_mont_group_copy(EC_GROUP * dest, const EC_GROUP * src) } return 1; - err: +err: if (dest->field_data1 != NULL) { BN_MONT_CTX_free(dest->field_data1); dest->field_data1 = NULL; @@ -228,7 +225,7 @@ ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, BN_free(group->field_data2); group->field_data2 = NULL; } - err: +err: BN_CTX_free(new_ctx); BN_MONT_CTX_free(mont); BN_free(one); diff --git a/lib/libcrypto/ec/ecp_nist.c b/lib/libcrypto/ec/ecp_nist.c index 8aa9f49592f..027a07d5c05 100644 --- a/lib/libcrypto/ec/ecp_nist.c +++ b/lib/libcrypto/ec/ecp_nist.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_nist.c,v 1.11 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_nist.c,v 1.12 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Nils Larsch for the OpenSSL project. */ @@ -151,7 +151,7 @@ ec_GFp_nist_group_set_curve(EC_GROUP *group, const BIGNUM *p, ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -179,7 +179,7 @@ ec_GFp_nist_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, goto err; ret = 1; - err: +err: BN_CTX_free(ctx_new); return ret; } @@ -206,7 +206,7 @@ ec_GFp_nist_field_sqr(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, goto err; ret = 1; - err: +err: BN_CTX_free(ctx_new); return ret; } diff --git a/lib/libcrypto/ec/ecp_nistp224.c b/lib/libcrypto/ec/ecp_nistp224.c index 3921508094a..1ba8cb09a09 100644 --- a/lib/libcrypto/ec/ecp_nistp224.c +++ b/lib/libcrypto/ec/ecp_nistp224.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_nistp224.c,v 1.20 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_nistp224.c,v 1.21 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Emilia Kasper (Google) for the OpenSSL project. */ @@ -1281,7 +1281,7 @@ ec_GFp_nistp224_group_set_curve(EC_GROUP * group, const BIGNUM * p, } group->field_mod_func = BN_nist_mod_224; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1537,7 +1537,7 @@ ec_GFp_nistp224_points_mul(const EC_GROUP * group, EC_POINT * r, } ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); @@ -1666,7 +1666,7 @@ ec_GFp_nistp224_precompute_mult(EC_GROUP * group, BN_CTX * ctx) goto err; ret = 1; pre = NULL; - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ecp_nistp256.c b/lib/libcrypto/ec/ecp_nistp256.c index 7046dcebc06..3b0784f153d 100644 --- a/lib/libcrypto/ec/ecp_nistp256.c +++ b/lib/libcrypto/ec/ecp_nistp256.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_nistp256.c,v 1.19 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_nistp256.c,v 1.20 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Adam Langley (Google) for the OpenSSL project */ @@ -1830,7 +1830,7 @@ ec_GFp_nistp256_group_set_curve(EC_GROUP * group, const BIGNUM * p, } group->field_mod_func = BN_nist_mod_256; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -2090,7 +2090,7 @@ ec_GFp_nistp256_points_mul(const EC_GROUP * group, EC_POINT * r, } ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); @@ -2213,7 +2213,7 @@ ec_GFp_nistp256_precompute_mult(EC_GROUP * group, BN_CTX * ctx) goto err; ret = 1; pre = NULL; - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ecp_nistp521.c b/lib/libcrypto/ec/ecp_nistp521.c index 7c20daae28c..823e7a0d518 100644 --- a/lib/libcrypto/ec/ecp_nistp521.c +++ b/lib/libcrypto/ec/ecp_nistp521.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_nistp521.c,v 1.20 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_nistp521.c,v 1.21 2018/07/15 05:38:48 jsg Exp $ */ /* * Written by Adam Langley (Google) for the OpenSSL project */ @@ -1721,7 +1721,7 @@ ec_GFp_nistp521_group_set_curve(EC_GROUP * group, const BIGNUM * p, } group->field_mod_func = BN_nist_mod_521; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1979,7 +1979,7 @@ ec_GFp_nistp521_points_mul(const EC_GROUP * group, EC_POINT * r, } ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx); - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); @@ -2088,7 +2088,7 @@ ec_GFp_nistp521_precompute_mult(EC_GROUP * group, BN_CTX * ctx) goto err; ret = 1; pre = NULL; - err: +err: BN_CTX_end(ctx); EC_POINT_free(generator); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ecp_nistz256.c b/lib/libcrypto/ec/ecp_nistz256.c index 3d529387217..71c2952d8ca 100644 --- a/lib/libcrypto/ec/ecp_nistz256.c +++ b/lib/libcrypto/ec/ecp_nistz256.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_nistz256.c,v 1.4 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_nistz256.c,v 1.5 2018/07/15 05:38:48 jsg Exp $ */ /* Copyright (c) 2014, Intel Corporation. * * Permission to use, copy, modify, and/or distribute this software for any @@ -565,7 +565,7 @@ ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, } ret = 1; - err: +err: free(table); free(p_str); free(scalars); @@ -712,7 +712,7 @@ ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx) ec_pre_comp = NULL; ret = 1; - err: +err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -985,7 +985,7 @@ ecp_nistz256_points_mul(const EC_GROUP *group, EC_POINT *r, ret = 1; - err: +err: if (ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); diff --git a/lib/libcrypto/ec/ecp_oct.c b/lib/libcrypto/ec/ecp_oct.c index da9eccfe6a1..3d50f707c00 100644 --- a/lib/libcrypto/ec/ecp_oct.c +++ b/lib/libcrypto/ec/ecp_oct.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_oct.c,v 1.9 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_oct.c,v 1.10 2018/07/15 05:38:48 jsg Exp $ */ /* Includes code written by Lenka Fibikova * for the OpenSSL project. * Includes code written by Bodo Moeller for the OpenSSL project. @@ -190,7 +190,7 @@ ec_GFp_simple_set_compressed_coordinates(const EC_GROUP * group, ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -294,7 +294,7 @@ ec_GFp_simple_point2oct(const EC_GROUP * group, const EC_POINT * point, point_co BN_CTX_free(new_ctx); return ret; - err: +err: if (used_ctx) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -388,7 +388,7 @@ ec_GFp_simple_oct2point(const EC_GROUP * group, EC_POINT * point, } ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; diff --git a/lib/libcrypto/ec/ecp_smpl.c b/lib/libcrypto/ec/ecp_smpl.c index 57e83453643..1fe55307b49 100644 --- a/lib/libcrypto/ec/ecp_smpl.c +++ b/lib/libcrypto/ec/ecp_smpl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ecp_smpl.c,v 1.19 2018/07/10 22:06:14 tb Exp $ */ +/* $OpenBSD: ecp_smpl.c,v 1.20 2018/07/15 05:38:48 jsg Exp $ */ /* Includes code written by Lenka Fibikova * for the OpenSSL project. * Includes code written by Bodo Moeller for the OpenSSL project. @@ -103,9 +103,6 @@ EC_GFp_simple_method(void) .point_cmp = ec_GFp_simple_cmp, .make_affine = ec_GFp_simple_make_affine, .points_make_affine = ec_GFp_simple_points_make_affine, - .mul_generator_ct = ec_GFp_simple_mul_generator_ct, - .mul_single_ct = ec_GFp_simple_mul_single_ct, - .mul_double_nonct = ec_GFp_simple_mul_double_nonct, .field_mul = ec_GFp_simple_field_mul, .field_sqr = ec_GFp_simple_field_sqr }; @@ -223,7 +220,7 @@ ec_GFp_simple_group_set_curve(EC_GROUP * group, ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -268,7 +265,7 @@ ec_GFp_simple_group_get_curve(const EC_GROUP * group, BIGNUM * p, BIGNUM * a, BI } ret = 1; - err: +err: BN_CTX_free(new_ctx); return ret; } @@ -349,7 +346,7 @@ ec_GFp_simple_group_check_discriminant(const EC_GROUP * group, BN_CTX * ctx) } ret = 1; - err: +err: if (ctx != NULL) BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -459,7 +456,7 @@ ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP * group, EC_POINT * } ret = 1; - err: +err: BN_CTX_free(new_ctx); return ret; } @@ -507,7 +504,7 @@ ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP * group, const EC_P ret = 1; - err: +err: BN_CTX_free(new_ctx); return ret; } @@ -627,7 +624,7 @@ ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP * group, const EC_POIN ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -814,7 +811,7 @@ ec_GFp_simple_add(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, cons ret = 1; - end: +end: if (ctx) /* otherwise we already called BN_CTX_end */ BN_CTX_end(ctx); BN_CTX_free(new_ctx); @@ -957,7 +954,7 @@ ec_GFp_simple_dbl(const EC_GROUP * group, EC_POINT * r, const EC_POINT * a, BN_C ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1078,7 +1075,7 @@ ec_GFp_simple_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX ret = (0 == BN_ucmp(tmp, rh)); - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1180,7 +1177,7 @@ ec_GFp_simple_cmp(const EC_GROUP * group, const EC_POINT * a, const EC_POINT * b /* points are equal */ ret = 0; - end: +end: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1218,7 +1215,7 @@ ec_GFp_simple_make_affine(const EC_GROUP * group, EC_POINT * point, BN_CTX * ctx } ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; @@ -1383,7 +1380,7 @@ ec_GFp_simple_points_make_affine(const EC_GROUP * group, size_t num, EC_POINT * ret = 1; - err: +err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); if (heap != NULL) { @@ -1412,248 +1409,3 @@ ec_GFp_simple_field_sqr(const EC_GROUP * group, BIGNUM * r, const BIGNUM * a, BN { return BN_mod_sqr(r, a, &group->field, ctx); } - -#define EC_POINT_BN_set_flags(P, flags) do { \ - BN_set_flags(&(P)->X, (flags)); \ - BN_set_flags(&(P)->Y, (flags)); \ - BN_set_flags(&(P)->Z, (flags)); \ -} while(0) - -#define EC_POINT_CSWAP(c, a, b, w, t) do { \ - if (!BN_swap_ct(c, &(a)->X, &(b)->X, w) || \ - !BN_swap_ct(c, &(a)->Y, &(b)->Y, w) || \ - !BN_swap_ct(c, &(a)->Z, &(b)->Z, w)) \ - goto err; \ - t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \ - (a)->Z_is_one ^= (t); \ - (b)->Z_is_one ^= (t); \ -} while(0) - -/* - * This function computes (in constant time) a point multiplication over the - * EC group. - * - * At a high level, it is Montgomery ladder with conditional swaps. - * - * It performs either a fixed point multiplication - * (scalar * generator) - * when point is NULL, or a variable point multiplication - * (scalar * point) - * when point is not NULL. - * - * scalar should be in the range [0,n) otherwise all constant time bets are off. - * - * NB: This says nothing about EC_POINT_add and EC_POINT_dbl, - * which of course are not constant time themselves. - * - * The product is stored in r. - * - * Returns 1 on success, 0 otherwise. - */ -static int -ec_GFp_simple_mul_ct(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, - const EC_POINT *point, BN_CTX *ctx) -{ - int i, cardinality_bits, group_top, kbit, pbit, Z_is_one; - EC_POINT *s = NULL; - BIGNUM *k = NULL; - BIGNUM *lambda = NULL; - BIGNUM *cardinality = NULL; - BN_CTX *new_ctx = NULL; - int ret = 0; - - if (ctx == NULL && (ctx = new_ctx = BN_CTX_new()) == NULL) - return 0; - - BN_CTX_start(ctx); - - if ((s = EC_POINT_new(group)) == NULL) - goto err; - - if (point == NULL) { - if (!EC_POINT_copy(s, group->generator)) - goto err; - } else { - if (!EC_POINT_copy(s, point)) - goto err; - } - - EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME); - - if ((cardinality = BN_CTX_get(ctx)) == NULL) - goto err; - if ((lambda = BN_CTX_get(ctx)) == NULL) - goto err; - if ((k = BN_CTX_get(ctx)) == NULL) - goto err; - if (!BN_mul(cardinality, &group->order, &group->cofactor, ctx)) - goto err; - - /* - * Group cardinalities are often on a word boundary. - * So when we pad the scalar, some timing diff might - * pop if it needs to be expanded due to carries. - * So expand ahead of time. - */ - cardinality_bits = BN_num_bits(cardinality); - group_top = cardinality->top; - if ((bn_wexpand(k, group_top + 1) == NULL) || - (bn_wexpand(lambda, group_top + 1) == NULL)) - goto err; - - if (!BN_copy(k, scalar)) - goto err; - - BN_set_flags(k, BN_FLG_CONSTTIME); - - if (BN_num_bits(k) > cardinality_bits || BN_is_negative(k)) { - /* - * This is an unusual input, and we don't guarantee - * constant-timeness - */ - if (!BN_nnmod(k, k, cardinality, ctx)) - goto err; - } - - if (!BN_add(lambda, k, cardinality)) - goto err; - BN_set_flags(lambda, BN_FLG_CONSTTIME); - if (!BN_add(k, lambda, cardinality)) - goto err; - /* - * lambda := scalar + cardinality - * k := scalar + 2*cardinality - */ - kbit = BN_is_bit_set(lambda, cardinality_bits); - if (!BN_swap_ct(kbit, k, lambda, group_top + 1)) - goto err; - - group_top = group->field.top; - if ((bn_wexpand(&s->X, group_top) == NULL) || - (bn_wexpand(&s->Y, group_top) == NULL) || - (bn_wexpand(&s->Z, group_top) == NULL) || - (bn_wexpand(&r->X, group_top) == NULL) || - (bn_wexpand(&r->Y, group_top) == NULL) || - (bn_wexpand(&r->Z, group_top) == NULL)) - goto err; - - /* top bit is a 1, in a fixed pos */ - if (!EC_POINT_copy(r, s)) - goto err; - - EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME); - - if (!EC_POINT_dbl(group, s, s, ctx)) - goto err; - - pbit = 0; - - /* - * The ladder step, with branches, is - * - * k[i] == 0: S = add(R, S), R = dbl(R) - * k[i] == 1: R = add(S, R), S = dbl(S) - * - * Swapping R, S conditionally on k[i] leaves you with state - * - * k[i] == 0: T, U = R, S - * k[i] == 1: T, U = S, R - * - * Then perform the ECC ops. - * - * U = add(T, U) - * T = dbl(T) - * - * Which leaves you with state - * - * k[i] == 0: U = add(R, S), T = dbl(R) - * k[i] == 1: U = add(S, R), T = dbl(S) - * - * Swapping T, U conditionally on k[i] leaves you with state - * - * k[i] == 0: R, S = T, U - * k[i] == 1: R, S = U, T - * - * Which leaves you with state - * - * k[i] == 0: S = add(R, S), R = dbl(R) - * k[i] == 1: R = add(S, R), S = dbl(S) - * - * So we get the same logic, but instead of a branch it's a - * conditional swap, followed by ECC ops, then another conditional swap. - * - * Optimization: The end of iteration i and start of i-1 looks like - * - * ... - * CSWAP(k[i], R, S) - * ECC - * CSWAP(k[i], R, S) - * (next iteration) - * CSWAP(k[i-1], R, S) - * ECC - * CSWAP(k[i-1], R, S) - * ... - * - * So instead of two contiguous swaps, you can merge the condition - * bits and do a single swap. - * - * k[i] k[i-1] Outcome - * 0 0 No Swap - * 0 1 Swap - * 1 0 Swap - * 1 1 No Swap - * - * This is XOR. pbit tracks the previous bit of k. - */ - - for (i = cardinality_bits - 1; i >= 0; i--) { - kbit = BN_is_bit_set(k, i) ^ pbit; - EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one); - if (!EC_POINT_add(group, s, r, s, ctx)) - goto err; - if (!EC_POINT_dbl(group, r, r, ctx)) - goto err; - /* - * pbit logic merges this cswap with that of the - * next iteration - */ - pbit ^= kbit; - } - /* one final cswap to move the right value into r */ - EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one); - - ret = 1; - - err: - EC_POINT_free(s); - if (ctx != NULL) - BN_CTX_end(ctx); - BN_CTX_free(new_ctx); - - return ret; -} - -#undef EC_POINT_BN_set_flags -#undef EC_POINT_CSWAP - -int -ec_GFp_simple_mul_generator_ct(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, BN_CTX *ctx) -{ - return ec_GFp_simple_mul_ct(group, r, scalar, NULL, ctx); -} - -int -ec_GFp_simple_mul_single_ct(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, const EC_POINT *point, BN_CTX *ctx) -{ - return ec_GFp_simple_mul_ct(group, r, scalar, point, ctx); -} - -int -ec_GFp_simple_mul_double_nonct(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *g_scalar, const BIGNUM *p_scalar, const EC_POINT *point, - BN_CTX *ctx) -{ - return ec_wNAF_mul(group, r, g_scalar, 1, &point, &p_scalar, ctx); -} diff --git a/lib/libcrypto/man/EC_POINT_add.3 b/lib/libcrypto/man/EC_POINT_add.3 index e2a33b6a72e..a9ad5563cc9 100644 --- a/lib/libcrypto/man/EC_POINT_add.3 +++ b/lib/libcrypto/man/EC_POINT_add.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: EC_POINT_add.3,v 1.9 2018/07/11 08:42:38 tb Exp $ +.\" $OpenBSD: EC_POINT_add.3,v 1.10 2018/07/15 05:38:48 jsg Exp $ .\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100 .\" .\" This file was written by Matt Caswell . @@ -48,7 +48,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: July 11 2018 $ +.Dd $Mdocdate: July 15 2018 $ .Dt EC_POINT_ADD 3 .Os .Sh NAME @@ -217,30 +217,12 @@ The value .Fa n may be .Dv NULL , -in which case the result is just +in which case the result is just q * m. .Pp -.Dl q * m. -.Pp -.Fn EC_POINTs_mul -only supports the values 0 and 1 for -.Fa num . -If it is 1, then .Fn EC_POINTs_mul calculates the value .Pp -.Dl generator * n + q[0] * m[0]. -.Pp -If -.Fa num -is 0 then -.Fa q -and -.Fa m -must be -.Dv NULL , -and the result is just -.Pp -.Dl generator * n . +.Dl generator * n + q[0] * m[0] + ... + q[num-1] * m[num-1] .Pp As for .Fn EC_POINT_mul ,