changeset 17280:f09a6beb1e23

8175110: Higher quality ECDSA operations Reviewed-by: jnimeh, valeriep, vinnie, xuelei
author apetcher
date Fri, 12 May 2017 17:30:47 +0100
parents d7236673d845
children f8955f187094
files src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp src/jdk.crypto.ec/share/native/libsunec/impl/ec.c src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c src/jdk.crypto.ec/share/native/libsunec/impl/ecc_impl.h src/jdk.crypto.ec/share/native/libsunec/impl/ecl-priv.h src/jdk.crypto.ec/share/native/libsunec/impl/ecl.h src/jdk.crypto.ec/share/native/libsunec/impl/ecl_mult.c src/jdk.crypto.ec/share/native/libsunec/impl/ecp.h src/jdk.crypto.ec/share/native/libsunec/impl/ecp_aff.c src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jac.c src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jm.c
diffstat 14 files changed, 162 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/classes/sun/security/ec/ECDSASignature.java	Fri May 12 17:30:47 2017 +0100
@@ -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
@@ -370,9 +370,15 @@
         }
         random.nextBytes(seed);
 
+        // random bits needed for timing countermeasures
+        int timingArgument = random.nextInt();
+        // values must be non-zero to enable countermeasures
+        timingArgument |= 1;
+
         byte[] sig;
         try {
-            sig = signDigest(getDigestValue(), s, encodedParams, seed);
+            sig = signDigest(getDigestValue(), s, encodedParams, seed,
+                timingArgument);
         } catch (GeneralSecurityException e) {
             throw new SignatureException("Could not sign data", e);
         }
@@ -509,11 +515,19 @@
      * @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.
--- a/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/ECC_JNI.cpp	Fri May 12 17:30:47 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, 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
@@ -196,7 +196,7 @@
  */
 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);
@@ -256,7 +256,7 @@
 
     // 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;
     }
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <vipul.gupta@sun.com> and
  *   Douglas Stebila <douglas@stebila.ca>, 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 @@
  */
 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 @@
                 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 */
@@ -333,7 +333,8 @@
     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;
 
@@ -610,7 +611,8 @@
     }
 
     /* 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;
 
@@ -645,7 +647,8 @@
  */
 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;
@@ -715,16 +718,6 @@
     }
 
     /*
-     * 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
     **
     ** Compute kG
@@ -732,7 +725,7 @@
     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;
 
@@ -854,7 +847,7 @@
 */
 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;
@@ -872,7 +865,7 @@
     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) {
@@ -1018,7 +1011,8 @@
     ** 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;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2.h	Fri May 12 17:30:47 2017 +0100
@@ -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 <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _EC2_H
@@ -79,7 +80,7 @@
  * 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
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_aff.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ec2.h"
@@ -329,7 +330,8 @@
     /* 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;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ec2_mont.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <fungstep@hotmail.com>, and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
  *
+ *  Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ec2.h"
@@ -181,10 +182,12 @@
 /* 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;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecc_impl.h	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecc_impl.h	Fri May 12 17:30:47 2017 +0100
@@ -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 <vipul.gupta@sun.com> and
  *   Douglas Stebila <douglas@stebila.ca>, 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 @@
     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,
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-priv.h	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl-priv.h	Fri May 12 17:30:47 2017 +0100
@@ -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 <fungstep@hotmail.com> and
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECL_PRIV_H
@@ -193,12 +194,13 @@
                                                  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 @@
 /* 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
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.h	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl.h	Fri May 12 17:30:47 2017 +0100
@@ -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 <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECL_H
@@ -70,7 +71,8 @@
  * 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 @@
  * 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
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_mult.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecl_mult.c	Fri May 12 17:30:47 2017 +0100
@@ -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
@@ -33,7 +33,7 @@
  * Contributor(s):
  *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
- * Last Modified Date from the Original Code: Nov 2016
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "mpi.h"
@@ -50,7 +50,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;
@@ -76,16 +77,16 @@
                         kt.flag = (mp_sign)0;
                         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 {
                         kt.flag = (mp_sign)0;
-                        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) {
@@ -107,7 +108,7 @@
 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;
@@ -119,9 +120,9 @@
 
         /* 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;
@@ -129,8 +130,8 @@
         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));
@@ -162,7 +163,7 @@
 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];
@@ -177,9 +178,9 @@
 
         /* 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 */
@@ -311,7 +312,8 @@
  * 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;
@@ -348,9 +350,9 @@
 
         /* 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:
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp.h	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp.h	Fri May 12 17:30:47 2017 +0100
@@ -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 <douglas@stebila.ca>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #ifndef _ECP_H
@@ -122,7 +123,7 @@
 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 @@
  * 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 */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_aff.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_aff.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <nla@trustcenter.de>, and
  *   Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -340,7 +341,8 @@
     /* 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;
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jac.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jac.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <nla@trustcenter.de>, and
  *   Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -406,7 +407,7 @@
 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];
@@ -430,9 +431,9 @@
 
         /* 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 */
--- a/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jm.c	Fri May 12 08:20:11 2017 -0700
+++ b/src/jdk.crypto.ec/share/native/libsunec/impl/ecp_jm.c	Fri May 12 17:30:47 2017 +0100
@@ -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 <fungstep@hotmail.com>, Sun Microsystems Laboratories
  *
+ * Last Modified Date from the Original Code: May 2017
  *********************************************************************** */
 
 #include "ecp.h"
@@ -213,19 +214,23 @@
  * 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;
@@ -239,7 +244,9 @@
 
         /* 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)));
 
@@ -295,19 +302,64 @@
         /* 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 */
         MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
 
@@ -321,6 +373,8 @@
         }
         mp_clear(&tpx);
         mp_clear(&tpy);
+        mp_clear(&tpz);
+        mp_clear(&tpaz4);
         mp_clear(&rz);
         mp_clear(&raz4);
 #ifdef _KERNEL