Esempio n. 1
0
char filter(){
  fp_t abs = fp_add(fp_add(fp_mul(acc[0], acc[0]),
                           fp_mul(acc[1], acc[1])),
                    fp_mul(acc[2], acc[2]));
  ////////////////////////////////////////////////////////////////////////////////
  //idle state filter
  if (!(fp_cmp(abs, d2fp(0.32))==1 ||
        fp_cmp(abs, d2fp(0.27))==-1)) { // if between 0.01 - 0.09
    return false;
  }

  ////////////////////////////////////////////////////////////////////////////////
  // def = directional equivalence filter
  fp_t def_sensitivity = d2fp(0.08);
  if (fp_cmp(acc[0], fp_sub(dir_filter_ref[0], def_sensitivity))==-1 ||
      fp_cmp(acc[0], fp_add(dir_filter_ref[0], def_sensitivity))== 1 ||
      fp_cmp(acc[1], fp_sub(dir_filter_ref[1], def_sensitivity))==-1 ||
      fp_cmp(acc[1], fp_add(dir_filter_ref[1], def_sensitivity))== 1 ||
      fp_cmp(acc[2], fp_sub(dir_filter_ref[2], def_sensitivity))==-1 ||
      fp_cmp(acc[2], fp_add(dir_filter_ref[2], def_sensitivity))==1) {
    dir_filter_ref[0] = acc[0];
    dir_filter_ref[1] = acc[1];
    dir_filter_ref[2] = acc[2];
    return true;
  }
  return false;
}
Esempio n. 2
0
char filter(){
  fp_t abs = fp_add(fp_add(fp_mul(acc[0], acc[0]),
                           fp_mul(acc[1], acc[1])),
                    fp_mul(acc[2], acc[2]));
  ////////////////////////////////////////////////////////////////////////////////
  //idle state filter
  if (!(fp_cmp(abs, 10486)==1 /*0.32*/ ||
        fp_cmp(abs, 8847)==2 /*0.27*/)) { // if between 0.01 - 0.09
    return false;
  }

  ////////////////////////////////////////////////////////////////////////////////
  // def = directional equivalence filter
  const fp_t def_sensitivity = 2621; //0.08
  if (fp_cmp(acc[0], fp_sub(dir_filter_ref[0], def_sensitivity))==2 ||
      fp_cmp(acc[0], fp_add(dir_filter_ref[0], def_sensitivity))== 1 ||
      fp_cmp(acc[1], fp_sub(dir_filter_ref[1], def_sensitivity))==2 ||
      fp_cmp(acc[1], fp_add(dir_filter_ref[1], def_sensitivity))== 1 ||
      fp_cmp(acc[2], fp_sub(dir_filter_ref[2], def_sensitivity))==2 ||
      fp_cmp(acc[2], fp_add(dir_filter_ref[2], def_sensitivity))==1) {
    dir_filter_ref[0] = acc[0];
    dir_filter_ref[1] = acc[1];
    dir_filter_ref[2] = acc[2];
    return true;
  }
  return false;
}
Esempio n. 3
0
int ep_cmp(const ep_t p, const ep_t q) {
	if (fp_cmp(p->x, q->x) != CMP_EQ) {
		return CMP_NE;
	}

	if (fp_cmp(p->y, q->y) != CMP_EQ) {
		return CMP_NE;
	}

	if (fp_cmp(p->z, q->z) != CMP_EQ) {
		return CMP_NE;
	}

	return CMP_EQ;
}
Esempio n. 4
0
void fp_rdcn_low(dig_t *c, dig_t *a) {
	int i;
	dig_t r, c0, c1, u, *tmp;
	const dig_t *m;

	u = *(fp_prime_get_rdc());
	m = fp_prime_get();

	tmp = a;

	c1 = 0;
	for (i = 0; i < FP_DIGS; i++, tmp++) {
		r = (dig_t)(*tmp * u);
		c0 = mpn_addmul_1(tmp, m, FP_DIGS, r);
		c1 += mpn_add_1(tmp + FP_DIGS, tmp + FP_DIGS, FP_DIGS - i, c0);
	}
	for (i = 0; i < FP_DIGS; i++, tmp++) {
		c[i] = *tmp;
	}
	for (i = 0; i < c1; i++) {
		fp_subn_low(c, c, m);
	}
	if (fp_cmp(c, m) != CMP_LT) {
		fp_subn_low(c, c, m);
	}
}
Esempio n. 5
0
//Called at the end of the gesture,
//Returns the id of the recognized gesture or -1 if none.
char input_end(){
  fp_t prob;
  char recognized = -1; // which gesture has been recognized
  fp_t recogprob = -1; // probability of this gesture
  fp_t tmpgesture;
  char i, j;

  started = false;
  for (i = 0; i < 2; i++){
    prob = 0;
    // add probabilities
    for (j = 0; j < 8; j++){
      prob = fp_add(prob, s[j]);
    }
    if (fp_cmp(prob, recogprob)==1) {
      recogprob = prob;
      recognized = i;
    }
  }
  
  //printf("m->prob = %.30f\n", fp2d(recogprob));
  
  UARTSendArray("p=", 2);
  UARTSendInt(recogprob);
  //dir_filter_ref[0] = 0; //reset for next time
  return recognized;
}
Esempio n. 6
0
int fp_cmp_dig(const fp_t a, dig_t b) {
#if FP_RDC == MONTY
	fp_t t;
	int r = CMP_EQ;

	fp_null(t);

	TRY {
		fp_new(t);

		fp_prime_conv_dig(t, b);
		r = fp_cmp(a, t);
	} CATCH_ANY {
		THROW(ERR_CAUGHT);
	} FINALLY {
		fp_free(t);
	}

	return r;
#else
	for (int i = 1; i < FP_DIGS; i++) {
		if (a[i] > 0) {
			return CMP_GT;
		}
	}

	return fp_cmp1_low(a[0], b);
#endif
}
Esempio n. 7
0
 bool operator< (const Entry& rhs) const
 {
     if (fp_cmp (weight, rhs.weight)) {
         return height > rhs.height;
     } else {
         return weight < rhs.weight;
     }
 }
Esempio n. 8
0
int ed_cmp(const ed_t p, const ed_t q) {
	int ret = CMP_NE;

	if (fp_cmp(p->x, q->x) != CMP_EQ) {
		ret = CMP_NE;
	} else if (fp_cmp(p->y, q->y) != CMP_EQ) {
		ret = CMP_NE;
	} else if (fp_cmp(p->z, q->z) != CMP_EQ) {
		ret = CMP_NE;
#if ED_ADD == EXTND
	} else if (fp_cmp(p->t, q->t) != CMP_EQ) {
		ret = CMP_NE;
#endif
	} else {
		ret = CMP_EQ;
	}

	return ret;
}
void fp_rdcn_low(dig_t *c, dig_t *a) {
	dig_t r1, *m, *tmpc;

	m = fp_prime_get();
	tmpc = c;

	r1 = fp_rdci_low(c, a);

	if (r1 || fp_cmp(c, m) != CMP_LT) {
		fp_subn_low(c, c, m);
	}
}
Esempio n. 10
0
static int compare(void *a, void *b)
{
   int ret;
   LTC_ARGCHK(a != NULL);
   LTC_ARGCHK(b != NULL);
   ret = fp_cmp(a, b);
   switch (ret) {
      case FP_LT: return LTC_MP_LT;
      case FP_EQ: return LTC_MP_EQ;
      case FP_GT: return LTC_MP_GT;
   }
   return 0;
}
Esempio n. 11
0
void fp_rdcn_low(dig_t *c, dig_t *a) {
	int i, j;
	dig_t r0, r1, r2, u, v;
	dig_t *m, *tmp, *tmpm, *tmpc;

	dig_t t[2 * FP_DIGS] = {0};
	m = fp_prime_get();
	tmpc = c;

	r1 = fp_rdci_low(c, a);

	if (r1 || fp_cmp(c, m) != CMP_LT) {
		fp_subn_low(c, c, m);
	}
}
Esempio n. 12
0
int ed_is_valid(const ed_t p) {
	ed_t t;
#if ED_ADD == EXTND
	fp_t x_times_y;
#endif
	int r = 0;

	ed_null(t);
#if ED_ADD == EXTND
	fp_null(x_times_y);
#endif

	if (fp_is_zero(p->z)) {
		r = 0;
	} else {
		TRY {
#if ED_ADD == EXTND
			fp_new(x_times_y);
#endif
			ed_new(t);
			ed_norm(t, p);

			// check t coordinate
#if ED_ADD == PROJC
			r = ed_affine_is_valid(t->x, t->y);
#elif ED_ADD == EXTND
			fp_mul(x_times_y, t->x, t->y);
			if (fp_cmp(x_times_y, t->t) != CMP_EQ) {
				r = 0;
			} else {
				r = ed_affine_is_valid(t->x, t->y);
			}
#endif
			// if (r == 0) {
			// 	util_printf("\n\n(X, Y, T, Z) = \n");
			// 	ed_print(p);
			// }
		} CATCH_ANY {
			THROW(ERR_CAUGHT);
		} FINALLY {
#if ED_ADD == EXTND
			fp_free(x_times_y);
#endif
			ed_free(t);
		}
	}
	return r;
}
Esempio n. 13
0
static int
tfm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
{
    fp_int s, priv_key, p, peer_pub;
    size_t size = 0;
    int ret;

    if (dh->pub_key == NULL || dh->g == NULL || dh->priv_key == NULL)
	return -1;

    fp_init(&p);
    BN2mpz(&p, dh->p);

    fp_init(&peer_pub);
    BN2mpz(&peer_pub, pub);

    /* check if peers pubkey is reasonable */
    if (fp_isneg(&peer_pub)
	|| fp_cmp(&peer_pub, &p) >= 0
	|| fp_cmp_d(&peer_pub, 1) <= 0)
    {
	fp_zero(&p);
	fp_zero(&peer_pub);
	return -1;
    }

    fp_init(&priv_key);
    BN2mpz(&priv_key, dh->priv_key);

    fp_init(&s);

    ret = fp_exptmod(&peer_pub, &priv_key, &p, &s);

    fp_zero(&p);
    fp_zero(&peer_pub);
    fp_zero(&priv_key);

    if (ret != 0)
	return -1;

    size = fp_unsigned_bin_size(&s);
    fp_to_unsigned_bin(&s, shared);
    fp_zero(&s);

    return size;
}
Esempio n. 14
0
int fp_cmp_dig(const fp_t a, dig_t b) {
	fp_t t;
	int r = RLC_EQ;

	fp_null(t);

	TRY {
		fp_new(t);
		fp_prime_conv_dig(t, b);
		r = fp_cmp(a, t);
	} CATCH_ANY {
		THROW(ERR_CAUGHT);
	} FINALLY {
		fp_free(t);
	}

	return r;
}
Esempio n. 15
0
int ep_is_valid(const ep_t p) {
	ep_t t;
	int r = 0;

	ep_null(t);

	TRY {
		ep_new(t);

		ep_norm(t, p);

		ep_rhs(t->x, t);
		fp_sqr(t->y, t->y);
		r = (fp_cmp(t->x, t->y) == CMP_EQ) || ep_is_infty(p);
	} CATCH_ANY {
		THROW(ERR_CAUGHT);
	} FINALLY {
		ep_free(t);
	}
	return r;
}
Esempio n. 16
0
/**
 * Detects an optimization based on the curve coefficients.
 *
 * @param[out] opt		- the resulting optimization.
 * @param[in] a			- the curve coefficient.
 */
static void detect_opt(int *opt, fp_t a) {
	fp_t t;

	fp_null(t);

	TRY {
		fp_new(t);
		fp_prime_conv_dig(t, 3);
		fp_neg(t, t);

		if (fp_cmp(a, t) == CMP_EQ) {
			*opt = OPT_MINUS3;
		} else {
			if (fp_is_zero(a)) {
				*opt = OPT_ZERO;
			} else {
				fp_set_dig(t, 1);
				if (fp_cmp_dig(a, 1) == CMP_EQ) {
					*opt = OPT_ONE;
				} else {
					if (fp_cmp_dig(a, 2) == CMP_EQ) {
						*opt = OPT_TWO;
					} else {
						if (fp_bits(a) <= FP_DIGIT) {
							*opt = OPT_DIGIT;
						} else {
							*opt = RELIC_OPT_NONE;
						}
					}
				}
			}
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		fp_free(t);
	}
}
Esempio n. 17
0
unsigned char derive_group2(){
  fp_t a, b, c, d;
  fp_t minDist = 0x7fff; //0x7fff;
  char minGroup=0;
  fp_t *ref;
  char i;

  for (i = 0; i < 14; i++){
    ref = quantizerMap2[i];
    a = fp_sub(ref[0], acc[0]);
    b = fp_sub(ref[1], acc[1]);
    c = fp_sub(ref[2], acc[2]);
    d = fp_add(fp_add(fp_mul(a,a), fp_mul(b,b)), fp_mul(c,c));
    if (fp_cmp(d, minDist) == 2){
      minDist = d;
      minGroup = i;
    }
  }
  /* UARTSendArray("group=", 6); */
  /* UARTSendInt(minGroup); */
  return minGroup;
}
Esempio n. 18
0
//Called at the end of the gesture,
//Returns the id of the recognized gesture or -1 if none.
char input_end(){
  fp_t prob, prob2;
  char recognized; // which gesture has been recognized
  char j;

  started = false;
    prob = 0;
    prob2 = 0;
    // add probabilities
    for (j = 0; j < 8; j++){
      prob = fp_add(prob, s[j]);
      prob2 = fp_add(prob2, s2[j]);
    }
    if (fp_cmp(prob, prob2)==1) {
      recognized = 0;
    } else {
    	recognized = 1;
    }
  //printf("\np = %d %d\n", prob, prob2);

  return recognized;
}
Esempio n. 19
0
static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *Mp)
{
   fp_int t1, t2;
   fp_digit mp;

   LTC_ARGCHK(P       != NULL);
   LTC_ARGCHK(R       != NULL);
   LTC_ARGCHK(modulus != NULL);
   LTC_ARGCHK(Mp      != NULL);

   mp = *((fp_digit*)Mp);

   fp_init(&t1);
   fp_init(&t2);

   if (P != R) {
      fp_copy(P->x, R->x);
      fp_copy(P->y, R->y);
      fp_copy(P->z, R->z);
   }

   /* t1 = Z * Z */
   fp_sqr(R->z, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);
   /* Z = Y * Z */
   fp_mul(R->z, R->y, R->z);
   fp_montgomery_reduce(R->z, modulus, mp);
   /* Z = 2Z */
   fp_add(R->z, R->z, R->z);
   if (fp_cmp(R->z, modulus) != FP_LT) {
      fp_sub(R->z, modulus, R->z);
   }
   
   /* &t2 = X - T1 */
   fp_sub(R->x, &t1, &t2);
   if (fp_cmp_d(&t2, 0) == FP_LT) {
      fp_add(&t2, modulus, &t2);
   }
   /* T1 = X + T1 */
   fp_add(&t1, R->x, &t1);
   if (fp_cmp(&t1, modulus) != FP_LT) {
      fp_sub(&t1, modulus, &t1);
   }
   /* T2 = T1 * T2 */
   fp_mul(&t1, &t2, &t2);
   fp_montgomery_reduce(&t2, modulus, mp);
   /* T1 = 2T2 */
   fp_add(&t2, &t2, &t1);
   if (fp_cmp(&t1, modulus) != FP_LT) {
      fp_sub(&t1, modulus, &t1);
   }
   /* T1 = T1 + T2 */
   fp_add(&t1, &t2, &t1);
   if (fp_cmp(&t1, modulus) != FP_LT) {
      fp_sub(&t1, modulus, &t1);
   }

   /* Y = 2Y */
   fp_add(R->y, R->y, R->y);
   if (fp_cmp(R->y, modulus) != FP_LT) {
      fp_sub(R->y, modulus, R->y);
   }
   /* Y = Y * Y */
   fp_sqr(R->y, R->y);
   fp_montgomery_reduce(R->y, modulus, mp);
   /* T2 = Y * Y */
   fp_sqr(R->y, &t2);
   fp_montgomery_reduce(&t2, modulus, mp);
   /* T2 = T2/2 */
   if (fp_isodd(&t2)) {
      fp_add(&t2, modulus, &t2);
   }
   fp_div_2(&t2, &t2);
   /* Y = Y * X */
   fp_mul(R->y, R->x, R->y);
   fp_montgomery_reduce(R->y, modulus, mp);

   /* X  = T1 * T1 */
   fp_sqr(&t1, R->x);
   fp_montgomery_reduce(R->x, modulus, mp);
   /* X = X - Y */
   fp_sub(R->x, R->y, R->x);
   if (fp_cmp_d(R->x, 0) == FP_LT) {
      fp_add(R->x, modulus, R->x);
   }
   /* X = X - Y */
   fp_sub(R->x, R->y, R->x);
   if (fp_cmp_d(R->x, 0) == FP_LT) {
      fp_add(R->x, modulus, R->x);
   }

   /* Y = Y - X */     
   fp_sub(R->y, R->x, R->y);
   if (fp_cmp_d(R->y, 0) == FP_LT) {
      fp_add(R->y, modulus, R->y);
   }
   /* Y = Y * T1 */
   fp_mul(R->y, &t1, R->y);
   fp_montgomery_reduce(R->y, modulus, mp);
   /* Y = Y - T2 */
   fp_sub(R->y, &t2, R->y);
   if (fp_cmp_d(R->y, 0) == FP_LT) {
      fp_add(R->y, modulus, R->y);
   }
 
   return CRYPT_OK;
}
Esempio n. 20
0
int fp_srt(fp_t c, const fp_t a) {
	bn_t e;
	fp_t t0;
	fp_t t1;
	int r = 0;

	bn_null(e);
	fp_null(t0);
	fp_null(t1);

	TRY {
		bn_new(e);
		fp_new(t0);
		fp_new(t1);

		/* Make e = p. */
		e->used = FP_DIGS;
		dv_copy(e->dp, fp_prime_get(), FP_DIGS);

		if (fp_prime_get_mod8() == 3 || fp_prime_get_mod8() == 7) {
			/* Easy case, compute a^((p + 1)/4). */
			bn_add_dig(e, e, 1);
			bn_rsh(e, e, 2);

			fp_exp(t0, a, e);
			fp_sqr(t1, t0);
			r = (fp_cmp(t1, a) == CMP_EQ);
			fp_copy(c, t0);
		} else {
			int f = 0, m = 0;

			/* First, check if there is a root. Compute t1 = a^((p - 1)/2). */
			bn_rsh(e, e, 1);
			fp_exp(t0, a, e);

			if (fp_cmp_dig(t0, 1) != CMP_EQ) {
				/* Nope, there is no square root. */
				r = 0;
			} else {
				r = 1;
				/* Find a quadratic non-residue modulo p, that is a number t2
				 * such that (t2 | p) = t2^((p - 1)/2)!= 1. */
				do {
					fp_rand(t1);
					fp_exp(t0, t1, e);
				} while (fp_cmp_dig(t0, 1) == CMP_EQ);

				/* Write p - 1 as (e * 2^f), odd e. */
				bn_lsh(e, e, 1);
				while (bn_is_even(e)) {
					bn_rsh(e, e, 1);
					f++;
				}

				/* Compute t2 = t2^e. */
				fp_exp(t1, t1, e);

				/* Compute t1 = a^e, c = a^((e + 1)/2) = a^(e/2 + 1), odd e. */
				bn_rsh(e, e, 1);
				fp_exp(t0, a, e);
				fp_mul(e->dp, t0, a);
				fp_sqr(t0, t0);
				fp_mul(t0, t0, a);
				fp_copy(c, e->dp);

				while (1) {
					if (fp_cmp_dig(t0, 1) == CMP_EQ) {
						break;
					}
					fp_copy(e->dp, t0);
					for (m = 0; (m < f) && (fp_cmp_dig(t0, 1) != CMP_EQ); m++) {
						fp_sqr(t0, t0);
					}
					fp_copy(t0, e->dp);
					for (int i = 0; i < f - m - 1; i++) {
						fp_sqr(t1, t1);
					}
					fp_mul(c, c, t1);
					fp_sqr(t1, t1);
					fp_mul(t0, t0, t1);
					f = m;
				}
			}
		}
	}
	CATCH_ANY {
		THROW(ERR_CAUGHT);
	}
	FINALLY {
		bn_free(e);
		fp_free(t0);
		fp_free(t1);
	}
	return r;
}
Esempio n. 21
0
void fp_addm_low(dig_t *c, const dig_t *a, const dig_t *b) {
	fp_addn_low(c, a, b);
	if (fp_cmp(c, fp_prime_get()) != CMP_LT) {
		fp_subn_low(c, c, fp_prime_get());
	}
}
Esempio n. 22
0
/**
   Add two ECC points
   @param P        The point to add
   @param Q        The point to add
   @param R        [out] The destination of the double
   @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
*/
static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *Mp)
{
   fp_int  t1, t2, x, y, z;
   fp_digit mp;  
   
   LTC_ARGCHK(P       != NULL);
   LTC_ARGCHK(Q       != NULL);
   LTC_ARGCHK(R       != NULL);
   LTC_ARGCHK(modulus != NULL);
   LTC_ARGCHK(Mp      != NULL);

   mp = *((fp_digit*)Mp);

   fp_init(&t1);
   fp_init(&t2);
   fp_init(&x);
   fp_init(&y);
   fp_init(&z);

   /* should we dbl instead? */
   fp_sub(modulus, Q->y, &t1);
   if ( (fp_cmp(P->x, Q->x) == FP_EQ) && 
        (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
        (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
        return tfm_ecc_projective_dbl_point(P, R, modulus, Mp);
   }

   fp_copy(P->x, &x);
   fp_copy(P->y, &y);
   fp_copy(P->z, &z);

   /* if Z is one then these are no-operations */
   if (Q->z != NULL) {
      /* T1 = Z' * Z' */
      fp_sqr(Q->z, &t1);
      fp_montgomery_reduce(&t1, modulus, mp);
      /* X = X * T1 */
      fp_mul(&t1, &x, &x);
      fp_montgomery_reduce(&x, modulus, mp);
      /* T1 = Z' * T1 */
      fp_mul(Q->z, &t1, &t1);
      fp_montgomery_reduce(&t1, modulus, mp);
      /* Y = Y * T1 */
      fp_mul(&t1, &y, &y);
      fp_montgomery_reduce(&y, modulus, mp);
   }

   /* T1 = Z*Z */
   fp_sqr(&z, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);
   /* T2 = X' * T1 */
   fp_mul(Q->x, &t1, &t2);
   fp_montgomery_reduce(&t2, modulus, mp);
   /* T1 = Z * T1 */
   fp_mul(&z, &t1, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);
   /* T1 = Y' * T1 */
   fp_mul(Q->y, &t1, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);

   /* Y = Y - T1 */
   fp_sub(&y, &t1, &y);
   if (fp_cmp_d(&y, 0) == FP_LT) {
      fp_add(&y, modulus, &y);
   }
   /* T1 = 2T1 */
   fp_add(&t1, &t1, &t1);
   if (fp_cmp(&t1, modulus) != FP_LT) {
      fp_sub(&t1, modulus, &t1);
   }
   /* T1 = Y + T1 */
   fp_add(&t1, &y, &t1);
   if (fp_cmp(&t1, modulus) != FP_LT) {
      fp_sub(&t1, modulus, &t1);
   }
   /* X = X - T2 */
   fp_sub(&x, &t2, &x);
   if (fp_cmp_d(&x, 0) == FP_LT) {
      fp_add(&x, modulus, &x);
   }
   /* T2 = 2T2 */
   fp_add(&t2, &t2, &t2);
   if (fp_cmp(&t2, modulus) != FP_LT) {
      fp_sub(&t2, modulus, &t2);
   }
   /* T2 = X + T2 */
   fp_add(&t2, &x, &t2);
   if (fp_cmp(&t2, modulus) != FP_LT) {
      fp_sub(&t2, modulus, &t2);
   }

   /* if Z' != 1 */
   if (Q->z != NULL) {
      /* Z = Z * Z' */
      fp_mul(&z, Q->z, &z);
      fp_montgomery_reduce(&z, modulus, mp);
   }

   /* Z = Z * X */
   fp_mul(&z, &x, &z);
   fp_montgomery_reduce(&z, modulus, mp);

   /* T1 = T1 * X  */
   fp_mul(&t1, &x, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);
   /* X = X * X */
   fp_sqr(&x, &x);
   fp_montgomery_reduce(&x, modulus, mp);
   /* T2 = T2 * x */
   fp_mul(&t2, &x, &t2);
   fp_montgomery_reduce(&t2, modulus, mp);
   /* T1 = T1 * X  */
   fp_mul(&t1, &x, &t1);
   fp_montgomery_reduce(&t1, modulus, mp);
 
   /* X = Y*Y */
   fp_sqr(&y, &x);
   fp_montgomery_reduce(&x, modulus, mp);
   /* X = X - T2 */
   fp_sub(&x, &t2, &x);
   if (fp_cmp_d(&x, 0) == FP_LT) {
      fp_add(&x, modulus, &x);
   }

   /* T2 = T2 - X */
   fp_sub(&t2, &x, &t2);
   if (fp_cmp_d(&t2, 0) == FP_LT) {
      fp_add(&t2, modulus, &t2);
   } 
   /* T2 = T2 - X */
   fp_sub(&t2, &x, &t2);
   if (fp_cmp_d(&t2, 0) == FP_LT) {
      fp_add(&t2, modulus, &t2);
   }
   /* T2 = T2 * Y */
   fp_mul(&t2, &y, &t2);
   fp_montgomery_reduce(&t2, modulus, mp);
   /* Y = T2 - T1 */
   fp_sub(&t2, &t1, &y);
   if (fp_cmp_d(&y, 0) == FP_LT) {
      fp_add(&y, modulus, &y);
   }
   /* Y = Y/2 */
   if (fp_isodd(&y)) {
      fp_add(&y, modulus, &y);
   }
   fp_div_2(&y, &y);

   fp_copy(&x, R->x);
   fp_copy(&y, R->y);
   fp_copy(&z, R->z);
   
   return CRYPT_OK;
}
Esempio n. 23
0
int main(void)
{
   fp_int d, e, n, c, m, e_m;
   clock_t t1;
   int x;

   /* read in the parameters */
   fp_read_radix(&n, "ce032e860a9809a5ec31e4b0fd4b546f8c40043e3d2ec3d8f49d8f2f3dd19e887094ee1af75caa1c2e6cd9ec78bf1dfd6280002ac8c30ecd72da2e4c59a28a9248048aaae2a8fa627f71bece979cebf9f8eee2bd594d4a4f2e791647573c7ec1fcbd320d3825be3fa8a17c97086fdae56f7086ce512b81cc2fe44161270ec5e9", 16);
   fp_read_radix(&e, "10001", 16);
   fp_read_radix(&m, "39f5a911250f45b99390e2df322b33c729099ab52b5879d06b00818cce57c649a66ed7eb6d8ae214d11caf9c81e83a7368cf0edb2b71dad791f13fecf546123b40377851e67835ade1d6be57f4de18a62db4cdb1880f4ab2e6a29acfd85ca22a13dc1f6fee2621ef0fc8689cd738e6f065c033ec7c148d8d348688af83d6f6bd", 16);
   fp_read_radix(&c, "9ff70ea6968a04530e6b06bf01aa937209cc8450e76ac19477743de996ba3fb445923c947f8d0add8c57efa51d15485309918459da6c1e5a97f215193b797dce98db51bdb4639c2ecfa90ebb051e3a2daeffd27a7d6e62043703a7b15e0ada5170427b63099cd01ef52cd92d8723e5774bea32716aaa7f5adbae817fb12a5b50", 16);

   /* test it */
   fp_exptmod(&m, &e, &n, &e_m);
   if (fp_cmp(&e_m, &c)) {
      char buf[1024];
      printf("Encrypted text not equal\n");
      fp_toradix(&e_m, buf, 16);
      printf("e_m == %s\n", buf);
      return 0;
   }

   printf("CLOCKS_PER_SEC = %llu\n", (unsigned long long)CLOCKS_PER_SEC);
   t1 = clock();
   for (x = 0; x < 1000; x++) {
      fp_exptmod(&m, &e, &n, &e_m);
   }
   t1 = clock() - t1;
   printf("1000 RSA operations took     %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC);
   printf("RSA encrypt/sec              %10.5g\n", (double)CLOCKS_PER_SEC / ((double)t1 / 1000.0) );

   /* read in the parameters */
   fp_read_radix(&n, "a7f30e2e04d31acc6936916af1e404a4007adfb9e97864de28d1c7ba3034633bee2cd9d5da3ea3cdcdc9a6f3daf5702ef750f4c3aadb0e27410ac04532176795995148cdb4691bd09a8a846e3e24e073ce2f89b34dfeb2ee89b646923ca60ee3f73c4d5397478380425e7260f75dfdc54826e160395b0889b1162cf115a9773f", 16);
   fp_read_radix(&d, "16d166f3c9a404d810d3611e6e8ed43293fe1db75c8906eb4810785a4b82529929dade1db7f11ac0335d5a59773e3167b022479eedefa514a0399db5c900750a56323cf9f5b0f21e7d60a46d75f3fcaabf30a63cbe34048b741a57ac36a13914afda798709dea5771f8d456cf72ec5f3afc1d88d023de40311143a36e7028739", 16);
   fp_read_radix(&c, "7d216641c32543f5b8428bdd0b11d819cfbdb16f1df285247f677aa4d44de62ab064f4a0d060ec99cb94aa398113a4317f2c550d0371140b0fd2c88886cac771812e72faad4b7adf495b9b850b142ccd7f45c0a27f164c8c7731731c0015f69d0241812e769d961054618aeb9e8e8989dba95714a2cf56c9e525c5e34b5812dd", 16);
   fp_read_radix(&m, "5f323bf0b394b98ffd78727dc9883bb4f42287def6b60fa2a964b2510bc55d61357bf5a6883d2982b268810f8fef116d3ae68ebb41fd10d65a0af4bec0530eb369f37c14b55c3be60223b582372fb6589b648d5a0c7252d1ae2dae5809785d993e9e5d0c4d9b0bcba0cde0d6671734747fba5483c735e1dab7df7b10ec6f62d8", 16);

   /* test it */
   fp_exptmod(&c, &d, &n, &e_m);
   if (fp_cmp(&e_m, &m)) {
      char buf[1024];
      printf("Decrypted text not equal\n");
      fp_toradix(&e_m, buf, 16);
      printf("e_m == %s\n", buf);
      return 0;
   }

   t1 = clock();
   for (x = 0; x < 100; x++) {
      fp_exptmod(&c, &d, &n, &e_m);
   }
   t1 = clock() - t1;
   printf("100 RSA operations took      %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC);
   printf("RSA decrypt/sec              %10.5g\n", (double)CLOCKS_PER_SEC / ((double)t1 / 100.0) );


   /* test half size */
   fp_rshd(&n, n.used >> 1);
   fp_rshd(&d, d.used >> 1);
   fp_rshd(&c, c.used >> 1);
   printf("n.used == %4d bits\n", n.used * DIGIT_BIT);

   /* ensure n is odd */
   n.dp[0] |= 1;
   t1 = clock();
   for (x = 0; x < 100; x++) {
      fp_exptmod(&c, &d, &n, &e_m);
   }
   t1 = clock() - t1;
   printf("100 RSA-half operations took %10.5g seconds\n", (double)t1 / (double)CLOCKS_PER_SEC);
   printf("RSA decrypt/sec              %10.5g (estimate of RSA-1024-CRT) \n", (double)CLOCKS_PER_SEC / ((double)t1 / 50.0) );



   return 0;
}
Esempio n. 24
0
static int
tfm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
{
    fp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
    int counter, ret, bitsp;

    if (bits < 789)
	return -1;

    bitsp = (bits + 1) / 2;

    ret = -1;

    fp_init_multi(&el, &p, &q, &n, &n, &d, &dmp1, &dmq1, &iqmp, &t1, &t2, &t3, NULL);

    BN2mpz(&el, e);

    /* generate p and q so that p != q and bits(pq) ~ bits */
    counter = 0;
    do {
	BN_GENCB_call(cb, 2, counter++);
	CHECK(random_num(&p, bitsp), 0);
	CHECK(fp_find_prime(&p), FP_YES);

	fp_sub_d(&p, 1, &t1);
	fp_gcd(&t1, &el, &t2);
    } while(fp_cmp_d(&t2, 1) != 0);

    BN_GENCB_call(cb, 3, 0);

    counter = 0;
    do {
	BN_GENCB_call(cb, 2, counter++);
	CHECK(random_num(&q, bits - bitsp), 0);
	CHECK(fp_find_prime(&q), FP_YES);

	if (fp_cmp(&p, &q) == 0) /* don't let p and q be the same */
	    continue;

	fp_sub_d(&q, 1, &t1);
	fp_gcd(&t1, &el, &t2);
    } while(fp_cmp_d(&t2, 1) != 0);

    /* make p > q */
    if (fp_cmp(&p, &q) < 0) {
	fp_int c;
	fp_copy(&p, &c);
	fp_copy(&q, &p);
	fp_copy(&c, &q);
    }

    BN_GENCB_call(cb, 3, 1);

    /* calculate n,  		n = p * q */
    fp_mul(&p, &q, &n);

    /* calculate d, 		d = 1/e mod (p - 1)(q - 1) */
    fp_sub_d(&p, 1, &t1);
    fp_sub_d(&q, 1, &t2);
    fp_mul(&t1, &t2, &t3);
    fp_invmod(&el, &t3, &d);

    /* calculate dmp1		dmp1 = d mod (p-1) */
    fp_mod(&d, &t1, &dmp1);
    /* calculate dmq1		dmq1 = d mod (q-1) */
    fp_mod(&d, &t2, &dmq1);
    /* calculate iqmp 		iqmp = 1/q mod p */
    fp_invmod(&q, &p, &iqmp);

    /* fill in RSA key */

    rsa->e = mpz2BN(&el);
    rsa->p = mpz2BN(&p);
    rsa->q = mpz2BN(&q);
    rsa->n = mpz2BN(&n);
    rsa->d = mpz2BN(&d);
    rsa->dmp1 = mpz2BN(&dmp1);
    rsa->dmq1 = mpz2BN(&dmq1);
    rsa->iqmp = mpz2BN(&iqmp);

    ret = 1;

out:
    fp_zero_multi(&el, &p, &q, &n, &d, &dmp1,
		  &dmq1, &iqmp, &t1, &t2, &t3, NULL);

    return ret;
}
Esempio n. 25
0
static int
tfm_rsa_private_decrypt(int flen, const unsigned char* from,
			unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *ptr;
    int res;
    int size;
    fp_int in, out, n, e;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

    size = RSA_size(rsa);
    if (flen > size)
	return -2;

    fp_init_multi(&in, &out, NULL);

    BN2mpz(&n, rsa->n);
    BN2mpz(&e, rsa->e);

    fp_read_unsigned_bin(&in, rk_UNCONST(from), flen);

    if(fp_isneg(&in) || fp_cmp(&in, &n) >= 0) {
	size = -2;
	goto out;
    }

    if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
	fp_int p, q, dmp1, dmq1, iqmp;

	BN2mpz(&p, rsa->p);
	BN2mpz(&q, rsa->q);
	BN2mpz(&dmp1, rsa->dmp1);
	BN2mpz(&dmq1, rsa->dmq1);
	BN2mpz(&iqmp, rsa->iqmp);

	res = tfm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out);

	fp_zero_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);

	if (res != 0) {
	    size = -3;
	    goto out;
	}

    } else {
	fp_int d;

	if(fp_isneg(&in) || fp_cmp(&in, &n) >= 0)
	    return -4;

	BN2mpz(&d, rsa->d);
	res = fp_exptmod(&in, &d, &n, &out);
	fp_zero(&d);
	if (res != 0) {
	    size = -5;
	    goto out;
	}
    }

    ptr = to;
    {
	size_t ssize;
	ssize = fp_unsigned_bin_size(&out);
	assert(size >= ssize);
	fp_to_unsigned_bin(&out, ptr);
	size = ssize;
    }

    /* head zero was skipped by mp_int_to_unsigned */
    if (*ptr != 2) {
	size = -6;
	goto out;
    }
    size--; ptr++;
    while (size && *ptr != 0) {
	size--; ptr++;
    }
    if (size == 0)
	return -7;
    size--; ptr++;

    memmove(to, ptr, size);

 out:
    fp_zero_multi(&e, &n, &in, &out, NULL);

    return size;
}
Esempio n. 26
0
/* a/b => cb + d == a */
int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
{
  fp_int  q, x, y, t1, t2;
  int     n, t, i, norm, neg;

  /* is divisor zero ? */
  if (fp_iszero (b) == 1) {
    return FP_VAL;
  }

  /* if a < b then q=0, r = a */
  if (fp_cmp_mag (a, b) == FP_LT) {
    if (d != NULL) {
      fp_copy (a, d);
    } 
    if (c != NULL) {
      fp_zero (c);
    }
    return FP_OKAY;
  }

  fp_init(&q);
  q.used = a->used + 2;

  fp_init(&t1);
  fp_init(&t2);
  fp_init_copy(&x, a);
  fp_init_copy(&y, b);

  /* fix the sign */
  neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG;
  x.sign = y.sign = FP_ZPOS;

  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
  norm = fp_count_bits(&y) % DIGIT_BIT;
  if (norm < (int)(DIGIT_BIT-1)) {
     norm = (DIGIT_BIT-1) - norm;
     fp_mul_2d (&x, norm, &x);
     fp_mul_2d (&y, norm, &y);
  } else {
     norm = 0;
  }

  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
  n = x.used - 1;
  t = y.used - 1;

  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
  fp_lshd (&y, n - t);                                             /* y = y*b**{n-t} */

  while (fp_cmp (&x, &y) != FP_LT) {
    ++(q.dp[n - t]);
    fp_sub (&x, &y, &x);
  }

  /* reset y by shifting it back down */
  fp_rshd (&y, n - t);

  /* step 3. for i from n down to (t + 1) */
  for (i = n; i >= (t + 1); i--) {
    if (i > x.used) {
      continue;
    }

    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
    if (x.dp[i] == y.dp[t]) {
      q.dp[i - t - 1] = ((((fp_word)1) << DIGIT_BIT) - 1);
    } else {
      fp_word tmp;
      tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT);
      tmp |= ((fp_word) x.dp[i - 1]);
      tmp /= ((fp_word) y.dp[t]);
      q.dp[i - t - 1] = (fp_digit) (tmp);
    }

    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
             xi * b**2 + xi-1 * b + xi-2 
     
       do q{i-t-1} -= 1; 
    */
    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
    do {
      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);

      /* find left hand */
      fp_zero (&t1);
      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
      t1.dp[1] = y.dp[t];
      t1.used = 2;
      fp_mul_d (&t1, q.dp[i - t - 1], &t1);

      /* find right hand */
      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
      t2.dp[2] = x.dp[i];
      t2.used = 3;
    } while (fp_cmp_mag(&t1, &t2) == FP_GT);

    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
    fp_mul_d (&y, q.dp[i - t - 1], &t1);
    fp_lshd  (&t1, i - t - 1);
    fp_sub   (&x, &t1, &x);

    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
    if (x.sign == FP_NEG) {
      fp_copy (&y, &t1);
      fp_lshd (&t1, i - t - 1);
      fp_add (&x, &t1, &x);
      q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
    }
  }

  /* now q is the quotient and x is the remainder 
   * [which we have to normalize] 
   */
  
  /* get sign before writing to c */
  x.sign = x.used == 0 ? FP_ZPOS : a->sign;

  if (c != NULL) {
    fp_clamp (&q);
    fp_copy (&q, c);
    c->sign = neg;
  }

  if (d != NULL) {
    fp_div_2d (&x, norm, &x, NULL);

/* the following is a kludge, essentially we were seeing the right remainder but 
   with excess digits that should have been zero
 */
    for (i = b->used; i < x.used; i++) {
        x.dp[i] = 0;
    }
    fp_clamp(&x);
    fp_copy (&x, d);
  }

  return FP_OKAY;
}
Esempio n. 27
0
static int
tfm_rsa_public_decrypt(int flen, const unsigned char* from,
		       unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *p;
    int res;
    size_t size;
    fp_int s, us, n, e;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

    if (flen > RSA_size(rsa))
	return -2;

    BN2mpz(&n, rsa->n);
    BN2mpz(&e, rsa->e);

#if 0
    /* Check that the exponent is larger then 3 */
    if (mp_int_compare_value(&e, 3) <= 0) {
	fp_zero_multi(&e, &n, NULL);
	return -3;
    }
#endif

    fp_init_multi(&s, &us, NULL);
    fp_read_unsigned_bin(&s, rk_UNCONST(from), flen);

    if (fp_cmp(&s, &n) >= 0) {
	fp_zero_multi(&e, &n, NULL);
	return -4;
    }

    res = fp_exptmod(&s, &e, &n, &us);

    fp_zero_multi(&s, &e, &n, NULL);

    if (res != 0)
	return -5;
    p = to;


    size = fp_unsigned_bin_size(&us);
    assert(size <= RSA_size(rsa));
    fp_to_unsigned_bin(&us, p);

    fp_zero(&us);

    /* head zero was skipped by fp_to_unsigned_bin */
    if (*p == 0)
	return -6;
    if (*p != 1)
	return -7;
    size--; p++;
    while (size && *p == 0xff) {
	size--; p++;
    }
    if (size == 0 || *p != 0)
	return -8;
    size--; p++;

    memmove(to, p, size);

    return size;
}
Esempio n. 28
0
static int
tfm_rsa_private_encrypt(int flen, const unsigned char* from,
			unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *p, *p0;
    int res;
    int size;
    fp_int in, out, n, e;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

    size = RSA_size(rsa);

    if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
	return -2;

    p0 = p = malloc(size);
    *p++ = 0;
    *p++ = 1;
    memset(p, 0xff, size - flen - 3);
    p += size - flen - 3;
    *p++ = 0;
    memcpy(p, from, flen);
    p += flen;
    assert((p - p0) == size);

    BN2mpz(&n, rsa->n);
    BN2mpz(&e, rsa->e);

    fp_init_multi(&in, &out, NULL);
    fp_read_unsigned_bin(&in, p0, size);
    free(p0);

    if(fp_isneg(&in) || fp_cmp(&in, &n) >= 0) {
	size = -3;
	goto out;
    }

    if (rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp) {
	fp_int p, q, dmp1, dmq1, iqmp;

	BN2mpz(&p, rsa->p);
	BN2mpz(&q, rsa->q);
	BN2mpz(&dmp1, rsa->dmp1);
	BN2mpz(&dmq1, rsa->dmq1);
	BN2mpz(&iqmp, rsa->iqmp);

	res = tfm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out);

	fp_zero_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);

	if (res != 0) {
	    size = -4;
	    goto out;
	}
    } else {
	fp_int d;

	BN2mpz(&d, rsa->d);
	res = fp_exptmod(&in, &d, &n, &out);
	fp_zero(&d);
	if (res != 0) {
	    size = -5;
	    goto out;
	}
    }

    if (size > 0) {
	size_t ssize;
	ssize = fp_unsigned_bin_size(&out);
	assert(size >= ssize);
	fp_to_unsigned_bin(&out, to);
	size = ssize;
    }

 out:
    fp_zero_multi(&e, &n, &in, &out, NULL);

    return size;
}
Esempio n. 29
0
int fp3_cmp(fp3_t a, fp3_t b) {
	return (fp_cmp(a[0], b[0]) == CMP_EQ) && (fp_cmp(a[1], b[1]) == CMP_EQ) &&
			(fp_cmp(a[2], b[2]) == CMP_EQ) ? CMP_EQ : CMP_NE;
}
Esempio n. 30
0
/* 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;
}