Blame lib/nettle/ecc/eccdata.c

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