int main(void) { mpz_t x; signed char* wmnaf = NULL; size_t wmnaf_len; int i, j; mpz_init(x); printf("\nRunning tests for ecc_wMNAF()\n\n"); for (i = -MAX_NUM; i <= MAX_NUM; ++i) { mpz_set_si(x, i); wmnaf = ecc_wMNAF(x, &wmnaf_len); printf("\"%5i\" has wMNAF repr. = [", i); for (j = wmnaf_len - 1; j > 0; --j) { printf(" %i,", wmnaf[j]); } printf(" %i ]\n", wmnaf[0]); free(wmnaf); } mpz_clear(x); return 0; }
/* Perform a point wMNAF-multiplication utilizing cache This version tries to be timing resistant @param k The scalar to multiply by @param id The curve's id @param R [out] Destination for kG @param a The curve's A value @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 GNUTLS_E_SUCCESS on success */ int ecc_mulmod_cached_timing (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R, mpz_t a, mpz_t modulus, int map) { int j, err; gnutls_ecc_curve_cache_entry_t *cache = NULL; signed char *wmnaf = NULL; size_t wmnaf_len; signed char digit; /* point for throttle */ ecc_point *T; if (k == NULL || R == NULL || modulus == NULL || id == 0) return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* prepare T point */ T = ecc_new_point (); if (T == NULL) return GNUTLS_E_MEMORY_ERROR; /* calculate wMNAF */ wmnaf = ecc_wMNAF (k, &wmnaf_len); if (!wmnaf) { err = GNUTLS_E_INTERNAL_ERROR; goto done; } /* set R to neutral */ mpz_set_ui (R->x, 1); mpz_set_ui (R->y, 1); mpz_set_ui (R->z, 0); /* set T to neutral */ mpz_set_ui (T->x, 1); mpz_set_ui (T->y, 1); mpz_set_ui (T->z, 0); /* do cache lookup */ cache = ecc_wmnaf_cache + id - 1; /* perform ops */ for (j = wmnaf_len - 1; j >= 0; --j) { if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0) goto done; digit = wmnaf[j]; if (digit) { if (digit > 0) { if ((err = ecc_projective_madd (R, cache->pos[(digit / 2)], R, a, modulus)) != 0) goto done; } else { if ((err = ecc_projective_madd (R, cache->neg[(-digit / 2)], R, a, modulus)) != 0) goto done; } } else { /* we add middle element of pos array as a general case * there is no real difference between using pos and neg */ if ((err = ecc_projective_madd (R, cache-> pos[(WMNAF_PRECOMPUTED_LENGTH / 2)], T, a, modulus)) != 0) goto done; } } /* map R back from projective space */ if (map) { err = ecc_map (R, modulus); } else { err = GNUTLS_E_SUCCESS; } done: ecc_del_point (T); if (wmnaf) free (wmnaf); return err; }
/* Perform a point wMNAF-multiplication utilizing cache @param k The scalar to multiply by @param id The curve's id @param R [out] Destination for kG @param a The curve's A value @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 GNUTLS_E_SUCCESS on success */ int ecc_mulmod_cached (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R, mpz_t a, mpz_t modulus, int map) { int j, err; gnutls_ecc_curve_cache_entry_t *cache = NULL; signed char *wmnaf = NULL; size_t wmnaf_len; signed char digit; if (k == NULL || R == NULL || modulus == NULL || id == 0) return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* calculate wMNAF */ wmnaf = ecc_wMNAF (k, &wmnaf_len); if (!wmnaf) { err = GNUTLS_E_INTERNAL_ERROR; goto done; } /* set R to neutral */ mpz_set_ui (R->x, 1); mpz_set_ui (R->y, 1); mpz_set_ui (R->z, 0); /* do cache lookup */ cache = ecc_wmnaf_cache + id - 1; /* perform ops */ for (j = wmnaf_len - 1; j >= 0; --j) { if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0) goto done; digit = wmnaf[j]; if (digit) { if (digit > 0) { if ((err = ecc_projective_madd (R, cache->pos[(digit / 2)], R, a, modulus)) != 0) goto done; } else { if ((err = ecc_projective_madd (R, cache->neg[(-digit / 2)], R, a, modulus)) != 0) goto done; } } } /* map R back from projective space */ if (map) { err = ecc_map (R, modulus); } else { err = GNUTLS_E_SUCCESS; } done: if (wmnaf) free (wmnaf); return err; }
/* Perform a point multiplication using wMNAF representation @param k The scalar to multiply by @param G The base point @param R [out] Destination for kG @param a The curve's A value @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 GNUTLS_E_SUCCESS on success */ int ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus, int map) { ecc_point *pos[WMNAF_PRECOMPUTED_LENGTH], *neg[WMNAF_PRECOMPUTED_LENGTH]; int i, j, err; signed char *wmnaf = NULL; size_t wmnaf_len; signed char digit; if (k == NULL || G == NULL || R == NULL || modulus == NULL) return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* alloc ram for precomputed values */ for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i) { pos[i] = ecc_new_point (); neg[i] = ecc_new_point (); if (pos[i] == NULL || neg[i] == NULL) { for (j = 0; j < i; ++j) { ecc_del_point (pos[j]); ecc_del_point (neg[j]); } return GNUTLS_E_MEMORY_ERROR; } } /* fill in pos and neg arrays with precomputed values * pos holds kG for k == 1, 3, 5, ..., (2^w - 1) * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1) */ /* pos[0] == 2G for a while, later it will be set to the expected 1G */ if ((err = ecc_projective_dbl_point (G, pos[0], a, modulus)) != 0) goto done; /* pos[1] == 3G */ if ((err = ecc_projective_add_point (pos[0], G, pos[1], a, modulus)) != 0) goto done; /* fill in kG for k = 5, 7, ..., (2^w - 1) */ for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j) { if ((err = ecc_projective_add_point (pos[j - 1], pos[0], pos[j], a, modulus)) != 0) goto done; } /* set pos[0] == 1G as expected * after this step we don't need G at all * and can change it without worries even if R == G */ mpz_set (pos[0]->x, G->x); mpz_set (pos[0]->y, G->y); mpz_set (pos[0]->z, G->z); /* neg[i] == -pos[i] */ for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j) { if ((err = ecc_projective_negate_point (pos[j], neg[j], modulus)) != 0) goto done; } /* calculate wMNAF */ wmnaf = ecc_wMNAF (k, &wmnaf_len); if (!wmnaf) { err = GNUTLS_E_INTERNAL_ERROR; goto done; } /* actual point computation */ /* set R to neutral */ mpz_set_ui (R->x, 1); mpz_set_ui (R->y, 1); mpz_set_ui (R->z, 0); /* perform ops */ for (j = wmnaf_len - 1; j >= 0; --j) { if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0) goto done; digit = wmnaf[j]; if (digit) { if (digit > 0) { if ((err = ecc_projective_add_point (R, pos[(digit / 2)], R, a, modulus)) != 0) goto done; } else { if ((err = ecc_projective_add_point (R, neg[(-digit / 2)], R, a, modulus)) != 0) goto done; } } } /* map R back from projective space */ if (map) { err = ecc_map (R, modulus); } else { err = GNUTLS_E_SUCCESS; } done: for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i) { ecc_del_point (pos[i]); ecc_del_point (neg[i]); } if (wmnaf) free (wmnaf); return err; }