/* In-memory version of matrixX509ReadPubKey. This function was written strictly for clarity in the PeerSec crypto API subset. It extracts only the public key from a certificate file for use in the lower level encrypt/decrypt RSA routines. */ int32 matrixX509ParsePubKey(psPool_t *pool, unsigned char *certBuf, int32 certLen, sslRsaKey_t **key) { sslRsaKey_t *lkey; sslRsaCert_t *certStruct; int32 err; if (matrixX509ParseCert(pool, certBuf, certLen, &certStruct) < 0) { matrixX509FreeCert(certStruct); return -1; } lkey = *key = psMalloc(pool, sizeof(sslRsaKey_t)); memset(lkey, 0x0, sizeof(sslRsaKey_t)); if ((err = _mp_init_multi(pool, &lkey->e, &lkey->N, NULL, NULL, NULL, NULL, NULL, NULL)) != MP_OKAY) { matrixX509FreeCert(certStruct); psFree(lkey); return err; } mp_copy(&certStruct->publicKey.e, &lkey->e); mp_copy(&certStruct->publicKey.N, &lkey->N); mp_shrink(&lkey->e); mp_shrink(&lkey->N); lkey->size = certStruct->publicKey.size; matrixX509FreeCert(certStruct); return 0; }
/* calc a value mod 2^b */ int mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; /* if b is <= 0 then zero the int */ if (b <= 0) { mp_zero (c); return MP_OKAY; } /* if the modulus is larger than the value than return */ if (b > (int) (a->used * DIGIT_BIT)) { res = mp_copy (a, c); return res; } /* copy */ if ((res = mp_copy (a, c)) != MP_OKAY) { return res; } /* zero digits above the last digit of the modulus */ for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { c->dp[x] = 0; } /* clear the digit that is not completely outside/inside the modulus */ c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); mp_clamp (c); return MP_OKAY; }
/* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */ mp_err testPreCompute(ECGroup *ecgroup) { ecfp_chud_pt precomp[16]; ecfp_aff_pt p; EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; int i; mp_err res; mp_int x, y, ny, x2, y2; MP_DIGITS(&x) = 0; MP_DIGITS(&y) = 0; MP_DIGITS(&ny) = 0; MP_DIGITS(&x2) = 0; MP_DIGITS(&y2) = 0; MP_CHECKOK(mp_init(&x)); MP_CHECKOK(mp_init(&y)); MP_CHECKOK(mp_init(&ny)); MP_CHECKOK(mp_init(&x2)); MP_CHECKOK(mp_init(&y2)); ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); /* Perform precomputation */ group->precompute_chud(precomp, &p, group); M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000); /* Calculate addition to compare against */ MP_CHECKOK(mp_copy(&ecgroup->genx, &x)); MP_CHECKOK(mp_copy(&ecgroup->geny, &y)); MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup); for (i = 0; i < 8; i++) { MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup)); MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup)); ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup); MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); } CLEANUP: if (res == MP_OKAY) printf(" Test Passed - Precomputation\n"); else printf("TEST FAILED - Precomputation\n"); mp_clear(&x); mp_clear(&y); mp_clear(&ny); mp_clear(&x2); mp_clear(&y2); return res; }
/* * Verify that the public data in an RSA key matches the private * data. We also check the private data itself: we ensure that p > * q and that iqmp really is the inverse of q mod p. */ bool rsa_verify(RSAKey *key) { mp_int *n, *ed, *pm1, *qm1; unsigned ok = 1; /* Preliminary checks: p,q must actually be nonzero. */ if (mp_eq_integer(key->p, 0) | mp_eq_integer(key->q, 0)) return false; /* n must equal pq. */ n = mp_mul(key->p, key->q); ok &= mp_cmp_eq(n, key->modulus); mp_free(n); /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */ pm1 = mp_copy(key->p); mp_sub_integer_into(pm1, pm1, 1); ed = mp_modmul(key->exponent, key->private_exponent, pm1); mp_free(pm1); ok &= mp_eq_integer(ed, 1); mp_free(ed); qm1 = mp_copy(key->q); mp_sub_integer_into(qm1, qm1, 1); ed = mp_modmul(key->exponent, key->private_exponent, qm1); mp_free(qm1); ok &= mp_eq_integer(ed, 1); mp_free(ed); /* * Ensure p > q. * * I have seen key blobs in the wild which were generated with * p < q, so instead of rejecting the key in this case we * should instead flip them round into the canonical order of * p > q. This also involves regenerating iqmp. */ mp_int *p_new = mp_max(key->p, key->q); mp_int *q_new = mp_min(key->p, key->q); mp_free(key->p); mp_free(key->q); mp_free(key->iqmp); key->p = p_new; key->q = q_new; key->iqmp = mp_invert(key->q, key->p); return ok; }
static void two_complement_bitop(mp_int *a, mp_int *b, mp_int *c, int (*mp_bitop)(mp_int *, mp_int *, mp_int *)) { mp_int d; if (SIGN(a) ^ SIGN(b)) { /* exactly one of them is negative, so need to perform * some magic. tommath stores a sign bit, but Perl 6 expects * 2's complement */ mp_init(&d); if (MP_NEG == SIGN(a)) { grow_and_negate(a, USED(b), &d); mp_bitop(&d, b, c); } else { grow_and_negate(b, USED(a), &d); mp_bitop(a, &d, c); } if (DIGIT(c, USED(c) - 1) & ((mp_digit)1<<(mp_digit)(DIGIT_BIT - 1))) { grow_and_negate(c, c->used, &d); mp_copy(&d, c); mp_neg(c, c); } mp_clear(&d); } else { mp_bitop(a, b, c); } }
/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in * Montgomery projective coordinates. Uses algorithm Madd in appendix of * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation". */ static mp_err gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2, const ECGroup *group, int kmflag) { mp_err res = MP_OKAY; mp_int t1, t2; MP_DIGITS(&t1) = 0; MP_DIGITS(&t2) = 0; MP_CHECKOK(mp_init(&t1, kmflag)); MP_CHECKOK(mp_init(&t2, kmflag)); MP_CHECKOK(mp_copy(x, &t1)); MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth)); MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth)); MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth)); MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth)); MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth)); MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth)); MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth)); CLEANUP: mp_clear(&t1); mp_clear(&t2); return res; }
/* Field multiplication using Montgomery reduction. */ mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r, const GFMethod *meth) { mp_err res = MP_OKAY; #ifdef MP_MONT_USE_MP_MUL /* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont * is not implemented and we have to use mp_mul and s_mp_redc directly */ MP_CHECKOK(mp_mul(a, b, r)); MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); #else mp_int s; MP_DIGITS(&s) = 0; /* s_mp_mul_mont doesn't allow source and destination to be the same */ if ((a == r) || (b == r)) { MP_CHECKOK(mp_init(&s)); MP_CHECKOK(s_mp_mul_mont (a, b, &s, (mp_mont_modulus *) meth->extra1)); MP_CHECKOK(mp_copy(&s, r)); mp_clear(&s); } else { return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1); } #endif CLEANUP: return res; }
void mpi_rshift(const mpi *p, unsigned bits, mpi *q) { if (!bits) return; const unsigned digits = bits / MP_DIGIT_BITS; bits %= MP_DIGIT_BITS; const unsigned pbits = mpi_significant_bits(p); if (pbits <= bits) { mpi_zero(q); return; } if (p == q) { if (digits) { q->size -= digits; mp_copy(q->digits + digits, q->size, q->digits); } mp_rshifti(q->digits, q->size, bits); } else { const mp_size qsize = p->size - digits; MPI_SIZE(q, qsize); mp_rshift(p->digits + digits, qsize, bits, q->digits); } q->size -= (q->digits[q->size - 1] == 0); ASSERT(q->size != 0); }
void mpi_mul(const mpi *a, const mpi *b, mpi *c) { if (a->size == 0 || b->size == 0) { mpi_zero(c); return; } if (a == b) { mpi_sqr(a, c); return; } mp_size csize = a->size + b->size; if (a == c || b == c) { mp_digit *prod = MP_TMP_ALLOC(csize); mp_mul(a->digits, a->size, b->digits, b->size, prod); csize -= (prod[csize - 1] == 0); MPI_SIZE(c, csize); mp_copy(prod, csize, c->digits); MP_TMP_FREE(prod); } else { ASSERT(a->digits[a->size - 1] != 0); ASSERT(b->digits[b->size - 1] != 0); MPI_MIN_ALLOC(c, csize); mp_mul(a->digits, a->size, b->digits, b->size, c->digits); c->size = csize - (c->digits[csize - 1] == 0); } c->sign = a->sign ^ b->sign; }
void mpi_div(const mpi *a, const mpi *b, mpi *q) { mp_size qsize; ASSERT(b->size != 0); if (a->size == 0 || a->size < b->size) { mpi_zero(q); return; } if (a == b) { mpi_set_u32(q, 1); return; } qsize = a->size - b->size + 1; if (a == q || b == q) { mp_digit *quot = MP_TMP_ALLOC(qsize); mp_div(a->digits, a->size, b->digits, b->size, quot); qsize -= (quot[qsize - 1] == 0); MPI_SIZE(q, qsize); mp_copy(quot, qsize, q->digits); MP_TMP_FREE(quot); } else { MPI_MIN_ALLOC(q, qsize); mp_div(a->digits, a->size, b->digits, b->size, q->digits); MP_NORMALIZE(q->digits, q->size); } q->sign = a->sign ^ b->sign; }
/* sets given mp_int p,q as the numerator,denominator in mp_rat a */ int mpq_set(mp_rat * a, mp_int * p, mp_int * q) { int e; if ((e = mp_copy(p, &a->numerator)) != MP_OKAY) { return e; } if ((e = mp_copy(q, &a->denominator)) != MP_OKAY) { return e; } mpq_normalize_sign(a); if ((e = mpq_reduce(a)) != MP_OKAY) { return e; } return MP_OKAY; }
void mpi_divexact(const mpi *a, const mpi *b, mpi *q) { ASSERT(b->size != 0); if (a->size == 0 || a->size < b->size) { /* FIXME: raise an error here? */ mpi_zero(q); return; } if (a == b) { mpi_set_u32(q, 1); return; } mp_size qsize = a->size - b->size + 1; if (a == q || b == q) { mp_digit *quot = MP_TMP_ALLOC(qsize); mp_divexact(a->digits, a->size, b->digits, b->size, quot); MP_NORMALIZE(quot, qsize); MPI_SIZE(q, qsize); mp_copy(quot, qsize, q->digits); MP_TMP_FREE(quot); } else { MPI_MIN_ALLOC(q, qsize); mp_divexact(a->digits, a->size, b->digits, b->size, q->digits); MP_NORMALIZE(q->digits, qsize); } q->size = qsize; q->sign = a->sign ^ b->sign; }
int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3) { mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp; int err; if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) { return err; } /* initialize, (u1,u2,u3) = (1,0,a) */ mp_set(&u1, 1); if ((err = mp_copy(a, &u3)) != MP_OKAY) { goto _ERR; } /* initialize, (v1,v2,v3) = (0,1,b) */ mp_set(&v2, 1); if ((err = mp_copy(b, &v3)) != MP_OKAY) { goto _ERR; } /* loop while v3 != 0 */ while (mp_iszero(&v3) == MP_NO) { /* q = u3/v3 */ if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY) { goto _ERR; } /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */ if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY) { goto _ERR; } if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY) { goto _ERR; } if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY) { goto _ERR; } /* (u1,u2,u3) = (v1,v2,v3) */ if ((err = mp_copy(&v1, &u1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v2, &u2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&v3, &u3)) != MP_OKAY) { goto _ERR; } /* (v1,v2,v3) = (t1,t2,t3) */ if ((err = mp_copy(&t1, &v1)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t2, &v2)) != MP_OKAY) { goto _ERR; } if ((err = mp_copy(&t3, &v3)) != MP_OKAY) { goto _ERR; } } /* make sure U3 >= 0 */ if (u3.sign == MP_NEG) { mp_neg(&u1, &u1); mp_neg(&u2, &u2); mp_neg(&u3, &u3); } /* copy result out */ if (U1 != NULL) { mp_exch(U1, &u1); } if (U2 != NULL) { mp_exch(U2, &u2); } if (U3 != NULL) { mp_exch(U3, &u3); } err = MP_OKAY; _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL); return err; }
static void initialise_common( struct ec_curve *curve, EllipticCurveType type, mp_int *p) { curve->type = type; curve->p = mp_copy(p); curve->fieldBits = mp_get_nbits(p); curve->fieldBytes = (curve->fieldBits + 7) / 8; }
void mpi_mul_u64(const mpi *a, uint64_t b, mpi *p) { if (mpi_is_zero(a) || b == 0) { mpi_zero(p); return; } else if (b == 1) { if (a != p) mpi_set_mpi(p, a); return; } else if ((b & (b-1)) == 0) { /* B is a power of 2 */ mpi_lshift(a, __builtin_ctzll(b), p); return; } else if (b == (mp_digit)b) { /* B fits in an mp_digit */ if (a == p) { mp_digit cy = mp_dmuli(p->digits, p->size, (mp_digit)b); if (cy) { MPI_MIN_ALLOC(p, p->size + 1); p->digits[p->size++] = cy; } } else { MPI_MIN_ALLOC(p, a->size); mp_digit cy = mp_dmul(a->digits, a->size, (mp_digit)b, p->digits); if (cy) { MPI_MIN_ALLOC(p, a->size + 1); p->digits[a->size] = cy; p->size = a->size + 1; } else { p->size = a->size; } } } else { unsigned bits = CHAR_BIT * sizeof(uint64_t) - __builtin_clzll(b); mp_size size = (bits + MP_DIGIT_BITS - 1) / MP_DIGIT_BITS; mp_digit *bp = MP_TMP_ALLOC(size); #if MP_DIGIT_BITS >= 64 bp[0] = b; #else for (mp_size j=0; j<size; j++) { bp[j] = (mp_digit)b; b >>= MP_DIGIT_BITS; } #endif if (a == p) { mp_digit *tmp = MP_TMP_ALLOC(p->size + size); mp_mul(p->digits, p->size, bp, size, tmp); MPI_MIN_ALLOC(p, p->size + size); mp_copy(tmp, p->size + size, p->digits); p->size = mp_rsize(p->digits, p->size + size); MP_TMP_FREE(tmp); } else { MPI_MIN_ALLOC(p, a->size + size); mp_mul(a->digits, a->size, bp, size, p->digits); p->size = mp_rsize(p->digits, a->size + size); } MP_TMP_FREE(bp); } }
/* Negates a field element. Note that for binary polynomial fields, the * negation of a field element is the field element itself. */ mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth) { if (a == r) { return MP_OKAY; } else { return mp_copy(a, r); } }
/* creates "a" then copies b into it */ int mp_init_copy (mp_int * a, mp_int * b) { int res; if ((res = mp_init_size (a, b->used)) != MP_OKAY) { return res; } return mp_copy (b, a); }
/* creates "a" then copies b into it */ int mp_init_copy (mp_int * a, mp_int * b) { int res; if ((res = mp_init (a)) != MP_OKAY) { return res; } return mp_copy (b, a); }
/*-------------------------------------------------------------------*/ static void convert_to_integer(gmp_poly_t *alg_sqrt, mp_t *n, mp_t *c, signed_mp_t *m1, signed_mp_t *m0, mp_t *res) { /* given the completed square root, apply the homomorphism to convert the polynomial to an integer. We do this by evaluating alg_sqrt at c*m0/m1, with all calculations performed mod n */ uint32 i; mpz_t gmp_n; mp_t m1_pow; mp_t m1_tmp; mp_t m0_tmp; mp_t next_coeff; mpz_init(gmp_n); mp2gmp(n, gmp_n); gmp_poly_mod_q(alg_sqrt, gmp_n, alg_sqrt); mpz_clear(gmp_n); mp_copy(&m1->num, &m1_tmp); if (m1->sign == NEGATIVE) mp_sub(n, &m1_tmp, &m1_tmp); mp_copy(&m1_tmp, &m1_pow); mp_modmul(&m0->num, c, n, &m0_tmp); if (m0->sign == POSITIVE) mp_sub(n, &m0_tmp, &m0_tmp); i = alg_sqrt->degree; gmp2mp(alg_sqrt->coeff[i], res); for (i--; (int32)i >= 0; i--) { mp_modmul(res, &m0_tmp, n, res); gmp2mp(alg_sqrt->coeff[i], &next_coeff); mp_modmul(&next_coeff, &m1_pow, n, &next_coeff); mp_add(res, &next_coeff, res); if (i > 0) mp_modmul(&m1_pow, &m1_tmp, n, &m1_pow); } if (mp_cmp(res, n) > 0) mp_sub(res, n, res); }
/* 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; }
/* Construct a generic GFMethod for arithmetic over prime fields with * irreducible irr. */ GFMethod * GFMethod_consGFp(const mp_int *irr) { mp_err res = MP_OKAY; GFMethod *meth = NULL; meth = GFMethod_new(); if (meth == NULL) return NULL; MP_CHECKOK(mp_copy(irr, &meth->irr)); meth->irr_arr[0] = mpl_significant_bits(irr); meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] = meth->irr_arr[4] = 0; switch (MP_USED(&meth->irr)) { /* maybe we need 1 and 2 words here as well?*/ case 3: meth->field_add = &ec_GFp_add_3; meth->field_sub = &ec_GFp_sub_3; break; case 4: meth->field_add = &ec_GFp_add_4; meth->field_sub = &ec_GFp_sub_4; break; case 5: meth->field_add = &ec_GFp_add_5; meth->field_sub = &ec_GFp_sub_5; break; case 6: meth->field_add = &ec_GFp_add_6; meth->field_sub = &ec_GFp_sub_6; break; default: meth->field_add = &ec_GFp_add; meth->field_sub = &ec_GFp_sub; } meth->field_neg = &ec_GFp_neg; meth->field_mod = &ec_GFp_mod; meth->field_mul = &ec_GFp_mul; meth->field_sqr = &ec_GFp_sqr; meth->field_div = &ec_GFp_div; meth->field_enc = NULL; meth->field_dec = NULL; meth->extra1 = NULL; meth->extra2 = NULL; meth->extra_free = NULL; CLEANUP: if (res != MP_OKAY) { GFMethod_free(meth); return NULL; } return meth; }
static void initialise_wcurve( struct ec_curve *curve, mp_int *p, mp_int *a, mp_int *b, mp_int *nonsquare, mp_int *G_x, mp_int *G_y, mp_int *G_order) { initialise_common(curve, EC_WEIERSTRASS, p); curve->w.wc = ecc_weierstrass_curve(p, a, b, nonsquare); curve->w.G = ecc_weierstrass_point_new(curve->w.wc, G_x, G_y); curve->w.G_order = mp_copy(G_order); }
static void initialise_ecurve( struct ec_curve *curve, mp_int *p, mp_int *d, mp_int *a, mp_int *nonsquare, mp_int *G_x, mp_int *G_y, mp_int *G_order) { initialise_common(curve, EC_EDWARDS, p); curve->e.ec = ecc_edwards_curve(p, d, a, nonsquare); curve->e.G = ecc_edwards_point_new(curve->e.ec, G_x, G_y); curve->e.G_order = mp_copy(G_order); }
STATIC mp_err s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont) { mp_err res; /* xMont = x * R mod N where N is modulus */ MP_CHECKOK( mp_copy( x, xMont ) ); MP_CHECKOK( s_mp_lshd( xMont, MP_USED(&mmm->N) ) ); /* xMont = x << b */ MP_CHECKOK( mp_div(xMont, &mmm->N, 0, xMont) ); /* mod N */ CLEANUP: return res; }
/* Decode a field element from Montgomery form. */ mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth) { mp_err res = MP_OKAY; if (a != r) { MP_CHECKOK(mp_copy(a, r)); } MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); CLEANUP: return res; }
/* sets given mp_int b as the numerator in mp_rat a */ int mpq_set_num(mp_rat * a, mp_int * b) { int e; if ((e = mp_copy(b, &a->numerator)) != MP_OKAY) { return e; } mpq_normalize_sign(a); if ((e = mpq_reduce(a)) != MP_OKAY) { return e; } return MP_OKAY; }
/* Construct a generic ECGroup for elliptic curves over binary polynomial * fields. */ ECGroup * ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5], const mp_int *curvea, const mp_int *curveb, const mp_int *genx, const mp_int *geny, const mp_int *order, int cofactor) { mp_err res = MP_OKAY; ECGroup *group = NULL; group = ECGroup_new(); if (group == NULL) return NULL; group->meth = GFMethod_consGF2m(irr, irr_arr); if (group->meth == NULL) { res = MP_MEM; goto CLEANUP; } MP_CHECKOK(mp_copy(curvea, &group->curvea)); MP_CHECKOK(mp_copy(curveb, &group->curveb)); MP_CHECKOK(mp_copy(genx, &group->genx)); MP_CHECKOK(mp_copy(geny, &group->geny)); MP_CHECKOK(mp_copy(order, &group->order)); group->cofactor = cofactor; group->point_add = &ec_GF2m_pt_add_aff; group->point_sub = &ec_GF2m_pt_sub_aff; group->point_dbl = &ec_GF2m_pt_dbl_aff; group->point_mul = &ec_GF2m_pt_mul_mont; group->base_point_mul = NULL; group->points_mul = &ec_pts_mul_basic; group->validate_point = &ec_GF2m_validate_point; CLEANUP: if (res != MP_OKAY) { ECGroup_free(group); return NULL; } return group; }
/* Converts a point P(px, py, pz) from Jacobian projective coordinates to * affine coordinates R(rx, ry). P and R can share x and y coordinates. * Assumes input is already field-encoded using field_enc, and returns * output that is still field-encoded. */ mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz, mp_int *rx, mp_int *ry, const ECGroup *group) { mp_err res = MP_OKAY; mp_int z1, z2, z3; MP_DIGITS(&z1) = 0; MP_DIGITS(&z2) = 0; MP_DIGITS(&z3) = 0; MP_CHECKOK(mp_init(&z1)); MP_CHECKOK(mp_init(&z2)); MP_CHECKOK(mp_init(&z3)); /* if point at infinity, then set point at infinity and exit */ if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry)); goto CLEANUP; } /* transform (px, py, pz) into (px / pz^2, py / pz^3) */ if (mp_cmp_d(pz, 1) == 0) { MP_CHECKOK(mp_copy(px, rx)); MP_CHECKOK(mp_copy(py, ry)); } else { MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth)); MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth)); MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth)); MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth)); MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth)); } CLEANUP: mp_clear(&z1); mp_clear(&z2); mp_clear(&z3); return res; }
/* b = |a| * * Simple function copies the input and fixes the sign to positive */ int mp_abs(mp_int * a, mp_int * b) { int res; /* copy a to b */ if (a != b) { if ((res = mp_copy(a, b)) != MP_OKAY) { return res; } } /* force the sign of b to positive */ b->sign = MP_ZPOS; return MP_OKAY; }
void mpi_set_mpi(mpi *p, const mpi *q) { ASSERT(p != NULL); ASSERT(q != NULL); if (p != q) { if (q->size == 0) { mpi_zero(p); } else { MPI_SIZE(p, q->size); mp_copy(q->digits, q->size, p->digits); p->sign = q->sign; } } }