From 41156ddc8efb54315fdbcecee18c73e03aa9ea80 Mon Sep 17 00:00:00 2001 From: robm Date: Wed, 24 May 2017 17:35:54 +0100 Subject: [PATCH] 8175110: Higher quality ECDSA operations Reviewed-by: xuelei, apetcher --- .../sun/security/ec/ECDSASignature.java | 22 +++++-- src/share/native/sun/security/ec/ECC_JNI.cpp | 6 +- src/share/native/sun/security/ec/impl/ec.c | 38 +++++------ src/share/native/sun/security/ec/impl/ec2.h | 5 +- .../native/sun/security/ec/impl/ec2_aff.c | 6 +- .../native/sun/security/ec/impl/ec2_mont.c | 9 ++- .../native/sun/security/ec/impl/ecc_impl.h | 6 +- .../native/sun/security/ec/impl/ecl-priv.h | 14 ++-- src/share/native/sun/security/ec/impl/ecl.h | 8 ++- .../native/sun/security/ec/impl/ecl_mult.c | 34 +++++----- src/share/native/sun/security/ec/impl/ecp.h | 13 ++-- .../native/sun/security/ec/impl/ecp_aff.c | 6 +- .../native/sun/security/ec/impl/ecp_jac.c | 9 +-- .../native/sun/security/ec/impl/ecp_jm.c | 64 +++++++++++++++++-- 14 files changed, 161 insertions(+), 79 deletions(-) diff --git a/src/share/classes/sun/security/ec/ECDSASignature.java b/src/share/classes/sun/security/ec/ECDSASignature.java index 2abc26280..ccd5a0295 100644 --- a/src/share/classes/sun/security/ec/ECDSASignature.java +++ b/src/share/classes/sun/security/ec/ECDSASignature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -287,11 +287,15 @@ abstract class ECDSASignature extends SignatureSpi { } random.nextBytes(seed); - try { + // random bits needed for timing countermeasures + int timingArgument = random.nextInt(); + // values must be non-zero to enable countermeasures + timingArgument |= 1; + try { return encodeSignature( - signDigest(getDigestValue(), s, encodedParams, seed)); - + signDigest(getDigestValue(), s, encodedParams, seed, + timingArgument)); } catch (GeneralSecurityException e) { throw new SignatureException("Could not sign data", e); } @@ -418,11 +422,19 @@ abstract class ECDSASignature extends SignatureSpi { * @param s the private key's S value. * @param encodedParams the curve's DER encoded object identifier. * @param seed the random seed. + * @param timing When non-zero, the implmentation will use timing + * countermeasures to hide secrets from timing channels. The EC + * implementation will disable the countermeasures when this value is + * zero, because the underlying EC functions are shared by several + * crypto operations, some of which do not use the countermeasures. + * The high-order 31 bits must be uniformly random. The entropy from + * these bits is used by the countermeasures. * * @return byte[] the signature. */ private static native byte[] signDigest(byte[] digest, byte[] s, - byte[] encodedParams, byte[] seed) throws GeneralSecurityException; + byte[] encodedParams, byte[] seed, int timing) + throws GeneralSecurityException; /** * Verifies the signed digest using the public key. diff --git a/src/share/native/sun/security/ec/ECC_JNI.cpp b/src/share/native/sun/security/ec/ECC_JNI.cpp index 5c07645d0..b7fb6750e 100644 --- a/src/share/native/sun/security/ec/ECC_JNI.cpp +++ b/src/share/native/sun/security/ec/ECC_JNI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -190,7 +190,7 @@ cleanup: */ JNIEXPORT jbyteArray JNICALL Java_sun_security_ec_ECDSASignature_signDigest - (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed) + (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing) { jbyte* pDigestBuffer = NULL; jint jDigestLength = env->GetArrayLength(digest); @@ -250,7 +250,7 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest // Sign the digest (using the supplied seed) if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item, - (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) { + (unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) { ThrowException(env, KEY_EXCEPTION); goto cleanup; } diff --git a/src/share/native/sun/security/ec/impl/ec.c b/src/share/native/sun/security/ec/impl/ec.c index 2561237b9..4e94d2779 100644 --- a/src/share/native/sun/security/ec/impl/ec.c +++ b/src/share/native/sun/security/ec/impl/ec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ * Dr Vipul Gupta and * Douglas Stebila , Sun Microsystems Laboratories * - * Last Modified Date from the Original Code: November 2016 + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "mplogic.h" @@ -87,7 +87,7 @@ ec_point_at_infinity(SECItem *pointP) */ SECStatus ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, - const SECItem *pointP, SECItem *pointQ, int kmflag) + const SECItem *pointP, SECItem *pointQ, int kmflag, int timing) { mp_int Px, Py, Qx, Qy; mp_int Gx, Gy, order, irreducible, a, b; @@ -199,9 +199,9 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, goto cleanup; if ((k2 != NULL) && (pointP != NULL)) { - CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) ); + CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy, timing) ); } else { - CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) ); + CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy, timing) ); } /* Construct the SECItem representation of point Q */ @@ -332,7 +332,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, (mp_size) len) ); - rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag); + /* key generation does not support timing mitigation */ + rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag, /*timing*/ 0); if (rv != SECSuccess) goto cleanup; *privKey = key; @@ -609,7 +610,8 @@ ECDH_Derive(SECItem *publicValue, } /* Multiply our private key and peer's public point */ - if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) || + /* ECDH doesn't support timing mitigation */ + if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag, /*timing*/ 0) != SECSuccess) || ec_point_at_infinity(&pointQ)) goto cleanup; @@ -644,7 +646,8 @@ cleanup: */ SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, - const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag) + const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag, + int timing) { SECStatus rv = SECFailure; mp_int x1; @@ -713,16 +716,6 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, goto cleanup; } - /* - * Using an equivalent exponent of fixed length (same as n or 1 bit less - * than n) to keep the kG timing relatively constant. - * - * Note that this is an extra step on top of the approach defined in - * ANSI X9.62 so as to make a fixed length K. - */ - CHECK_MPI_OK( mp_add(&k, &n, &k) ); - CHECK_MPI_OK( mp_div_2(&k, &k) ); - /* ** ANSI X9.62, Section 5.3.2, Step 2 ** @@ -731,7 +724,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, kGpoint.len = 2*flen + 1; kGpoint.data = PORT_Alloc(2*flen + 1, kmflag); if ((kGpoint.data == NULL) || - (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag) + (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag, timing) != SECSuccess)) goto cleanup; @@ -853,7 +846,7 @@ cleanup: */ SECStatus ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest, - const unsigned char* random, int randomLen, int kmflag) + const unsigned char* random, int randomLen, int kmflag, int timing) { SECStatus rv = SECFailure; int len; @@ -871,7 +864,7 @@ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest, if (kBytes == NULL) goto cleanup; /* Generate ECDSA signature with the specified k value */ - rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag); + rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag, timing); cleanup: if (kBytes) { @@ -1017,7 +1010,8 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ** Here, A = u1.G B = u2.Q and C = A + B ** If the result, C, is the point at infinity, reject the signature */ - if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag) + /* verification does not support timing mitigation */ + if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag, /*timing*/ 0) != SECSuccess) { rv = SECFailure; goto cleanup; diff --git a/src/share/native/sun/security/ec/impl/ec2.h b/src/share/native/sun/security/ec/impl/ec2.h index aa5f2bba4..72df04ef4 100644 --- a/src/share/native/sun/security/ec/impl/ec2.h +++ b/src/share/native/sun/security/ec/impl/ec2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -33,6 +33,7 @@ * Contributor(s): * Douglas Stebila , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #ifndef _EC2_H @@ -79,7 +80,7 @@ mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, * determines the field GF2m. Uses Montgomery projective coordinates. */ mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); + const ECGroup *group, int timing); #ifdef ECL_ENABLE_GF2M_PROJ /* Converts a point P(px, py) from affine coordinates to projective diff --git a/src/share/native/sun/security/ec/impl/ec2_aff.c b/src/share/native/sun/security/ec/impl/ec2_aff.c index 5a546c054..8d0f5460f 100644 --- a/src/share/native/sun/security/ec/impl/ec2_aff.c +++ b/src/share/native/sun/security/ec/impl/ec2_aff.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -33,6 +33,7 @@ * Contributor(s): * Douglas Stebila , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "ec2.h" @@ -329,7 +330,8 @@ ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) /* 4: Verify that the order of the curve times the publicValue * is the point at infinity. */ - MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); + /* timing mitigation is not supported */ + MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) ); if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { res = MP_NO; goto CLEANUP; diff --git a/src/share/native/sun/security/ec/impl/ec2_mont.c b/src/share/native/sun/security/ec/impl/ec2_mont.c index b91e65ea0..bb605536f 100644 --- a/src/share/native/sun/security/ec/impl/ec2_mont.c +++ b/src/share/native/sun/security/ec/impl/ec2_mont.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -35,6 +35,7 @@ * Stephen Fung , and * Douglas Stebila , Sun Microsystems Laboratories. * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "ec2.h" @@ -181,10 +182,12 @@ gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1, /* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast * multiplication on elliptic curves over GF(2^m) without * precomputation". Elliptic curve points P and R can be identical. Uses - * Montgomery projective coordinates. */ + * Montgomery projective coordinates. The timing parameter is ignored + * because this algorithm resists timing attacks by default. */ mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group, + int timing) { mp_err res = MP_OKAY; mp_int x1, x2, z1, z2; diff --git a/src/share/native/sun/security/ec/impl/ecc_impl.h b/src/share/native/sun/security/ec/impl/ecc_impl.h index 0739f4c88..48aa13a4b 100644 --- a/src/share/native/sun/security/ec/impl/ecc_impl.h +++ b/src/share/native/sun/security/ec/impl/ecc_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -34,7 +34,7 @@ * Dr Vipul Gupta and * Douglas Stebila , Sun Microsystems Laboratories * - * Last Modified Date from the Original Code: November 2013 + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #ifndef _ECC_IMPL_H @@ -258,7 +258,7 @@ extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, const unsigned char* random, int randomlen, int); /* This function has been modified to accept an array of random bytes */ extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *, - const unsigned char* random, int randomlen, int); + const unsigned char* random, int randomlen, int, int timing); extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *, const SECItem *, int); extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t, diff --git a/src/share/native/sun/security/ec/impl/ecl-priv.h b/src/share/native/sun/security/ec/impl/ecl-priv.h index fa232ddfe..bdfe61547 100644 --- a/src/share/native/sun/security/ec/impl/ecl-priv.h +++ b/src/share/native/sun/security/ec/impl/ecl-priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -34,6 +34,7 @@ * Stephen Fung and * Douglas Stebila , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #ifndef _ECL_PRIV_H @@ -193,12 +194,13 @@ struct ECGroupStr { mp_int *ry, const ECGroup *group); mp_err (*point_mul) (const mp_int *n, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); + const ECGroup *group, int timing); mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry, const ECGroup *group); mp_err (*points_mul) (const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + mp_int *ry, const ECGroup *group, + int timing); mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group); /* Extra storage for implementation-specific data. Any memory * allocated to these extra fields will be cleared by extra_free. */ @@ -262,10 +264,12 @@ void ec_GFp_extra_free_mont(GFMethod *meth); /* point multiplication */ mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + mp_int *ry, const ECGroup *group, + int timing); mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + mp_int *ry, const ECGroup *group, + int timing); /* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should * be an array of signed char's to output to, bitsize should be the number diff --git a/src/share/native/sun/security/ec/impl/ecl.h b/src/share/native/sun/security/ec/impl/ecl.h index 3a83a9e1f..deff0aa11 100644 --- a/src/share/native/sun/security/ec/impl/ecl.h +++ b/src/share/native/sun/security/ec/impl/ecl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -33,6 +33,7 @@ * Contributor(s): * Douglas Stebila , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #ifndef _ECL_H @@ -70,7 +71,8 @@ void EC_FreeCurveParams(ECCurveParams * params); * of the group of points on the elliptic curve. Input and output values * are assumed to be NOT field-encoded. */ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, - const mp_int *py, mp_int *qx, mp_int *qy); + const mp_int *py, mp_int *qx, mp_int *qy, + int timing); /* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of @@ -78,7 +80,7 @@ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, * be NOT field-encoded. */ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, - mp_int *qx, mp_int *qy); + mp_int *qx, mp_int *qy, int timing); /* Validates an EC public key as described in Section 5.2.2 of X9.62. * Returns MP_YES if the public key is valid, MP_NO if the public key diff --git a/src/share/native/sun/security/ec/impl/ecl_mult.c b/src/share/native/sun/security/ec/impl/ecl_mult.c index 176be78e0..273eac9d1 100644 --- a/src/share/native/sun/security/ec/impl/ecl_mult.c +++ b/src/share/native/sun/security/ec/impl/ecl_mult.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -49,7 +49,8 @@ * are assumed to be NOT field-encoded. */ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry) + const mp_int *py, mp_int *rx, mp_int *ry, + int timing) { mp_err res = MP_OKAY; mp_int kt; @@ -74,15 +75,15 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, } else { MP_CHECKOK(group-> point_mul(&kt, &group->genx, &group->geny, rx, ry, - group)); + group, timing)); } } else { if (group->meth->field_enc) { MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); MP_CHECKOK(group->meth->field_enc(py, ry, group->meth)); - MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group)); + MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group, timing)); } else { - MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group)); + MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group, timing)); } } if (group->meth->field_dec) { @@ -104,7 +105,7 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const ECGroup *group, int timing) { mp_err res = MP_OKAY; mp_int sx, sy; @@ -116,9 +117,9 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, /* if some arguments are not defined used ECPoint_mul */ if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); + return ECPoint_mul(group, k2, px, py, rx, ry, timing); } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing); } MP_DIGITS(&sx) = 0; @@ -126,8 +127,8 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, MP_CHECKOK(mp_init(&sx, FLAG(k1))); MP_CHECKOK(mp_init(&sy, FLAG(k1))); - MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); - MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); + MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy, timing)); + MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry, timing)); if (group->meth->field_enc) { MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); @@ -159,7 +160,7 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const ECGroup *group, int timing) { mp_err res = MP_OKAY; mp_int precomp[4][4][2]; @@ -174,9 +175,9 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, /* if some arguments are not defined used ECPoint_mul */ if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); + return ECPoint_mul(group, k2, px, py, rx, ry, timing); } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing); } /* initialize precomputation table */ @@ -308,7 +309,8 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, * Input and output values are assumed to be NOT field-encoded. */ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, - const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry) + const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, + int timing) { mp_err res = MP_OKAY; mp_int k1t, k2t; @@ -345,9 +347,9 @@ ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, /* if points_mul is defined, then use it */ if (group->points_mul) { - res = group->points_mul(k1p, k2p, px, py, rx, ry, group); + res = group->points_mul(k1p, k2p, px, py, rx, ry, group, timing); } else { - res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); + res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group, timing); } CLEANUP: diff --git a/src/share/native/sun/security/ec/impl/ecp.h b/src/share/native/sun/security/ec/impl/ecp.h index c2aad8e83..b367b909e 100644 --- a/src/share/native/sun/security/ec/impl/ecp.h +++ b/src/share/native/sun/security/ec/impl/ecp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -33,6 +33,7 @@ * Contributor(s): * Douglas Stebila , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #ifndef _ECP_H @@ -122,7 +123,7 @@ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, mp_err ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); + const ECGroup *group, int timing); /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic * curve points P and R can be identical. Uses mixed Modified-Jacobian @@ -131,9 +132,13 @@ mp_err * returns output that is still field-encoded. Uses 5-bit window NAF * method (algorithm 11) for scalar-point multiplication from Brown, * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic - * Curves Over Prime Fields. */ + * Curves Over Prime Fields. The implementation includes a countermeasure + * that attempts to hide the size of n from timing channels. This counter- + * measure is enabled using the timing argument. The high-rder bits of timing + * must be uniformly random in order for this countermeasure to work. */ mp_err ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group); + mp_int *rx, mp_int *ry, const ECGroup *group, + int timing); #endif /* _ECP_H */ diff --git a/src/share/native/sun/security/ec/impl/ecp_aff.c b/src/share/native/sun/security/ec/impl/ecp_aff.c index f150ca16f..c9d923271 100644 --- a/src/share/native/sun/security/ec/impl/ecp_aff.c +++ b/src/share/native/sun/security/ec/impl/ecp_aff.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -38,6 +38,7 @@ * Nils Larsch , and * Lenka Fibikova , the OpenSSL Project * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "ecp.h" @@ -340,7 +341,8 @@ ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) /* 4: Verify that the order of the curve times the publicValue * is the point at infinity. */ - MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); + /* timing mitigation is not supported */ + MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt, /*timing*/ 0) ); if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { res = MP_NO; goto CLEANUP; diff --git a/src/share/native/sun/security/ec/impl/ecp_jac.c b/src/share/native/sun/security/ec/impl/ecp_jac.c index 716d931f1..9e1bdf20f 100644 --- a/src/share/native/sun/security/ec/impl/ecp_jac.c +++ b/src/share/native/sun/security/ec/impl/ecp_jac.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -38,6 +38,7 @@ * Nils Larsch , and * Lenka Fibikova , the OpenSSL Project * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "ecp.h" @@ -415,7 +416,7 @@ ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py, mp_err ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const ECGroup *group, int timing) { mp_err res = MP_OKAY; mp_int precomp[4][4][2]; @@ -439,9 +440,9 @@ ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, /* if some arguments are not defined used ECPoint_mul */ if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); + return ECPoint_mul(group, k2, px, py, rx, ry, timing); } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + return ECPoint_mul(group, k1, NULL, NULL, rx, ry, timing); } /* initialize precomputation table */ diff --git a/src/share/native/sun/security/ec/impl/ecp_jm.c b/src/share/native/sun/security/ec/impl/ecp_jm.c index 440d0b3fb..c5cdef9bf 100644 --- a/src/share/native/sun/security/ec/impl/ecp_jm.c +++ b/src/share/native/sun/security/ec/impl/ecp_jm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * * This library is free software; you can redistribute it and/or @@ -33,6 +33,7 @@ * Contributor(s): * Stephen Fung , Sun Microsystems Laboratories * + * Last Modified Date from the Original Code: May 2017 *********************************************************************** */ #include "ecp.h" @@ -223,19 +224,23 @@ CLEANUP: * Curves Over Prime Fields. */ mp_err ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group, + int timing) { mp_err res = MP_OKAY; - mp_int precomp[16][2], rz, tpx, tpy; - mp_int raz4; + mp_int precomp[16][2], rz, tpx, tpy, tpz; + mp_int raz4, tpaz4; mp_int scratch[MAX_SCRATCH]; signed char *naf = NULL; int i, orderBitSize; + int numDoubles, numAdds, extraDoubles, extraAdds; MP_DIGITS(&rz) = 0; MP_DIGITS(&raz4) = 0; MP_DIGITS(&tpx) = 0; MP_DIGITS(&tpy) = 0; + MP_DIGITS(&tpz) = 0; + MP_DIGITS(&tpaz4) = 0; for (i = 0; i < 16; i++) { MP_DIGITS(&precomp[i][0]) = 0; MP_DIGITS(&precomp[i][1]) = 0; @@ -249,7 +254,9 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, /* initialize precomputation table */ MP_CHECKOK(mp_init(&tpx, FLAG(n))); - MP_CHECKOK(mp_init(&tpy, FLAG(n)));; + MP_CHECKOK(mp_init(&tpy, FLAG(n))); + MP_CHECKOK(mp_init(&tpz, FLAG(n))); + MP_CHECKOK(mp_init(&tpaz4, FLAG(n))); MP_CHECKOK(mp_init(&rz, FLAG(n))); MP_CHECKOK(mp_init(&raz4, FLAG(n))); @@ -305,17 +312,62 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, /* Compute 5NAF */ ec_compute_wNAF(naf, orderBitSize, n, 5); + numAdds = 0; + numDoubles = orderBitSize; /* wNAF method */ for (i = orderBitSize; i >= 0; i--) { + + if (ec_GFp_pt_is_inf_jac(rx, ry, &rz) == MP_YES) { + numDoubles--; + } + /* R = 2R */ ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz, &raz4, scratch, group); + if (naf[i] != 0) { ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4, &precomp[(naf[i] + 15) / 2][0], &precomp[(naf[i] + 15) / 2][1], rx, ry, &rz, &raz4, scratch, group); + numAdds++; + } + } + + /* extra operations to make timing less dependent on secrets */ + if (timing) { + /* low-order bit of timing argument contains no entropy */ + timing >>= 1; + + MP_CHECKOK(ec_GFp_pt_set_inf_jac(&tpx, &tpy, &tpz)); + mp_zero(&tpaz4); + + /* Set the temp value to a non-infinite point */ + ec_GFp_pt_add_jm_aff(&tpx, &tpy, &tpz, &tpaz4, + &precomp[8][0], + &precomp[8][1], &tpx, &tpy, + &tpz, &tpaz4, scratch, group); + + /* two bits of extra adds */ + extraAdds = timing & 0x3; + timing >>= 2; + /* Window size is 5, so the maximum number of additions is ceil(orderBitSize/5) */ + /* This is the same as (orderBitSize + 4) / 5 */ + for(i = numAdds; i <= (orderBitSize + 4) / 5 + extraAdds; i++) { + ec_GFp_pt_add_jm_aff(&tpx, &tpy, &tpz, &tpaz4, + &precomp[9 + (i % 3)][0], + &precomp[9 + (i % 3)][1], &tpx, &tpy, + &tpz, &tpaz4, scratch, group); } + + /* two bits of extra doubles */ + extraDoubles = timing & 0x3; + timing >>= 2; + for(i = numDoubles; i <= orderBitSize + extraDoubles; i++) { + ec_GFp_pt_dbl_jm(&tpx, &tpy, &tpz, &tpaz4, &tpx, &tpy, &tpz, + &tpaz4, scratch, group); + } + } /* convert result S to affine coordinates */ @@ -331,6 +383,8 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, } mp_clear(&tpx); mp_clear(&tpy); + mp_clear(&tpz); + mp_clear(&tpaz4); mp_clear(&rz); mp_clear(&raz4); #ifdef _KERNEL -- GitLab