示例#1
0
/* free single cache entry */
static void
_ecc_wmnaf_cache_entry_free (gnutls_ecc_curve_cache_entry_t * p)
{
  int i;

  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
    {
      ecc_del_point (p->pos[i]);
      ecc_del_point (p->neg[i]);
    }
}
示例#2
0
/* initialize single cache entry
 * for a curve with the given id */
static int
_ecc_wmnaf_cache_entry_init (gnutls_ecc_curve_cache_entry_t * p,
                             gnutls_ecc_curve_t id)
{
  int i, j, err;
  ecc_point *G;
  mpz_t a, modulus;

  const gnutls_ecc_curve_entry_st *st = NULL;

  if (p == NULL || id == 0)
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

  G = ecc_new_point ();
  if (G == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }

  st = _gnutls_ecc_curve_get_params (id);
  if (st == NULL)
    {
      err = GNUTLS_E_INTERNAL_ERROR;
      goto done;
    }

  if ((err = mp_init_multi (&a, &modulus, NULL) != 0))
    return err;

  /* set id */
  p->id = id;

  /* set modulus */
  mpz_set_str (modulus, st->prime, 16);

  /* get generator point */
  mpz_set_str (G->x, st->Gx, 16);
  mpz_set_str (G->y, st->Gy, 16);
  mpz_set_ui (G->z, 1);

  /* set A */
  mpz_set_str (a, st->A, 16);

  /* alloc ram for precomputed values */
  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
    {
      p->pos[i] = ecc_new_point ();
      p->neg[i] = ecc_new_point ();
      if (p->pos[i] == NULL || p->neg[i] == NULL)
        {
          for (j = 0; j < i; ++j)
            {
              ecc_del_point (p->pos[j]);
              ecc_del_point (p->neg[j]);
            }

          err = GNUTLS_E_MEMORY_ERROR;
          goto done;
        }
    }

  /* fill in pos and neg arrays with precomputed values
   * pos holds kG for k ==  1, 3, 5, ..., (2^w - 1)
   * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1)
   */

  /* pos[0] == 2G for a while, later it will be set to the expected 1G */
  if ((err = ecc_projective_dbl_point (G, p->pos[0], a, modulus)) != 0)
    goto done;

  /* pos[1] == 3G */
  if ((err =
       ecc_projective_add_point (p->pos[0], G, p->pos[1], a,
                                    modulus)) != 0)
    goto done;

  /* fill in kG for k = 5, 7, ..., (2^w - 1) */
  for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
    {
      if ((err =
           ecc_projective_add_point (p->pos[j - 1], p->pos[0], p->pos[j],
                                        a, modulus)) != 0)
        goto done;
    }

  /* set pos[0] == 1G as expected
   * after this step we don't need G at all */
  mpz_set (p->pos[0]->x, G->x);
  mpz_set (p->pos[0]->y, G->y);
  mpz_set (p->pos[0]->z, G->z);

  /* map to affine all elements in pos
   * this will allow to use ecc_projective_madd later
   * set neg[i] == -pos[i] */
  for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
    {
      if ((err = ecc_map (p->pos[j], modulus)) != 0)
        goto done;

      if ((err =
           ecc_projective_negate_point (p->pos[j], p->neg[j], modulus)) != 0)
        goto done;
    }

  err = 0;
done:
  ecc_del_point (G);
  mp_clear_multi (&a, &modulus, NULL);

  return err;
}
示例#3
0
/*
   Perform a point wMNAF-multiplication utilizing cache
   This version tries to be timing resistant
   @param k    The scalar to multiply by
   @param id   The curve's id
   @param R    [out] Destination for kG
   @param a        The curve's A value
   @param modulus  The modulus of the field the ECC curve is in
   @param map      Boolean whether to map back to affine or not (1 == map, 0 == leave in projective)
   @return     GNUTLS_E_SUCCESS on success
*/
int
ecc_mulmod_cached_timing (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R,
                                mpz_t a, mpz_t modulus, int map)
{
  int j, err;

  gnutls_ecc_curve_cache_entry_t *cache = NULL;
  signed char *wmnaf = NULL;
  size_t wmnaf_len;
  signed char digit;
  /* point for throttle */
  ecc_point *T;

  if (k == NULL || R == NULL || modulus == NULL || id == 0)
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

  /* prepare T point */
  T = ecc_new_point ();
  if (T == NULL)
    return GNUTLS_E_MEMORY_ERROR;

  /* calculate wMNAF */
  wmnaf = ecc_wMNAF (k, &wmnaf_len);
  if (!wmnaf)
    {
      err = GNUTLS_E_INTERNAL_ERROR;
      goto done;
    }

  /* set R to neutral */
  mpz_set_ui (R->x, 1);
  mpz_set_ui (R->y, 1);
  mpz_set_ui (R->z, 0);

  /* set T to neutral */
  mpz_set_ui (T->x, 1);
  mpz_set_ui (T->y, 1);
  mpz_set_ui (T->z, 0);

  /* do cache lookup */
  cache = ecc_wmnaf_cache + id - 1;

  /* perform ops */
  for (j = wmnaf_len - 1; j >= 0; --j)
    {
      if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0)
        goto done;

      digit = wmnaf[j];

      if (digit)
        {
          if (digit > 0)
            {
              if ((err =
                   ecc_projective_madd (R, cache->pos[(digit / 2)], R, a,
                                        modulus)) != 0)
                goto done;
            }
          else
            {
              if ((err =
                   ecc_projective_madd (R, cache->neg[(-digit / 2)], R, a,
                                        modulus)) != 0)
                goto done;
            }
        }
      else
        {
          /* we add middle element of pos array as a general case
           * there is no real difference between using pos and neg */
          if ((err =
               ecc_projective_madd (R,
                                    cache->
                                    pos[(WMNAF_PRECOMPUTED_LENGTH / 2)], T, a,
                                    modulus)) != 0)
            goto done;
        }
    }


  /* map R back from projective space */
  if (map)
    {
      err = ecc_map (R, modulus);
    }
  else
    {
      err = GNUTLS_E_SUCCESS;
    }
done:
  ecc_del_point (T);
  if (wmnaf)
    free (wmnaf);
  return err;
}
示例#4
0
文件: ecc_mulmod.c 项目: intgr/gnutls
/*
   Perform a point multiplication using wMNAF representation
   @param k    The scalar to multiply by
   @param G    The base point
   @param R    [out] Destination for kG
   @param a        The curve's A value
   @param modulus  The modulus of the field the ECC curve is in
   @param map      Boolean whether to map back to affine or not (1 == map, 0 == leave in projective)
   @return     GNUTLS_E_SUCCESS on success
*/
int
ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a,
                  mpz_t modulus, int map)
{
  ecc_point *pos[WMNAF_PRECOMPUTED_LENGTH], *neg[WMNAF_PRECOMPUTED_LENGTH];
  int i, j, err;

  signed char *wmnaf = NULL;
  size_t wmnaf_len;
  signed char digit;

  if (k == NULL || G == NULL || R == NULL || modulus == NULL)
    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

  /* alloc ram for precomputed values */
  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
    {
      pos[i] = ecc_new_point ();
      neg[i] = ecc_new_point ();
      if (pos[i] == NULL || neg[i] == NULL)
        {
          for (j = 0; j < i; ++j)
            {
              ecc_del_point (pos[j]);
              ecc_del_point (neg[j]);
            }

          return GNUTLS_E_MEMORY_ERROR;
        }
    }

  /* fill in pos and neg arrays with precomputed values
   * pos holds kG for k ==  1, 3, 5, ..., (2^w - 1)
   * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1)
   */

  /* pos[0] == 2G for a while, later it will be set to the expected 1G */
  if ((err = ecc_projective_dbl_point (G, pos[0], a, modulus)) != 0)
    goto done;

  /* pos[1] == 3G */
  if ((err =
       ecc_projective_add_point (pos[0], G, pos[1], a, modulus)) != 0)
    goto done;

  /* fill in kG for k = 5, 7, ..., (2^w - 1) */
  for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
    {
      if ((err =
           ecc_projective_add_point (pos[j - 1], pos[0], pos[j], a,
                                        modulus)) != 0)
        goto done;
    }

  /* set pos[0] == 1G as expected
   * after this step we don't need G at all 
   * and can change it without worries even if R == G */
  mpz_set (pos[0]->x, G->x);
  mpz_set (pos[0]->y, G->y);
  mpz_set (pos[0]->z, G->z);

  /* neg[i] == -pos[i] */
  for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
    {
      if ((err = ecc_projective_negate_point (pos[j], neg[j], modulus)) != 0)
        goto done;
    }

  /* calculate wMNAF */
  wmnaf = ecc_wMNAF (k, &wmnaf_len);
  if (!wmnaf)
    {
      err = GNUTLS_E_INTERNAL_ERROR;
      goto done;
    }

  /* actual point computation */

  /* set R to neutral */
  mpz_set_ui (R->x, 1);
  mpz_set_ui (R->y, 1);
  mpz_set_ui (R->z, 0);

  /* perform ops */
  for (j = wmnaf_len - 1; j >= 0; --j)
    {
      if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0)
        goto done;

      digit = wmnaf[j];

      if (digit)
        {
          if (digit > 0)
            {
              if ((err =
                   ecc_projective_add_point (R, pos[(digit / 2)], R, a,
                                                modulus)) != 0)
                goto done;
            }
          else
            {
              if ((err =
                   ecc_projective_add_point (R, neg[(-digit / 2)], R, a,
                                                modulus)) != 0)
                goto done;
            }
        }
    }


  /* map R back from projective space */
  if (map)
    {
      err = ecc_map (R, modulus);
    }
  else
    {
      err = GNUTLS_E_SUCCESS;
    }
done:
  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
    {
      ecc_del_point (pos[i]);
      ecc_del_point (neg[i]);
    }
  if (wmnaf)
    free (wmnaf);
  return err;
}
示例#5
0
/**
   Perform a point multiplication 
   @param k    The scalar to multiply by
   @param G    The base point
   @param R    [out] Destination for kG
   @param modulus  The modulus of the field the ECC curve is in
   @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
   @return CRYPT_OK on success
*/
int
ecc_mulmod (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a, mpz_t modulus,
                int map)

{
   ecc_point *tG, *M[8];
   int        i, j, err, bitidx;
   int        first, bitbuf, bitcpy, mode;

   if (k == NULL || G == NULL || R == NULL || modulus == NULL)
     return -1;

  /* alloc ram for window temps */
  for (i = 0; i < 8; i++) {
      M[i] = ecc_new_point();
      if (M[i] == NULL) {
         for (j = 0; j < i; j++) {
             ecc_del_point(M[j]);
         }

         return -1;
      }
  }

   /* make a copy of G incase R==G */
   tG = ecc_new_point();
   if (tG == NULL)
     { 
       err = -1;
       goto done; 
     }

   /* tG = G  and convert to montgomery */
   mpz_set (tG->x, G->x);
   mpz_set (tG->y, G->y);
   mpz_set (tG->z, G->z);

   /* calc the M tab, which holds kG for k==8..15 */
   /* M[0] == 8G */
   if ((err = ecc_projective_dbl_point (tG, M[0], a, modulus)) != 0)
     goto done;

   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
     goto done;

   if ((err = ecc_projective_dbl_point (M[0], M[0], a, modulus)) != 0)
     goto done;
 
   /* now find (8+k)G for k=1..7 */
   for (j = 9; j < 16; j++) {
     if (ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus) != 0)
       goto done;
   }

   /* setup sliding window */
   mode   = 0;
   bitidx = mpz_size (k) * GMP_NUMB_BITS - 1;
   bitcpy = bitbuf = 0;
   first  = 1;

   /* perform ops */
   for (;;) {
     /* grab next digit as required */
     if (bitidx == -1) {
       break;
     }

     /* grab the next msb from the ltiplicand */
     i = mpz_tstbit (k, bitidx--);

     /* skip leading zero bits */
     if (mode == 0 && i == 0) {
        continue;
     }

     /* if the bit is zero and mode == 1 then we double */
     if (mode == 1 && i == 0) {
        if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
          goto done;
        continue;
     }

     /* else we add it to the window */
     bitbuf |= (i << (WINSIZE - ++bitcpy));
     mode = 2;

     if (bitcpy == WINSIZE) {
       /* if this is the first window we do a simple copy */
       if (first == 1) {
          /* R = kG [k = first window] */
          mpz_set(R->x, M[bitbuf-8]->x);
          mpz_set(R->y, M[bitbuf-8]->y);
          mpz_set(R->z, M[bitbuf-8]->z);
          first = 0;
       } else {
         /* normal window */
         /* ok window is filled so double as required and add  */
         /* double first */
         for (j = 0; j < WINSIZE; j++) {
           if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
             goto done;
         }

         /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
         if ((err = ecc_projective_add_point(R, M[bitbuf-8], R, a, modulus)) != 0)
           goto done;
       }
       /* empty window and reset */
       bitcpy = bitbuf = 0;
       mode = 1;
    }
  }

   /* if bits remain then double/add */
   if (mode == 2 && bitcpy > 0) {
     /* double then add */
     for (j = 0; j < bitcpy; j++) {
       /* only double if we have had at least one add first */
       if (first == 0) {
          if ((err = ecc_projective_dbl_point(R, R, a, modulus)) != 0)
            goto done;
       }

       bitbuf <<= 1;
       if ((bitbuf & (1 << WINSIZE)) != 0) {
         if (first == 1){
            /* first add, so copy */
            mpz_set(R->x, tG->x);
            mpz_set(R->y, tG->y);
            mpz_set(R->z, tG->z);
            first = 0;
         } else {
            /* then add */
            if ((err = ecc_projective_add_point(R, tG, R, a, modulus)) != 0)
              goto done;
         }
       }
     }
   }

   /* map R back from projective space */
   if (map) {
      err = ecc_map(R, modulus);
   } else {
      err = 0;
   }
done:
   ecc_del_point(tG);
   for (i = 0; i < 8; i++) {
       ecc_del_point(M[i]);
   }
   return err;
}
int
ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key,
                 mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy,
                 int timing_res)
{
  int err;
  ecc_point *base;
  unsigned char *buf;
  int keysize;

  if (key == NULL || random == NULL)
    return -1;

  keysize = nettle_mpz_sizeinbase_256_u (order);

  /* allocate ram */
  base = NULL;
  buf = malloc (keysize);
  if (buf == NULL)
    return -1;

  /* make up random string */
  random (random_ctx, keysize, buf);

  /* setup the key variables */
  if ((err =
       mp_init_multi (&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
                      &key->prime, &key->order, &key->A, &key->B, &key->Gx, &key->Gy,
                      NULL)) != 0)
    {
      goto ERR_BUF;
    }
  base = ecc_new_point ();
  if (base == NULL)
    {
      err = -1;
      goto errkey;
    }

  /* read in the specs for this key */
  mpz_set (key->prime, prime);
  mpz_set (key->order, order);
  mpz_set (key->Gx, Gx);
  mpz_set (key->Gy, Gy);
  mpz_set (key->A, A);
  mpz_set (key->B, B);

  mpz_set (base->x, key->Gx);
  mpz_set (base->y, key->Gy);
  mpz_set_ui (base->z, 1);
  
  nettle_mpz_set_str_256_u (key->k, keysize, buf);

  /* the key should be smaller than the order of base point */
  if (mpz_cmp (key->k, key->order) >= 0)
    {
      mpz_mod (key->k, key->k, key->order);
    }
  /* make the public key */
  if (timing_res)
    err = ecc_mulmod_timing (key->k, base, &key->pubkey, key->A, key->prime, 1);
  else
    err = ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime, 1);

  if (err != 0)
    goto errkey;

  key->type = PK_PRIVATE;

  /* free up ram */
  err = 0;
  goto cleanup;
errkey:
  mp_clear_multi (&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
                  &key->order, &key->prime, &key->Gx, &key->Gy, &key->A, &key->B,
                  NULL);
cleanup:
  ecc_del_point (base);
ERR_BUF:
  free (buf);
  return err;
}
示例#7
0
文件: pk.c 项目: intgr/gnutls
static int
wrap_nettle_pk_verify_params (gnutls_pk_algorithm_t algo,
                              const gnutls_pk_params_st * params)
{
  int ret;

  switch (algo)
    {
    case GNUTLS_PK_RSA:
      {
        bigint_t t1 = NULL, t2 = NULL;

        if (params->params_nr != RSA_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        
        t1 = _gnutls_mpi_new (256);
        if (t1 == NULL)
          return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

        _gnutls_mpi_mulm (t1, params->params[RSA_PRIME1], params->params[RSA_PRIME2], params->params[RSA_MODULUS]);
        if (_gnutls_mpi_cmp_ui(t1, 0) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }

        mpz_invert (TOMPZ(t1), TOMPZ (params->params[RSA_PRIME2]), TOMPZ (params->params[RSA_PRIME1]));
        if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF]) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }

        /* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */
        _gnutls_mpi_sub_ui (t1, params->params[RSA_PRIME1], 1);
        t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1);
        if (t2 == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto rsa_cleanup;
          }
  
        if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }
        
        _gnutls_mpi_sub_ui (t1, params->params[RSA_PRIME2], 1);
        _gnutls_mpi_release(&t2);

        t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1);
        if (t2 == NULL)
          {
            ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
            goto rsa_cleanup;
          }
  
        if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto rsa_cleanup;
          }
        
        ret = 0;

rsa_cleanup:
        _gnutls_mpi_release(&t1);
        _gnutls_mpi_release(&t2);
      }

      break;
    case GNUTLS_PK_DSA:
      {
        bigint_t t1 = NULL;

        if (params->params_nr != DSA_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
        
        t1 = _gnutls_mpi_new (256);
        if (t1 == NULL)
          return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

        _gnutls_mpi_powm (t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]);

        if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto dsa_cleanup;
          }

        ret = 0;

dsa_cleanup:
        _gnutls_mpi_release(&t1);
      }

      break;
    case GNUTLS_PK_EC:
      {
        int curve = params->flags;
        ecc_key ecc_priv;
        ecc_point *R;
        ecc_point zero;

        if (params->params_nr != ECC_PRIVATE_PARAMS)
          return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

        if (is_supported_curve(curve) == 0)
          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);

        _ecc_params_to_privkey(params, &ecc_priv);
        R = ecc_new_point();

        /* verify that x,y lie on the curve */
        ret = ecc_projective_check_point(&ecc_priv.pubkey, TOMPZ(params->params[ECC_B]), params->params[ECC_PRIME]);
        if (ret != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }

        memcpy(&zero.x, ecc_priv.Gx, sizeof(mpz_t));
        memcpy(&zero.y, ecc_priv.Gy, sizeof(mpz_t));
        memcpy(&zero.z, ecc_priv.pubkey.z, sizeof(mpz_t)); /* z = 1 */

        /* verify that k*(Gx,Gy)=(x,y) */
        ret = ecc_mulmod_cached(ecc_priv.k, curve, R, TOMPZ(params->params[ECC_A]), TOMPZ(params->params[ECC_PRIME]), 1);
        if (ret != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }

        if (mpz_cmp(ecc_priv.pubkey.x, R->x) != 0 || mpz_cmp(ecc_priv.pubkey.y, R->y) != 0)
          {
            ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
            goto ecc_cleanup;
          }
        
        ret = 0;

ecc_cleanup:
        _ecc_params_clear(&ecc_priv);
        ecc_del_point(R);
      }  
      break;
    default:
      ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
    }

  return ret;
}