Blame lib/nettle/ecc/eccdata.c

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
}