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
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,
/* 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);
@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;
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 */
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:
#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 $ */
--- /dev/null
+/*
+ * 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* 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 $ */
{
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;
}