|
Packit Service |
4684c1 |
/* eccdata.c
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Generate compile time constant (but machine dependent) tables.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Copyright (C) 2013, 2014, 2017 Niels Möller
|
|
Packit Service |
4684c1 |
Copyright (C) 2017 Daiki Ueno
|
|
Packit Service |
4684c1 |
Copyright (C) 2017 Red Hat, Inc.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
This file is part of GNU Nettle.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
GNU Nettle is free software: you can redistribute it and/or
|
|
Packit Service |
4684c1 |
modify it under the terms of either:
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
* the GNU Lesser General Public License as published by the Free
|
|
Packit Service |
4684c1 |
Software Foundation; either version 3 of the License, or (at your
|
|
Packit Service |
4684c1 |
option) any later version.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
or
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
* the GNU General Public License as published by the Free
|
|
Packit Service |
4684c1 |
Software Foundation; either version 2 of the License, or (at your
|
|
Packit Service |
4684c1 |
option) any later version.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
or both in parallel, as here.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
GNU Nettle is distributed in the hope that it will be useful,
|
|
Packit Service |
4684c1 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
4684c1 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
4684c1 |
General Public License for more details.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
You should have received copies of the GNU General Public License and
|
|
Packit Service |
4684c1 |
the GNU Lesser General Public License along with this program. If
|
|
Packit Service |
4684c1 |
not, see http://www.gnu.org/licenses/.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Development of Nettle's ECC support was funded by the .SE Internet Fund. */
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <assert.h>
|
|
Packit Service |
4684c1 |
#include <stdio.h>
|
|
Packit Service |
4684c1 |
#include <stdlib.h>
|
|
Packit Service |
4684c1 |
#include <string.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#include <gmp.h>
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Affine coordinates, for simplicity. Infinity point, i.e., te
|
|
Packit Service |
4684c1 |
neutral group element, is represented using the is_zero flag. */
|
|
Packit Service |
4684c1 |
struct ecc_point
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int is_zero;
|
|
Packit Service |
4684c1 |
mpz_t x;
|
|
Packit Service |
4684c1 |
mpz_t y;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
enum ecc_type
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* y^2 = x^3 - 3x + b (mod p) */
|
|
Packit Service |
4684c1 |
ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
/* x^2 + y^2 = 1 - d x^2 y^2 */
|
|
Packit Service |
4684c1 |
ECC_TYPE_EDWARDS,
|
|
Packit Service |
4684c1 |
/* -x^2 + y^2 = 1 - d x^2 y^2 */
|
|
Packit Service |
4684c1 |
ECC_TYPE_TWISTED_EDWARDS,
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
struct ecc_curve
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned bit_size;
|
|
Packit Service |
4684c1 |
unsigned pippenger_k;
|
|
Packit Service |
4684c1 |
unsigned pippenger_c;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
enum ecc_type type;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Prime */
|
|
Packit Service |
4684c1 |
mpz_t p;
|
|
Packit Service |
4684c1 |
mpz_t b;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Curve order */
|
|
Packit Service |
4684c1 |
mpz_t q;
|
|
Packit Service |
4684c1 |
struct ecc_point g;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Table for pippenger's algorithm.
|
|
Packit Service |
4684c1 |
Element
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
i 2^c + j_0 + j_1 2 + j_2 2^2 + ... + j_{c-1} 2^{c-1}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
holds
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
2^{ikc} ( j_0 + j_1 2^k + j_2 2^{2k} + ... + j_{c-1} 2^{(c-1)k}) g
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
mp_size_t table_size;
|
|
Packit Service |
4684c1 |
struct ecc_point *table;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* If non-NULL, holds 2g, 3g, 4g */
|
|
Packit Service |
4684c1 |
struct ecc_point *ref;
|
|
Packit Service |
4684c1 |
};
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_init (struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_init (p->x);
|
|
Packit Service |
4684c1 |
mpz_init (p->y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_clear (struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_clear (p->x);
|
|
Packit Service |
4684c1 |
mpz_clear (p->y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
ecc_zero_p (const struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return p->is_zero;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static int
|
|
Packit Service |
4684c1 |
ecc_equal_p (const struct ecc_point *p, const struct ecc_point *q)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
return p->is_zero ? q->is_zero
|
|
Packit Service |
4684c1 |
: !q->is_zero && mpz_cmp (p->x, q->x) == 0 && mpz_cmp (p->y, q->y) == 0;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_set_zero (const struct ecc_curve *ecc, struct ecc_point *r)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
r->is_zero = 1;
|
|
Packit Service |
4684c1 |
mpz_set_ui (r->x, 0);
|
|
Packit Service |
4684c1 |
mpz_set_ui (r->y, ecc->type != ECC_TYPE_WEIERSTRASS);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_set (struct ecc_point *r, const struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
r->is_zero = p->is_zero;
|
|
Packit Service |
4684c1 |
mpz_set (r->x, p->x);
|
|
Packit Service |
4684c1 |
mpz_set (r->y, p->y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_add (const struct ecc_curve *ecc, struct ecc_point *r,
|
|
Packit Service |
4684c1 |
const struct ecc_point *p, const struct ecc_point *q);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Needs to support in-place operation. */
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_dup (const struct ecc_curve *ecc,
|
|
Packit Service |
4684c1 |
struct ecc_point *r, const struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (ecc->type != ECC_TYPE_WEIERSTRASS)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_add (ecc, r, p, p);
|
|
Packit Service |
4684c1 |
return;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (ecc_zero_p (p))
|
|
Packit Service |
4684c1 |
ecc_set_zero (ecc, r);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t m, t, x, y;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (m);
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
mpz_init (x);
|
|
Packit Service |
4684c1 |
mpz_init (y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* m = (2 y)^-1 */
|
|
Packit Service |
4684c1 |
mpz_mul_ui (m, p->y, 2);
|
|
Packit Service |
4684c1 |
mpz_invert (m, m, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* t = 3 (x^2 - 1) * m */
|
|
Packit Service |
4684c1 |
mpz_mul (t, p->x, p->x);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_sub_ui (t, t, 1);
|
|
Packit Service |
4684c1 |
mpz_mul_ui (t, t, 3);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, m);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* x' = t^2 - 2 x */
|
|
Packit Service |
4684c1 |
mpz_mul (x, t, t);
|
|
Packit Service |
4684c1 |
mpz_submul_ui (x, p->x, 2);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* y' = (x - x') * t - y */
|
|
Packit Service |
4684c1 |
mpz_sub (y, p->x, x);
|
|
Packit Service |
4684c1 |
mpz_mul (y, y, t);
|
|
Packit Service |
4684c1 |
mpz_sub (y, y, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
r->is_zero = 0;
|
|
Packit Service |
4684c1 |
mpz_swap (x, r->x);
|
|
Packit Service |
4684c1 |
mpz_swap (y, r->y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (m);
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
mpz_clear (x);
|
|
Packit Service |
4684c1 |
mpz_clear (y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_add (const struct ecc_curve *ecc, struct ecc_point *r,
|
|
Packit Service |
4684c1 |
const struct ecc_point *p, const struct ecc_point *q)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (ecc->type == ECC_TYPE_WEIERSTRASS)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (ecc_zero_p (p))
|
|
Packit Service |
4684c1 |
ecc_set (r, q);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
else if (ecc_zero_p (q))
|
|
Packit Service |
4684c1 |
ecc_set (r, p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
else if (mpz_cmp (p->x, q->x) == 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (mpz_cmp (p->y, q->y) == 0)
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, r, p);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
ecc_set_zero (ecc, r);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t s, t, x, y;
|
|
Packit Service |
4684c1 |
mpz_init (s);
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
mpz_init (x);
|
|
Packit Service |
4684c1 |
mpz_init (y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* t = (q_y - p_y) / (q_x - p_x) */
|
|
Packit Service |
4684c1 |
mpz_sub (t, q->x, p->x);
|
|
Packit Service |
4684c1 |
mpz_invert (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_sub (s, q->y, p->y);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, s);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* x' = t^2 - p_x - q_x */
|
|
Packit Service |
4684c1 |
mpz_mul (x, t, t);
|
|
Packit Service |
4684c1 |
mpz_sub (x, x, p->x);
|
|
Packit Service |
4684c1 |
mpz_sub (x, x, q->x);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* y' = (x - x') * t - y */
|
|
Packit Service |
4684c1 |
mpz_sub (y, p->x, x);
|
|
Packit Service |
4684c1 |
mpz_mul (y, y, t);
|
|
Packit Service |
4684c1 |
mpz_sub (y, y, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
r->is_zero = 0;
|
|
Packit Service |
4684c1 |
mpz_swap (x, r->x);
|
|
Packit Service |
4684c1 |
mpz_swap (y, r->y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (s);
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
mpz_clear (x);
|
|
Packit Service |
4684c1 |
mpz_clear (y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (ecc->type == ECC_TYPE_EDWARDS)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t s, t, x, y;
|
|
Packit Service |
4684c1 |
mpz_init (s);
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
mpz_init (x);
|
|
Packit Service |
4684c1 |
mpz_init (y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* t = d p_x p_y q_x q_y */
|
|
Packit Service |
4684c1 |
mpz_mul (t, ecc->b, p->x);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, q->x);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* x' = (p_x q_y + q_x p_y) / (1 + t) */
|
|
Packit Service |
4684c1 |
mpz_mul (x, p->x, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_addmul (x, q->x, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_add_ui (s, t, 1);
|
|
Packit Service |
4684c1 |
mpz_invert (s, s, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (x, x, s);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* y' = (p_y q_y - p_x q_x) / (1 - t) */
|
|
Packit Service |
4684c1 |
mpz_mul (y, p->y, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_submul (y, p->x, q->x);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_set_ui (s, 1);
|
|
Packit Service |
4684c1 |
mpz_sub (s, s, t);
|
|
Packit Service |
4684c1 |
mpz_invert (s, s, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (y, y, s);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_swap (x, r->x);
|
|
Packit Service |
4684c1 |
mpz_swap (y, r->y);
|
|
Packit Service |
4684c1 |
r->is_zero = mpz_cmp_ui (r->x, 0) == 0 && mpz_cmp_ui (r->y, 1) == 0;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (s);
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
mpz_clear (x);
|
|
Packit Service |
4684c1 |
mpz_clear (y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Untwisted:
|
|
Packit Service |
4684c1 |
x = (p_x q_y + p_y q_x) / (1 - d p_x p_y q_x q_y)
|
|
Packit Service |
4684c1 |
y = (p_y q_y - p_x q_x) / (1 + d p_x p_y q_x q_y)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Twisted:
|
|
Packit Service |
4684c1 |
x = (p_x q_y + p_y q_x) / (1 - d p_x p_y q_x q_y)
|
|
Packit Service |
4684c1 |
y = (p_y q_y + p_x q_x) / (1 + d p_x p_y q_x q_y)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
So they differ only by a sign in the expression for the new y
|
|
Packit Service |
4684c1 |
coordinate.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_t s, t, x, y;
|
|
Packit Service |
4684c1 |
mpz_init (s);
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
mpz_init (x);
|
|
Packit Service |
4684c1 |
mpz_init (y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* t = d p_x p_y q_x q_y */
|
|
Packit Service |
4684c1 |
mpz_mul (t, ecc->b, p->x);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, q->x);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* x' = (p_x q_y + q_x p_y) / (1 - t) */
|
|
Packit Service |
4684c1 |
mpz_mul (x, p->x, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_addmul (x, q->x, p->y);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_ui_sub (s, 1, t);
|
|
Packit Service |
4684c1 |
mpz_invert (s, s, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (x, x, s);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* y' = (p_y q_y - p_x q_x) / (1 + t) */
|
|
Packit Service |
4684c1 |
mpz_mul (y, p->y, q->y);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_addmul (y, p->x, q->x);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_add_ui (s, t, 1);
|
|
Packit Service |
4684c1 |
mpz_invert (s, s, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (y, y, s);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_swap (x, r->x);
|
|
Packit Service |
4684c1 |
mpz_swap (y, r->y);
|
|
Packit Service |
4684c1 |
r->is_zero = (mpz_cmp_ui (r->x, 0) == 0 && mpz_cmp_ui (r->y, 1) == 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (s);
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
mpz_clear (x);
|
|
Packit Service |
4684c1 |
mpz_clear (y);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_mul_binary (const struct ecc_curve *ecc,
|
|
Packit Service |
4684c1 |
struct ecc_point *r, const mpz_t n, const struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Avoid the mp_bitcnt_t type for compatibility with older GMP
|
|
Packit Service |
4684c1 |
versions. */
|
|
Packit Service |
4684c1 |
unsigned k;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
assert (r != p);
|
|
Packit Service |
4684c1 |
assert (mpz_sgn (n) > 0);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set (r, p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Index of highest one bit */
|
|
Packit Service |
4684c1 |
for (k = mpz_sizeinbase (n, 2) - 1; k-- > 0; )
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, r, r);
|
|
Packit Service |
4684c1 |
if (mpz_tstbit (n, k))
|
|
Packit Service |
4684c1 |
ecc_add (ecc, r, r, p);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static struct ecc_point *
|
|
Packit Service |
4684c1 |
ecc_alloc (size_t n)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
struct ecc_point *p = malloc (n * sizeof(*p));
|
|
Packit Service |
4684c1 |
size_t i;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (!p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "Virtual memory exhausted.\n");
|
|
Packit Service |
4684c1 |
exit (EXIT_FAILURE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
for (i = 0; i < n; i++)
|
|
Packit Service |
4684c1 |
ecc_init (&p[i]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
return p;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_set_str (struct ecc_point *p,
|
|
Packit Service |
4684c1 |
const char *x, const char *y)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
p->is_zero = 0;
|
|
Packit Service |
4684c1 |
mpz_set_str (p->x, x, 16);
|
|
Packit Service |
4684c1 |
mpz_set_str (p->y, y, 16);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (struct ecc_curve *ecc, enum ecc_type type,
|
|
Packit Service |
4684c1 |
const char *p, const char *b, const char *q,
|
|
Packit Service |
4684c1 |
const char *gx, const char *gy)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc->type = type;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init_set_str (ecc->p, p, 16);
|
|
Packit Service |
4684c1 |
mpz_init_set_str (ecc->b, b, 16);
|
|
Packit Service |
4684c1 |
mpz_init_set_str (ecc->q, q, 16);
|
|
Packit Service |
4684c1 |
ecc_init (&ecc->g);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->g, gx, gy);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->pippenger_k = 0;
|
|
Packit Service |
4684c1 |
ecc->pippenger_c = 0;
|
|
Packit Service |
4684c1 |
ecc->table = NULL;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = NULL;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_curve_init (struct ecc_curve *ecc, const char *curve)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (!strcmp (curve, "secp192r1"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
/* p = 2^{192} - 2^{64} - 1 */
|
|
Packit Service |
4684c1 |
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE"
|
|
Packit Service |
4684c1 |
"FFFFFFFFFFFFFFFF",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"64210519e59c80e70fa7e9ab72243049"
|
|
Packit Service |
4684c1 |
"feb8deecc146b9b1",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffff99def836"
|
|
Packit Service |
4684c1 |
"146bc9b1b4d22831",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"188da80eb03090f67cbf20eb43a18800"
|
|
Packit Service |
4684c1 |
"f4ff0afd82ff1012",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"07192b95ffc8da78631011ed6b24cdd5"
|
|
Packit Service |
4684c1 |
"73f977a11e794811");
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"dafebf5828783f2ad35534631588a3f629a70fb16982a888",
|
|
Packit Service |
4684c1 |
"dd6bda0d993da0fa46b27bbc141b868f59331afa5c7e93ab");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"76e32a2557599e6edcd283201fb2b9aadfd0d359cbb263da",
|
|
Packit Service |
4684c1 |
"782c37e372ba4520aa62e0fed121d49ef3b543660cfd05fd");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"35433907297cc378b0015703374729d7a4fe46647084e4ba",
|
|
Packit Service |
4684c1 |
"a2649984f2135c301ea3acb0776cd4f125389b311db3be32");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "secp224r1"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
/* p = 2^{224} - 2^{96} + 1 */
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"000000000000000000000001",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"b4050a850c04b3abf54132565044b0b7"
|
|
Packit Service |
4684c1 |
"d7bfd8ba270b39432355ffb4",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffff16a2"
|
|
Packit Service |
4684c1 |
"e0b8f03e13dd29455c5c2a3d",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"b70e0cbd6bb4bf7f321390b94a03c1d3"
|
|
Packit Service |
4684c1 |
"56c21122343280d6115c1d21",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"bd376388b5f723fb4c22dfe6cd4375a0"
|
|
Packit Service |
4684c1 |
"5a07476444d5819985007e34");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"706a46dc76dcb76798e60e6d89474788d16dc18032d268fd1a704fa6",
|
|
Packit Service |
4684c1 |
"1c2b76a7bc25e7702a704fa986892849fca629487acf3709d2e4e8bb");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"df1b1d66a551d0d31eff822558b9d2cc75c2180279fe0d08fd896d04",
|
|
Packit Service |
4684c1 |
"a3f7f03cadd0be444c0aa56830130ddf77d317344e1af3591981a925");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"ae99feebb5d26945b54892092a8aee02912930fa41cd114e40447301",
|
|
Packit Service |
4684c1 |
"482580a0ec5bc47e88bc8c378632cd196cb3fa058a7114eb03054c9");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "secp256r1"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
/* p = 2^{256} - 2^{224} + 2^{192} + 2^{96} - 1 */
|
|
Packit Service |
4684c1 |
"FFFFFFFF000000010000000000000000"
|
|
Packit Service |
4684c1 |
"00000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"5AC635D8AA3A93E7B3EBBD55769886BC"
|
|
Packit Service |
4684c1 |
"651D06B0CC53B0F63BCE3C3E27D2604B",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"FFFFFFFF00000000FFFFFFFFFFFFFFFF"
|
|
Packit Service |
4684c1 |
"BCE6FAADA7179E84F3B9CAC2FC632551",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"6B17D1F2E12C4247F8BCE6E563A440F2"
|
|
Packit Service |
4684c1 |
"77037D812DEB33A0F4A13945D898C296",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E16"
|
|
Packit Service |
4684c1 |
"2BCE33576B315ECECBB6406837BF51F5");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978",
|
|
Packit Service |
4684c1 |
"7775510db8ed040293d9ac69f7430dbba7dade63ce982299e04b79d227873d1");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c",
|
|
Packit Service |
4684c1 |
"8734640c4998ff7e374b06ce1a64a2ecd82ab036384fb83d9a79b127a27d5032");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852",
|
|
Packit Service |
4684c1 |
"e0f1575a4c633cc719dfee5fda862d764efc96c3f30ee0055c42c23f184ed8c6");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "secp384r1"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
/* p = 2^{384} - 2^{128} - 2^{96} + 2^{32} - 1 */
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffffe"
|
|
Packit Service |
4684c1 |
"ffffffff0000000000000000ffffffff",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"b3312fa7e23ee7e4988e056be3f82d19"
|
|
Packit Service |
4684c1 |
"181d9c6efe8141120314088f5013875a"
|
|
Packit Service |
4684c1 |
"c656398d8a2ed19d2a85c8edd3ec2aef",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffc7634d81f4372ddf"
|
|
Packit Service |
4684c1 |
"581a0db248b0a77aecec196accc52973",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"aa87ca22be8b05378eb1c71ef320ad74"
|
|
Packit Service |
4684c1 |
"6e1d3b628ba79b9859f741e082542a38"
|
|
Packit Service |
4684c1 |
"5502f25dbf55296c3a545e3872760ab7",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"3617de4a96262c6f5d9e98bf9292dc29"
|
|
Packit Service |
4684c1 |
"f8f41dbd289a147ce9da3113b5f0b8c0"
|
|
Packit Service |
4684c1 |
"0a60b1ce1d7e819d7a431d7c90ea0e5f");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"8d999057ba3d2d969260045c55b97f089025959a6f434d651d207d19fb96e9e4fe0e86ebe0e64f85b96a9c75295df61",
|
|
Packit Service |
4684c1 |
"8e80f1fa5b1b3cedb7bfe8dffd6dba74b275d875bc6cc43e904e505f256ab4255ffd43e94d39e22d61501e700a940e80");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"77a41d4606ffa1464793c7e5fdc7d98cb9d3910202dcd06bea4f240d3566da6b408bbae5026580d02d7e5c70500c831",
|
|
Packit Service |
4684c1 |
"c995f7ca0b0c42837d0bbe9602a9fc998520b41c85115aa5f7684c0edc111eacc24abd6be4b5d298b65f28600a2f1df1");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"138251cd52ac9298c1c8aad977321deb97e709bd0b4ca0aca55dc8ad51dcfc9d1589a1597e3a5120e1efd631c63e1835",
|
|
Packit Service |
4684c1 |
"cacae29869a62e1631e8a28181ab56616dc45d918abc09f3ab0e63cf792aa4dced7387be37bba569549f1c02b270ed67");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "secp521r1"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
"1ff" /* p = 2^{521} - 1 */
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"051"
|
|
Packit Service |
4684c1 |
"953eb9618e1c9a1f929a21a0b68540ee"
|
|
Packit Service |
4684c1 |
"a2da725b99b315f3b8b489918ef109e1"
|
|
Packit Service |
4684c1 |
"56193951ec7e937b1652c0bd3bb1bf07"
|
|
Packit Service |
4684c1 |
"3573df883d2c34f1ef451fd46b503f00",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"1ff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffffa"
|
|
Packit Service |
4684c1 |
"51868783bf2f966b7fcc0148f709a5d0"
|
|
Packit Service |
4684c1 |
"3bb5c9b8899c47aebb6fb71e91386409",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"c6"
|
|
Packit Service |
4684c1 |
"858e06b70404e9cd9e3ecb662395b442"
|
|
Packit Service |
4684c1 |
"9c648139053fb521f828af606b4d3dba"
|
|
Packit Service |
4684c1 |
"a14b5e77efe75928fe1dc127a2ffa8de"
|
|
Packit Service |
4684c1 |
"3348b3c1856a429bf97e7e31c2e5bd66",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"118"
|
|
Packit Service |
4684c1 |
"39296a789a3bc0045c8a5fb42c7d1bd9"
|
|
Packit Service |
4684c1 |
"98f54449579b446817afbd17273e662c"
|
|
Packit Service |
4684c1 |
"97ee72995ef42640c550b9013fad0761"
|
|
Packit Service |
4684c1 |
"353c7086a272c24088be94769fd16650");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"433c219024277e7e682fcb288148c282747403279b1ccc06352c6e5505d769be97b3b204da6ef55507aa104a3a35c5af41cf2fa364d60fd967f43e3933ba6d783d",
|
|
Packit Service |
4684c1 |
"f4bb8cc7f86db26700a7f3eceeeed3f0b5c6b5107c4da97740ab21a29906c42dbbb3e377de9f251f6b93937fa99a3248f4eafcbe95edc0f4f71be356d661f41b02");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"1a73d352443de29195dd91d6a64b5959479b52a6e5b123d9ab9e5ad7a112d7a8dd1ad3f164a3a4832051da6bd16b59fe21baeb490862c32ea05a5919d2ede37ad7d",
|
|
Packit Service |
4684c1 |
"13e9b03b97dfa62ddd9979f86c6cab814f2f1557fa82a9d0317d2f8ab1fa355ceec2e2dd4cf8dc575b02d5aced1dec3c70cf105c9bc93a590425f588ca1ee86c0e5");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"35b5df64ae2ac204c354b483487c9070cdc61c891c5ff39afc06c5d55541d3ceac8659e24afe3d0750e8b88e9f078af066a1d5025b08e5a5e2fbc87412871902f3",
|
|
Packit Service |
4684c1 |
"82096f84261279d2b673e0178eb0b4abb65521aef6e6e32e1b5ae63fe2f19907f279f283e54ba385405224f750a95b85eebb7faef04699d1d9e21f47fc346e4d0d");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "curve25519"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* curve25519, y^2 = x^3 + 486662 x^2 + x (mod p), with p = 2^{255} - 19.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
According to http://cr.yp.to/papers.html#newelliptic, this
|
|
Packit Service |
4684c1 |
is birationally equivalent to the Edwards curve
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
x^2 + y^2 = 1 + (121665/121666) x^2 y^2 (mod p).
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
-x^2 + y^2 = 1 - (121665/121666) x^2 y^2, with p = 2^{255} - 19.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
The generator is
|
|
Packit Service |
4684c1 |
x = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a
|
|
Packit Service |
4684c1 |
y = 0x6666666666666666666666666666666666666666666666666666666666666658
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Also birationally equivalent to the curve25519 Montgomery curve,
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
y^2 = x^3 + 486662 x^2 + x (mod p)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_TWISTED_EDWARDS,
|
|
Packit Service |
4684c1 |
"7fffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffed",
|
|
Packit Service |
4684c1 |
/* (121665/121666) mod p, from PARI/GP
|
|
Packit Service |
4684c1 |
c = Mod(121665, p); c / (c+1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
"2dfc9311d490018c7338bf8688861767"
|
|
Packit Service |
4684c1 |
"ff8ff5b2bebe27548a14b235eca6874a",
|
|
Packit Service |
4684c1 |
/* Order of the subgroup is 2^252 + q_0, where
|
|
Packit Service |
4684c1 |
q_0 = 27742317777372353535851937790883648493,
|
|
Packit Service |
4684c1 |
125 bits.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
"10000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"14def9dea2f79cd65812631a5cf5d3ed",
|
|
Packit Service |
4684c1 |
/* Generator */
|
|
Packit Service |
4684c1 |
"216936d3cd6e53fec0a4e231fdd6dc5c"
|
|
Packit Service |
4684c1 |
"692cc7609525a7b2c9562d608f25d51a",
|
|
Packit Service |
4684c1 |
"66666666666666666666666666666666"
|
|
Packit Service |
4684c1 |
"66666666666666666666666666666658");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"36ab384c9f5a046c3d043b7d1833e7ac"
|
|
Packit Service |
4684c1 |
"080d8e4515d7a45f83c5a14e2843ce0e",
|
|
Packit Service |
4684c1 |
"2260cdf3092329c21da25ee8c9a21f56"
|
|
Packit Service |
4684c1 |
"97390f51643851560e5f46ae6af8a3c9");
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"67ae9c4a22928f491ff4ae743edac83a"
|
|
Packit Service |
4684c1 |
"6343981981624886ac62485fd3f8e25c",
|
|
Packit Service |
4684c1 |
"1267b1d177ee69aba126a18e60269ef7"
|
|
Packit Service |
4684c1 |
"9f16ec176724030402c3684878f5b4d4");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"203da8db56cff1468325d4b87a3520f9"
|
|
Packit Service |
4684c1 |
"1a739ec193ce1547493aa657c4c9f870",
|
|
Packit Service |
4684c1 |
"47d0e827cb1595e1470eb88580d5716c"
|
|
Packit Service |
4684c1 |
"4cf22832ea2f0ff0df38ab61ca32112f");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "gost_gc256b"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffd97",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"000000000000000000000000000000a6",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"6c611070995ad10045841b09b761b893",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000001",
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
"8d91e471e0989cda27df505a453f2b76"
|
|
Packit Service |
4684c1 |
"35294f2ddf23e3b122acc99c9e9f1e14");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd95",
|
|
Packit Service |
4684c1 |
"726e1b8e1f676325d820afa5bac0d489cad6b0d220dc1c4edd5336636160df83");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"8e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38e38d2c",
|
|
Packit Service |
4684c1 |
"76bcd1ca9a23b041d4d9baf507a6cd821267a94c838768e8486117796b788a51");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"f7063e7063e7063e7063e7063e7063e7063e7063e7063e7063e7063e7063e4b7",
|
|
Packit Service |
4684c1 |
"83ccf17ba6706d73625cc3534c7a2b9d6ec1ee6a9a7e07c10d84b388de59f741");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "gost_gc512a"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_WEIERSTRASS,
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffdc7",
|
|
Packit Service |
4684c1 |
"e8c2505dedfc86ddc1bd0b2b6667f1da"
|
|
Packit Service |
4684c1 |
"34b82574761cb0e879bd081cfd0b6265"
|
|
Packit Service |
4684c1 |
"ee3cb090f30d27614cb4574010da90dd"
|
|
Packit Service |
4684c1 |
"862ef9d4ebee4761503190785a71c760",
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"27e69532f48d89116ff22b8d4e056060"
|
|
Packit Service |
4684c1 |
"9b4b38abfad2b85dcacdb1411f10b275",
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000000"
|
|
Packit Service |
4684c1 |
"00000000000000000000000000000003",
|
|
Packit Service |
4684c1 |
"7503cfe87a836ae3a61b8816e25450e6"
|
|
Packit Service |
4684c1 |
"ce5e1c93acf1abc1778064fdcbefa921"
|
|
Packit Service |
4684c1 |
"df1626be4fd036e93d75e6a50e3a41e9"
|
|
Packit Service |
4684c1 |
"8028fe5fc235f5b889a589cb5215f2a4");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"3b89dcfc622996ab97a5869dbff15cf51db00954f43a58a5e5f6b0470a132b2f4434bbcd405d2a9516151d2a6a04f2e4375bf48de1fdb21fb982afd9d2ea137c",
|
|
Packit Service |
4684c1 |
"c813c4e2e2e0a8a391774c7903da7a6f14686e98e183e670ee6fb784809a3e92ca209dc631d85b1c7534ed3b37fddf64d854d7e01f91f18bb3fd307591afc051");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"a1ff1ab2712a267eb53935ddb5a567f84db156cc096168a1174291d5f488fba543d2840b4d2dd35d764b2f57b308907aec55cfba10544e8416e134687ccb87c3",
|
|
Packit Service |
4684c1 |
"3cb5c4417ec4637f30374f189bb5b984c41e3a48d7f84fbfa3819e3f333f7eb311d3af7e67c4c16eeacfac2fe94c6dd4c6366f711a4fb6c7125cd7ec518d90d6");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"b7bfb80956c8670031ba191929f64e301d681634236d47a60e571a4bedc0ef257452ef78b5b98dbb3d9f3129d9349433ce2a3a35cb519c91e2d633d7b373ae16",
|
|
Packit Service |
4684c1 |
"3bee95e29eecc5d5ad2beba941abcbf9f1cad478df0fecf614f63aeebef77850da7efdb93de8f3df80bc25eac09239c14175f5c29704ce9a3e383f1b3ec0e929");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else if (!strcmp (curve, "curve448"))
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* curve448, y^2 = x^3 + 156326 x^2 + x (mod p), with p = 2^{448} - 2^{224} - 1.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
According to RFC 7748, this is 4-isogenious to the Edwards
|
|
Packit Service |
4684c1 |
curve called "edwards448"
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
x^2 + y^2 = 1 - 39081 x^2 y^2 (mod p).
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
And since the constant is not a square, the Edwards formulas
|
|
Packit Service |
4684c1 |
should be "complete", with no special cases needed for
|
|
Packit Service |
4684c1 |
doubling, neutral element, negatives, etc.
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
Generator is x = 5, with y coordinate
|
|
Packit Service |
4684c1 |
355293926785568175264127502063783334808976399387714271831880898435169088786967410002932673765864550910142774147268105838985595290606362,
|
|
Packit Service |
4684c1 |
according to
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
x = Mod(5, 2^448-2^224-1); sqrt(x^3 + 156326*x^2 + x)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
in PARI/GP. Also, in PARI notation,
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
curve448 = Mod([0, 156326, 0, 1, 0], 2^448-2^224-1)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
ecc_curve_init_str (ecc, ECC_TYPE_EDWARDS,
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffeffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffff",
|
|
Packit Service |
4684c1 |
/* -39081 mod p, from PARI/GP
|
|
Packit Service |
4684c1 |
c = Mod(-39081, p)
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"ffffffffffffffffffffffffeffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffff6756",
|
|
Packit Service |
4684c1 |
/* Order of the subgroup is 2^446 - q_0, where
|
|
Packit Service |
4684c1 |
q_0 = 13818066809895115352007386748515426880336692474882178609894547503885,
|
|
Packit Service |
4684c1 |
224 bits.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
"3ffffffffffffffffffffffffffffff"
|
|
Packit Service |
4684c1 |
"fffffffffffffffffffffffff7cca23"
|
|
Packit Service |
4684c1 |
"e9c44edb49aed63690216cc2728dc58"
|
|
Packit Service |
4684c1 |
"f552378c292ab5844f3",
|
|
Packit Service |
4684c1 |
"4f1970c66bed0ded221d15a622bf36d"
|
|
Packit Service |
4684c1 |
"a9e146570470f1767ea6de324a3d3a4"
|
|
Packit Service |
4684c1 |
"6412ae1af72ab66511433b80e18b009"
|
|
Packit Service |
4684c1 |
"38e2626a82bc70cc05e",
|
|
Packit Service |
4684c1 |
"693f46716eb6bc248876203756c9c76"
|
|
Packit Service |
4684c1 |
"24bea73736ca3984087789c1e05a0c2"
|
|
Packit Service |
4684c1 |
"d73ad3ff1ce67c39c4fdbd132c4ed7c"
|
|
Packit Service |
4684c1 |
"8ad9808795bf230fa14");
|
|
Packit Service |
4684c1 |
ecc->ref = ecc_alloc (3);
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[0], /* 2 g */
|
|
Packit Service |
4684c1 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
Packit Service |
4684c1 |
"aaaaaaaaaaaaaaaaaaaaaaa955555555"
|
|
Packit Service |
4684c1 |
"55555555555555555555555555555555"
|
|
Packit Service |
4684c1 |
"5555555555555555",
|
|
Packit Service |
4684c1 |
"ae05e9634ad7048db359d6205086c2b0"
|
|
Packit Service |
4684c1 |
"036ed7a035884dd7b7e36d728ad8c4b8"
|
|
Packit Service |
4684c1 |
"0d6565833a2a3098bbbcb2bed1cda06b"
|
|
Packit Service |
4684c1 |
"daeafbcdea9386ed");
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[1], /* 3 g */
|
|
Packit Service |
4684c1 |
"865886b9108af6455bd64316cb694333"
|
|
Packit Service |
4684c1 |
"2241b8b8cda82c7e2ba077a4a3fcfe8d"
|
|
Packit Service |
4684c1 |
"aa9cbf7f6271fd6e862b769465da8575"
|
|
Packit Service |
4684c1 |
"728173286ff2f8f",
|
|
Packit Service |
4684c1 |
"e005a8dbd5125cf706cbda7ad43aa644"
|
|
Packit Service |
4684c1 |
"9a4a8d952356c3b9fce43c82ec4e1d58"
|
|
Packit Service |
4684c1 |
"bb3a331bdb6767f0bffa9a68fed02daf"
|
|
Packit Service |
4684c1 |
"b822ac13588ed6fc");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_set_str (&ecc->ref[2], /* 4 g */
|
|
Packit Service |
4684c1 |
"49dcbc5c6c0cce2c1419a17226f929ea"
|
|
Packit Service |
4684c1 |
"255a09cf4e0891c693fda4be70c74cc3"
|
|
Packit Service |
4684c1 |
"01b7bdf1515dd8ba21aee1798949e120"
|
|
Packit Service |
4684c1 |
"e2ce42ac48ba7f30",
|
|
Packit Service |
4684c1 |
"d49077e4accde527164b33a5de021b97"
|
|
Packit Service |
4684c1 |
"9cb7c02f0457d845c90dc3227b8a5bc1"
|
|
Packit Service |
4684c1 |
"c0d8f97ea1ca9472b5d444285d0d4f5b"
|
|
Packit Service |
4684c1 |
"32e236f86de51839");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "No known curve with name %s\n", curve);
|
|
Packit Service |
4684c1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
ecc->bit_size = mpz_sizeinbase (ecc->p, 2);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_curve_clear (struct ecc_curve *ecc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_clear (ecc->p);
|
|
Packit Service |
4684c1 |
mpz_clear (ecc->b);
|
|
Packit Service |
4684c1 |
mpz_clear (ecc->q);
|
|
Packit Service |
4684c1 |
ecc_clear (&ecc->g);
|
|
Packit Service |
4684c1 |
if (ecc->table)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t i;
|
|
Packit Service |
4684c1 |
for (i = 0; i < ecc->table_size; i++)
|
|
Packit Service |
4684c1 |
ecc_clear (&ecc->table[i]);
|
|
Packit Service |
4684c1 |
free (ecc->table);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (ecc->ref)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
size_t i;
|
|
Packit Service |
4684c1 |
for (i = 0; i < 3; i++)
|
|
Packit Service |
4684c1 |
ecc_clear (&ecc->ref[i]);
|
|
Packit Service |
4684c1 |
free (ecc->ref);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static unsigned
|
|
Packit Service |
4684c1 |
ecc_table_size(unsigned bits, unsigned k, unsigned c)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned p = (bits + k-1) / k;
|
|
Packit Service |
4684c1 |
unsigned M = (p + c-1)/c;
|
|
Packit Service |
4684c1 |
return M;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_pippenger_precompute (struct ecc_curve *ecc, unsigned k, unsigned c)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned M = ecc_table_size (ecc->bit_size, k, c);
|
|
Packit Service |
4684c1 |
unsigned i, j;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (M < 2)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "Invalid parameters, implies M = %u\n", M);
|
|
Packit Service |
4684c1 |
exit (EXIT_FAILURE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (M == ecc_table_size (ecc->bit_size, k-1, c))
|
|
Packit Service |
4684c1 |
fprintf(stderr,
|
|
Packit Service |
4684c1 |
"warn: Parameters k = %u, c = %d are suboptimal, could use smaller k\n",
|
|
Packit Service |
4684c1 |
k, c);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc->pippenger_k = k;
|
|
Packit Service |
4684c1 |
ecc->pippenger_c = c;
|
|
Packit Service |
4684c1 |
ecc->table_size = M << c;
|
|
Packit Service |
4684c1 |
assert (ecc->table_size >= 2);
|
|
Packit Service |
4684c1 |
ecc->table = ecc_alloc (ecc->table_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Compute the first 2^c entries */
|
|
Packit Service |
4684c1 |
ecc_set_zero (ecc, &ecc->table[0]);
|
|
Packit Service |
4684c1 |
ecc_set (&ecc->table[1], &ecc->g);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (j = 2; j < (1U<
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* T[j] = 2^k T[j/2] */
|
|
Packit Service |
4684c1 |
assert (j < ecc->table_size);
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &ecc->table[j], &ecc->table[j/2]);
|
|
Packit Service |
4684c1 |
for (i = 1; i < k; i++)
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &ecc->table[j], &ecc->table[j]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 1; i < j; i++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
assert (j + i < ecc->table_size);
|
|
Packit Service |
4684c1 |
ecc_add (ecc, &ecc->table[j + i], &ecc->table[j], &ecc->table[i]);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
for (j = 1<<c; j < ecc->table_size; j++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* T[j] = 2^{kc} T[j-2^c] */
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &ecc->table[j], &ecc->table[j - (1<
|
|
Packit Service |
4684c1 |
for (i = 1; i < k*c; i++)
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &ecc->table[j], &ecc->table[j]);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_mul_pippenger (const struct ecc_curve *ecc,
|
|
Packit Service |
4684c1 |
struct ecc_point *r, const mpz_t n_input)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t n;
|
|
Packit Service |
4684c1 |
unsigned k, c;
|
|
Packit Service |
4684c1 |
unsigned i, j;
|
|
Packit Service |
4684c1 |
unsigned bit_rows;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (n);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_mod (n, n_input, ecc->q);
|
|
Packit Service |
4684c1 |
ecc_set_zero (ecc, r);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
k = ecc->pippenger_k;
|
|
Packit Service |
4684c1 |
c = ecc->pippenger_c;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bit_rows = (ecc->bit_size + k - 1) / k;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = k; i-- > 0; )
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, r, r);
|
|
Packit Service |
4684c1 |
for (j = 0; j * c < bit_rows; j++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned bits;
|
|
Packit Service |
4684c1 |
mp_size_t bit_index;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Extract c bits of the exponent, stride k, starting at i + kcj, ending at
|
|
Packit Service |
4684c1 |
i + k (cj + c - 1)*/
|
|
Packit Service |
4684c1 |
for (bits = 0, bit_index = i + k*(c*j+c); bit_index > i + k*c*j; )
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
bit_index -= k;
|
|
Packit Service |
4684c1 |
bits = (bits << 1) | mpz_tstbit (n, bit_index);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_add (ecc, r, r, &ecc->table[(j << c) | bits]);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
mpz_clear (n);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_point_out (FILE *f, const struct ecc_point *p)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if (p->is_zero)
|
|
Packit Service |
4684c1 |
fprintf (f, "zero");
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (f, "(");
|
|
Packit Service |
4684c1 |
mpz_out_str (f, 16, p->x);
|
|
Packit Service |
4684c1 |
fprintf (f, ",\n ");
|
|
Packit Service |
4684c1 |
mpz_out_str (f, 16, (p)->y);
|
|
Packit Service |
4684c1 |
fprintf (f, ")");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
#define ASSERT_EQUAL(p, q) do { \
|
|
Packit Service |
4684c1 |
if (!ecc_equal_p (p, q)) \
|
|
Packit Service |
4684c1 |
{ \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "%s:%d: ASSERT_EQUAL (%s, %s) failed.\n", \
|
|
Packit Service |
4684c1 |
__FILE__, __LINE__, #p, #q); \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "p = "); \
|
|
Packit Service |
4684c1 |
ecc_point_out (stderr, (p)); \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\nq = "); \
|
|
Packit Service |
4684c1 |
ecc_point_out (stderr, (q)); \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n"); \
|
|
Packit Service |
4684c1 |
abort(); \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
} while (0)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
#define ASSERT_ZERO(p) do { \
|
|
Packit Service |
4684c1 |
if (!ecc_zero_p (p)) \
|
|
Packit Service |
4684c1 |
{ \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "%s:%d: ASSERT_ZERO (%s) failed.\n", \
|
|
Packit Service |
4684c1 |
__FILE__, __LINE__, #p); \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "p = "); \
|
|
Packit Service |
4684c1 |
ecc_point_out (stderr, (p)); \
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n"); \
|
|
Packit Service |
4684c1 |
abort(); \
|
|
Packit Service |
4684c1 |
} \
|
|
Packit Service |
4684c1 |
} while (0)
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
ecc_curve_check (const struct ecc_curve *ecc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
struct ecc_point p, q;
|
|
Packit Service |
4684c1 |
mpz_t n;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_init (&p);
|
|
Packit Service |
4684c1 |
ecc_init (&q);
|
|
Packit Service |
4684c1 |
mpz_init (n);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &p, &ecc->g);
|
|
Packit Service |
4684c1 |
if (ecc->ref)
|
|
Packit Service |
4684c1 |
ASSERT_EQUAL (&p, &ecc->ref[0]);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "g2 = ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, p.x);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, p.y);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
ecc_add (ecc, &q, &p, &ecc->g);
|
|
Packit Service |
4684c1 |
if (ecc->ref)
|
|
Packit Service |
4684c1 |
ASSERT_EQUAL (&q, &ecc->ref[1]);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "g3 = ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.x);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.y);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_add (ecc, &q, &q, &ecc->g);
|
|
Packit Service |
4684c1 |
if (ecc->ref)
|
|
Packit Service |
4684c1 |
ASSERT_EQUAL (&q, &ecc->ref[2]);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "g4 = ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.x);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.y);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_dup (ecc, &q, &p);
|
|
Packit Service |
4684c1 |
if (ecc->ref)
|
|
Packit Service |
4684c1 |
ASSERT_EQUAL (&q, &ecc->ref[2]);
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "g4 = ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.x);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n ");
|
|
Packit Service |
4684c1 |
mpz_out_str (stderr, 16, q.y);
|
|
Packit Service |
4684c1 |
fprintf (stderr, "\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_mul_binary (ecc, &p, ecc->q, &ecc->g);
|
|
Packit Service |
4684c1 |
ASSERT_ZERO (&p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_mul_pippenger (ecc, &q, ecc->q);
|
|
Packit Service |
4684c1 |
ASSERT_ZERO (&q);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_clear (&p);
|
|
Packit Service |
4684c1 |
ecc_clear (&q);
|
|
Packit Service |
4684c1 |
mpz_clear (n);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
output_digits (const mpz_t x,
|
|
Packit Service |
4684c1 |
unsigned size, unsigned bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t t;
|
|
Packit Service |
4684c1 |
mpz_t mask;
|
|
Packit Service |
4684c1 |
mpz_t limb;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
const char *suffix;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
mpz_init (mask);
|
|
Packit Service |
4684c1 |
mpz_init (limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_setbit (mask, bits_per_limb);
|
|
Packit Service |
4684c1 |
mpz_sub_ui (mask, mask, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
suffix = bits_per_limb > 32 ? "ULL" : "UL";
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init_set (t, x);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 0; i < size; i++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
if ( (i % 8) == 0)
|
|
Packit Service |
4684c1 |
printf("\n ");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_and (limb, mask, t);
|
|
Packit Service |
4684c1 |
printf (" 0x");
|
|
Packit Service |
4684c1 |
mpz_out_str (stdout, 16, limb);
|
|
Packit Service |
4684c1 |
printf ("%s,", suffix);
|
|
Packit Service |
4684c1 |
mpz_tdiv_q_2exp (t, t, bits_per_limb);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
mpz_clear (mask);
|
|
Packit Service |
4684c1 |
mpz_clear (limb);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
output_bignum (const char *name, const mpz_t x,
|
|
Packit Service |
4684c1 |
unsigned size, unsigned bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
printf ("static const mp_limb_t %s[%d] = {", name, size);
|
|
Packit Service |
4684c1 |
output_digits (x, size, bits_per_limb);
|
|
Packit Service |
4684c1 |
printf("\n};\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
output_point (const struct ecc_curve *ecc,
|
|
Packit Service |
4684c1 |
const struct ecc_point *p, int use_redc,
|
|
Packit Service |
4684c1 |
unsigned size, unsigned bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t x, y, t;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (x);
|
|
Packit Service |
4684c1 |
mpz_init (y);
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_set (x, p->x);
|
|
Packit Service |
4684c1 |
mpz_set (y, p->y);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (use_redc)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_mul_2exp (x, x, size * bits_per_limb);
|
|
Packit Service |
4684c1 |
mpz_mod (x, x, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul_2exp (y, y, size * bits_per_limb);
|
|
Packit Service |
4684c1 |
mpz_mod (y, y, ecc->p);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
output_digits (x, size, bits_per_limb);
|
|
Packit Service |
4684c1 |
output_digits (y, size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (x);
|
|
Packit Service |
4684c1 |
mpz_clear (y);
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static unsigned
|
|
Packit Service |
4684c1 |
output_modulo (const char *name, const mpz_t x,
|
|
Packit Service |
4684c1 |
unsigned size, unsigned bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_t mod;
|
|
Packit Service |
4684c1 |
unsigned bits;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (mod);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_setbit (mod, bits_per_limb * size);
|
|
Packit Service |
4684c1 |
mpz_mod (mod, mod, x);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bits = mpz_sizeinbase (mod, 2);
|
|
Packit Service |
4684c1 |
output_bignum (name, mod, size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (mod);
|
|
Packit Service |
4684c1 |
return bits;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
static void
|
|
Packit Service |
4684c1 |
output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
unsigned limb_size = (ecc->bit_size + bits_per_limb - 1)/bits_per_limb;
|
|
Packit Service |
4684c1 |
unsigned i;
|
|
Packit Service |
4684c1 |
unsigned bits, e;
|
|
Packit Service |
4684c1 |
int redc_limbs;
|
|
Packit Service |
4684c1 |
mpz_t t;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (t);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("/* For NULL. */\n#include <stddef.h>\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("#define ECC_LIMB_SIZE %u\n", limb_size);
|
|
Packit Service |
4684c1 |
printf ("#define ECC_PIPPENGER_K %u\n", ecc->pippenger_k);
|
|
Packit Service |
4684c1 |
printf ("#define ECC_PIPPENGER_C %u\n", ecc->pippenger_c);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_p", ecc->p, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_b", ecc->b, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_q", ecc->q, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
bits = output_modulo ("ecc_Bmodp", ecc->p, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
printf ("#define ECC_BMODP_SIZE %u\n",
|
|
Packit Service |
4684c1 |
(bits + bits_per_limb - 1) / bits_per_limb);
|
|
Packit Service |
4684c1 |
bits = output_modulo ("ecc_Bmodq", ecc->q, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
printf ("#define ECC_BMODQ_SIZE %u\n",
|
|
Packit Service |
4684c1 |
(bits + bits_per_limb - 1) / bits_per_limb);
|
|
Packit Service |
4684c1 |
bits = mpz_sizeinbase (ecc->q, 2);
|
|
Packit Service |
4684c1 |
if (bits < ecc->bit_size)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* for curve25519, with q = 2^k + q', with a much smaller q' */
|
|
Packit Service |
4684c1 |
unsigned mbits;
|
|
Packit Service |
4684c1 |
unsigned shift;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Shift to align the one bit at B */
|
|
Packit Service |
4684c1 |
shift = bits_per_limb * limb_size + 1 - bits;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_set (t, ecc->q);
|
|
Packit Service |
4684c1 |
mpz_clrbit (t, bits-1);
|
|
Packit Service |
4684c1 |
mbits = mpz_sizeinbase (t, 2);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* The shifted value must be a limb smaller than q. */
|
|
Packit Service |
4684c1 |
if (mbits + shift + bits_per_limb <= bits)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* q of the form 2^k + q', with q' a limb smaller */
|
|
Packit Service |
4684c1 |
mpz_mul_2exp (t, t, shift);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_mBmodq_shifted", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (ecc->bit_size < limb_size * bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
int shift;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_set_ui (t, 0);
|
|
Packit Service |
4684c1 |
mpz_setbit (t, ecc->bit_size);
|
|
Packit Service |
4684c1 |
mpz_sub (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_Bmodp_shifted", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
shift = limb_size * bits_per_limb - ecc->bit_size;
|
|
Packit Service |
4684c1 |
if (shift > 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Check condition for reducing hi limbs. If s is the
|
|
Packit Service |
4684c1 |
normalization shift and n is the bit size (so that s + n
|
|
Packit Service |
4684c1 |
= limb_size * bite_per_limb), then we need
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
(2^n - 1) + (2^s - 1) (2^n - p) < 2p
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
or equivalently,
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
2^s (2^n - p) <= p
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
To a allow a carry limb to be added in at the same time,
|
|
Packit Service |
4684c1 |
substitute s+1 for s.
|
|
Packit Service |
4684c1 |
*/
|
|
Packit Service |
4684c1 |
/* FIXME: For ecdsa verify, we actually need the stricter
|
|
Packit Service |
4684c1 |
inequality < 2 q. */
|
|
Packit Service |
4684c1 |
mpz_mul_2exp (t, t, shift + 1);
|
|
Packit Service |
4684c1 |
if (mpz_cmp (t, ecc->p) > 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "Reduction condition failed for %u-bit curve.\n",
|
|
Packit Service |
4684c1 |
ecc->bit_size);
|
|
Packit Service |
4684c1 |
exit (EXIT_FAILURE);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
printf ("#define ecc_Bmodp_shifted ecc_Bmodp\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (bits < limb_size * bits_per_limb)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_set_ui (t, 0);
|
|
Packit Service |
4684c1 |
mpz_setbit (t, bits);
|
|
Packit Service |
4684c1 |
mpz_sub (t, t, ecc->q);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_Bmodq_shifted", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
printf ("#define ecc_Bmodq_shifted ecc_Bmodq\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_add_ui (t, ecc->p, 1);
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (t, t, 1);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_pp1h", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_add_ui (t, ecc->q, 1);
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (t, t, 1);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_qp1h", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Trailing zeros in p+1 correspond to trailing ones in p. */
|
|
Packit Service |
4684c1 |
redc_limbs = mpz_scan0 (ecc->p, 0) / bits_per_limb;
|
|
Packit Service |
4684c1 |
if (redc_limbs > 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_add_ui (t, ecc->p, 1);
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (t, t, redc_limbs * bits_per_limb);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_redc_ppm1", t, limb_size - redc_limbs, bits_per_limb);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* Trailing zeros in p-1 correspond to zeros just above the low
|
|
Packit Service |
4684c1 |
bit of p */
|
|
Packit Service |
4684c1 |
redc_limbs = mpz_scan1 (ecc->p, 1) / bits_per_limb;
|
|
Packit Service |
4684c1 |
if (redc_limbs > 0)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
printf ("#define ecc_redc_ppm1 (ecc_p + %d)\n",
|
|
Packit Service |
4684c1 |
redc_limbs);
|
|
Packit Service |
4684c1 |
redc_limbs = -redc_limbs;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
printf ("#define ecc_redc_ppm1 NULL\n");
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
printf ("#define ECC_REDC_SIZE %d\n", redc_limbs);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* For mod p square root computation. */
|
|
Packit Service |
4684c1 |
if (mpz_fdiv_ui (ecc->p, 4) == 3)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* x = a^{(p+1)/4} gives square root of a (if it exists,
|
|
Packit Service |
4684c1 |
otherwise the square root of -a). */
|
|
Packit Service |
4684c1 |
e = 1;
|
|
Packit Service |
4684c1 |
mpz_add_ui (t, ecc->p, 1);
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (t, t, 2);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
else
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
/* p-1 = 2^e s, s odd, t = (s-1)/2*/
|
|
Packit Service |
4684c1 |
unsigned g, i;
|
|
Packit Service |
4684c1 |
mpz_t s;
|
|
Packit Service |
4684c1 |
mpz_t z;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_init (s);
|
|
Packit Service |
4684c1 |
mpz_init (z);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_sub_ui (s, ecc->p, 1);
|
|
Packit Service |
4684c1 |
e = mpz_scan1 (s, 0);
|
|
Packit Service |
4684c1 |
assert (e > 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (s, s, e);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
/* Find a non-square g, g^{(p-1)/2} = -1,
|
|
Packit Service |
4684c1 |
and z = g^{(p-1)/4 */
|
|
Packit Service |
4684c1 |
for (g = 2; ; g++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_set_ui (z, g);
|
|
Packit Service |
4684c1 |
mpz_powm (z, z, s, ecc->p);
|
|
Packit Service |
4684c1 |
mpz_mul (t, z, z);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
for (i = 2; i < e; i++)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
mpz_mul (t, t, t);
|
|
Packit Service |
4684c1 |
mpz_mod (t, t, ecc->p);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
if (mpz_cmp_ui (t, 1) != 0)
|
|
Packit Service |
4684c1 |
break;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
mpz_add_ui (t, t, 1);
|
|
Packit Service |
4684c1 |
assert (mpz_cmp (t, ecc->p) == 0);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_sqrt_z", z, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_fdiv_q_2exp (t, s, 1);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (s);
|
|
Packit Service |
4684c1 |
mpz_clear (z);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
printf ("#define ECC_SQRT_E %u\n", e);
|
|
Packit Service |
4684c1 |
printf ("#define ECC_SQRT_T_BITS %u\n",
|
|
Packit Service |
4684c1 |
(unsigned) mpz_sizeinbase (t, 2));
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_sqrt_t", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("#if USE_REDC\n");
|
|
Packit Service |
4684c1 |
printf ("#define ecc_unit ecc_Bmodp\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("static const mp_limb_t ecc_table[%lu] = {",
|
|
Packit Service |
4684c1 |
(unsigned long) (2*ecc->table_size * limb_size));
|
|
Packit Service |
4684c1 |
for (i = 0; i < ecc->table_size; i++)
|
|
Packit Service |
4684c1 |
output_point (ecc, &ecc->table[i], 1, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("\n};\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("#else\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_set_ui (t, 1);
|
|
Packit Service |
4684c1 |
output_bignum ("ecc_unit", t, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf ("static const mp_limb_t ecc_table[%lu] = {",
|
|
Packit Service |
4684c1 |
(unsigned long) (2*ecc->table_size * limb_size));
|
|
Packit Service |
4684c1 |
for (i = 0; i < ecc->table_size; i++)
|
|
Packit Service |
4684c1 |
output_point (ecc, &ecc->table[i], 0, limb_size, bits_per_limb);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
printf("\n};\n");
|
|
Packit Service |
4684c1 |
printf ("#endif\n");
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
mpz_clear (t);
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
int
|
|
Packit Service |
4684c1 |
main (int argc, char **argv)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
struct ecc_curve ecc;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (argc < 4)
|
|
Packit Service |
4684c1 |
{
|
|
Packit Service |
4684c1 |
fprintf (stderr, "Usage: %s CURVE K C [BITS-PER-LIMB]\n", argv[0]);
|
|
Packit Service |
4684c1 |
return EXIT_FAILURE;
|
|
Packit Service |
4684c1 |
}
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_curve_init (&ecc, argv[1]);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_pippenger_precompute (&ecc, atoi(argv[2]), atoi(argv[3]));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
fprintf (stderr, "Table size: %lu entries\n",
|
|
Packit Service |
4684c1 |
(unsigned long) ecc.table_size);
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_curve_check (&ecc;;
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
if (argc > 4)
|
|
Packit Service |
4684c1 |
output_curve (&ecc, atoi(argv[4]));
|
|
Packit Service |
4684c1 |
|
|
Packit Service |
4684c1 |
ecc_curve_clear (&ecc;;
|
|
Packit Service |
4684c1 |
return EXIT_SUCCESS;
|
|
Packit Service |
4684c1 |
}
|