Пример #1
0
/* Test point doubling in Jacobian coordinates */
mp_err
testPointDoubleJac(ECGroup *ecgroup)
{
	mp_err res;
	mp_int pz, rx, ry, rz, rx2, ry2, rz2;
	ecfp_jac_pt p, p2;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&rz) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&rz2) = 0;

	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&rz2));

	MP_CHECKOK(mp_set_int(&pz, 5));

	/* Set p2 = 2P */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(p.z, &pz, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	group->pt_dbl_jac(&p, &p2, group);
	M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000);

	/* Calculate doubling to compare against */
	ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
					  &rz2, ecgroup);
	ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);

	/* Do comparison */
	MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Doubling - Jacobian\n");
	else
		printf("TEST FAILED - Point Doubling - Jacobian\n");

	mp_clear(&pz);
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&rz);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&rz2);

	return res;
}
Пример #2
0
/* initialize and set a digit */
int mp_init_set_int (mp_int * a, unsigned long b)
{
  int err;
  if ((err = mp_init(a)) != MP_OKAY) {
     return err;
  }
  return mp_set_int(a, b);
}
Пример #3
0
/* sets given unsigned longs p,q as the numerator,denominator in mp_rat a */
int mpq_set_int(mp_rat * a, long p, long q)
{
    int e;

    if ((e = mp_set_int(&a->numerator, labs(p))) != MP_OKAY) {
	return e;
    }
    if ((e = mp_set_int(&a->denominator, labs(q))) != MP_OKAY) {
	return e;
    }
    if ((p * q) < 0) {
	mpq_set_sign(a, MP_NEG);
    }
    if ((e = mpq_reduce(a)) != MP_OKAY) {
	return e;
    }
    return MP_OKAY;
}
Пример #4
0
/* Tests point addition of Jacobian + Affine -> Jacobian */
mp_err
testPointAddJacAff(ECGroup *ecgroup)
{
	mp_err res;
	mp_int pz, rx2, ry2, rz2;
	ecfp_jac_pt p, r;
	ecfp_aff_pt q;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	/* Init */
	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&rz2) = 0;
	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&rz2));

	MP_CHECKOK(mp_set_int(&pz, 5));

	/* Set p */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(p.z, &pz, ecgroup);
	/* Set q */
	ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
	ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);

	/* Do calculations */
	group->pt_add_jac_aff(&p, &q, &r, group);

	/* Do calculation in integer to compare against */
	MP_CHECKOK(ec_GFp_pt_add_jac_aff
			   (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny,
				&ecgroup->genx, &rx2, &ry2, &rz2, ecgroup));
	/* convert result R to affine coordinates */
	ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);

	MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Addition - Jacobian & Affine\n");
	else
		printf("TEST FAILED - Point Addition - Jacobian & Affine\n");

	mp_clear(&pz);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&rz2);

	return res;
}
Пример #5
0
/* Tests point doubling in Chudnovsky Jacobian coordinates */
mp_err
testPointDoubleChud(ECGroup *ecgroup)
{
	mp_err res;
	mp_int px, py, pz, rx2, ry2, rz2;
	ecfp_aff_pt p;
	ecfp_chud_pt p2;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&rz2) = 0;
	MP_DIGITS(&px) = 0;
	MP_DIGITS(&py) = 0;
	MP_DIGITS(&pz) = 0;

	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&rz2));
	MP_CHECKOK(mp_init(&px));
	MP_CHECKOK(mp_init(&py));
	MP_CHECKOK(mp_init(&pz));

	/* Set p2 = 2P */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	group->pt_dbl_aff2chud(&p, &p2, group);

	/* Calculate doubling to compare against */
	MP_CHECKOK(mp_set_int(&pz, 1));
	ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
					  &rz2, ecgroup);
	ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);

	/* Do comparison and check az^4 */
	MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Doubling - Chudnovsky Jacobian\n");
	else
		printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n");

	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&rz2);
	mp_clear(&px);
	mp_clear(&py);
	mp_clear(&pz);

	return res;
}
Пример #6
0
unsigned char *cli_decodesig(const char *sig, unsigned int plen, mp_int e, mp_int n)
{
	int i, slen = strlen(sig), dec;
	unsigned char *plain;
	mp_int r, p, c;


    mp_init(&r);
    mp_init(&c);
    for(i = 0; i < slen; i++) {
	if((dec = cli_ndecode(sig[i])) < 0) {
	    mp_clear(&r);
	    mp_clear(&c);
	    return NULL;
	}
	mp_set_int(&r, dec);
	mp_mul_2d(&r, 6 * i, &r);
	mp_add(&r, &c, &c);
    }

    plain = (unsigned char *) cli_calloc(plen + 1, sizeof(unsigned char));
    if(!plain) {
	cli_errmsg("cli_decodesig: Can't allocate memory for 'plain'\n");
	mp_clear(&r);
	mp_clear(&c);
	return NULL;
    }
    mp_init(&p);
    mp_exptmod(&c, &e, &n, &p); /* plain = cipher^e mod n */
    mp_clear(&c);
    mp_set_int(&c, 256);
    for(i = plen - 1; i >= 0; i--) { /* reverse */
	mp_div(&p, &c, &p, &r);
	plain[i] = mp_get_int(&r);
    }
    mp_clear(&c);
    mp_clear(&p);
    mp_clear(&r);

    return plain;
}
Пример #7
0
Файл: ec.c Проект: txazo/hotspot
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
 * random number generator.
 *
 * Parameters
 * - order: a buffer that holds the curve's group order
 * - len: the length in octets of the order buffer
 * - random: a buffer of 2 * len random bytes
 * - randomlen: the length in octets of the random buffer
 *
 * Return Value
 * Returns a buffer of len octets that holds the private key. The caller
 * is responsible for freeing the buffer with PORT_ZFree.
 */
static unsigned char *
ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
    const unsigned char *random, int randomlen, int kmflag)
{
    SECStatus rv = SECSuccess;
    mp_err err;
    unsigned char *privKeyBytes = NULL;
    mp_int privKeyVal, order_1, one;

    MP_DIGITS(&privKeyVal) = 0;
    MP_DIGITS(&order_1) = 0;
    MP_DIGITS(&one) = 0;
    CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
    CHECK_MPI_OK( mp_init(&order_1, kmflag) );
    CHECK_MPI_OK( mp_init(&one, kmflag) );

    /*
     * Reduces the 2*len buffer of random bytes modulo the group order.
     */
    if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
    if (randomlen != 2 * len) {
        randomlen = 2 * len;
    }
    /* No need to generate - random bytes are now supplied */
    /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
    memcpy(privKeyBytes, random, randomlen);

    CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
    CHECK_MPI_OK( mp_set_int(&one, 1) );
    CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
    CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
    CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
    memset(privKeyBytes+len, 0, len);
cleanup:
    mp_clear(&privKeyVal);
    mp_clear(&order_1);
    mp_clear(&one);
    if (err < MP_OKAY) {
        MP_TO_SEC_ERROR(err);
        rv = SECFailure;
    }
    if (rv != SECSuccess && privKeyBytes) {
#ifdef _KERNEL
        kmem_free(privKeyBytes, 2*len);
#else
        free(privKeyBytes);
#endif
        privKeyBytes = NULL;
    }
    return privKeyBytes;
}
Пример #8
0
/* mostly taken from libtomcrypt's rsa key generation routine */
dropbear_rsa_key * gen_rsa_priv_key(unsigned int size) {

	dropbear_rsa_key * key;
	DEF_MP_INT(pminus);
	DEF_MP_INT(qminus);
	DEF_MP_INT(lcm);

	if (size < 512 || size > 4096 || (size % 8 != 0)) {
		dropbear_exit("Bits must satisfy 512 <= bits <= 4096, and be a"
			" multiple of 8");
	}

	key = m_malloc(sizeof(*key));
	m_mp_alloc_init_multi(&key->e, &key->n, &key->d, &key->p, &key->q, NULL);
	m_mp_init_multi(&pminus, &lcm, &qminus, NULL);

	if (mp_set_int(key->e, RSA_E) != MP_OKAY) {
		fprintf(stderr, "RSA generation failed\n");
		exit(1);
	}

	while (1) {
		getrsaprime(key->p, &pminus, key->e, size/16);
		getrsaprime(key->q, &qminus, key->e, size/16);

		if (mp_mul(key->p, key->q, key->n) != MP_OKAY) {
			fprintf(stderr, "RSA generation failed\n");
			exit(1);
		}

		if ((unsigned int)mp_count_bits(key->n) == size) {
			break;
		}
	}

	/* lcm(p-1, q-1) */
	if (mp_lcm(&pminus, &qminus, &lcm) != MP_OKAY) {
		fprintf(stderr, "RSA generation failed\n");
		exit(1);
	}

	/* de = 1 mod lcm(p-1,q-1) */
	/* therefore d = (e^-1) mod lcm(p-1,q-1) */
	if (mp_invmod(key->e, &lcm, key->d) != MP_OKAY) {
		fprintf(stderr, "RSA generation failed\n");
		exit(1);
	}

	mp_clear_multi(&pminus, &qminus, &lcm, NULL);

	return key;
}	
Пример #9
0
/* sets given unsigned long b as the denominator in mp_rat a */
int mpq_set_den_int(mp_rat * a, long b)
{
    int e;

    if ((e = mp_set_int(&a->denominator, labs(b))) != MP_OKAY) {
	return e;
    }
    if (b < 0) {
	mpq_set_sign(a, MP_NEG);
    }
    if ((e = mpq_reduce(a)) != MP_OKAY) {
	return e;
    }
    return MP_OKAY;
}
Пример #10
0
/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
 * random number generator.
 *
 * Parameters
 * - order: a buffer that holds the curve's group order
 * - len: the length in octets of the order buffer
 *
 * Return Value
 * Returns a buffer of len octets that holds the private key. The caller
 * is responsible for freeing the buffer with PORT_ZFree.
 */
static unsigned char *
ec_GenerateRandomPrivateKey(const unsigned char *order, int len, int kmflag)
{
    SECStatus rv = SECSuccess;
    mp_err err;
    unsigned char *privKeyBytes = NULL;
    mp_int privKeyVal, order_1, one;

    MP_DIGITS(&privKeyVal) = 0;
    MP_DIGITS(&order_1) = 0;
    MP_DIGITS(&one) = 0;
    CHECK_MPI_OK( mp_init(&privKeyVal) );
    CHECK_MPI_OK( mp_init(&order_1) );
    CHECK_MPI_OK( mp_init(&one) );

    /* Generates 2*len random bytes using the global random bit generator
     * (which implements Algorithm 1 of FIPS 186-2 Change Notice 1) then
     * reduces modulo the group order.
     */
    if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
    CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
    CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
    CHECK_MPI_OK( mp_set_int(&one, 1) );
    CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
    CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
    CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
    memset(privKeyBytes+len, 0, len);
cleanup:
    mp_clear(&privKeyVal);
    mp_clear(&order_1);
    mp_clear(&one);
    if (err < MP_OKAY) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    if (rv != SECSuccess && privKeyBytes) {
#ifdef _KERNEL
	kmem_free(privKeyBytes, 2*len);
#else
	free(privKeyBytes);
#endif
	privKeyBytes = NULL;
    }
    return privKeyBytes;
}
Пример #11
0
/* Converts a point P(px, py) from affine coordinates to Jacobian
 * projective coordinates R(rx, ry, rz). Assumes input is already
 * field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
				  mp_int *ry, mp_int *rz, const ECGroup *group)
{
	mp_err res = MP_OKAY;

	if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
		MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
	} else {
		MP_CHECKOK(mp_copy(px, rx));
		MP_CHECKOK(mp_copy(py, ry));
		MP_CHECKOK(mp_set_int(rz, 1));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
		}
	}
  CLEANUP:
	return res;
}
Пример #12
0
/* Divides two field elements. If a is NULL, then returns the inverse of
 * b. */
mp_err
ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r,
            const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_int t;

    /* If a is NULL, then return the inverse of b, otherwise return a/b. */
    if (a == NULL) {
        /* The GF(2^m) portion of MPI doesn't support invmod, so we
         * compute 1/b. */
        MP_CHECKOK(mp_init(&t));
        MP_CHECKOK(mp_set_int(&t, 1));
        MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r));
    CLEANUP:
        mp_clear(&t);
        return res;
    } else {
        return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r);
    }
}
Пример #13
0
/**
* Generate a numberOfBits-bit long random integer.  Note: The most-significant
* bit will not be random: it will always be 1.  The number of random bits
* therefore is numberOfBits - 1.
*
* @return random number
*/
mp_int *fhe_new_random_integer(unsigned long long int numberOfBits) {
#if defined(__linux__)
    int c;
    unsigned int bitmask;
    unsigned long int i;
    INIT_MP_INT(randomInteger);
    INIT_MP_INT(tmp1);


    /* The whole bytes */
    for (bitmask = 0xff, i = numberOfBits; i > 0;) {
        if ((c = fgetc(randomFile)) == EOF) {
            perror("Error reading " RANDOM_FILE);
            exit(EXIT_FAILURE);
        }

        /* Ensure the most-significant bit of the random integer is always 1 */
        if (i == numberOfBits) {
            assert(i > 0);
            c |= 0x1 << ((i < 8 ? i : 8) - 1);
        }

        if (i < 8) {
            // The last few bits will have a bitmask
            bitmask = 0xff >> (8 - i);
        }
        for (unsigned long int j = 0; j < i; j++) {
            mp_mul_2(randomInteger, randomInteger);
        }
        mp_set_int(tmp1, c & bitmask);
        mp_add(randomInteger, tmp1, randomInteger);

        /* Decrement; check for underflow */
        if (i < 8) {
            break;
        }
        else {
            i -= 8;
        }
    }
Пример #14
0
Object* UnMarshaller::get_positive_varint() {
    bool done;
    unsigned long val = get_varint(&done);

    bool is_fixnum = done;
    mp_int mp_val;

    // do we need to switch to bignum math?
    if(!done) {
        int shift = sizeof(long) * 7;
        mp_int a;

        mp_init_set_int(&mp_val, val);
        mp_init(&a);

#if (__WORDSIZE == 64)
        // mp_(init_)set_int can only deal with 32 bit values,
        // so the above call only copied the lower 32 bits of _val_.
        // Handle the upper 32 bits as well:
        mp_set_int(&a, val >> 32);
        mp_mul_2d(&a, 32, &a);
        mp_add(&a, &mp_val, &mp_val);
#endif

        while(!done) {
            unsigned int byte = stream.get();

            mp_set_int(&a, byte & ~128);
            mp_mul_2d(&a, shift, &a);
            mp_add(&a, &mp_val, &mp_val);

            shift += 7;
            done = byte < 128;
        }

        mp_clear(&a);
    }
Пример #15
0
int main (int argc, char **argv){

    mp_int num1,den1,num2,den2;
    mp_rat q1,q2,q3,q4;
    //mp_rat *bernoulli;
    int i;
    clock_t start,stop;

    if (argc < 5) {
	fprintf(stderr, "usage: %s integer integer integer integer \n", argv[0]);
	exit(EXIT_FAILURE);
    }

    mp_init_multi(&num1,&den1,&num2,&den2,NULL);

    mp_get_str(argv[1], &num1, 10);
    mp_get_str(argv[2], &den1, 10);
    mp_get_str(argv[3], &num2, 10);
    mp_get_str(argv[4], &den2, 10);

    printf("Numerator   1: ");mp_print(&num1);puts("");
    printf("Denominator 1: ");mp_print(&den1);puts("");
    printf("Numerator   2: ");mp_print(&num2);puts("");
    printf("Denominator 2: ");mp_print(&den2);puts("");

    mpq_init_multi(&q1,&q2,&q3,&q4,NULL);puts("000");

    mpq_set(&q1,&num1,&den1);puts("111");
    printf("Rational1: ");mpq_print(&q1);puts("");
    mpq_set(&q2,&num2,&den2);puts("222");
    printf("Rational2: ");mpq_print(&q2);puts("");

    mpq_add(&q1,&q2,&q3);;
    printf("R1 + R2 = ");mpq_print(&q3);puts("");
    mpq_sub(&q1,&q2,&q3);
    printf("R1 - R2 = ");mpq_print(&q3);puts("");
    mpq_mul(&q1,&q2,&q3);
    printf("R1 * R2 = ");mpq_print(&q3);puts("");
    mpq_div(&q1,&q2,&q3);
    printf("R1 / R2 = ");mpq_print(&q3);puts("");
    //mpq_pow_d(&q1,123,&q3);
    printf("R1 ^ 123 = ");mpq_print(&q3);puts("");
    printf("cmp(R1, R2) = %d\n",mpq_cmp(&q1,&q2));
    printf("cmp(R2, R1) = %d\n",mpq_cmp(&q2,&q1));
    printf("cmp(R1, R1) = %d\n",mpq_cmp(&q1,&q1));
    mp_set_int(&num2,123);
    //mp_expt(&num1,&num2,&num1);
    printf("num1 ^123 = ");mp_fwrite(&num1,10,stdout);puts("");
    mpq_set_epsilon(50);
//mpq_set_int(&q1,128,2);
//mpq_set_int(&q1,529,1849);
//mpq_set_int(&q1,3481,11664);
//mpq_set_int(&q1,1764,1849);
mpq_set_int(&q1,44521,46656);
    mpq_sqrt(&q1,&q1);
    printf("sqrt(R1) = ");mpq_print(&q1);puts("");
    //SeidelBernoulli(20);
    //bernoulli = malloc(sizeof(mp_rat) * 102);
    start = clock();
    //bern_rat_init(10);
    //bhbern(50);
    stop = clock();
    puts("bernoulli");
    for(i=0;i<=(50);i++){
      //mpq_print(&bern_array[i]);printf("  %d\n",i);
    }
    mpq_bernoulli(10,&q1);
    printf("B_10 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(4,&q1);
    printf("B_4 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(0,&q1);
    printf("B_0 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(1,&q1);
    printf("B_1 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(2,&q1);
    printf("B_3 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(100,&q1);
    printf("B_100 = ");mpq_print(&q1);puts("");
    mpq_bernoulli(98,&q1);
    printf("B_98 = ");mpq_print(&q1);puts("");
    printf("Time: %6.6f\n",( (double)stop - (double)start )/((double)CLOCKS_PER_SEC)  );
    mpq_bernoulli_free();
    exit(EXIT_SUCCESS);
}
Пример #16
0
/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
 * R can be identical. Uses affine coordinates. Assumes input is already
 * field-encoded using field_enc, and returns output that is still
 * field-encoded. */
mp_err
ec_GFp_pt_mul_aff(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 k, k3, qx, qy, sx, sy;
    int b1, b3, i, l;

    MP_DIGITS(&k) = 0;
    MP_DIGITS(&k3) = 0;
    MP_DIGITS(&qx) = 0;
    MP_DIGITS(&qy) = 0;
    MP_DIGITS(&sx) = 0;
    MP_DIGITS(&sy) = 0;
    MP_CHECKOK(mp_init(&k));
    MP_CHECKOK(mp_init(&k3));
    MP_CHECKOK(mp_init(&qx));
    MP_CHECKOK(mp_init(&qy));
    MP_CHECKOK(mp_init(&sx));
    MP_CHECKOK(mp_init(&sy));

    /* if n = 0 then r = inf */
    if (mp_cmp_z(n) == 0) {
        mp_zero(rx);
        mp_zero(ry);
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* Q = P, k = n */
    MP_CHECKOK(mp_copy(px, &qx));
    MP_CHECKOK(mp_copy(py, &qy));
    MP_CHECKOK(mp_copy(n, &k));
    /* if n < 0 then Q = -Q, k = -k */
    if (mp_cmp_z(n) < 0) {
        MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth));
        MP_CHECKOK(mp_neg(&k, &k));
    }
#ifdef ECL_DEBUG /* basic double and add method */
    l = mpl_significant_bits(&k) - 1;
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    for (i = l - 1; i >= 0; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        /* if k_i = 1, then S = S + Q */
        if (mpl_get_bit(&k, i) != 0) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#else /* double and add/subtract method from \
               * standard */
    /* k3 = 3 * k */
    MP_CHECKOK(mp_set_int(&k3, 3));
    MP_CHECKOK(mp_mul(&k, &k3, &k3));
    /* S = Q */
    MP_CHECKOK(mp_copy(&qx, &sx));
    MP_CHECKOK(mp_copy(&qy, &sy));
    /* l = index of high order bit in binary representation of 3*k */
    l = mpl_significant_bits(&k3) - 1;
    /* for i = l-1 downto 1 */
    for (i = l - 1; i >= 1; i--) {
        /* S = 2S */
        MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
        b3 = MP_GET_BIT(&k3, i);
        b1 = MP_GET_BIT(&k, i);
        /* if k3_i = 1 and k_i = 0, then S = S + Q */
        if ((b3 == 1) && (b1 == 0)) {
            MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
            /* if k3_i = 0 and k_i = 1, then S = S - Q */
        } else if ((b3 == 0) && (b1 == 1)) {
            MP_CHECKOK(group->point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
        }
    }
#endif
    /* output S */
    MP_CHECKOK(mp_copy(&sx, rx));
    MP_CHECKOK(mp_copy(&sy, ry));

CLEANUP:
    mp_clear(&k);
    mp_clear(&k3);
    mp_clear(&qx);
    mp_clear(&qy);
    mp_clear(&sx);
    mp_clear(&sy);
    return res;
}
Пример #17
0
/* Generate our side of the diffie-hellman key exchange value (dh_f), and
 * calculate the session key using the diffie-hellman algorithm. Following
 * that, the session hash is calculated, and signed with RSA or DSS. The
 * result is sent to the client. 
 *
 * See the ietf-secsh-transport draft, section 6, for details */
static void send_msg_kexdh_reply(mp_int *dh_e) {

	mp_int dh_p, dh_q, dh_g, dh_y, dh_f;
	unsigned char randbuf[DH_P_LEN];
	int dh_q_len;
	hash_state hs;

	TRACE(("enter send_msg_kexdh_reply"));
	
	assert(ses.kexstate.recvkexinit);

	m_mp_init_multi(&dh_g, &dh_p, &dh_q, &dh_y, &dh_f, NULL);

	/* read the prime and generator*/
	if (mp_read_unsigned_bin(&dh_p, (unsigned char*)dh_p_val, DH_P_LEN)
			!= MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	
	if (mp_set_int(&dh_g, dh_g_val) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* calculate q = (p-1)/2 */
	if (mp_sub_d(&dh_p, 1, &dh_y) != MP_OKAY) { /*dh_y is just a temp var here*/
		dropbear_exit("Diffie-Hellman error");
	}
	if (mp_div_2(&dh_y, &dh_q) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	dh_q_len = mp_unsigned_bin_size(&dh_q);

	/* calculate our random value dh_y */
	do {
		assert((unsigned int)dh_q_len <= sizeof(randbuf));
		genrandom(randbuf, dh_q_len);
		if (mp_read_unsigned_bin(&dh_y, randbuf, dh_q_len) != MP_OKAY) {
			dropbear_exit("Diffie-Hellman error");
		}
	} while (mp_cmp(&dh_y, &dh_q) == MP_GT || mp_cmp_d(&dh_y, 0) != MP_GT);

	/* f = g^y mod p */
	if (mp_exptmod(&dh_g, &dh_y, &dh_p, &dh_f) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}
	mp_clear(&dh_g);

	/* K = e^y mod p */
	ses.dh_K = (mp_int*)m_malloc(sizeof(mp_int));
	m_mp_init(ses.dh_K);
	if (mp_exptmod(dh_e, &dh_y, &dh_p, ses.dh_K) != MP_OKAY) {
		dropbear_exit("Diffie-Hellman error");
	}

	/* clear no longer needed vars */
	mp_clear_multi(&dh_y, &dh_p, &dh_q, NULL);

	/* Create the remainder of the hash buffer, to generate the exchange hash */
	/* K_S, the host key */
	buf_put_pub_key(ses.kexhashbuf, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey);
	/* e, exchange value sent by the client */
	buf_putmpint(ses.kexhashbuf, dh_e);
	/* f, exchange value sent by the server */
	buf_putmpint(ses.kexhashbuf, &dh_f);
	/* K, the shared secret */
	buf_putmpint(ses.kexhashbuf, ses.dh_K);

	/* calculate the hash H to sign */
	sha1_init(&hs);
	buf_setpos(ses.kexhashbuf, 0);
	sha1_process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
			ses.kexhashbuf->len);
	sha1_done(&hs, ses.hash);
	buf_free(ses.kexhashbuf);
	ses.kexhashbuf = NULL;
	
	/* first time around, we set the session_id to H */
	if (ses.session_id == NULL) {
		/* create the session_id, this never needs freeing */
		ses.session_id = (unsigned char*)m_malloc(SHA1_HASH_SIZE);
		memcpy(ses.session_id, ses.hash, SHA1_HASH_SIZE);
	}
	
	/* we can start creating the kexdh_reply packet */
	CHECKCLEARTOWRITE();
	buf_putbyte(ses.writepayload, SSH_MSG_KEXDH_REPLY);
	buf_put_pub_key(ses.writepayload, ses.opts->hostkey,
			ses.newkeys->algo_hostkey);

	/* put f */
	buf_putmpint(ses.writepayload, &dh_f);
	mp_clear(&dh_f);

	/* calc the signature */
	buf_put_sign(ses.writepayload, ses.opts->hostkey, 
			ses.newkeys->algo_hostkey, ses.hash, SHA1_HASH_SIZE);

	/* the SSH_MSG_KEXDH_REPLY is done */
	encrypt_packet();

	TRACE(("leave send_msg_kexdh_reply"));
}
Пример #18
0
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P,
 * Q, and R can all be identical. Uses affine coordinates. Assumes input
 * is already field-encoded using field_enc, and returns output that is
 * still field-encoded. */
mp_err
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
                  const mp_int *qy, mp_int *rx, mp_int *ry,
                  const ECGroup *group)
{
    mp_err res = MP_OKAY;
    mp_int lambda, temp, tempx, tempy;

    MP_DIGITS(&lambda) = 0;
    MP_DIGITS(&temp) = 0;
    MP_DIGITS(&tempx) = 0;
    MP_DIGITS(&tempy) = 0;
    MP_CHECKOK(mp_init(&lambda));
    MP_CHECKOK(mp_init(&temp));
    MP_CHECKOK(mp_init(&tempx));
    MP_CHECKOK(mp_init(&tempy));
    /* if P = inf, then R = Q */
    if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
        MP_CHECKOK(mp_copy(qx, rx));
        MP_CHECKOK(mp_copy(qy, ry));
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* if Q = inf, then R = P */
    if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
        MP_CHECKOK(mp_copy(px, rx));
        MP_CHECKOK(mp_copy(py, ry));
        res = MP_OKAY;
        goto CLEANUP;
    }
    /* if px != qx, then lambda = (py-qy) / (px-qx) */
    if (mp_cmp(px, qx) != 0) {
        MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
        MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
        MP_CHECKOK(group->meth->field_div(&tempy, &tempx, &lambda, group->meth));
    } else {
        /* if py != qy or qy = 0, then R = inf */
        if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
            mp_zero(rx);
            mp_zero(ry);
            res = MP_OKAY;
            goto CLEANUP;
        }
        /* lambda = (3qx^2+a) / (2qy) */
        MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
        MP_CHECKOK(mp_set_int(&temp, 3));
        if (group->meth->field_enc) {
            MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
        }
        MP_CHECKOK(group->meth->field_mul(&tempx, &temp, &tempx, group->meth));
        MP_CHECKOK(group->meth->field_add(&tempx, &group->curvea, &tempx, group->meth));
        MP_CHECKOK(mp_set_int(&temp, 2));
        if (group->meth->field_enc) {
            MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
        }
        MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
        MP_CHECKOK(group->meth->field_div(&tempx, &tempy, &lambda, group->meth));
    }
    /* rx = lambda^2 - px - qx */
    MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
    /* ry = (x1-x2) * lambda - y1 */
    MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
    MP_CHECKOK(group->meth->field_mul(&tempy, &lambda, &tempy, group->meth));
    MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
    MP_CHECKOK(mp_copy(&tempx, rx));
    MP_CHECKOK(mp_copy(&tempy, ry));

CLEANUP:
    mp_clear(&lambda);
    mp_clear(&temp);
    mp_clear(&tempx);
    mp_clear(&tempy);
    return res;
}
Пример #19
0
/* Tests a point multiplication (various algorithms) */
mp_err
testPointMul(ECGroup *ecgroup)
{
	mp_err res;
	char s[1000];
	mp_int rx, ry, order_1;

	/* Init */
	MP_DIGITS(&rx) = 0;
	MP_DIGITS(&ry) = 0;
	MP_DIGITS(&order_1) = 0;

	MP_CHECKOK(mp_init(&rx));
	MP_CHECKOK(mp_init(&ry));
	MP_CHECKOK(mp_init(&order_1));

	MP_CHECKOK(mp_set_int(&order_1, 1));
	MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1));

	/* Test Algorithm 1: Jacobian-Affine Double & Add */
	ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
						 &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny,
						 &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	/* Test Algorithm 2: 4-bit Window in Jacobian */
	ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny,
							   &rx, &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx,
							   &ecgroup->geny, &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	/* Test Algorithm 3: wNAF with modified Jacobian coordinates */
	ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx,
							 &ry, ecgroup);
	MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth));
	if ((mp_cmp(&rx, &ecgroup->genx) != 0)
		|| (mp_cmp(&ry, &ecgroup->geny) != 0)) {
		printf
			("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

	ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx,
							 &ecgroup->geny, &rx, &ry, ecgroup);
	if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
		printf
			("  Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n");
		MP_CHECKOK(mp_toradix(&rx, s, 16));
		printf("rx   %s\n", s);
		MP_CHECKOK(mp_toradix(&ry, s, 16));
		printf("ry   %s\n", s);
		res = MP_NO;
		goto CLEANUP;
	}

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Multiplication\n");
	else
		printf("TEST FAILED - Point Multiplication\n");
	mp_clear(&rx);
	mp_clear(&ry);
	mp_clear(&order_1);

	return res;
}
Пример #20
0
/* Tests point doubling in Modified Jacobian coordinates */
mp_err
testPointDoubleJm(ECGroup *ecgroup)
{
	mp_err res;
	mp_int pz, paz4, rx2, ry2, rz2, raz4;
	ecfp_jm_pt p, r;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&paz4) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&rz2) = 0;
	MP_DIGITS(&raz4) = 0;

	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&paz4));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&rz2));
	MP_CHECKOK(mp_init(&raz4));

	/* Set p */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	/* paz4 = az^4 */
	MP_CHECKOK(mp_set_int(&pz, 5));
	mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
	mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
	mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);

	ecfp_i2fp(p.z, &pz, ecgroup);
	ecfp_i2fp(p.az4, &paz4, ecgroup);

	group->pt_dbl_jm(&p, &r, group);

	M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000);

	/* Calculate doubling to compare against */
	ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2,
					  &rz2, ecgroup);
	ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup);

	/* Do comparison and check az^4 */
	MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf("  Test Passed - Point Doubling - Modified Jacobian\n");
	else
		printf("TEST FAILED - Point Doubling - Modified Jacobian\n");
	mp_clear(&pz);
	mp_clear(&paz4);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&rz2);
	mp_clear(&raz4);

	return res;

}
Пример #21
0
int main(void)
{
   mp_int a, b, c, d, e, f;
   unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
      gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
   unsigned rr;
   int i, n, err, cnt, ix, old_kara_m, old_kara_s;
   mp_digit mp;


   mp_init(&a);
   mp_init(&b);
   mp_init(&c);
   mp_init(&d);
   mp_init(&e);
   mp_init(&f);

   srand(time(NULL));

#if 0
   // test montgomery
   printf("Testing montgomery...\n");
   for (i = 1; i < 10; i++) {
      printf("Testing digit size: %d\n", i);
      for (n = 0; n < 1000; n++) {
         mp_rand(&a, i);
         a.dp[0] |= 1;

         // let's see if R is right
         mp_montgomery_calc_normalization(&b, &a);
         mp_montgomery_setup(&a, &mp);

         // now test a random reduction
         for (ix = 0; ix < 100; ix++) {
             mp_rand(&c, 1 + abs(rand()) % (2*i));
             mp_copy(&c, &d);
             mp_copy(&c, &e);

             mp_mod(&d, &a, &d);
             mp_montgomery_reduce(&c, &a, mp);
             mp_mulmod(&c, &b, &a, &c);

             if (mp_cmp(&c, &d) != MP_EQ) {
printf("d = e mod a, c = e MOD a\n");
mp_todecimal(&a, buf); printf("a = %s\n", buf);
mp_todecimal(&e, buf); printf("e = %s\n", buf);
mp_todecimal(&d, buf); printf("d = %s\n", buf);
mp_todecimal(&c, buf); printf("c = %s\n", buf);
printf("compare no compare!\n"); exit(EXIT_FAILURE); }
         }
      }
   }
   printf("done\n");

   // test mp_get_int
   printf("Testing: mp_get_int\n");
   for (i = 0; i < 1000; ++i) {
      t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
      mp_set_int(&a, t);
      if (t != mp_get_int(&a)) {
	 printf("mp_get_int() bad result!\n");
	 return 1;
      }
   }
   mp_set_int(&a, 0);
   if (mp_get_int(&a) != 0) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   mp_set_int(&a, 0xffffffff);
   if (mp_get_int(&a) != 0xffffffff) {
      printf("mp_get_int() bad result!\n");
      return 1;
   }
   // test mp_sqrt
   printf("Testing: mp_sqrt\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);
      n = (rand() & 15) + 1;
      mp_rand(&a, n);
      if (mp_sqrt(&a, &b) != MP_OKAY) {
	 printf("mp_sqrt() error!\n");
	 return 1;
      }
      mp_n_root(&a, 2, &a);
      if (mp_cmp_mag(&b, &a) != MP_EQ) {
	 printf("mp_sqrt() bad result!\n");
	 return 1;
      }
   }

   printf("\nTesting: mp_is_square\n");
   for (i = 0; i < 1000; ++i) {
      printf("%6d\r", i);
      fflush(stdout);

      /* test mp_is_square false negatives */
      n = (rand() & 7) + 1;
      mp_rand(&a, n);
      mp_sqr(&a, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fn:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 0) {
	 printf("fn:mp_is_square() bad result!\n");
	 return 1;
      }

      /* test for false positives */
      mp_add_d(&a, 1, &a);
      if (mp_is_square(&a, &n) != MP_OKAY) {
	 printf("fp:mp_is_square() error!\n");
	 return 1;
      }
      if (n == 1) {
	 printf("fp:mp_is_square() bad result!\n");
	 return 1;
      }

   }
   printf("\n\n");

   /* test for size */
   for (ix = 10; ix < 128; ix++) {
      printf("Testing (not safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    (rand() & 1) ? LTM_PRIME_2MSB_OFF :
			    LTM_PRIME_2MSB_ON, myrng, NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
   }

   for (ix = 16; ix < 128; ix++) {
      printf("Testing (   safe-prime): %9d bits    \r", ix);
      fflush(stdout);
      err =
	 mp_prime_random_ex(&a, 8, ix,
			    ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
			     LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
			    NULL);
      if (err != MP_OKAY) {
	 printf("failed with err code %d\n", err);
	 return EXIT_FAILURE;
      }
      if (mp_count_bits(&a) != ix) {
	 printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
	 return EXIT_FAILURE;
      }
      /* let's see if it's really a safe prime */
      mp_sub_d(&a, 1, &a);
      mp_div_2(&a, &a);
      mp_prime_is_prime(&a, 8, &cnt);
      if (cnt != MP_YES) {
	 printf("sub is not prime!\n");
	 return EXIT_FAILURE;
      }
   }

   printf("\n\n");

   mp_read_radix(&a, "123456", 10);
   mp_toradix_n(&a, buf, 10, 3);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 4);
   printf("a == %s\n", buf);
   mp_toradix_n(&a, buf, 10, 30);
   printf("a == %s\n", buf);


#if 0
   for (;;) {
      fgets(buf, sizeof(buf), stdin);
      mp_read_radix(&a, buf, 10);
      mp_prime_next_prime(&a, 5, 1);
      mp_toradix(&a, buf, 10);
      printf("%s, %lu\n", buf, a.dp[0] & 3);
   }
#endif

   /* test mp_cnt_lsb */
   printf("testing mp_cnt_lsb...\n");
   mp_set(&a, 1);
   for (ix = 0; ix < 1024; ix++) {
      if (mp_cnt_lsb(&a) != ix) {
	 printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
	 return 0;
      }
      mp_mul_2(&a, &a);
   }

/* test mp_reduce_2k */
   printf("Testing mp_reduce_2k...\n");
   for (cnt = 3; cnt <= 128; ++cnt) {
      mp_digit tmp;

      mp_2expt(&a, cnt);
      mp_sub_d(&a, 2, &a);	/* a = 2**cnt - 2 */


      printf("\nTesting %4d bits", cnt);
      printf("(%d)", mp_reduce_is_2k(&a));
      mp_reduce_2k_setup(&a, &tmp);
      printf("(%d)", tmp);
      for (ix = 0; ix < 1000; ix++) {
	 if (!(ix & 127)) {
	    printf(".");
	    fflush(stdout);
	 }
	 mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
	 mp_copy(&c, &b);
	 mp_mod(&c, &a, &c);
	 mp_reduce_2k(&b, &a, 2);
	 if (mp_cmp(&c, &b)) {
	    printf("FAILED\n");
	    exit(0);
	 }
      }
   }

/* test mp_div_3  */
   printf("Testing mp_div_3...\n");
   mp_set(&d, 3);
   for (cnt = 0; cnt < 10000;) {
      mp_digit r1, r2;

      if (!(++cnt & 127))
	 printf("%9d\r", cnt);
      mp_rand(&a, abs(rand()) % 128 + 1);
      mp_div(&a, &d, &b, &e);
      mp_div_3(&a, &c, &r2);

      if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
	 printf("\n\nmp_div_3 => Failure\n");
      }
   }
   printf("\n\nPassed div_3 testing\n");

/* test the DR reduction */
   printf("testing mp_dr_reduce...\n");
   for (cnt = 2; cnt < 32; cnt++) {
      printf("%d digit modulus\n", cnt);
      mp_grow(&a, cnt);
      mp_zero(&a);
      for (ix = 1; ix < cnt; ix++) {
	 a.dp[ix] = MP_MASK;
      }
      a.used = cnt;
      a.dp[0] = 3;

      mp_rand(&b, cnt - 1);
      mp_copy(&b, &c);

      rr = 0;
      do {
	 if (!(rr & 127)) {
	    printf("%9lu\r", rr);
	    fflush(stdout);
	 }
	 mp_sqr(&b, &b);
	 mp_add_d(&b, 1, &b);
	 mp_copy(&b, &c);

	 mp_mod(&b, &a, &b);
	 mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);

	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("Failed on trial %lu\n", rr);
	    exit(-1);

	 }
      } while (++rr < 500);
      printf("Passed DR test for %d digits\n", cnt);
   }

#endif

/* test the mp_reduce_2k_l code */
#if 0
#if 0
/* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
   mp_2expt(&a, 1024);
   mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
   mp_sub(&a, &b, &a);
#elif 1
/*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
   mp_2expt(&a, 2048);
   mp_read_radix(&b,
		 "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
		 16);
   mp_sub(&a, &b, &a);
#endif

   mp_todecimal(&a, buf);
   printf("p==%s\n", buf);
/* now mp_reduce_is_2k_l() should return */
   if (mp_reduce_is_2k_l(&a) != 1) {
      printf("mp_reduce_is_2k_l() return 0, should be 1\n");
      return EXIT_FAILURE;
   }
   mp_reduce_2k_setup_l(&a, &d);
   /* now do a million square+1 to see if it varies */
   mp_rand(&b, 64);
   mp_mod(&b, &a, &b);
   mp_copy(&b, &c);
   printf("testing mp_reduce_2k_l...");
   fflush(stdout);
   for (cnt = 0; cnt < (1UL << 20); cnt++) {
      mp_sqr(&b, &b);
      mp_add_d(&b, 1, &b);
      mp_reduce_2k_l(&b, &a, &d);
      mp_sqr(&c, &c);
      mp_add_d(&c, 1, &c);
      mp_mod(&c, &a, &c);
      if (mp_cmp(&b, &c) != MP_EQ) {
	 printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
	 mp_tohex(&b, buf);
	 printf("b == %s\n", buf);
	 mp_tohex(&c, buf);
	 printf("c == %s\n", buf);
	 return EXIT_FAILURE;
      }
   }
   printf("...Passed\n");
#endif

   div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
      sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
      sub_d_n = 0;

   /* force KARA and TOOM to enable despite cutoffs */
   KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
   TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

   for (;;) {
      /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
      switch (abs(rand()) % 7) {
      case 0:
	 mp_clear(&a);
	 mp_init(&a);
	 break;
      case 1:
	 mp_clear(&b);
	 mp_init(&b);
	 break;
      case 2:
	 mp_clear(&c);
	 mp_init(&c);
	 break;
      case 3:
	 mp_clear(&d);
	 mp_init(&d);
	 break;
      case 4:
	 mp_clear(&e);
	 mp_init(&e);
	 break;
      case 5:
	 mp_clear(&f);
	 mp_init(&f);
	 break;
      case 6:
	 break;			/* don't clear any */
      }


      printf
	 ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
	  add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
	  expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
      fgets(cmd, 4095, stdin);
      cmd[strlen(cmd) - 1] = 0;
      printf("%s  ]\r", cmd);
      fflush(stdout);
      if (!strcmp(cmd, "mul2d")) {
	 ++mul2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_mul_2d(&a, rr, &a);
	 a.sign = b.sign;
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("mul2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div2d")) {
	 ++div2d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &rr);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);

	 mp_div_2d(&a, rr, &a, &e);
	 a.sign = b.sign;
	 if (a.used == b.used && a.used == 0) {
	    a.sign = b.sign = MP_ZPOS;
	 }
	 if (mp_cmp(&a, &b) != MP_EQ) {
	    printf("div2d failed, rr == %d\n", rr);
	    draw(&a);
	    draw(&b);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add")) {
	 ++add_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_add(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("add %lu failure!\n", add_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

	 /* test the sign/unsigned storage functions */

	 rr = mp_signed_bin_size(&c);
	 mp_to_signed_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mp_signed_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }


	 rr = mp_unsigned_bin_size(&c);
	 mp_to_unsigned_bin(&c, (unsigned char *) cmd);
	 memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
	 mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
	 if (mp_cmp_mag(&c, &d) != MP_EQ) {
	    printf("mp_unsigned_bin failure!\n");
	    draw(&c);
	    draw(&d);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sub")) {
	 ++sub_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_sub(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("sub %lu failure!\n", sub_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul")) {
	 ++mul_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_mul(&d, &b, &d);
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("mul %lu failure!\n", mul_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "div")) {
	 ++div_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);

	 mp_div(&a, &b, &e, &f);
	 if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
	    printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
		   mp_cmp(&d, &f));
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    draw(&f);
	    return 0;
	 }

      } else if (!strcmp(cmd, "sqr")) {
	 ++sqr_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_copy(&a, &c);
	 mp_sqr(&c, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sqr %lu failure!\n", sqr_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "gcd")) {
	 ++gcd_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_gcd(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("gcd %lu failure!\n", gcd_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "lcm")) {
	 ++lcm_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_copy(&a, &d);
	 mp_lcm(&d, &b, &d);
	 d.sign = c.sign;
	 if (mp_cmp(&c, &d) != MP_EQ) {
	    printf("lcm %lu failure!\n", lcm_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    return 0;
	 }
      } else if (!strcmp(cmd, "expt")) {
	 ++expt_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&d, buf, 64);
	 mp_copy(&a, &e);
	 mp_exptmod(&e, &b, &c, &e);
	 if (mp_cmp(&d, &e) != MP_EQ) {
	    printf("expt %lu failure!\n", expt_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    draw(&e);
	    return 0;
	 }
      } else if (!strcmp(cmd, "invmod")) {
	 ++inv_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&c, buf, 64);
	 mp_invmod(&a, &b, &d);
	 mp_mulmod(&d, &a, &b, &e);
	 if (mp_cmp_d(&e, 1) != MP_EQ) {
	    printf("inv [wrong value from MPI?!] failure\n");
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    draw(&d);
	    mp_gcd(&a, &b, &e);
	    draw(&e);
	    return 0;
	 }

      } else if (!strcmp(cmd, "div2")) {
	 ++div2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_div_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("div_2 %lu failure\n", div2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "mul2")) {
	 ++mul2_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_mul_2(&a, &c);
	 if (mp_cmp(&c, &b) != MP_EQ) {
	    printf("mul_2 %lu failure\n", mul2_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    return 0;
	 }
      } else if (!strcmp(cmd, "add_d")) {
	 ++add_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_add_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("add_d %lu failure\n", add_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      } else if (!strcmp(cmd, "sub_d")) {
	 ++sub_d_n;
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&a, buf, 64);
	 fgets(buf, 4095, stdin);
	 sscanf(buf, "%d", &ix);
	 fgets(buf, 4095, stdin);
	 mp_read_radix(&b, buf, 64);
	 mp_sub_d(&a, ix, &c);
	 if (mp_cmp(&b, &c) != MP_EQ) {
	    printf("sub_d %lu failure\n", sub_d_n);
	    draw(&a);
	    draw(&b);
	    draw(&c);
	    printf("d == %d\n", ix);
	    return 0;
	 }
      }
   }
   return 0;
}
Пример #22
0
int mp_isperfpower(mp_int *z, mp_int *rootout, mp_int *exponent)
{
   mp_int root, power, tempr;
   mp_bitset_t *bst;
   unsigned long p, max, highbit, lowbit;
   int ret, e;
   p = 2;
   /* Place some sanity checks here */
   /* No, really! Do it! */

   /* ceil(log_2(n)) */
   max = (unsigned long) mp_highbit(z);
   highbit = max;
   lowbit = (unsigned long) mp_lowbit(z);

   /* Is it N=2^p ? */
   if (highbit == lowbit) {
      if (exponent != NULL) {
         if ((e = mp_set_int(exponent, (mp_digit) highbit)) != MP_OKAY) {
            return e;
         }
      }
      if (rootout != NULL) {
         if ((e = mp_set_int(rootout, (mp_digit)(2))) != MP_OKAY) {
            return e;
         }
      }
      return MP_YES;
   }
   /* mp_is[_]square() is not much faster, but still a bit */
   if (rootout != NULL) {
      if ((e = mp_issquare(z, &ret, rootout)) != MP_OKAY) {
         return e;
      }
   } else {
      if ((e = mp_is_square(z, &ret)) != MP_OKAY) {
         return e;
      }
   }
   if (ret != 0) {
      if (exponent != NULL) {
         if ((e = mp_set_int(exponent, (mp_digit)(2))) != MP_OKAY) {
            return e;
         }
      }
      return MP_YES;
   }

   if ((e = mp_init_multi(&root, &power, &tempr, NULL)) != MP_OKAY) {
      return e;
   }

   /* find perfection in higher powers */
   bst = malloc(sizeof(mp_bitset_t));
   if (bst == NULL) {
      return MP_MEM;
   }
   mp_bitset_alloc(bst, max);
   /*
      libtommath contains a small table (ltm_prime_tab) with the first 256
      primes, the largest is therefore 1619 which is not enough, sadly.
      The table for is_small_prime() has the primes up to 2^16 which is enough
      for more than 41,000 decimal digits. Sounds a lot but is it sufficient to
      code a branch?
      A sieve of that size would easily fit into the L1 processor cache and
      might fit into the cache of an embedded processor. The table is quite
      large and might fit into the cache of a modern server processor but
      it is doubtlful if it fits in the cache of an embedded cpu.
      That would result in a lot of preprocessor branches.
      BTW: it is nigh impossible to get specifications from the manufactoring
      companies, they are quite mute about their L* caches.
    */
   mp_eratosthenes(bst);

   while ((p = mp_bitset_nextset(bst, p + 1)) < max) {
      if ((e = mp_n_root(z, p, &root)) != MP_OKAY) {
         return e;
      }
      if ((e = mp_copy(&root, &tempr)) != MP_OKAY) {
         return e;
      }
      if ((e = mp_expt_d(&root, p, &power)) != MP_OKAY) {
         return e;
      }
      if (mp_cmp(z, &power) == MP_EQ) {
         if (rootout != NULL) {
            if ((e = mp_copy(&tempr, rootout)) != MP_OKAY) {
               return e;
            }
         }
         if (exponent != NULL) {
            if ((e = mp_set_int(exponent, (mp_digit)(p))) != MP_OKAY) {
               return e;
            }
         }
         mp_clear_multi(&tempr, &root, &power,NULL);
         mp_bitset_free(bst);
         return MP_YES;
      }
   }
   if (rootout != NULL) {
      if ((e = mp_set_int(rootout, (mp_digit)(0))) != MP_OKAY) {
         return e;
      }
   }
   if (exponent != NULL) {
      if ((e = mp_set_int(exponent, (mp_digit)(0))) != MP_OKAY) {
         return e;
      }
   }
   mp_clear_multi(&root, &power,NULL);
   mp_bitset_free(bst);
   return MP_NO;
}
Пример #23
0
/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian ->
 * Modified Jacobian coordinates. */
mp_err
testPointAddJmChud(ECGroup *ecgroup)
{
	mp_err res;
	mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz;
	ecfp_chud_pt q;
	ecfp_jm_pt p, r;
	EC_group_fp *group = (EC_group_fp *) ecgroup->extra1;

	MP_DIGITS(&qx) = 0;
	MP_DIGITS(&qy) = 0;
	MP_DIGITS(&qz) = 0;
	MP_DIGITS(&pz) = 0;
	MP_DIGITS(&paz4) = 0;
	MP_DIGITS(&iz) = 0;
	MP_DIGITS(&rx2) = 0;
	MP_DIGITS(&ry2) = 0;
	MP_DIGITS(&ix) = 0;
	MP_DIGITS(&iy) = 0;
	MP_DIGITS(&iz) = 0;
	MP_DIGITS(&test) = 0;

	MP_CHECKOK(mp_init(&qx));
	MP_CHECKOK(mp_init(&qy));
	MP_CHECKOK(mp_init(&qz));
	MP_CHECKOK(mp_init(&pz));
	MP_CHECKOK(mp_init(&paz4));
	MP_CHECKOK(mp_init(&rx2));
	MP_CHECKOK(mp_init(&ry2));
	MP_CHECKOK(mp_init(&ix));
	MP_CHECKOK(mp_init(&iy));
	MP_CHECKOK(mp_init(&iz));
	MP_CHECKOK(mp_init(&test));

	/* Test Modified Jacobian form addition */
	/* Set p */
	ecfp_i2fp(p.x, &ecgroup->genx, ecgroup);
	ecfp_i2fp(p.y, &ecgroup->geny, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);
	/* paz4 = az^4 */
	MP_CHECKOK(mp_set_int(&pz, 5));
	mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4);
	mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4);
	mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4);
	ecfp_i2fp(p.z, &pz, ecgroup);
	ecfp_i2fp(p.az4, &paz4, ecgroup);

	/* Set q */
	MP_CHECKOK(mp_set_int(&qz, 105));
	ecfp_i2fp(q.x, &ecgroup->geny, ecgroup);
	ecfp_i2fp(q.y, &ecgroup->genx, ecgroup);
	ecfp_i2fp(q.z, &qz, ecgroup);
	mp_sqrmod(&qz, &ecgroup->meth->irr, &test);
	ecfp_i2fp(q.z2, &test, ecgroup);
	mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test);
	ecfp_i2fp(q.z3, &test, ecgroup);

	/* Do calculation */
	group->pt_add_jm_chud(&p, &q, &r, group);

	/* Calculate addition to compare against */
	ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy,
					  ecgroup);
	ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy,
						  &ix, &iy, &iz, ecgroup);
	ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup);

	MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup));

  CLEANUP:
	if (res == MP_OKAY)
		printf
			("  Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n");
	else
		printf
			("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n");

	mp_clear(&qx);
	mp_clear(&qy);
	mp_clear(&qz);
	mp_clear(&pz);
	mp_clear(&paz4);
	mp_clear(&rx2);
	mp_clear(&ry2);
	mp_clear(&ix);
	mp_clear(&iy);
	mp_clear(&iz);
	mp_clear(&test);

	return res;
}
Пример #24
0
/*
  Sets ret to nonzero value if arg is square, 0 if not
  Sets t to the square root of arg if one is available, 0 if not
 */
static int mp_issquare(mp_int *arg, int *ret, mp_int *t)
{
   int res;
   mp_digit c;
   mp_int tmp;

   unsigned long r;

   /* Default to Non-square :) */
   *ret = MP_NO;

   if (arg->sign == MP_NEG) {
      return MP_VAL;
   }

   /* digits used?  (TSD) */
   if (arg->used == 0) {
      return MP_OKAY;
   }

   /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
   if (rem_128[127 & DIGIT(arg, 0)] == 1) {
      mp_set_int(t, (mp_digit)(0));
      return MP_OKAY;
   }

   /* Next check mod 105 (3*5*7) */
   if ((res = mp_mod_d(arg, 105, &c)) != MP_OKAY) {
      mp_set_int(t, (mp_digit)(0));
      return res;
   }
   if (rem_105[c] == 1) {
      mp_set_int(t, (mp_digit)(0));
      return MP_OKAY;
   }
   if ((res =
           mp_init_set_int(t,
                           11L * 13L * 17L * 19L * 23L * 29L * 31L)) != MP_OKAY) {
      mp_set_int(t, (mp_digit)(0));
      return res;
   }
   if ((res = mp_mod(arg, t, t)) != MP_OKAY) {
      goto ERR;
   }
   r = mp_get_int(t);
   /* Check for other prime modules. We know that res
    * is already equal to MP_OKAY from the mp_mod call
    */
   if ((1L << (r % 11)) & 0x5C4L)
      goto ERR;
   if ((1L << (r % 13)) & 0x9E4L)
      goto ERR;
   if ((1L << (r % 17)) & 0x5CE8L)
      goto ERR;
   if ((1L << (r % 19)) & 0x4F50CL)
      goto ERR;
   if ((1L << (r % 23)) & 0x7ACCA0L)
      goto ERR;
   if ((1L << (r % 29)) & 0xC2EDD0CL)
      goto ERR;
   if ((1L << (r % 31)) & 0x6DE2B848L)
      goto ERR;

   /* Final check - is sqr(sqrt(arg)) == arg ? */
   if ((res = mp_sqrt(arg, t)) != MP_OKAY) {
      goto ERR;
   }
   mp_init(&tmp);
   if ((res = mp_sqr(t, &tmp)) != MP_OKAY) {
      goto ERR;
   }

   *ret = (mp_cmp_mag(&tmp, arg) == MP_EQ) ? MP_YES : MP_NO;
   mp_clear(&tmp);
   return res;
ERR:
   mp_set_int(t, (mp_digit)(0));
   mp_clear(&tmp);
   return res;
}
Пример #25
0
/* ---- trivial ---- */
static int set_int(void *a, unsigned long b)
{
   LTC_ARGCHK(a != NULL);
   return mpi_to_ltc_error(mp_set_int(a, b));
}
Пример #26
0
/* Performs basic tests of elliptic curve cryptography over prime fields.
 * If tests fail, then it prints an error message, aborts, and returns an
 * error code. Otherwise, returns 0. */
int
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
                 int generic)
{

    mp_int one, order_1, gx, gy, rx, ry, n;
    int size;
    mp_err res;
    char s[1000];

    /* initialize values */
    MP_CHECKOK(mp_init(&one));
    MP_CHECKOK(mp_init(&order_1));
    MP_CHECKOK(mp_init(&gx));
    MP_CHECKOK(mp_init(&gy));
    MP_CHECKOK(mp_init(&rx));
    MP_CHECKOK(mp_init(&ry));
    MP_CHECKOK(mp_init(&n));

    MP_CHECKOK(mp_set_int(&one, 1));
    MP_CHECKOK(mp_sub(&group->order, &one, &order_1));

    /* encode base point */
    if (group->meth->field_dec) {
        MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
        MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
    } else {
        MP_CHECKOK(mp_copy(&group->genx, &gx));
        MP_CHECKOK(mp_copy(&group->geny, &gy));
    }
    if (ectestPrint) {
        /* output base point */
        printf("  base point P:\n");
        MP_CHECKOK(mp_toradix(&gx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&gy, s, 16));
        printf("    %s\n", s);
        if (group->meth->field_enc) {
            printf("  base point P (encoded):\n");
            MP_CHECKOK(mp_toradix(&group->genx, s, 16));
            printf("    %s\n", s);
            MP_CHECKOK(mp_toradix(&group->geny, s, 16));
            printf("    %s\n", s);
        }
    }

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
    if (ectestPrint) {
        printf("  (order-1)*P (affine):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
    if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
    if (ectestPrint) {
        printf("  (order-1)*P (jacobian):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
    if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* multiply base point by order - 1 and check for negative of base
     * point */
    MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
                                 group));
    if (ectestPrint) {
        printf("  (order)*P (affine):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
                                 group));
    if (ectestPrint) {
        printf("  (order)*P (jacobian):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }
#endif

    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
    if (ectestPrint) {
        printf("  (order)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* multiply base point by order and check for point at infinity */
    MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
    if (ectestPrint) {
        printf("  (order)*P (ECPoint_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
        printf("  Error: invalid result (expected point at infinity).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* check that (order-1)P + (order-1)P + P == (order-1)P */
    MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
    MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
    if (ectestPrint) {
        printf("  (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
        MP_CHECKOK(mp_toradix(&rx, s, 16));
        printf("    %s\n", s);
        MP_CHECKOK(mp_toradix(&ry, s, 16));
        printf("    %s\n", s);
    }
    MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
    if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
        printf("  Error: invalid result (expected (- base point)).\n");
        res = MP_NO;
        goto CLEANUP;
    }

    /* test validate_point function */
    if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
        printf("  Error: validate point on base point failed.\n");
        res = MP_NO;
        goto CLEANUP;
    }
    MP_CHECKOK(mp_add_d(&gy, 1, &ry));
    if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
        printf("  Error: validate point on invalid point passed.\n");
        res = MP_NO;
        goto CLEANUP;
    }

    if (ectestTime) {
        /* compute random scalar */
        size = mpl_significant_bits(&group->meth->irr);
        if (size < MP_OKAY) {
            goto CLEANUP;
        }
        MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
        MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
        /* timed test */
        if (generic) {
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
            M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
                                       group)),
                            100);
#endif
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
        } else {
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
                            100);
            M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
        }
    }

CLEANUP:
    mp_clear(&one);
    mp_clear(&order_1);
    mp_clear(&gx);
    mp_clear(&gy);
    mp_clear(&rx);
    mp_clear(&ry);
    mp_clear(&n);
    if (res != MP_OKAY) {
        printf("  Error: exiting with error value %i\n", res);
    }
    return res;
}
Пример #27
0
/* Make an RSA key for size bits, with e specified, 65537 is a good e */
int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
{
    mp_int p, q, tmp1, tmp2, tmp3;
    int    err;

    if (key == NULL || rng == NULL)
        return BAD_FUNC_ARG;

    if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
        return BAD_FUNC_ARG;

    if (e < 3 || (e & 1) == 0)
        return BAD_FUNC_ARG;

    if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
        return err;

    err = mp_set_int(&tmp3, e);

    /* make p */
    if (err == MP_OKAY) {
        do {
            err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */

            if (err == MP_OKAY)
                err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */

            if (err == MP_OKAY)
                err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
        } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
    }

    /* make q */
    if (err == MP_OKAY) {
        do {
            err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */

            if (err == MP_OKAY)
                err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */

            if (err == MP_OKAY)
                err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
        } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
    }

    if (err == MP_OKAY)
        err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);

    if (err == MP_OKAY)
        err = mp_init_multi(&key->dP, &key->dP, &key->u, NULL, NULL, NULL);

    if (err == MP_OKAY)
        err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */

    if (err == MP_OKAY)
        err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */

    /* make key */
    if (err == MP_OKAY)
        err = mp_set_int(&key->e, e);  /* key->e = e */

    if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
        err = mp_invmod(&key->e, &tmp1, &key->d);

    if (err == MP_OKAY)
        err = mp_mul(&p, &q, &key->n);  /* key->n = pq */

    if (err == MP_OKAY)
        err = mp_sub_d(&p, 1, &tmp1);

    if (err == MP_OKAY)
        err = mp_sub_d(&q, 1, &tmp2);

    if (err == MP_OKAY)
        err = mp_mod(&key->d, &tmp1, &key->dP);

    if (err == MP_OKAY)
        err = mp_mod(&key->d, &tmp2, &key->dQ);

    if (err == MP_OKAY)
        err = mp_invmod(&q, &p, &key->u);

    if (err == MP_OKAY)
        err = mp_copy(&p, &key->p);

    if (err == MP_OKAY)
        err = mp_copy(&q, &key->q);

    if (err == MP_OKAY)
        key->type = RSA_PRIVATE; 

    mp_clear(&tmp3); 
    mp_clear(&tmp2); 
    mp_clear(&tmp1); 
    mp_clear(&q); 
    mp_clear(&p);

    if (err != MP_OKAY) {
        FreeRsaKey(key);        
        return err;
    }

    return 0;
}
//http://numbers.computation.free.fr/Constants/Algorithms/splitting.html
int mp_acoth_binary_splitting(mp_int * q, mp_int * a, mp_int * b, mp_int * P,
			      mp_int * Q, mp_int * R)
{
    int err;
    mp_int p1, q1, r1, p2, q2, r2, t1, t2, one;
    if ((err =
	 mp_init_multi(&p1, &q1, &r1, &p2, &q2, &r2, &t1, &t2, &one,
		       NULL)) != MP_OKAY) {
	return err;
    }

    err = MP_OKAY;
    mp_set(&one, 1);
    if ((err = mp_sub(b, a, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if (mp_cmp(&t1, &one) == MP_EQ) {
	if ((err = mp_mul_2d(a, 1, &t1)) != MP_OKAY) {
	    goto _ERR;
	}
	if ((err = mp_add_d(&t1, 3, &t1)) != MP_OKAY) {
	    goto _ERR;
	}

	if ((err = mp_set_int(P, 1)) != MP_OKAY) {
	    goto _ERR;
	}
	if ((err = mp_sqr(q, &t2)) != MP_OKAY) {
	    goto _ERR;
	}
	if ((err = mp_mul(&t1, &t2, Q)) != MP_OKAY) {
	    goto _ERR;
	}
	if ((err = mp_copy(&t1, R)) != MP_OKAY) {
	    goto _ERR;
	}
	goto _ERR;
    }

    if ((err = mp_add(a, b, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_div_2d(&t1, 1, &t1, NULL)) != MP_OKAY) {
	goto _ERR;
    }

    if ((err = mp_acoth_binary_splitting(q, a, &t1, &p1, &q1, &r1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_acoth_binary_splitting(q, &t1, b, &p2, &q2, &r2)) != MP_OKAY) {
	goto _ERR;
    }
    //P = q2*p1 + r1*p2
    if ((err = mp_mul(&q2, &p1, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&r1, &p2, &t2)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&t1, &t2, P)) != MP_OKAY) {
	goto _ERR;
    }
    //Q =  q1*q2
    if ((err = mp_mul(&q1, &q2, Q)) != MP_OKAY) {
	goto _ERR;
    }
    //R = r1*r2
    if ((err = mp_mul(&r1, &r2, R)) != MP_OKAY) {
	goto _ERR;
    }

  _ERR:
    mp_clear_multi(&p1, &q1, &r1, &p2, &q2, &r2, &t1, &t2, &one, NULL);
    return err;
}
Пример #29
0
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
 * using Montgomery point multiplication algorithm Mxy() in appendix of
 * Lopex, J. and Dahab, R.  "Fast multiplication on elliptic curves over
 * GF(2^m) without precomputation". Returns: 0 on error 1 if return value
 * should be the point at infinity 2 otherwise */
static int
gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1,
                 mp_int *x2, mp_int *z2, const ECGroup *group)
{
        mp_err res = MP_OKAY;
        int ret = 0;
        mp_int t3, t4, t5;

        MP_DIGITS(&t3) = 0;
        MP_DIGITS(&t4) = 0;
        MP_DIGITS(&t5) = 0;
        MP_CHECKOK(mp_init(&t3, FLAG(x2)));
        MP_CHECKOK(mp_init(&t4, FLAG(x2)));
        MP_CHECKOK(mp_init(&t5, FLAG(x2)));

        if (mp_cmp_z(z1) == 0) {
                mp_zero(x2);
                mp_zero(z2);
                ret = 1;
                goto CLEANUP;
        }

        if (mp_cmp_z(z2) == 0) {
                MP_CHECKOK(mp_copy(x, x2));
                MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth));
                ret = 2;
                goto CLEANUP;
        }

        MP_CHECKOK(mp_set_int(&t5, 1));
        if (group->meth->field_enc) {
                MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth));
        }

        MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth));

        MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth));
        MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth));
        MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth));
        MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth));
        MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth));

        MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth));
        MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth));
        MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth));
        MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth));
        MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth));

        MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth));
        MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth));
        MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth));
        MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth));
        MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth));

        MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth));
        MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth));

        ret = 2;

  CLEANUP:
        mp_clear(&t3);
        mp_clear(&t4);
        mp_clear(&t5);
        if (res == MP_OKAY) {
                return ret;
        } else {
                return 0;
        }
}
Пример #30
0
/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R.  "Fast
 * multiplication on elliptic curves over GF(2^m) without
 * precomputation". Elliptic curve points P and R can be identical. Uses
 * Montgomery projective coordinates. */
mp_err
ec_GF2m_pt_mul_mont(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 x1, x2, z1, z2;
        int i, j;
        mp_digit top_bit, mask;

        MP_DIGITS(&x1) = 0;
        MP_DIGITS(&x2) = 0;
        MP_DIGITS(&z1) = 0;
        MP_DIGITS(&z2) = 0;
        MP_CHECKOK(mp_init(&x1, FLAG(n)));
        MP_CHECKOK(mp_init(&x2, FLAG(n)));
        MP_CHECKOK(mp_init(&z1, FLAG(n)));
        MP_CHECKOK(mp_init(&z2, FLAG(n)));

        /* if result should be point at infinity */
        if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
                MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
                goto CLEANUP;
        }

        MP_CHECKOK(mp_copy(px, &x1));   /* x1 = px */
        MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
        MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth));      /* z2 =
                                                                                                                                 * x1^2 =
                                                                                                                                 * px^2 */
        MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
        MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth));      /* x2
                                                                                                                                                                 * =
                                                                                                                                                                 * px^4
                                                                                                                                                                 * +
                                                                                                                                                                 * b
                                                                                                                                                                 */

        /* find top-most bit and go one past it */
        i = MP_USED(n) - 1;
        j = MP_DIGIT_BIT - 1;
        top_bit = 1;
        top_bit <<= MP_DIGIT_BIT - 1;
        mask = top_bit;
        while (!(MP_DIGITS(n)[i] & mask)) {
                mask >>= 1;
                j--;
        }
        mask >>= 1;
        j--;

        /* if top most bit was at word break, go to next word */
        if (!mask) {
                i--;
                j = MP_DIGIT_BIT - 1;
                mask = top_bit;
        }

        for (; i >= 0; i--) {
                for (; j >= 0; j--) {
                        if (MP_DIGITS(n)[i] & mask) {
                                MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group, FLAG(n)));
                                MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group, FLAG(n)));
                        } else {
                                MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group, FLAG(n)));
                                MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group, FLAG(n)));
                        }
                        mask >>= 1;
                }
                j = MP_DIGIT_BIT - 1;
                mask = top_bit;
        }

        /* convert out of "projective" coordinates */
        i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group);
        if (i == 0) {
                res = MP_BADARG;
                goto CLEANUP;
        } else if (i == 1) {
                MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
        } else {
                MP_CHECKOK(mp_copy(&x2, rx));
                MP_CHECKOK(mp_copy(&z2, ry));
        }

  CLEANUP:
        mp_clear(&x1);
        mp_clear(&x2);
        mp_clear(&z1);
        mp_clear(&z2);
        return res;
}