コード例 #1
0
ファイル: ecp_fp.c プロジェクト: Akin-Net/mozilla-central
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
 * curve points P and R can be identical. Uses mixed Modified-Jacobian
 * co-ordinates for doubling and Chudnovsky Jacobian coordinates for
 * additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point 
 * multiplication from Brown, Hankerson, Lopez, Menezes. Software
 * Implementation of the NIST Elliptic Curves Over Prime Fields. */
mp_err
ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px,
						 const mp_int *py, mp_int *rx, mp_int *ry,
						 const ECGroup *ecgroup)
{
	mp_err res = MP_OKAY;
	mp_int sx, sy, sz;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;
	ecfp_chud_pt precomp[16];

	ecfp_aff_pt p;
	ecfp_jm_pt r;

	signed char naf[group->orderBitSize + 1];
	int i;

	MP_DIGITS(&sx) = 0;
	MP_DIGITS(&sy) = 0;
	MP_DIGITS(&sz) = 0;
	MP_CHECKOK(mp_init(&sx));
	MP_CHECKOK(mp_init(&sy));
	MP_CHECKOK(mp_init(&sz));

	/* if n = 0 then r = inf */
	if (mp_cmp_z(n) == 0) {
		mp_zero(rx);
		mp_zero(ry);
		res = MP_OKAY;
		goto CLEANUP;
		/* if n < 0 then out of range error */
	} else if (mp_cmp_z(n) < 0) {
		res = MP_RANGE;
		goto CLEANUP;
	}

	/* Convert from integer to floating point */
	ecfp_i2fp(p.x, px, ecgroup);
	ecfp_i2fp(p.y, py, ecgroup);
	ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup);

	/* Perform precomputation */
	group->precompute_chud(precomp, &p, group);

	/* Compute 5NAF */
	ec_compute_wNAF(naf, group->orderBitSize, n, 5);

	/* Init R = pt at infinity */
	for (i = 0; i < group->numDoubles; i++) {
		r.z[i] = 0;
	}

	/* wNAF method */
	for (i = group->orderBitSize; i >= 0; i--) {
		/* R = 2R */
		group->pt_dbl_jm(&r, &r, group);

		if (naf[i] != 0) {
			group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r,
								  group);
		}
	}

	/* Convert from floating point to integer */
	ecfp_fp2i(&sx, r.x, ecgroup);
	ecfp_fp2i(&sy, r.y, ecgroup);
	ecfp_fp2i(&sz, r.z, ecgroup);

	/* convert result R to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup));

  CLEANUP:
	mp_clear(&sx);
	mp_clear(&sy);
	mp_clear(&sz);
	return res;
}
コード例 #2
0
ファイル: ecp_jm.c プロジェクト: AntinZhu/jdk-source
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
 * curve points P and R can be identical. Uses mixed Modified-Jacobian
 * co-ordinates for doubling and Chudnovsky Jacobian coordinates for
 * additions. Assumes input is already field-encoded using field_enc, and
 * returns output that is still field-encoded. Uses 5-bit window NAF
 * method (algorithm 11) for scalar-point multiplication from Brown,
 * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
 * Curves Over Prime Fields. */
mp_err
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
                                          mp_int *rx, mp_int *ry, const ECGroup *group)
{
        mp_err res = MP_OKAY;
        mp_int precomp[16][2], rz, tpx, tpy;
        mp_int raz4;
        mp_int scratch[MAX_SCRATCH];
        signed char *naf = NULL;
        int i, orderBitSize;

        MP_DIGITS(&rz) = 0;
        MP_DIGITS(&raz4) = 0;
        MP_DIGITS(&tpx) = 0;
        MP_DIGITS(&tpy) = 0;
        for (i = 0; i < 16; i++) {
                MP_DIGITS(&precomp[i][0]) = 0;
                MP_DIGITS(&precomp[i][1]) = 0;
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_DIGITS(&scratch[i]) = 0;
        }

        ARGCHK(group != NULL, MP_BADARG);
        ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

        /* initialize precomputation table */
        MP_CHECKOK(mp_init(&tpx, FLAG(n)));
        MP_CHECKOK(mp_init(&tpy, FLAG(n)));;
        MP_CHECKOK(mp_init(&rz, FLAG(n)));
        MP_CHECKOK(mp_init(&raz4, FLAG(n)));

        for (i = 0; i < 16; i++) {
                MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n)));
                MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n)));
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_CHECKOK(mp_init(&scratch[i], FLAG(n)));
        }

        /* Set out[8] = P */
        MP_CHECKOK(mp_copy(px, &precomp[8][0]));
        MP_CHECKOK(mp_copy(py, &precomp[8][1]));

        /* Set (tpx, tpy) = 2P */
        MP_CHECKOK(group->
                           point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
                                                 group));

        /* Set 3P, 5P, ..., 15P */
        for (i = 8; i < 15; i++) {
                MP_CHECKOK(group->
                                   point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
                                                         &precomp[i + 1][0], &precomp[i + 1][1],
                                                         group));
        }

        /* Set -15P, -13P, ..., -P */
        for (i = 0; i < 8; i++) {
                MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
                MP_CHECKOK(group->meth->
                                   field_neg(&precomp[15 - i][1], &precomp[i][1],
                                                         group->meth));
        }

        /* R = inf */
        MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

        orderBitSize = mpl_significant_bits(&group->order);

        /* Allocate memory for NAF */
#ifdef _KERNEL
        naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n));
#else
        naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
        if (naf == NULL) {
                res = MP_MEM;
                goto CLEANUP;
        }
#endif

        /* Compute 5NAF */
        ec_compute_wNAF(naf, orderBitSize, n, 5);

        /* wNAF method */
        for (i = orderBitSize; i >= 0; i--) {
                /* R = 2R */
                ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
                                             &raz4, scratch, group);
                if (naf[i] != 0) {
                        ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
                                                                 &precomp[(naf[i] + 15) / 2][0],
                                                                 &precomp[(naf[i] + 15) / 2][1], rx, ry,
                                                                 &rz, &raz4, scratch, group);
                }
        }

        /* convert result S to affine coordinates */
        MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

  CLEANUP:
        for (i = 0; i < MAX_SCRATCH; i++) {
                mp_clear(&scratch[i]);
        }
        for (i = 0; i < 16; i++) {
                mp_clear(&precomp[i][0]);
                mp_clear(&precomp[i][1]);
        }
        mp_clear(&tpx);
        mp_clear(&tpy);
        mp_clear(&rz);
        mp_clear(&raz4);
#ifdef _KERNEL
        kmem_free(naf, (orderBitSize + 1));
#else
        free(naf);
#endif
        return res;
}
コード例 #3
0
ファイル: p256.c プロジェクト: google/boringssl
static void ec_GFp_nistp256_point_mul_public(const EC_GROUP *group,
                                             EC_RAW_POINT *r,
                                             const EC_SCALAR *g_scalar,
                                             const EC_RAW_POINT *p,
                                             const EC_SCALAR *p_scalar) {
#define P256_WSIZE_PUBLIC 4
  // Precompute multiples of |p|. p_pre_comp[i] is (2*i+1) * |p|.
  fe p_pre_comp[1 << (P256_WSIZE_PUBLIC-1)][3];
  fe_from_generic(p_pre_comp[0][0], &p->X);
  fe_from_generic(p_pre_comp[0][1], &p->Y);
  fe_from_generic(p_pre_comp[0][2], &p->Z);
  fe p2[3];
  point_double(p2[0], p2[1], p2[2], p_pre_comp[0][0], p_pre_comp[0][1],
               p_pre_comp[0][2]);
  for (size_t i = 1; i < OPENSSL_ARRAY_SIZE(p_pre_comp); i++) {
    point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2],
              p_pre_comp[i - 1][0], p_pre_comp[i - 1][1], p_pre_comp[i - 1][2],
              0 /* not mixed */, p2[0], p2[1], p2[2]);
  }

  // Set up the coefficients for |p_scalar|.
  int8_t p_wNAF[257];
  ec_compute_wNAF(group, p_wNAF, p_scalar, 256, P256_WSIZE_PUBLIC);

  // Set |ret| to the point at infinity.
  int skip = 1;  // Save some point operations.
  fe ret[3] = {{0},{0},{0}};
  for (int i = 256; i >= 0; i--) {
    if (!skip) {
      point_double(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2]);
    }

    // For the |g_scalar|, we use the precomputed table without the
    // constant-time lookup.
    if (i <= 31) {
      // First, look 32 bits upwards.
      uint64_t bits = get_bit(g_scalar->bytes, i + 224) << 3;
      bits |= get_bit(g_scalar->bytes, i + 160) << 2;
      bits |= get_bit(g_scalar->bytes, i + 96) << 1;
      bits |= get_bit(g_scalar->bytes, i + 32);
      point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */,
                g_pre_comp[1][bits][0], g_pre_comp[1][bits][1],
                g_pre_comp[1][bits][2]);
      skip = 0;

      // Second, look at the current position.
      bits = get_bit(g_scalar->bytes, i + 192) << 3;
      bits |= get_bit(g_scalar->bytes, i + 128) << 2;
      bits |= get_bit(g_scalar->bytes, i + 64) << 1;
      bits |= get_bit(g_scalar->bytes, i);
      point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2], 1 /* mixed */,
                g_pre_comp[0][bits][0], g_pre_comp[0][bits][1],
                g_pre_comp[0][bits][2]);
    }

    int digit = p_wNAF[i];
    if (digit != 0) {
      assert(digit & 1);
      int idx = digit < 0 ? (-digit) >> 1 : digit >> 1;
      fe *y = &p_pre_comp[idx][1], tmp;
      if (digit < 0) {
        fe_opp(tmp, p_pre_comp[idx][1]);
        y = &tmp;
      }
      if (!skip) {
        point_add(ret[0], ret[1], ret[2], ret[0], ret[1], ret[2],
                  0 /* not mixed */, p_pre_comp[idx][0], *y, p_pre_comp[idx][2]);
      } else {
        fe_copy(ret[0], p_pre_comp[idx][0]);
        fe_copy(ret[1], *y);
        fe_copy(ret[2], p_pre_comp[idx][2]);
        skip = 0;
      }
    }
  }