void fp_add(fp_int *a, fp_int *b, fp_int *c) { int sa, sb; /* get sign of both inputs */ sa = a->sign; sb = b->sign; /* handle two cases, not four */ if (sa == sb) { /* both positive or both negative */ /* add their magnitudes, copy the sign */ c->sign = sa; s_fp_add (a, b, c); } else { /* one positive, the other negative */ /* subtract the one with the greater magnitude from */ /* the one of the lesser magnitude. The result gets */ /* the sign of the one with the greater magnitude. */ if (fp_cmp_mag (a, b) == FP_LT) { c->sign = sb; s_fp_sub (b, a, c); } else { c->sign = sa; s_fp_sub (a, b, c); } } }
/* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ void fp_montgomery_calc_normalization(z *a, z *b) { int x, bits; /* how many bits of last digit does b use */ bits = zBits(b) % BITS_PER_DIGIT; if (!bits) bits = BITS_PER_DIGIT; /* compute A = B^(n-1) * 2^(bits-1) */ if (b->size > 1) { fp_2expt (a, (b->size - 1) * BITS_PER_DIGIT + bits - 1); } else { //printf("b.size == 1\n"); sp2z((fp_digit)1,a); bits = 1; } /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)BITS_PER_DIGIT; x++) { fp_mul_2 (a, a); // zShiftLeft(a,a,1); if (fp_cmp_mag (a, b) != FP_LT) { s_fp_sub (a, b, a); } //if (zCompare(a,b) > 0) // zSub(a,b,a); } }
/* 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); } } }
/* computes x/R == x (mod N) via Montgomery Reduction */ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) { fp_digit c[FP_SIZE], *_c, *tmpm, mu; int oldused, x, y, pa; /* bail if too large */ if (m->used > (FP_SIZE/2)) { return; } #ifdef TFM_SMALL_MONT_SET if (m->used <= 16) { fp_montgomery_reduce_small(a, m, mp); return; } #endif #if defined(USE_MEMSET) /* now zero the buff */ memset(c, 0, sizeof c); #endif pa = m->used; /* copy the input */ oldused = a->used; for (x = 0; x < oldused; x++) { c[x] = a->dp[x]; } #if !defined(USE_MEMSET) for (; x < 2*pa+1; x++) { c[x] = 0; } #endif MONT_START; for (x = 0; x < pa; x++) { fp_digit cy = 0; /* get Mu for this round */ LOOP_START; _c = c + x; tmpm = m->dp; y = 0; #if (defined(TFM_SSE2) || defined(TFM_X86_64)) for (; y < (pa & ~7); y += 8) { INNERMUL8; _c += 8; tmpm += 8; } #endif for (; y < pa; y++) { INNERMUL; ++_c; } LOOP_END; while (cy) { PROPCARRY; ++_c; } } /* now copy out */ _c = c + pa; tmpm = a->dp; for (x = 0; x < pa+1; x++) { *tmpm++ = *_c++; } for (; x < oldused; x++) { *tmpm++ = 0; } MONT_FINI; a->used = pa+1; fp_clamp(a); /* if A >= m then A = A - m */ if (fp_cmp_mag (a, m) != FP_LT) { s_fp_sub (a, m, a); } }