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; }
static int ltm_rsa_private_calculate(mp_int * in, mp_int * p, mp_int * q, mp_int * dmp1, mp_int * dmq1, mp_int * iqmp, mp_int * out) { mp_int vp, vq, u; mp_init_multi(&vp, &vq, &u, NULL); /* vq = c ^ (d mod (q - 1)) mod q */ /* vp = c ^ (d mod (p - 1)) mod p */ mp_mod(in, p, &u); mp_exptmod(&u, dmp1, p, &vp); mp_mod(in, q, &u); mp_exptmod(&u, dmq1, q, &vq); /* C2 = 1/q mod p (iqmp) */ /* u = (vp - vq)C2 mod p. */ mp_sub(&vp, &vq, &u); if (mp_isneg(&u)) mp_add(&u, p, &u); mp_mul(&u, iqmp, &u); mp_mod(&u, p, &u); /* c ^ d mod n = vq + u q */ mp_mul(&u, q, &u); mp_add(&u, &vq, out); mp_clear_multi(&vp, &vq, &u, NULL); return 0; }
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); } }
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; }
void GenerateKeys(mp_int *d, mp_int *e, mp_int *n) { while (1) { mp_int p; mp_init(&p); mp_prime_random_ex(&p,8,2048, LTM_PRIME_2MSB_ON, &createRandom,NULL); mp_print("P",&p); mp_int q; mp_init(&q); mp_prime_random_ex(&q,8,2048, LTM_PRIME_2MSB_ON, &createRandom,NULL); mp_print("Q",&q); mp_int pp; mp_init(&pp); mp_sub_d(&p,1,&pp); mp_int qq; mp_init(&qq); mp_sub_d(&q,1,&qq); mp_int pq; mp_init(&pq); mp_mul(&pp,&qq,&pq); mp_mul(&p,&q,n); mp_set(d, 5); mp_int temp; mp_init(&temp); mp_int g; mp_init(&g); mp_int t; mp_init(&t); mp_exteuclid(d,&pq,e, &temp,&g); if (mp_cmp_d(&g,1) == 0) return ; // now we would have to add 1, but we prefer to get some new numbers /* printf("Havve to add 1\n"); mp_add_d(d, 1, &t); printf("Exchange 1\n"); mp_copy(&t,d);*/ } }
/* computes least common multiple as a*b/(a, b) */ int mp_lcm (mp_int * a, mp_int * b, mp_int * c) { int res; mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_mul (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } if ((res = mp_gcd (a, b, c)) != MP_OKAY) { mp_clear (&t); return res; } res = mp_div (&t, c, c, NULL); mp_clear (&t); return res; }
/* * multiply bigint a with int d and put the result in c * Like mp_mul_d() but with a signed long as the small input */ static int s_mp_mul_si(const mp_int *a, long d, mp_int *c) { mp_int t; int err, neg = 0; if ((err = mp_init(&t)) != MP_OKAY) { return err; } if (d < 0) { neg = 1; d = -d; } /* * mp_digit might be smaller than a long, which excludes * the use of mp_mul_d() here. */ if ((err = mp_set_long(&t, (unsigned long) d)) != MP_OKAY) { goto LBL_MPMULSI_ERR; } if ((err = mp_mul(a, &t, c)) != MP_OKAY) { goto LBL_MPMULSI_ERR; } if (neg == 1) { c->sign = (a->sign == MP_NEG) ? MP_ZPOS: MP_NEG; } LBL_MPMULSI_ERR: mp_clear(&t); return err; }
int main(int argc, char *argv[]) { mp_int a, b, c; if(argc < 3) { fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]); return 1; } mp_init(&a); mp_init(&b); mp_init(&c); mp_read_radix(&a, (unsigned char *)argv[1], 10); mp_read_radix(&b, (unsigned char *)argv[2], 10); mp_mul(&a, &b, &c); { int len = mp_radix_size(&c, 10); char *buf = malloc(len + 1); mp_todecimal(&c, (unsigned char *)buf); printf("a + b = %s\n", buf); free(buf); } mp_clear(&a); mp_clear(&b); mp_clear(&c); return 0; }
/* calculate c = a**b using a square-multiply algorithm */ int mp_expt_d MPA(mp_int * a, mp_digit b, mp_int * c) { int res; mp_int g; if ((res = mp_init_copy (MPST, &g, a)) != MP_OKAY) { return res; } /* set initial result */ mp_set (c, 1); while(b > 0) { /* if the bit is set multiply */ if(b & 1) { if ((res = mp_mul (MPST, c, &g, c)) != MP_OKAY) { mp_clear(&g); return res; } } /* square */ if (b > 1 && (res = mp_sqr (MPST, &g, &g)) != MP_OKAY) { mp_clear(&g); return res; } /* shift to next bit */ b >>= 1; } mp_clear (&g); return MP_OKAY; }
/* calculate c = a**b using a square-multiply algorithm */ int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) { int res, x; mp_int g; if ((res = mp_init_copy (&g, a)) != MP_OKAY) { return res; } /* set initial result */ mp_set (c, 1); for (x = 0; x < (int) DIGIT_BIT; x++) { /* square */ if ((res = mp_sqr (c, c)) != MP_OKAY) { mp_clear (&g); return res; } /* if the bit is set multiply */ if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { if ((res = mp_mul (c, &g, c)) != MP_OKAY) { mp_clear (&g); return res; } } /* shift to next bit */ b <<= 1; } mp_clear (&g); return MP_OKAY; }
/* mul */ static int mul(void *a, void *b, void *c) { LTC_ARGCHK(a != NULL); LTC_ARGCHK(b != NULL); LTC_ARGCHK(c != NULL); return mpi_to_ltc_error(mp_mul(a, b, c)); }
/* 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; }
static void unblind(mp_int *out, mp_int *bi, mp_int *n) { /* out' = (out * 1/b) mod n */ mp_mul(out, bi, out); mp_mod(out, n, out); }
void fpsqr_mont(const felm_t ma, felm_t mc) { // Multiprecision squaring, c = a^2 mod p. dfelm_t temp = {0}; mp_mul(ma, ma, temp, NWORDS_FIELD); rdc_mont(temp, mc); }
void fpmul_mont(const felm_t ma, const felm_t mb, felm_t mc) { // Multiprecision multiplication, c = a*b mod p. dfelm_t temp = {0}; mp_mul(ma, mb, temp, NWORDS_FIELD); rdc_mont(temp, mc); }
/* reduces a modulo n where n is of the form 2**p - d This differs from reduce_2k since "d" can be larger than a single digit. */ int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) { mp_int q; int p, res; if ((res = mp_init(&q)) != MP_OKAY) { return res; } p = mp_count_bits(n); top: /* q = a/2**p, a = a mod 2**p */ if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { goto LBL_ERR; } /* q = q * d */ if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { goto LBL_ERR; } /* a = a + q */ if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { goto LBL_ERR; } if (mp_cmp_mag(a, n) != MP_LT) { s_mp_sub(a, n, a); goto top; } LBL_ERR: mp_clear(&q); return res; }
/* ** RSA Private key operation using CRT. */ static SECStatus rsa_PrivateKeyOpCRTNoCheck(RSAPrivateKey *key, mp_int *m, mp_int *c) { mp_int p, q, d_p, d_q, qInv; mp_int m1, m2, h, ctmp; mp_err err = MP_OKAY; SECStatus rv = SECSuccess; MP_DIGITS(&p) = 0; MP_DIGITS(&q) = 0; MP_DIGITS(&d_p) = 0; MP_DIGITS(&d_q) = 0; MP_DIGITS(&qInv) = 0; MP_DIGITS(&m1) = 0; MP_DIGITS(&m2) = 0; MP_DIGITS(&h) = 0; MP_DIGITS(&ctmp) = 0; CHECK_MPI_OK( mp_init(&p) ); CHECK_MPI_OK( mp_init(&q) ); CHECK_MPI_OK( mp_init(&d_p) ); CHECK_MPI_OK( mp_init(&d_q) ); CHECK_MPI_OK( mp_init(&qInv) ); CHECK_MPI_OK( mp_init(&m1) ); CHECK_MPI_OK( mp_init(&m2) ); CHECK_MPI_OK( mp_init(&h) ); CHECK_MPI_OK( mp_init(&ctmp) ); /* copy private key parameters into mp integers */ SECITEM_TO_MPINT(key->prime1, &p); /* p */ SECITEM_TO_MPINT(key->prime2, &q); /* q */ SECITEM_TO_MPINT(key->exponent1, &d_p); /* d_p = d mod (p-1) */ SECITEM_TO_MPINT(key->exponent2, &d_q); /* d_q = d mod (q-1) */ SECITEM_TO_MPINT(key->coefficient, &qInv); /* qInv = q**-1 mod p */ /* 1. m1 = c**d_p mod p */ CHECK_MPI_OK( mp_mod(c, &p, &ctmp) ); CHECK_MPI_OK( mp_exptmod(&ctmp, &d_p, &p, &m1) ); /* 2. m2 = c**d_q mod q */ CHECK_MPI_OK( mp_mod(c, &q, &ctmp) ); CHECK_MPI_OK( mp_exptmod(&ctmp, &d_q, &q, &m2) ); /* 3. h = (m1 - m2) * qInv mod p */ CHECK_MPI_OK( mp_submod(&m1, &m2, &p, &h) ); CHECK_MPI_OK( mp_mulmod(&h, &qInv, &p, &h) ); /* 4. m = m2 + h * q */ CHECK_MPI_OK( mp_mul(&h, &q, m) ); CHECK_MPI_OK( mp_add(m, &m2, m) ); cleanup: mp_clear(&p); mp_clear(&q); mp_clear(&d_p); mp_clear(&d_q); mp_clear(&qInv); mp_clear(&m1); mp_clear(&m2); mp_clear(&h); mp_clear(&ctmp); if (err) { MP_TO_SEC_ERROR(err); rv = SECFailure; } return rv; }
/** * bignum_mul - c = a * b * @a: Bignum from bignum_init() * @b: Bignum from bignum_init() * @c: Bignum from bignum_init(); used to store the result of a * b * Returns: 0 on success, -1 on failure */ int bignum_mul(const struct bignum *a, const struct bignum *b, struct bignum *c) { if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); return -1; } return 0; }
/* d = a * b (mod c) */ int mp_mulmod_montgomery (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { int res; mp_int R; mp_digit mp; /* initialize R */ if ((res = mp_init(&R)) != MP_OKAY) { printf("Error initializing the number. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* get normalizzation */ if ((res = mp_montgomery_calc_normalization(&R,c)) != MP_OKAY) { printf("Error getting norm. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* get mp value */ if ((res = mp_montgomery_setup(c, &mp)) != MP_OKAY) { printf("Error setting up montgomery. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* normalize ‘a’ so now a is equal to aR */ if ((res = mp_mulmod(a, &R, c, a)) != MP_OKAY) { printf("Error computing aR. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* normalize ‘b’ so now a is equal to bR */ if ((res = mp_mulmod(b, &R, c, b)) != MP_OKAY) { printf("Error computing aR. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* compute a * b in Montgomery domain */ if ((res = mp_mul(a, b, d)) != MP_OKAY) { printf("Error multiplying. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* now reduce ‘d’ back down to d = a*b*R^2 * R^-1 == a*b*R */ if ((res = mp_montgomery_reduce(d, c, mp)) != MP_OKAY) { printf("Error reducing. %s", mp_error_to_string(res)); return EXIT_FAILURE; } /* now reduce ‘d’ back down to d = a*b*R * R^-1 == a*b */ if ((res = mp_montgomery_reduce(d, c, mp)) != MP_OKAY) { printf("Error reducing. %s", mp_error_to_string(res)); return EXIT_FAILURE; } mp_clear (&R); return res; }
static void blind(mp_int *in, mp_int *b, mp_int *e, mp_int *n) { mp_int t1; mp_init(&t1); /* in' = (in * b^e) mod n */ mp_exptmod(b, e, n, &t1); mp_mul(&t1, in, in); mp_mod(in, n, in); mp_clear(&t1); }
int main(int argc, char *argv[]) { int ntests, prec, ix; unsigned int seed; char *senv; clock_t start, stop; double multime; mp_int a, b, c; if((senv = getenv("SEED")) != NULL) seed = atoi(senv); else seed = (unsigned int)time(NULL); if(argc < 3) { fprintf(stderr, "Usage: %s <ntests> <nbits>\n", argv[0]); return 1; } if((ntests = abs(atoi(argv[1]))) == 0) { fprintf(stderr, "%s: must request at least 1 test.\n", argv[0]); return 1; } if((prec = abs(atoi(argv[2]))) < CHAR_BIT) { fprintf(stderr, "%s: must request at least %d bits.\n", argv[0], CHAR_BIT); return 1; } prec = (prec + (DIGIT_BIT - 1)) / DIGIT_BIT; mp_init_size(&a, prec); mp_init_size(&b, prec); mp_init_size(&c, 2 * prec); srand(seed); start = clock(); for(ix = 0; ix < ntests; ix++) { mpp_random_size(&a, prec); mpp_random_size(&b, prec); mp_mul(&a, &a, &c); } stop = clock(); multime = (double)(stop - start) / CLOCKS_PER_SEC; printf("Total: %.4f\n", multime); printf("Individual: %.4f\n", multime / ntests); mp_clear(&a); mp_clear(&b); mp_clear(&c); return 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; }
void fp2mul_mont(const f2elm_t *a, const f2elm_t *b, f2elm_t *c) { // GF(p^2) multiplication using Montgomery arithmetic, c = a*b in GF(p^2). // Inputs: a = a0+a1*i and b = b0+b1*i, where a0, a1, b0, b1 are in [0, 2*p-1] // Output: c = c0+c1*i, where c0, c1 are in [0, 2*p-1] felm_t t1, t2; dfelm_t tt1, tt2, tt3; digit_t mask; unsigned int i, borrow = 0; mp_mul(a->e[0], b->e[0], tt1, NWORDS_FIELD); // tt1 = a0*b0 mp_mul(a->e[1], b->e[1], tt2, NWORDS_FIELD); // tt2 = a1*b1 mp_addfast(a->e[0], a->e[1], t1); // t1 = a0+a1 mp_addfast(b->e[0], b->e[1], t2); // t2 = b0+b1 mask = mp_subfast(tt1, tt2, tt3); // tt3 = a0*b0 - a1*b1. If tt3 < 0 then mask = 0xFF..F, else if tt3 >= 0 then mask = 0x00..0 for (i = 0; i < NWORDS_FIELD; i++) { ADDC(borrow, tt3[NWORDS_FIELD+i], ((const digit_t*)PRIME)[i] & mask, borrow, tt3[NWORDS_FIELD+i]); } rdc_mont(tt3, c->e[0]); // c[0] = a0*b0 - a1*b1 mp_addfastx2(tt1, tt2, tt1); // tt1 = a0*b0 + a1*b1 mp_mul(t1, t2, tt2, NWORDS_FIELD); // tt2 = (a0+a1)*(b0+b1) mp_subfast(tt2, tt1, tt2); // tt2 = (a0+a1)*(b0+b1) - a0*b0 - a1*b1 rdc_mont(tt2, c->e[1]); // c[1] = (a0+a1)*(b0+b1) - a0*b0 - a1*b1 }
/* computes least common multiple as |a*b|/(a, b) */ int mp_lcm(const mp_int *a, const mp_int *b, mp_int *c) { int res; mp_int t1, t2; if ((res = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) { return res; } /* t1 = get the GCD of the two inputs */ if ((res = mp_gcd(a, b, &t1)) != MP_OKAY) { goto LBL_T; } /* divide the smallest by the GCD */ if (mp_cmp_mag(a, b) == MP_LT) { /* store quotient in t2 such that t2 * b is the LCM */ if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { goto LBL_T; } res = mp_mul(b, &t2, c); } else { /* store quotient in t2 such that t2 * a is the LCM */ if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { goto LBL_T; } res = mp_mul(a, &t2, c); } /* fix the sign to positive */ c->sign = MP_ZPOS; LBL_T: mp_clear_multi(&t1, &t2, NULL); return res; }
/** Map a projective jacbobian point back to affine space @param P [in/out] The point to map @param modulus The modulus of the field the ECC curve is in @param mp The "b" value from montgomery_setup() @return CRYPT_OK on success */ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp) { void *t1, *t2; int err; LTC_ARGCHK(P != NULL); LTC_ARGCHK(modulus != NULL); LTC_ARGCHK(mp != NULL); if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) { return CRYPT_MEM; } /* first map z back to normal */ if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK) { goto done; } /* get 1/z */ if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK) { goto done; } /* get 1/z^2 and 1/z^3 */ if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; } if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK) { goto done; } if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK) { goto done; } if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK) { goto done; } /* multiply against x/y */ if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK) { goto done; } if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK) { goto done; } if ((err = mp_set(P->z, 1)) != CRYPT_OK) { goto done; } err = CRYPT_OK; done: mp_clear_multi(t1, t2, NULL); return err; }
int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y) { void *prime, *a, *b, *t1, *t2; int err; if ((err = mp_init_multi(&prime, &a, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } /* load prime, a and b */ if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK) goto cleanup; if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK) goto cleanup; if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK) goto cleanup; /* compute y^2 */ if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup; /* compute x^3 */ if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup; /* compute y^2 - x^3 - a*x */ if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup; if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup; /* adjust range (0, prime) */ while (mp_cmp_d(t1, 0) == LTC_MP_LT) { if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup; } while (mp_cmp(t1, prime) != LTC_MP_LT) { if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup; } /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } cleanup: mp_clear_multi(prime, b, t1, t2, NULL); return err; }
/* * 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 int is_point(ecc_key *key) { void *prime, *b, *t1, *t2; int err; if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } /* load prime and b */ if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; } if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; } /* compute y^2 */ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } /* compute x^3 */ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; } if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; } if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } /* compute y^2 - x^3 + 3x */ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; } if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; } while (mp_cmp_d(t1, 0) == LTC_MP_LT) { if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; } } while (mp_cmp(t1, prime) != LTC_MP_LT) { if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; } } /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } error: mp_clear_multi(prime, b, t1, t2, NULL); return err; }
/* d = a * b (mod c) */ int mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *c, mp_int *d) { int res; mp_int t; if ((res = mp_init_size(&t, c->used)) != MP_OKAY) { return res; } if ((res = mp_mul(a, b, &t)) != MP_OKAY) { mp_clear(&t); return res; } res = mp_mod(&t, c, d); mp_clear(&t); return res; }
/* d = a * b (mod c) */ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { int res; mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { return res; } if ((res = mp_mul (a, b, &t)) != MP_OKAY) { mp_clear (&t); return res; } res = mp_mod (&t, c, d); mp_clear (&t); return res; }