From: Nikos Mavrogiannopoulos Date: Thu, 8 Dec 2011 23:02:06 +0000 (+0100) Subject: The timing resistant ecc_mulmod() is only used when signing using the ECDSA private... X-Git-Tag: gnutls_3_0_9~25 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4b39d65406cdca6b0323bf5d8b42819a31c16b73;p=thirdparty%2Fgnutls.git The timing resistant ecc_mulmod() is only used when signing using the ECDSA private key. This improves performance in all other cases that do not require timing resistance. --- diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am index 24552dc943..e637bb1cb3 100644 --- a/lib/nettle/Makefile.am +++ b/lib/nettle/Makefile.am @@ -37,4 +37,4 @@ libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \ multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \ ecc_map.c ecc_mulmod.c ecc_points.c ecc_projective_dbl_point_3.c \ ecc_projective_add_point.c ecc_projective_check_point.c \ - ecc_sign_hash.c ecc_verify_hash.c gnettle.h + ecc_sign_hash.c ecc_verify_hash.c gnettle.h ecc_mulmod_timing.c diff --git a/lib/nettle/ecc.h b/lib/nettle/ecc.h index d5a5fa013e..7e0ed01fa4 100644 --- a/lib/nettle/ecc.h +++ b/lib/nettle/ecc.h @@ -84,7 +84,7 @@ void ecc_sizes(int *low, int *high); int ecc_get_size(ecc_key *key); int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, const ecc_set_type *dp); -int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy); +int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy, int timing_res); void ecc_free(ecc_key *key); int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, @@ -111,6 +111,7 @@ int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t A, /* R = kG */ int ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, int map); +int ecc_mulmod_timing(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, int map); /* map P to affine from projective */ int ecc_map(ecc_point *P, mpz_t modulus); diff --git a/lib/nettle/ecc_make_key.c b/lib/nettle/ecc_make_key.c index 4972eabb30..34b6d63770 100644 --- a/lib/nettle/ecc_make_key.c +++ b/lib/nettle/ecc_make_key.c @@ -38,12 +38,14 @@ @param A The "a" parameter of the curve @param Gx The x coordinate of the base point @param Gy The y coordinate of the base point + @timing_res If non zero the function will try to return in constant time. @return 0 if successful, upon error all allocated memory will be freed */ int ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, - mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy) + mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy, + int timing_res) { int err; ecc_point *base; @@ -99,12 +101,14 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key, mpz_mod (key->k, key->k, key->order); } /* make the public key */ - if ((err = - ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime, - 1)) != 0) - { - goto errkey; - } + if (timing_res) + err = ecc_mulmod_timing (key->k, base, &key->pubkey, key->A, key->prime, 1); + else + err = ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime, 1); + + if (err != 0) + goto errkey; + key->type = PK_PRIVATE; /* free up ram */ @@ -142,7 +146,7 @@ ecc_make_key (void *random_ctx, nettle_random_func random, ecc_key * key, mpz_set_str (A, (char *) dp->A, 16); mpz_set_str (B, (char *) dp->B, 16); - err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy); + err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy, 0); mp_clear_multi (&prime, &order, &A, &B, &Gx, &Gy, NULL); cleanup: diff --git a/lib/nettle/ecc_mulmod.c b/lib/nettle/ecc_mulmod.c index 2f12759e9a..2c1d46eb16 100644 --- a/lib/nettle/ecc_mulmod.c +++ b/lib/nettle/ecc_mulmod.c @@ -24,153 +24,170 @@ #include "ecc.h" -/* - @file ecc_mulmod_timing.c - ECC Crypto, Tom St Denis -*/ +/* size of sliding window, don't change this! */ +#define WINSIZE 4 -/* - Perform a point multiplication (timing resistant) +/** + Perform a point multiplication @param k The scalar to multiply by @param G The base point @param R [out] Destination for kG - @param a The a value of the curve @param modulus The modulus of the field the ECC curve is in @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) - @return 0 on success + @return CRYPT_OK on success */ int ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus, int map) + { - ecc_point *tG, *M[3]; - int i, j, err; - int bit_to_read; - int mode; + ecc_point *tG, *M[8]; + int i, j, err, bitidx; + int first, bitbuf, bitcpy, bitcnt, mode; - if (k == NULL || G == NULL || R == NULL || modulus == NULL) - return -1; + if (k == NULL || G == NULL || R == NULL || modulus == NULL) + return -1; /* alloc ram for window temps */ - for (i = 0; i < 3; i++) - { - M[i] = ecc_new_point (); - if (M[i] == NULL) - { - for (j = 0; j < i; j++) - { - ecc_del_point (M[j]); - } - return -1; - } - } - - /* make a copy of G incase R==G */ - tG = ecc_new_point (); - if (tG == NULL) - { - err = -1; - goto done; - } - - /* tG = G and convert to montgomery */ - mpz_set (tG->x, G->x); - mpz_set (tG->y, G->y); - mpz_set (tG->z, G->z); - - /* calc the M tab */ - /* M[0] == G */ - mpz_set (M[0]->x, tG->x); - mpz_set (M[0]->y, tG->y); - mpz_set (M[0]->z, tG->z); - /* M[1] == 2G */ - if ((err = ecc_projective_dbl_point (tG, M[1], a, modulus)) != 0) - { - goto done; - } - - /* setup sliding window */ - mode = 0; - bit_to_read = mpz_size (k) * GMP_NUMB_BITS - 1; - - /* perform ops */ - for (;;) - { - /* grab next digit as required */ - if (bit_to_read == -1) - break; - i = mpz_tstbit (k, bit_to_read--); - - if (mode == 0 && i == 0) - { - /* dummy operations */ - if ((err = - ecc_projective_add_point (M[0], M[1], M[2], a, - modulus)) != 0) - { - goto done; - } - if ((err = - ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0) - { - goto done; - } - continue; - } - - if (mode == 0 && i == 1) - { - mode = 1; - /* dummy operations */ - if ((err = - ecc_projective_add_point (M[0], M[1], M[2], a, - modulus)) != 0) - { - goto done; - } - if ((err = - ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0) - { - goto done; - } - continue; - } - - if ((err = - ecc_projective_add_point (M[0], M[1], M[i ^ 1], a, - modulus)) != 0) - { + for (i = 0; i < 8; i++) { + M[i] = ecc_new_point(); + if (M[i] == NULL) { + for (j = 0; j < i; j++) { + ecc_del_point(M[j]); + } + + return -1; + } + } + + /* make a copy of G incase R==G */ + tG = ecc_new_point(); + if (tG == NULL) + { + err = -1; + goto done; + } + + /* tG = G and convert to montgomery */ + mpz_set (tG->x, G->x); + mpz_set (tG->y, G->y); + mpz_set (tG->z, G->z); + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == 8G */ + if ((err = ecc_projective_dbl_point (tG, M[0], a, modulus)) != 0) + goto done; + + if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0) + goto done; + + if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0) + goto done; + + /* now find (8+k)G for k=1..7 */ + for (j = 9; j < 16; j++) { + if (ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus) != 0) + goto done; + } + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + bitidx = mpz_size (k) * GMP_NUMB_BITS - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (bitidx == -1) { + break; + } + + /* grab the next msb from the ltiplicand */ + i = mpz_tstbit (k, bitidx--); + + /* skip leading zero bits */ + if (mode == 0 && i == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0) goto done; - } - if ((err = ecc_projective_dbl_point (M[i], M[i], a, modulus)) != 0) - { - goto done; - } - } - - /* copy result out */ - mpz_set (R->x, M[0]->x); - mpz_set (R->y, M[0]->y); - mpz_set (R->z, M[0]->z); - - /* map R back from projective space */ - if (map) - { - err = ecc_map (R, modulus); + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + mpz_set(R->x, M[bitbuf-8]->x); + mpz_set(R->y, M[bitbuf-8]->y); + mpz_set(R->z, M[bitbuf-8]->z); + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < WINSIZE; j++) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0) + goto done; + } + + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + if ((err = ecc_projective_add_point(R, M[bitbuf-8], R, a, modulus)) != 0) + goto done; + } + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; } - else - { + } + + /* if bits remain then double/add */ + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0) + goto done; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1){ + /* first add, so copy */ + mpz_set(R->x, tG->x); + mpz_set(R->y, tG->y); + mpz_set(R->z, tG->z); + first = 0; + } else { + /* then add */ + if ((err = ecc_projective_add_point(R, tG, R, a, modulus)) != 0) + goto done; + } + } + } + } + + /* map R back from projective space */ + if (map) { + err = ecc_map(R, modulus); + } else { err = 0; - } + } done: - ecc_del_point (tG); - for (i = 0; i < 3; i++) - { - ecc_del_point (M[i]); - } - return err; + ecc_del_point(tG); + for (i = 0; i < 8; i++) { + ecc_del_point(M[i]); + } + return err; } -/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_mulmod_timing.c,v $ */ -/* $Revision: 1.13 $ */ -/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/lib/nettle/ecc_mulmod_timing.c b/lib/nettle/ecc_mulmod_timing.c new file mode 100644 index 0000000000..349fdd8110 --- /dev/null +++ b/lib/nettle/ecc_mulmod_timing.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * This file is part of GNUTLS. + * + * The GNUTLS library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + */ + +/* Based on public domain code of LibTomCrypt by Tom St Denis. + * Adapted to gmp and nettle by Nikos Mavrogiannopoulos. + */ + +#include "ecc.h" + +/* + @file ecc_mulmod_timing.c + ECC Crypto, Tom St Denis +*/ + +/* + Perform a point multiplication (timing resistant) + @param k The scalar to multiply by + @param G The base point + @param R [out] Destination for kG + @param a The a value of the curve + @param modulus The modulus of the field the ECC curve is in + @param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective) + @return 0 on success +*/ +int +ecc_mulmod_timing (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus, + int map) +{ + ecc_point *tG, *M[3]; + int i, j, err; + int bit_to_read; + int mode; + + if (k == NULL || G == NULL || R == NULL || modulus == NULL) + return -1; + + /* alloc ram for window temps */ + for (i = 0; i < 3; i++) + { + M[i] = ecc_new_point (); + if (M[i] == NULL) + { + for (j = 0; j < i; j++) + { + ecc_del_point (M[j]); + } + return -1; + } + } + + /* make a copy of G incase R==G */ + tG = ecc_new_point (); + if (tG == NULL) + { + err = -1; + goto done; + } + + /* tG = G and convert to montgomery */ + mpz_set (tG->x, G->x); + mpz_set (tG->y, G->y); + mpz_set (tG->z, G->z); + + /* calc the M tab */ + /* M[0] == G */ + mpz_set (M[0]->x, tG->x); + mpz_set (M[0]->y, tG->y); + mpz_set (M[0]->z, tG->z); + /* M[1] == 2G */ + if ((err = ecc_projective_dbl_point (tG, M[1], a, modulus)) != 0) + { + goto done; + } + + /* setup sliding window */ + mode = 0; + bit_to_read = mpz_size (k) * GMP_NUMB_BITS - 1; + + /* perform ops */ + for (;;) + { + /* grab next digit as required */ + if (bit_to_read == -1) + break; + i = mpz_tstbit (k, bit_to_read--); + + if (mode == 0 && i == 0) + { + /* dummy operations */ + if ((err = + ecc_projective_add_point (M[0], M[1], M[2], a, + modulus)) != 0) + { + goto done; + } + if ((err = + ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0) + { + goto done; + } + continue; + } + + if (mode == 0 && i == 1) + { + mode = 1; + /* dummy operations */ + if ((err = + ecc_projective_add_point (M[0], M[1], M[2], a, + modulus)) != 0) + { + goto done; + } + if ((err = + ecc_projective_dbl_point (M[1], M[2], a, modulus)) != 0) + { + goto done; + } + continue; + } + + if ((err = + ecc_projective_add_point (M[0], M[1], M[i ^ 1], a, + modulus)) != 0) + { + goto done; + } + if ((err = ecc_projective_dbl_point (M[i], M[i], a, modulus)) != 0) + { + goto done; + } + } + + /* copy result out */ + mpz_set (R->x, M[0]->x); + mpz_set (R->y, M[0]->y); + mpz_set (R->z, M[0]->z); + + /* map R back from projective space */ + if (map) + { + err = ecc_map (R, modulus); + } + else + { + err = 0; + } +done: + ecc_del_point (tG); + for (i = 0; i < 3; i++) + { + ecc_del_point (M[i]); + } + return err; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_mulmod_timing.c,v $ */ +/* $Revision: 1.13 $ */ +/* $Date: 2007/05/12 14:32:35 $ */ diff --git a/lib/nettle/ecc_sign_hash.c b/lib/nettle/ecc_sign_hash.c index 04c3f1d0c8..674260f88f 100644 --- a/lib/nettle/ecc_sign_hash.c +++ b/lib/nettle/ecc_sign_hash.c @@ -72,7 +72,7 @@ ecc_sign_hash (const unsigned char *in, unsigned long inlen, { if ((err = ecc_make_key_ex (random_ctx, random, &pubkey, key->prime, - key->order, key->A, key->B, key->Gx, key->Gy)) != 0) + key->order, key->A, key->B, key->Gx, key->Gy, 1)) != 0) { goto errnokey; }