提交 f788bb7b 编写于 作者: R robm

8175110: Higher quality ECDSA operations

Reviewed-by: xuelei, apetcher
上级 f211122e
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -287,11 +287,15 @@ abstract class ECDSASignature extends SignatureSpi { ...@@ -287,11 +287,15 @@ abstract class ECDSASignature extends SignatureSpi {
} }
random.nextBytes(seed); 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( return encodeSignature(
signDigest(getDigestValue(), s, encodedParams, seed)); signDigest(getDigestValue(), s, encodedParams, seed,
timingArgument));
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e); throw new SignatureException("Could not sign data", e);
} }
...@@ -418,11 +422,19 @@ abstract class ECDSASignature extends SignatureSpi { ...@@ -418,11 +422,19 @@ abstract class ECDSASignature extends SignatureSpi {
* @param s the private key's S value. * @param s the private key's S value.
* @param encodedParams the curve's DER encoded object identifier. * @param encodedParams the curve's DER encoded object identifier.
* @param seed the random seed. * @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. * @return byte[] the signature.
*/ */
private static native byte[] signDigest(byte[] digest, byte[] s, 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. * Verifies the signed digest using the public key.
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -190,7 +190,7 @@ cleanup: ...@@ -190,7 +190,7 @@ cleanup:
*/ */
JNIEXPORT jbyteArray JNIEXPORT jbyteArray
JNICALL Java_sun_security_ec_ECDSASignature_signDigest 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; jbyte* pDigestBuffer = NULL;
jint jDigestLength = env->GetArrayLength(digest); jint jDigestLength = env->GetArrayLength(digest);
...@@ -250,7 +250,7 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest ...@@ -250,7 +250,7 @@ JNICALL Java_sun_security_ec_ECDSASignature_signDigest
// Sign the digest (using the supplied seed) // Sign the digest (using the supplied seed)
if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item, 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); ThrowException(env, KEY_EXCEPTION);
goto cleanup; goto cleanup;
} }
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* Dr Vipul Gupta <vipul.gupta@sun.com> and * Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * 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" #include "mplogic.h"
...@@ -87,7 +87,7 @@ ec_point_at_infinity(SECItem *pointP) ...@@ -87,7 +87,7 @@ ec_point_at_infinity(SECItem *pointP)
*/ */
SECStatus SECStatus
ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, 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 Px, Py, Qx, Qy;
mp_int Gx, Gy, order, irreducible, a, b; 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, ...@@ -199,9 +199,9 @@ ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
goto cleanup; goto cleanup;
if ((k2 != NULL) && (pointP != NULL)) { 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 { } 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 */ /* Construct the SECItem representation of point Q */
...@@ -332,7 +332,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, ...@@ -332,7 +332,8 @@ ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
(mp_size) len) ); (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; if (rv != SECSuccess) goto cleanup;
*privKey = key; *privKey = key;
...@@ -609,7 +610,8 @@ ECDH_Derive(SECItem *publicValue, ...@@ -609,7 +610,8 @@ ECDH_Derive(SECItem *publicValue,
} }
/* Multiply our private key and peer's public point */ /* 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)) ec_point_at_infinity(&pointQ))
goto cleanup; goto cleanup;
...@@ -644,7 +646,8 @@ cleanup: ...@@ -644,7 +646,8 @@ cleanup:
*/ */
SECStatus SECStatus
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 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; SECStatus rv = SECFailure;
mp_int x1; mp_int x1;
...@@ -713,16 +716,6 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, ...@@ -713,16 +716,6 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
goto cleanup; 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 ** ANSI X9.62, Section 5.3.2, Step 2
** **
...@@ -731,7 +724,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, ...@@ -731,7 +724,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
kGpoint.len = 2*flen + 1; kGpoint.len = 2*flen + 1;
kGpoint.data = PORT_Alloc(2*flen + 1, kmflag); kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
if ((kGpoint.data == NULL) || if ((kGpoint.data == NULL) ||
(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag) (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag, timing)
!= SECSuccess)) != SECSuccess))
goto cleanup; goto cleanup;
...@@ -853,7 +846,7 @@ cleanup: ...@@ -853,7 +846,7 @@ cleanup:
*/ */
SECStatus SECStatus
ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest, 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; SECStatus rv = SECFailure;
int len; int len;
...@@ -871,7 +864,7 @@ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest, ...@@ -871,7 +864,7 @@ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
if (kBytes == NULL) goto cleanup; if (kBytes == NULL) goto cleanup;
/* Generate ECDSA signature with the specified k value */ /* 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: cleanup:
if (kBytes) { if (kBytes) {
...@@ -1017,7 +1010,8 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ...@@ -1017,7 +1010,8 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
** Here, A = u1.G B = u2.Q and C = A + B ** Here, A = u1.G B = u2.Q and C = A + B
** If the result, C, is the point at infinity, reject the signature ** 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) { != SECSuccess) {
rv = SECFailure; rv = SECFailure;
goto cleanup; goto cleanup;
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#ifndef _EC2_H #ifndef _EC2_H
...@@ -79,7 +80,7 @@ mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, ...@@ -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. */ * determines the field GF2m. Uses Montgomery projective coordinates. */
mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, 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 mp_int *py, mp_int *rx, mp_int *ry,
const ECGroup *group); const ECGroup *group, int timing);
#ifdef ECL_ENABLE_GF2M_PROJ #ifdef ECL_ENABLE_GF2M_PROJ
/* Converts a point P(px, py) from affine coordinates to projective /* Converts a point P(px, py) from affine coordinates to projective
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#include "ec2.h" #include "ec2.h"
...@@ -329,7 +330,8 @@ ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) ...@@ -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 /* 4: Verify that the order of the curve times the publicValue
* is the point at infinity. * 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) { if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
res = MP_NO; res = MP_NO;
goto CLEANUP; goto CLEANUP;
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
* Stephen Fung <fungstep@hotmail.com>, and * Stephen Fung <fungstep@hotmail.com>, and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories. * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#include "ec2.h" #include "ec2.h"
...@@ -181,10 +182,12 @@ gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1, ...@@ -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 /* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast
* multiplication on elliptic curves over GF(2^m) without * multiplication on elliptic curves over GF(2^m) without
* precomputation". Elliptic curve points P and R can be identical. Uses * 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 mp_err
ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py, 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_err res = MP_OKAY;
mp_int x1, x2, z1, z2; mp_int x1, x2, z1, z2;
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* Dr Vipul Gupta <vipul.gupta@sun.com> and * Dr Vipul Gupta <vipul.gupta@sun.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * 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 #ifndef _ECC_IMPL_H
...@@ -258,7 +258,7 @@ extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, ...@@ -258,7 +258,7 @@ extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
const unsigned char* random, int randomlen, int); const unsigned char* random, int randomlen, int);
/* This function has been modified to accept an array of random bytes */ /* This function has been modified to accept an array of random bytes */
extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *, 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 *, extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
const SECItem *, int); const SECItem *, int);
extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t, extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
* Stephen Fung <fungstep@hotmail.com> and * Stephen Fung <fungstep@hotmail.com> and
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#ifndef _ECL_PRIV_H #ifndef _ECL_PRIV_H
...@@ -193,12 +194,13 @@ struct ECGroupStr { ...@@ -193,12 +194,13 @@ struct ECGroupStr {
mp_int *ry, const ECGroup *group); mp_int *ry, const ECGroup *group);
mp_err (*point_mul) (const mp_int *n, const mp_int *px, mp_err (*point_mul) (const mp_int *n, const mp_int *px,
const mp_int *py, mp_int *rx, mp_int *ry, 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, mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
const ECGroup *group); const ECGroup *group);
mp_err (*points_mul) (const mp_int *k1, const mp_int *k2, mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
const mp_int *px, const mp_int *py, mp_int *rx, 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); mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
/* Extra storage for implementation-specific data. Any memory /* Extra storage for implementation-specific data. Any memory
* allocated to these extra fields will be cleared by extra_free. */ * allocated to these extra fields will be cleared by extra_free. */
...@@ -262,10 +264,12 @@ void ec_GFp_extra_free_mont(GFMethod *meth); ...@@ -262,10 +264,12 @@ void ec_GFp_extra_free_mont(GFMethod *meth);
/* point multiplication */ /* point multiplication */
mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, 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, 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, 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, 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 /* 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 * be an array of signed char's to output to, bitsize should be the number
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#ifndef _ECL_H #ifndef _ECL_H
...@@ -70,7 +71,8 @@ void EC_FreeCurveParams(ECCurveParams * params); ...@@ -70,7 +71,8 @@ void EC_FreeCurveParams(ECCurveParams * params);
* of the group of points on the elliptic curve. Input and output values * of the group of points on the elliptic curve. Input and output values
* are assumed to be NOT field-encoded. */ * are assumed to be NOT field-encoded. */
mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, 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 + /* 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 * 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, ...@@ -78,7 +80,7 @@ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
* be NOT field-encoded. */ * be NOT field-encoded. */
mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1,
const mp_int *k2, const mp_int *px, const mp_int *py, 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. /* 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 * Returns MP_YES if the public key is valid, MP_NO if the public key
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -49,7 +49,8 @@ ...@@ -49,7 +49,8 @@
* are assumed to be NOT field-encoded. */ * are assumed to be NOT field-encoded. */
mp_err mp_err
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, 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_err res = MP_OKAY;
mp_int kt; mp_int kt;
...@@ -74,15 +75,15 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, ...@@ -74,15 +75,15 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
} else { } else {
MP_CHECKOK(group-> MP_CHECKOK(group->
point_mul(&kt, &group->genx, &group->geny, rx, ry, point_mul(&kt, &group->genx, &group->geny, rx, ry,
group)); group, timing));
} }
} else { } else {
if (group->meth->field_enc) { if (group->meth->field_enc) {
MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
MP_CHECKOK(group->meth->field_enc(py, ry, 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 { } 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) { if (group->meth->field_dec) {
...@@ -104,7 +105,7 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, ...@@ -104,7 +105,7 @@ ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
mp_err mp_err
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, 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 mp_int *py, mp_int *rx, mp_int *ry,
const ECGroup *group) const ECGroup *group, int timing)
{ {
mp_err res = MP_OKAY; mp_err res = MP_OKAY;
mp_int sx, sy; mp_int sx, sy;
...@@ -116,9 +117,9 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, ...@@ -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 some arguments are not defined used ECPoint_mul */
if (k1 == NULL) { 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)) { } 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; MP_DIGITS(&sx) = 0;
...@@ -126,8 +127,8 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, ...@@ -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(&sx, FLAG(k1)));
MP_CHECKOK(mp_init(&sy, FLAG(k1))); MP_CHECKOK(mp_init(&sy, FLAG(k1)));
MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy, timing));
MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry, timing));
if (group->meth->field_enc) { if (group->meth->field_enc) {
MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); 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, ...@@ -159,7 +160,7 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
mp_err mp_err
ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, 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 mp_int *py, mp_int *rx, mp_int *ry,
const ECGroup *group) const ECGroup *group, int timing)
{ {
mp_err res = MP_OKAY; mp_err res = MP_OKAY;
mp_int precomp[4][4][2]; 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, ...@@ -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 some arguments are not defined used ECPoint_mul */
if (k1 == NULL) { 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)) { } 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 */ /* initialize precomputation table */
...@@ -308,7 +309,8 @@ ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, ...@@ -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. */ * Input and output values are assumed to be NOT field-encoded. */
mp_err mp_err
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, 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_err res = MP_OKAY;
mp_int k1t, k2t; mp_int k1t, k2t;
...@@ -345,9 +347,9 @@ ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, ...@@ -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 points_mul is defined, then use it */
if (group->points_mul) { 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 { } 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: CLEANUP:
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Contributor(s): * Contributor(s):
* Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#ifndef _ECP_H #ifndef _ECP_H
...@@ -122,7 +123,7 @@ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, ...@@ -122,7 +123,7 @@ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px,
mp_err mp_err
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, 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 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 /* 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 * curve points P and R can be identical. Uses mixed Modified-Jacobian
...@@ -131,9 +132,13 @@ mp_err ...@@ -131,9 +132,13 @@ mp_err
* returns output that is still field-encoded. Uses 5-bit window NAF * returns output that is still field-encoded. Uses 5-bit window NAF
* method (algorithm 11) for scalar-point multiplication from Brown, * method (algorithm 11) for scalar-point multiplication from Brown,
* Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic * 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 mp_err
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, 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 */ #endif /* _ECP_H */
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
* Nils Larsch <nla@trustcenter.de>, and * Nils Larsch <nla@trustcenter.de>, and
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project * Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#include "ecp.h" #include "ecp.h"
...@@ -340,7 +341,8 @@ ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) ...@@ -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 /* 4: Verify that the order of the curve times the publicValue
* is the point at infinity. * 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) { if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
res = MP_NO; res = MP_NO;
goto CLEANUP; goto CLEANUP;
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
* Nils Larsch <nla@trustcenter.de>, and * Nils Larsch <nla@trustcenter.de>, and
* Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project * Lenka Fibikova <fibikova@exp-math.uni-essen.de>, the OpenSSL Project
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#include "ecp.h" #include "ecp.h"
...@@ -415,7 +416,7 @@ ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py, ...@@ -415,7 +416,7 @@ ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
mp_err mp_err
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, 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 mp_int *py, mp_int *rx, mp_int *ry,
const ECGroup *group) const ECGroup *group, int timing)
{ {
mp_err res = MP_OKAY; mp_err res = MP_OKAY;
mp_int precomp[4][4][2]; 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, ...@@ -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 some arguments are not defined used ECPoint_mul */
if (k1 == NULL) { 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)) { } 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 */ /* initialize precomputation table */
......
/* /*
* 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. * Use is subject to license terms.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
* Contributor(s): * Contributor(s):
* Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories * Stephen Fung <fungstep@hotmail.com>, Sun Microsystems Laboratories
* *
* Last Modified Date from the Original Code: May 2017
*********************************************************************** */ *********************************************************************** */
#include "ecp.h" #include "ecp.h"
...@@ -223,19 +224,23 @@ CLEANUP: ...@@ -223,19 +224,23 @@ CLEANUP:
* Curves Over Prime Fields. */ * Curves Over Prime Fields. */
mp_err mp_err
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, 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_err res = MP_OKAY;
mp_int precomp[16][2], rz, tpx, tpy; mp_int precomp[16][2], rz, tpx, tpy, tpz;
mp_int raz4; mp_int raz4, tpaz4;
mp_int scratch[MAX_SCRATCH]; mp_int scratch[MAX_SCRATCH];
signed char *naf = NULL; signed char *naf = NULL;
int i, orderBitSize; int i, orderBitSize;
int numDoubles, numAdds, extraDoubles, extraAdds;
MP_DIGITS(&rz) = 0; MP_DIGITS(&rz) = 0;
MP_DIGITS(&raz4) = 0; MP_DIGITS(&raz4) = 0;
MP_DIGITS(&tpx) = 0; MP_DIGITS(&tpx) = 0;
MP_DIGITS(&tpy) = 0; MP_DIGITS(&tpy) = 0;
MP_DIGITS(&tpz) = 0;
MP_DIGITS(&tpaz4) = 0;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
MP_DIGITS(&precomp[i][0]) = 0; MP_DIGITS(&precomp[i][0]) = 0;
MP_DIGITS(&precomp[i][1]) = 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, ...@@ -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 */ /* initialize precomputation table */
MP_CHECKOK(mp_init(&tpx, FLAG(n))); 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(&rz, FLAG(n)));
MP_CHECKOK(mp_init(&raz4, 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, ...@@ -305,17 +312,62 @@ ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
/* Compute 5NAF */ /* Compute 5NAF */
ec_compute_wNAF(naf, orderBitSize, n, 5); ec_compute_wNAF(naf, orderBitSize, n, 5);
numAdds = 0;
numDoubles = orderBitSize;
/* wNAF method */ /* wNAF method */
for (i = orderBitSize; i >= 0; i--) { for (i = orderBitSize; i >= 0; i--) {
if (ec_GFp_pt_is_inf_jac(rx, ry, &rz) == MP_YES) {
numDoubles--;
}
/* R = 2R */ /* R = 2R */
ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz, ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
&raz4, scratch, group); &raz4, scratch, group);
if (naf[i] != 0) { if (naf[i] != 0) {
ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4, ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
&precomp[(naf[i] + 15) / 2][0], &precomp[(naf[i] + 15) / 2][0],
&precomp[(naf[i] + 15) / 2][1], rx, ry, &precomp[(naf[i] + 15) / 2][1], rx, ry,
&rz, &raz4, scratch, group); &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 */ /* 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, ...@@ -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(&tpx);
mp_clear(&tpy); mp_clear(&tpy);
mp_clear(&tpz);
mp_clear(&tpaz4);
mp_clear(&rz); mp_clear(&rz);
mp_clear(&raz4); mp_clear(&raz4);
#ifdef _KERNEL #ifdef _KERNEL
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册