static void fp_sub(element_ptr c, element_ptr a, element_ptr b) { eptr ad = (eptr)a->data, bd = (eptr)b->data; if (!ad->flag) { fp_neg(c, b); } else if (!bd->flag) { fp_set(c, a); } else { fptr p = (fptr)c->field->data; size_t t = p->limbs; eptr cd = (eptr)c->data; int i = mpn_cmp(ad->d, bd->d, t); if (i == 0) { cd->flag = 0; } else { cd->flag = 2; mpn_sub_n(cd->d, ad->d, bd->d, t); if (i < 0) { mpn_add_n(cd->d, cd->d, p->primelimbs, t); } } } }
int fp_isprime(fp_int *a) { fp_int b; fp_digit d; int r, res; /* do trial division */ for (r = 0; r < 256; r++) { fp_mod_d(a, primes[r], &d); if (d == 0) { return FP_NO; } } /* now do 8 miller rabins */ fp_init(&b); for (r = 0; r < 8; r++) { fp_set(&b, primes[r]); fp_prime_miller_rabin(a, &b, &res); if (res == FP_NO) { return FP_NO; } } return FP_YES; }
static void fp_halve(element_ptr r, element_ptr a) { fp_field_data_ptr p = r->field->data; const size_t t = p->limbs; int carry = 0; mp_limb_t *alimb = a->data; mp_limb_t *rlimb = r->data; if (alimb[0] & 1) carry = mpn_add_n(rlimb, alimb, p->primelimbs, t); else fp_set(r, a); mpn_rshift(rlimb, rlimb, t, 1); if (carry) rlimb[t - 1] |= ((mp_limb_t) 1) << (sizeof(mp_limb_t) * 8 - 1); }
static void fp_add(element_ptr c, element_ptr a, element_ptr b) { eptr ad = (eptr)a->data, bd = (eptr)b->data; if (!ad->flag) { fp_set(c, b); } else if (!bd->flag) { fp_set(c, a); } else { eptr cd = (eptr)c->data; fptr p = (fptr)a->field->data; const size_t t = p->limbs; mp_limb_t carry; carry = mpn_add_n(cd->d, ad->d, bd->d, t); if (carry) { // Assumes result of following sub is not zero, // i.e. modulus cannot be 2^(n * bits_per_limb). mpn_sub_n(cd->d, cd->d, p->primelimbs, t); cd->flag = 2; } else { int i = mpn_cmp(cd->d, p->primelimbs, t); if (!i) { cd->flag = 0; } else { cd->flag = 2; if (i > 0) { mpn_sub_n(cd->d, cd->d, p->primelimbs, t); } } } } }
static void fp_halve(element_ptr c, element_ptr a) { eptr ad = (eptr)a->data, cd = (eptr)c->data; if (!ad->flag) { cd->flag = 0; } else { fptr p = (fptr)c->field->data; const size_t t = p->limbs; int carry = 0; mp_limb_t *alimb = ad->d; mp_limb_t *climb = cd->d; if (alimb[0] & 1) { carry = mpn_add_n(climb, alimb, p->primelimbs, t); } else fp_set(c, a); mpn_rshift(climb, climb, t, 1); if (carry) climb[t - 1] |= ((mp_limb_t)1) << (sizeof(mp_limb_t)* 8 - 1); } }
/* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) { int x, bits; /* how many bits of last digit does b use */ bits = fp_count_bits (b) % DIGIT_BIT; if (!bits) bits = DIGIT_BIT; /* compute A = B^(n-1) * 2^(bits-1) */ if (b->used > 1) { fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1); } else { fp_set(a, 1); bits = 1; } /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { fp_mul_2 (a, a); if (fp_cmp_mag (a, b) != FP_LT) { s_fp_sub (a, b, a); } } }
/* ---- trivial ---- */ static int set_int(void *a, unsigned long b) { LTC_ARGCHK(a != NULL); fp_set(a, b); return CRYPT_OK; }
/* ---- trivial ---- */ static int set_int(void *a, ltc_mp_digit b) { LTC_ARGCHK(a != NULL); fp_set(a, b); return CRYPT_OK; }
/* c = 1/a (mod b) for odd b only */ int fp_invmod(fp_int *a, fp_int *b, fp_int *c) { fp_int x, y, u, v, B, D; int neg; /* 2. [modified] b must be odd */ if (fp_iseven (b) == FP_YES) { return fp_invmod_slow(a,b,c); } /* init all our temps */ fp_init(&x); fp_init(&y); fp_init(&u); fp_init(&v); fp_init(&B); fp_init(&D); /* x == modulus, y == value to invert */ fp_copy(b, &x); /* we need y = |a| */ fp_abs(a, &y); /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ fp_copy(&x, &u); fp_copy(&y, &v); fp_set (&D, 1); top: /* 4. while u is even do */ while (fp_iseven (&u) == FP_YES) { /* 4.1 u = u/2 */ fp_div_2 (&u, &u); /* 4.2 if B is odd then */ if (fp_isodd (&B) == FP_YES) { fp_sub (&B, &x, &B); } /* B = B/2 */ fp_div_2 (&B, &B); } /* 5. while v is even do */ while (fp_iseven (&v) == FP_YES) { /* 5.1 v = v/2 */ fp_div_2 (&v, &v); /* 5.2 if D is odd then */ if (fp_isodd (&D) == FP_YES) { /* D = (D-x)/2 */ fp_sub (&D, &x, &D); } /* D = D/2 */ fp_div_2 (&D, &D); } /* 6. if u >= v then */ if (fp_cmp (&u, &v) != FP_LT) { /* u = u - v, B = B - D */ fp_sub (&u, &v, &u); fp_sub (&B, &D, &B); } else { /* v - v - u, D = D - B */ fp_sub (&v, &u, &v); fp_sub (&D, &B, &D); } /* if not zero goto step 4 */ if (fp_iszero (&u) == FP_NO) { goto top; } /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (fp_cmp_d (&v, 1) != FP_EQ) { return FP_VAL; } /* b is now the inverse */ neg = a->sign; while (D.sign == FP_NEG) { fp_add (&D, b, &D); } fp_copy (&D, c); c->sign = neg; return FP_OKAY; }
static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c) { fp_int x, y, u, v, A, B, C, D; int res; /* b cannot be negative */ if (b->sign == FP_NEG || fp_iszero(b) == 1) { return FP_VAL; } /* init temps */ fp_init(&x); fp_init(&y); fp_init(&u); fp_init(&v); fp_init(&A); fp_init(&B); fp_init(&C); fp_init(&D); /* x = a, y = b */ if ((res = fp_mod(a, b, &x)) != FP_OKAY) { return res; } fp_copy(b, &y); /* 2. [modified] if x,y are both even then return an error! */ if (fp_iseven (&x) == 1 && fp_iseven (&y) == 1) { return FP_VAL; } /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ fp_copy (&x, &u); fp_copy (&y, &v); fp_set (&A, 1); fp_set (&D, 1); top: /* 4. while u is even do */ while (fp_iseven (&u) == 1) { /* 4.1 u = u/2 */ fp_div_2 (&u, &u); /* 4.2 if A or B is odd then */ if (fp_isodd (&A) == 1 || fp_isodd (&B) == 1) { /* A = (A+y)/2, B = (B-x)/2 */ fp_add (&A, &y, &A); fp_sub (&B, &x, &B); } /* A = A/2, B = B/2 */ fp_div_2 (&A, &A); fp_div_2 (&B, &B); } /* 5. while v is even do */ while (fp_iseven (&v) == 1) { /* 5.1 v = v/2 */ fp_div_2 (&v, &v); /* 5.2 if C or D is odd then */ if (fp_isodd (&C) == 1 || fp_isodd (&D) == 1) { /* C = (C+y)/2, D = (D-x)/2 */ fp_add (&C, &y, &C); fp_sub (&D, &x, &D); } /* C = C/2, D = D/2 */ fp_div_2 (&C, &C); fp_div_2 (&D, &D); } /* 6. if u >= v then */ if (fp_cmp (&u, &v) != FP_LT) { /* u = u - v, A = A - C, B = B - D */ fp_sub (&u, &v, &u); fp_sub (&A, &C, &A); fp_sub (&B, &D, &B); } else { /* v - v - u, C = C - A, D = D - B */ fp_sub (&v, &u, &v); fp_sub (&C, &A, &C); fp_sub (&D, &B, &D); } /* if not zero goto step 4 */ if (fp_iszero (&u) == 0) goto top; /* now a = C, b = D, gcd == g*v */ /* if v != 1 then there is no inverse */ if (fp_cmp_d (&v, 1) != FP_EQ) { return FP_VAL; } /* if its too low */ while (fp_cmp_d(&C, 0) == FP_LT) { fp_add(&C, b, &C); } /* too big */ while (fp_cmp_mag(&C, b) != FP_LT) { fp_sub(&C, b, &C); } /* C is now the inverse */ fp_copy(&C, c); return FP_OKAY; }