Esempio n. 1
0
/* 6 words */
mp_err
ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
    mp_digit carry;

    switch (MP_USED(a)) {
        case 6:
            a5 = MP_DIGIT(a, 5);
        case 5:
            a4 = MP_DIGIT(a, 4);
        case 4:
            a3 = MP_DIGIT(a, 3);
        case 3:
            a2 = MP_DIGIT(a, 2);
        case 2:
            a1 = MP_DIGIT(a, 1);
        case 1:
            a0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 6:
            r5 = MP_DIGIT(b, 5);
        case 5:
            r4 = MP_DIGIT(b, 4);
        case 4:
            r3 = MP_DIGIT(b, 3);
        case 3:
            r2 = MP_DIGIT(b, 2);
        case 2:
            r1 = MP_DIGIT(b, 1);
        case 1:
            r0 = MP_DIGIT(b, 0);
    }

    carry = 0;
    MP_ADD_CARRY(a0, r0, r0, carry);
    MP_ADD_CARRY(a1, r1, r1, carry);
    MP_ADD_CARRY(a2, r2, r2, carry);
    MP_ADD_CARRY(a3, r3, r3, carry);
    MP_ADD_CARRY(a4, r4, r4, carry);
    MP_ADD_CARRY(a5, r5, r5, carry);

    MP_CHECKOK(s_mp_pad(r, 6));
    MP_DIGIT(r, 5) = r5;
    MP_DIGIT(r, 4) = r4;
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 6;

    /* Do quick 'subract' if we've gone over
     * (add the 2's complement of the curve field) */
    a5 = MP_DIGIT(&meth->irr, 5);
    if (carry || r5 > a5 ||
        ((r5 == a5) && mp_cmp(r, &meth->irr) != MP_LT)) {
        a4 = MP_DIGIT(&meth->irr, 4);
        a3 = MP_DIGIT(&meth->irr, 3);
        a2 = MP_DIGIT(&meth->irr, 2);
        a1 = MP_DIGIT(&meth->irr, 1);
        a0 = MP_DIGIT(&meth->irr, 0);
        carry = 0;
        MP_SUB_BORROW(r0, a0, r0, carry);
        MP_SUB_BORROW(r1, a1, r1, carry);
        MP_SUB_BORROW(r2, a2, r2, carry);
        MP_SUB_BORROW(r3, a3, r3, carry);
        MP_SUB_BORROW(r4, a4, r4, carry);
        MP_SUB_BORROW(r5, a5, r5, carry);
        MP_DIGIT(r, 5) = r5;
        MP_DIGIT(r, 4) = r4;
        MP_DIGIT(r, 3) = r3;
        MP_DIGIT(r, 2) = r2;
        MP_DIGIT(r, 1) = r1;
        MP_DIGIT(r, 0) = r0;
    }

    s_mp_clamp(r);

CLEANUP:
    return res;
}
Esempio n. 2
0
/* slower bit-bang division... also smaller */
int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
    mp_int ta, tb, tq, q;
    int    res, n, n2;

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

    /* if a < b then q=0, r = a */
    if (mp_cmp_mag (a, b) == MP_LT) {
        if (d != NULL) {
            res = mp_copy (a, d);
        } else {
            res = MP_OKAY;
        }
        if (c != NULL) {
            mp_zero (c);
        }
        return res;
    }

    /* init our temps */
    if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
        return res;
    }

    mp_set(&tq, 1);
    n = mp_count_bits(a) - mp_count_bits(b);
    if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
            ((res = mp_abs(b, &tb)) != MP_OKAY) ||
            ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
            ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
        goto LBL_ERR;
    }

    while (n-- >= 0) {
        if (mp_cmp(&tb, &ta) != MP_GT) {
            if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
                    ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
                goto LBL_ERR;
            }
        }
        if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
                ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
            goto LBL_ERR;
        }
    }

    /* now q == quotient and ta == remainder */
    n  = a->sign;
    n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
    if (c != NULL) {
        mp_exch(c, &q);
        c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
    }
    if (d != NULL) {
        mp_exch(d, &ta);
        d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
    }
LBL_ERR:
    mp_clear_multi(&ta, &tb, &tq, &q, NULL);
    return res;
}
/* Miller-Rabin test of "a" to the base of "b" as described in
 * HAC pp. 139 Algorithm 4.24
 *
 * Sets result to 0 if definitely composite or 1 if probably prime.
 * Randomly the chance of error is no more than 1/4 and often
 * very much lower.
 */
int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{
  mp_int  n1, y, r;
  int     s, j, err;

  /* default */
  *result = MP_NO;

  /* ensure b > 1 */
  if (mp_cmp_d(b, 1) != MP_GT) {
     return MP_VAL;
  }

  /* get n1 = a - 1 */
  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
    return err;
  }
  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* set 2**s * r = n1 */
  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
    goto LBL_N1;
  }

  /* count the number of least significant bits
   * which are zero
   */
  s = mp_cnt_lsb(&r);

  /* now divide n - 1 by 2**s */
  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
    goto LBL_R;
  }

  /* compute y = b**r mod a */
  if ((err = mp_init (&y)) != MP_OKAY) {
    goto LBL_R;
  }
  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
    goto LBL_Y;
  }

  /* if y != 1 and y != n1 do */
  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
    j = 1;
    /* while j <= s-1 and y != n1 */
    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
         goto LBL_Y;
      }

      /* if y == 1 then composite */
      if (mp_cmp_d (&y, 1) == MP_EQ) {
         goto LBL_Y;
      }

      ++j;
    }

    /* if y != n1 then composite */
    if (mp_cmp (&y, &n1) != MP_EQ) {
      goto LBL_Y;
    }
  }

  /* probably prime now */
  *result = MP_YES;
LBL_Y:mp_clear (&y);
LBL_R:mp_clear (&r);
LBL_N1:mp_clear (&n1);
  return err;
}
Esempio n. 4
0
/**
 * bignum_cmp - Signed comparison
 * @a: Bignum from bignum_init()
 * @b: Bignum from bignum_init()
 * Returns: 0 on success, -1 on failure
 */
int
bignum_cmp(const struct bignum *a, const struct bignum *b)
{
    return mp_cmp((mp_int *) a, (mp_int *) b);
}
Esempio n. 5
0
int rsa_exptmod(const unsigned char *in,  unsigned long inlen,
                      unsigned char *out, unsigned long *outlen, int which,
                      rsa_key *key)
{
   mp_int tmp, tmpa, tmpb;
   unsigned long x;
   int res;

   _ARGCHK(in != NULL);
   _ARGCHK(out != NULL);
   _ARGCHK(outlen != NULL);
   _ARGCHK(key != NULL);

   if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   /* must be a private or public operation */
   if (which != PK_PRIVATE && which != PK_PUBLIC) {
      return CRYPT_PK_INVALID_TYPE;
   }

   /* init and copy into tmp */
   if (mp_init_multi(&tmp, &tmpa, &tmpb, NULL) != MP_OKAY)                          { goto error; }
   if (mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen) != MP_OKAY)      { goto error; }

   /* sanity check on the input */
   if (mp_cmp(&key->N, &tmp) == MP_LT) {
      res = CRYPT_PK_INVALID_SIZE;
      goto done;
   }

   /* are we using the private exponent and is the key optimized? */
   if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) {
      /* tmpa = tmp^dP mod p */
      if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)    { goto error; }

      /* tmpb = tmp^dQ mod q */
      if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)    { goto error; }

      /* tmp = tmpa*qP + tmpb*pQ mod N */
      if (mp_mul(&tmpa, &key->qP, &tmpa) != MP_OKAY)                { goto error; }
      if (mp_mul(&tmpb, &key->pQ, &tmpb) != MP_OKAY)                { goto error; }
      if (mp_addmod(&tmpa, &tmpb, &key->N, &tmp) != MP_OKAY)        { goto error; }
   } else {
      /* exptmod it */
      if (mp_exptmod(&tmp, which==PK_PRIVATE?&key->d:&key->e, &key->N, &tmp) != MP_OKAY) { goto error; }
   }

   /* read it back */
   x = (unsigned long)mp_unsigned_bin_size(&tmp);
   if (x > *outlen) {
      res = CRYPT_BUFFER_OVERFLOW;
      goto done;
   }
   *outlen = x;

   /* convert it */
   if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)                    { goto error; }

   /* clean up and return */
   res = CRYPT_OK;
   goto done;
error:
   res = CRYPT_MEM;
done:
   mp_clear_multi(&tmp, &tmpa, &tmpb, NULL);
   return res;
}
Esempio n. 6
0
static void check_relation(relation_batch_t *rb,
			uint32 index,
			mp_t *prime_product) {

	uint32 i;
	cofactor_t *c = rb->relations + index;
	uint32 *f = rb->factors + c->factor_list_word;
	uint32 *lp1 = f + c->num_factors_r + c->num_factors_a;
	uint32 *lp2 = lp1 + c->lp_r_num_words;
	mp_t n, f1r, f2r, f1a, f2a, t0, t1;
	uint32 lp_r[MAX_LARGE_PRIMES];
	uint32 lp_a[MAX_LARGE_PRIMES];
	uint32 num_r, num_a;
	mp_t *small, *large;

	/* first compute gcd(prime_product, rational large cofactor).
	   The rational part will split into a cofactor with all 
	   factors <= the largest prime in rb->prime_product (stored
	   in f1r) and a cofactor with all factors larger (stored in f2r) */

	if (c->lp_r_num_words) {
		mp_clear(&n);
		n.nwords = c->lp_r_num_words;
		for (i = 0; i < c->lp_r_num_words; i++)
			n.val[i] = lp1[i];

		if (n.nwords == 1) {
			mp_copy(&n, &f1r);
			mp_clear(&f2r);
			f2r.nwords = f2r.val[0] = 1;
		}
		else {
			mp_gcd(prime_product, &n, &f1r);
			if (mp_is_one(&f1r))
				mp_copy(&n, &f2r);
			else
				mp_div(&n, &f1r, &f2r);
		}

		/* give up on this relation if
		     - f1r has a single factor, and that factor
		       exceeds the rational large prime cutoff
		     - f1r is more than 3 words long */

		if (f1r.nwords > 3 ||
		    (f1r.nwords == 1 && f1r.val[0] > rb->lp_cutoff_r))
			return;

		/* give up on this relation if
		     - f2r has a single factor, and that factor
		       exceeds the rational large prime cutoff
		     - f2r has two words and exceeds the square of the
		       cutoff (meaning at least one of the two factors in
		       f2r would exceed the large prime cutoff)
		     - f2r has two words and is smaller than the square
		       of the largest prime in rb->prime_product, meaning
		       that f2r is prime and way too large
		     - f2r has 3+ words. We don't know anything about
		       f2r in this case, except that all factors exceed the
		       largest prime in rb->prime_product, and it would be
		       much too expensive to find out anything more */

		if (f2r.nwords >= 3 ||
		    (f2r.nwords == 2 && 
		     		(mp_cmp(&f2r, &rb->max_prime2) <= 0 ||
		     		 mp_cmp(&f2r, &rb->lp_cutoff_r2) > 0)) ||
		    (f2r.nwords == 1 && f2r.val[0] > rb->lp_cutoff_r))
			return;
	}
	else {
		mp_clear(&f1r);
		mp_clear(&f2r);
	}

	/* repeat with the algebraic unfactored part, if any */

	if (c->lp_a_num_words) {
		mp_clear(&n);
		n.nwords = c->lp_a_num_words;
		for (i = 0; i < c->lp_a_num_words; i++)
			n.val[i] = lp2[i];

		if (n.nwords == 1) {
			mp_copy(&n, &f1a);
			mp_clear(&f2a);
			f2a.nwords = f2a.val[0] = 1;
		}
		else {
			mp_gcd(prime_product, &n, &f1a);
			if (mp_is_one(&f1a))
				mp_copy(&n, &f2a);
			else
				mp_div(&n, &f1a, &f2a);
		}

		if (f1a.nwords > 3 ||
		    (f1a.nwords == 1 && f1a.val[0] > rb->lp_cutoff_a))
			return;

		if (f2a.nwords >= 3 ||
		    (f2a.nwords == 2 && 
		     		(mp_cmp(&f2a, &rb->max_prime2) <= 0 ||
		     		 mp_cmp(&f2a, &rb->lp_cutoff_a2) > 0)) ||
		    (f2a.nwords == 1 && f2a.val[0] > rb->lp_cutoff_a))
			return;
	}
	else {
		mp_clear(&f1a);
		mp_clear(&f2a);
	}

	/* the relation isn't obviously bad; do more work
	   trying to factor everything. Note that when relations 
	   are expected to have three large primes then ~98% of 
	   relations do not make it to this point
	
	   Begin by performing compositeness tests on f2r and f2a,
	   which are necessary if they are two words in size and
	   f1r or f1a is not one (the latter being true means
	   that the sieving already performed the compositeness test) */

	for (i = num_r = num_a = 0; i < MAX_LARGE_PRIMES; i++)
		lp_r[i] = lp_a[i] = 1;

	if (f2r.nwords == 2 && !mp_is_one(&f1r)) {
		mp_t exponent, res;
		mp_sub_1(&f2r, 1, &exponent);
		mp_expo(&two, &exponent, &f2r, &res);
		if (mp_is_one(&res))
			return;
	}
	if (f2a.nwords == 2 && !mp_is_one(&f1a)) {
		mp_t exponent, res;
		mp_sub_1(&f2a, 1, &exponent);
		mp_expo(&two, &exponent, &f2a, &res);
		if (mp_is_one(&res))
			return;
	}

	/* now perform all the factorizations that
	   require SQUFOF, since it is much faster than the
	   QS code. We have to check all of f[1|2][r|a] but
	   for relations with three large primes then at most
	   two of the four choices need factoring */

	if (f1r.nwords == 1) {
		if (f1r.val[0] > 1)
			lp_r[num_r++] = f1r.val[0];
	}
	else if (f1r.nwords == 2) {
		i = squfof(&f1r);
		if (i <= 1 || i > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = i;
		mp_divrem_1(&f1r, i, &f1r);
		if (f1r.nwords > 1 || f1r.val[0] > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = f1r.val[0];
	}

	if (f2r.nwords == 1) {
		if (f2r.val[0] > 1)
			lp_r[num_r++] = f2r.val[0];
	}
	else if (f2r.nwords == 2) {
		i = squfof(&f2r);
		if (i <= 1 || i > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = i;
		mp_divrem_1(&f2r, i, &f2r);
		if (f2r.nwords > 1 || f2r.val[0] > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = f2r.val[0];
	}

	if (f1a.nwords == 1) {
		if (f1a.val[0] > 1)
			lp_a[num_a++] = f1a.val[0];
	}
	else if (f1a.nwords == 2) {
		i = squfof(&f1a);
		if (i <= 1 || i > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = i;
		mp_divrem_1(&f1a, i, &f1a);
		if (f1a.nwords > 1 || f1a.val[0] > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = f1a.val[0];
	}

	if (f2a.nwords == 1) {
		if (f2a.val[0] > 1)
			lp_a[num_a++] = f2a.val[0];
	}
	else if (f2a.nwords == 2) {
		i = squfof(&f2a);
		if (i <= 1 || i > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = i;
		mp_divrem_1(&f2a, i, &f2a);
		if (f2a.nwords > 1 || f2a.val[0] > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = f2a.val[0];
	}

	/* only use expensive factoring methods when we know 
	   f1r and/or f1a splits into three large primes and 
	   we know all three primes are smaller than the 
	   largest prime in rb->prime_product. When the latter 
	   is a good deal smaller than the large prime cutoff
	   this happens extremely rarely */

	if (f1r.nwords == 3) {
		if (tinyqs(&f1r, &t0, &t1) == 0)
			return;

		small = &t0;
		large = &t1;
		if (mp_cmp(small, large) > 0) {
			small = &t1;
			large = &t0;
		}

		if (small->nwords > 1 || small->val[0] > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = small->val[0];
		i = squfof(large);
		if (i <= 1 || i > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = i;
		mp_divrem_1(large, i, large);
		if (large->nwords > 1 || large->val[0] > rb->lp_cutoff_r)
			return;
		lp_r[num_r++] = large->val[0];
	}

	if (f1a.nwords == 3) {
		if (tinyqs(&f1a, &t0, &t1) == 0)
			return;

		small = &t0;
		large = &t1;
		if (mp_cmp(small, large) > 0) {
			small = &t1;
			large = &t0;
		}

		if (small->nwords > 1 || small->val[0] > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = small->val[0];
		i = squfof(large);
		if (i <= 1 || i > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = i;
		mp_divrem_1(large, i, large);
		if (large->nwords > 1 || large->val[0] > rb->lp_cutoff_a)
			return;
		lp_a[num_a++] = large->val[0];
	}

	/* yay! Another relation found */

	rb->num_success++;
	rb->print_relation(rb->savefile, c->a, c->b,
			f, c->num_factors_r, lp_r,
			f + c->num_factors_r, c->num_factors_a, lp_a);
}
Esempio n. 7
0
/* signature is caller-supplied buffer of at least 20 bytes.
** On input,  signature->len == size of buffer to hold signature.
**            digest->len    == size of digest.
*/
SECStatus 
DSA_VerifyDigest(DSAPublicKey *key, const SECItem *signature, 
                 const SECItem *digest)
{
    /* FIPS-compliance dictates that digest is a SHA1 hash. */
    mp_int p, q, g;      /* PQG parameters */
    mp_int r_, s_;       /* tuple (r', s') is received signature) */
    mp_int u1, u2, v, w; /* intermediate values used in verification */
    mp_int y;            /* public key */
    mp_err err;
    SECStatus verified = SECFailure;

    /* Check args. */
    if (!key || !signature || !digest ||
        (signature->len != DSA_SIGNATURE_LEN) ||
	(digest->len != SHA1_LENGTH)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    /* Initialize MPI integers. */
    MP_DIGITS(&p)  = 0;
    MP_DIGITS(&q)  = 0;
    MP_DIGITS(&g)  = 0;
    MP_DIGITS(&y)  = 0;
    MP_DIGITS(&r_) = 0;
    MP_DIGITS(&s_) = 0;
    MP_DIGITS(&u1) = 0;
    MP_DIGITS(&u2) = 0;
    MP_DIGITS(&v)  = 0;
    MP_DIGITS(&w)  = 0;
    CHECK_MPI_OK( mp_init(&p)  );
    CHECK_MPI_OK( mp_init(&q)  );
    CHECK_MPI_OK( mp_init(&g)  );
    CHECK_MPI_OK( mp_init(&y)  );
    CHECK_MPI_OK( mp_init(&r_) );
    CHECK_MPI_OK( mp_init(&s_) );
    CHECK_MPI_OK( mp_init(&u1) );
    CHECK_MPI_OK( mp_init(&u2) );
    CHECK_MPI_OK( mp_init(&v)  );
    CHECK_MPI_OK( mp_init(&w)  );
    /*
    ** Convert stored PQG and public key into MPI integers.
    */
    SECITEM_TO_MPINT(key->params.prime,    &p);
    SECITEM_TO_MPINT(key->params.subPrime, &q);
    SECITEM_TO_MPINT(key->params.base,     &g);
    SECITEM_TO_MPINT(key->publicValue,     &y);
    /*
    ** Convert received signature (r', s') into MPI integers.
    */
    OCTETS_TO_MPINT(signature->data, &r_, DSA_SUBPRIME_LEN);
    OCTETS_TO_MPINT(signature->data + DSA_SUBPRIME_LEN, &s_, DSA_SUBPRIME_LEN);
    /*
    ** Verify that 0 < r' < q and 0 < s' < q
    */
    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
        mp_cmp(&r_, &q) >= 0 || mp_cmp(&s_, &q) >= 0) {
	/* err is zero here. */
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	goto cleanup; /* will return verified == SECFailure */
    }
    /*
    ** FIPS 186-1, Section 6, Step 1
    **
    ** w = (s')**-1 mod q
    */
    CHECK_MPI_OK( mp_invmod(&s_, &q, &w) );      /* w = (s')**-1 mod q */
    /*
    ** FIPS 186-1, Section 6, Step 2
    **
    ** u1 = ((SHA1(M')) * w) mod q
    */
    SECITEM_TO_MPINT(*digest, &u1);              /* u1 = SHA1(M')     */
    CHECK_MPI_OK( mp_mulmod(&u1, &w, &q, &u1) ); /* u1 = u1 * w mod q */
    /*
    ** FIPS 186-1, Section 6, Step 3
    **
    ** u2 = ((r') * w) mod q
    */
    CHECK_MPI_OK( mp_mulmod(&r_, &w, &q, &u2) );
    /*
    ** FIPS 186-1, Section 6, Step 4
    **
    ** v = ((g**u1 * y**u2) mod p) mod q
    */
    CHECK_MPI_OK( mp_exptmod(&g, &u1, &p, &g) ); /* g = g**u1 mod p */
    CHECK_MPI_OK( mp_exptmod(&y, &u2, &p, &y) ); /* y = y**u2 mod p */
    CHECK_MPI_OK(  mp_mulmod(&g, &y, &p, &v)  ); /* v = g * y mod p */
    CHECK_MPI_OK(     mp_mod(&v, &q, &v)      ); /* v = v mod q     */
    /*
    ** Verification:  v == r'
    */
    if (mp_cmp(&v, &r_)) {
	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
	verified = SECFailure; /* Signature failed to verify. */
    } else {
	verified = SECSuccess; /* Signature verified. */
    }
cleanup:
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&g);
    mp_clear(&y);
    mp_clear(&r_);
    mp_clear(&s_);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&v);
    mp_clear(&w);
    if (err) {
	translate_mpi_error(err);
    }
    return verified;
}
/* computes the modular inverse via binary extended euclidean algorithm, 
 * that is c = 1/a mod b 
 *
 * Based on mp_invmod except this is optimized for the case where b is 
 * odd as per HAC Note 14.64 on pp. 610
 */
int
fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, B, D;
  int     res, neg;

  /* 2. [modified] if a,b are both even then return an error!
   *
   * That is if gcd(a,b) = 2**k * q then obviously there is no inverse.
   */
  if (mp_iseven (a) == 1 && mp_iseven (b) == 1) {
    return MP_VAL;
  }

  /* init all our temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x == modulus, y == value to invert */
  if ((res = mp_copy (b, &x)) != MP_OKAY) {
    goto __ERR;
  }

  /* we need y = |a| */
  if ((res = mp_abs (a, &y)) != MP_OKAY) {
    goto __ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto __ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto __ERR;
  }
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto __ERR;
    }
    /* 4.2 if B is odd then */
    if (mp_isodd (&B) == 1) {
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
        goto __ERR;
      }
    }
    /* B = B/2 */
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto __ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto __ERR;
    }
    /* 5.2 if D is odd then */
    if (mp_isodd (&D) == 1) {
      /* D = (D-x)/2 */
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
        goto __ERR;
      }
    }
    /* D = D/2 */
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto __ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto __ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto __ERR;
    }
  } else {
    /* v - v - u, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto __ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto __ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0) {
    goto top;
  }

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto __ERR;
  }

  /* b is now the inverse */
  neg = a->sign;
  while (D.sign == MP_NEG) {
    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
      goto __ERR;
    }
  }
  mp_exch (&D, c);
  c->sign = neg;
  res = MP_OKAY;

__ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
  return res;
}
Esempio n. 9
0
/* reduces x mod m, assumes 0 < x < m**2, mu is
 * precomputed via mp_reduce_setup.
 * From HAC pp.604 Algorithm 14.42
 */
int mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
{
   mp_int  q;
   int     res, um = m->used;

   /* q = x */
   if ((res = mp_init_copy(&q, x)) != MP_OKAY) {
      return res;
   }

   /* q1 = x / b**(k-1)  */
   mp_rshd(&q, um - 1);

   /* according to HAC this optimization is ok */
   if ((mp_digit)um > ((mp_digit)1 << (MP_DIGIT_BIT - 1))) {
      if ((res = mp_mul(&q, mu, &q)) != MP_OKAY) {
         goto CLEANUP;
      }
   } else {
#ifdef BN_S_MP_MUL_HIGH_DIGS_C
      if ((res = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) {
         goto CLEANUP;
      }
#elif defined(BN_S_MP_MUL_HIGH_DIGS_FAST_C)
      if ((res = s_mp_mul_high_digs_fast(&q, mu, &q, um)) != MP_OKAY) {
         goto CLEANUP;
      }
#else
      {
         res = MP_VAL;
         goto CLEANUP;
      }
#endif
   }

   /* q3 = q2 / b**(k+1) */
   mp_rshd(&q, um + 1);

   /* x = x mod b**(k+1), quick (no division) */
   if ((res = mp_mod_2d(x, MP_DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
      goto CLEANUP;
   }

   /* q = q * m mod b**(k+1), quick (no division) */
   if ((res = s_mp_mul_digs(&q, m, &q, um + 1)) != MP_OKAY) {
      goto CLEANUP;
   }

   /* x = x - q */
   if ((res = mp_sub(x, &q, x)) != MP_OKAY) {
      goto CLEANUP;
   }

   /* If x < 0, add b**(k+1) to it */
   if (mp_cmp_d(x, 0uL) == MP_LT) {
      mp_set(&q, 1uL);
      if ((res = mp_lshd(&q, um + 1)) != MP_OKAY)
         goto CLEANUP;
      if ((res = mp_add(x, &q, x)) != MP_OKAY)
         goto CLEANUP;
   }

   /* Back off if it's too big */
   while (mp_cmp(x, m) != MP_LT) {
      if ((res = s_mp_sub(x, m, x)) != MP_OKAY) {
         goto CLEANUP;
      }
   }

CLEANUP:
   mp_clear(&q);

   return res;
}
Esempio n. 10
0
int main(void)
{
    mp_int a, b, c, d, e, f;
    unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n,
             gcd_n, lcm_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n, t;
    unsigned rr;
    int i, n, err, cnt, ix, old_kara_m, old_kara_s;
    mp_digit mp;


    mp_init(&a);
    mp_init(&b);
    mp_init(&c);
    mp_init(&d);
    mp_init(&e);
    mp_init(&f);

    srand(time(NULL));

#if 0
    // test montgomery
    printf("Testing montgomery...\n");
    for (i = 1; i < 10; i++) {
        printf("Testing digit size: %d\n", i);
        for (n = 0; n < 1000; n++) {
            mp_rand(&a, i);
            a.dp[0] |= 1;

            // let's see if R is right
            mp_montgomery_calc_normalization(&b, &a);
            mp_montgomery_setup(&a, &mp);

            // now test a random reduction
            for (ix = 0; ix < 100; ix++) {
                mp_rand(&c, 1 + abs(rand()) % (2*i));
                mp_copy(&c, &d);
                mp_copy(&c, &e);

                mp_mod(&d, &a, &d);
                mp_montgomery_reduce(&c, &a, mp);
                mp_mulmod(&c, &b, &a, &c);

                if (mp_cmp(&c, &d) != MP_EQ) {
                    printf("d = e mod a, c = e MOD a\n");
                    mp_todecimal(&a, buf);
                    printf("a = %s\n", buf);
                    mp_todecimal(&e, buf);
                    printf("e = %s\n", buf);
                    mp_todecimal(&d, buf);
                    printf("d = %s\n", buf);
                    mp_todecimal(&c, buf);
                    printf("c = %s\n", buf);
                    printf("compare no compare!\n");
                    exit(EXIT_FAILURE);
                }
            }
        }
    }
    printf("done\n");

    // test mp_get_int
    printf("Testing: mp_get_int\n");
    for (i = 0; i < 1000; ++i) {
        t = ((unsigned long) rand() * rand() + 1) & 0xFFFFFFFF;
        mp_set_int(&a, t);
        if (t != mp_get_int(&a)) {
            printf("mp_get_int() bad result!\n");
            return 1;
        }
    }
    mp_set_int(&a, 0);
    if (mp_get_int(&a) != 0) {
        printf("mp_get_int() bad result!\n");
        return 1;
    }
    mp_set_int(&a, 0xffffffff);
    if (mp_get_int(&a) != 0xffffffff) {
        printf("mp_get_int() bad result!\n");
        return 1;
    }
    // test mp_sqrt
    printf("Testing: mp_sqrt\n");
    for (i = 0; i < 1000; ++i) {
        printf("%6d\r", i);
        fflush(stdout);
        n = (rand() & 15) + 1;
        mp_rand(&a, n);
        if (mp_sqrt(&a, &b) != MP_OKAY) {
            printf("mp_sqrt() error!\n");
            return 1;
        }
        mp_n_root(&a, 2, &a);
        if (mp_cmp_mag(&b, &a) != MP_EQ) {
            printf("mp_sqrt() bad result!\n");
            return 1;
        }
    }

    printf("\nTesting: mp_is_square\n");
    for (i = 0; i < 1000; ++i) {
        printf("%6d\r", i);
        fflush(stdout);

        /* test mp_is_square false negatives */
        n = (rand() & 7) + 1;
        mp_rand(&a, n);
        mp_sqr(&a, &a);
        if (mp_is_square(&a, &n) != MP_OKAY) {
            printf("fn:mp_is_square() error!\n");
            return 1;
        }
        if (n == 0) {
            printf("fn:mp_is_square() bad result!\n");
            return 1;
        }

        /* test for false positives */
        mp_add_d(&a, 1, &a);
        if (mp_is_square(&a, &n) != MP_OKAY) {
            printf("fp:mp_is_square() error!\n");
            return 1;
        }
        if (n == 1) {
            printf("fp:mp_is_square() bad result!\n");
            return 1;
        }

    }
    printf("\n\n");

    /* test for size */
    for (ix = 10; ix < 128; ix++) {
        printf("Testing (not safe-prime): %9d bits    \r", ix);
        fflush(stdout);
        err =
            mp_prime_random_ex(&a, 8, ix,
                               (rand() & 1) ? LTM_PRIME_2MSB_OFF :
                               LTM_PRIME_2MSB_ON, myrng, NULL);
        if (err != MP_OKAY) {
            printf("failed with err code %d\n", err);
            return EXIT_FAILURE;
        }
        if (mp_count_bits(&a) != ix) {
            printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
            return EXIT_FAILURE;
        }
    }

    for (ix = 16; ix < 128; ix++) {
        printf("Testing (   safe-prime): %9d bits    \r", ix);
        fflush(stdout);
        err =
            mp_prime_random_ex(&a, 8, ix,
                               ((rand() & 1) ? LTM_PRIME_2MSB_OFF :
                                LTM_PRIME_2MSB_ON) | LTM_PRIME_SAFE, myrng,
                               NULL);
        if (err != MP_OKAY) {
            printf("failed with err code %d\n", err);
            return EXIT_FAILURE;
        }
        if (mp_count_bits(&a) != ix) {
            printf("Prime is %d not %d bits!!!\n", mp_count_bits(&a), ix);
            return EXIT_FAILURE;
        }
        /* let's see if it's really a safe prime */
        mp_sub_d(&a, 1, &a);
        mp_div_2(&a, &a);
        mp_prime_is_prime(&a, 8, &cnt);
        if (cnt != MP_YES) {
            printf("sub is not prime!\n");
            return EXIT_FAILURE;
        }
    }

    printf("\n\n");

    mp_read_radix(&a, "123456", 10);
    mp_toradix_n(&a, buf, 10, 3);
    printf("a == %s\n", buf);
    mp_toradix_n(&a, buf, 10, 4);
    printf("a == %s\n", buf);
    mp_toradix_n(&a, buf, 10, 30);
    printf("a == %s\n", buf);


#if 0
    for (;;) {
        fgets(buf, sizeof(buf), stdin);
        mp_read_radix(&a, buf, 10);
        mp_prime_next_prime(&a, 5, 1);
        mp_toradix(&a, buf, 10);
        printf("%s, %lu\n", buf, a.dp[0] & 3);
    }
#endif

    /* test mp_cnt_lsb */
    printf("testing mp_cnt_lsb...\n");
    mp_set(&a, 1);
    for (ix = 0; ix < 1024; ix++) {
        if (mp_cnt_lsb(&a) != ix) {
            printf("Failed at %d, %d\n", ix, mp_cnt_lsb(&a));
            return 0;
        }
        mp_mul_2(&a, &a);
    }

    /* test mp_reduce_2k */
    printf("Testing mp_reduce_2k...\n");
    for (cnt = 3; cnt <= 128; ++cnt) {
        mp_digit tmp;

        mp_2expt(&a, cnt);
        mp_sub_d(&a, 2, &a);	/* a = 2**cnt - 2 */


        printf("\nTesting %4d bits", cnt);
        printf("(%d)", mp_reduce_is_2k(&a));
        mp_reduce_2k_setup(&a, &tmp);
        printf("(%d)", tmp);
        for (ix = 0; ix < 1000; ix++) {
            if (!(ix & 127)) {
                printf(".");
                fflush(stdout);
            }
            mp_rand(&b, (cnt / DIGIT_BIT + 1) * 2);
            mp_copy(&c, &b);
            mp_mod(&c, &a, &c);
            mp_reduce_2k(&b, &a, 2);
            if (mp_cmp(&c, &b)) {
                printf("FAILED\n");
                exit(0);
            }
        }
    }

    /* test mp_div_3  */
    printf("Testing mp_div_3...\n");
    mp_set(&d, 3);
    for (cnt = 0; cnt < 10000;) {
        mp_digit r1, r2;

        if (!(++cnt & 127))
            printf("%9d\r", cnt);
        mp_rand(&a, abs(rand()) % 128 + 1);
        mp_div(&a, &d, &b, &e);
        mp_div_3(&a, &c, &r2);

        if (mp_cmp(&b, &c) || mp_cmp_d(&e, r2)) {
            printf("\n\nmp_div_3 => Failure\n");
        }
    }
    printf("\n\nPassed div_3 testing\n");

    /* test the DR reduction */
    printf("testing mp_dr_reduce...\n");
    for (cnt = 2; cnt < 32; cnt++) {
        printf("%d digit modulus\n", cnt);
        mp_grow(&a, cnt);
        mp_zero(&a);
        for (ix = 1; ix < cnt; ix++) {
            a.dp[ix] = MP_MASK;
        }
        a.used = cnt;
        a.dp[0] = 3;

        mp_rand(&b, cnt - 1);
        mp_copy(&b, &c);

        rr = 0;
        do {
            if (!(rr & 127)) {
                printf("%9lu\r", rr);
                fflush(stdout);
            }
            mp_sqr(&b, &b);
            mp_add_d(&b, 1, &b);
            mp_copy(&b, &c);

            mp_mod(&b, &a, &b);
            mp_dr_reduce(&c, &a, (((mp_digit) 1) << DIGIT_BIT) - a.dp[0]);

            if (mp_cmp(&b, &c) != MP_EQ) {
                printf("Failed on trial %lu\n", rr);
                exit(-1);

            }
        } while (++rr < 500);
        printf("Passed DR test for %d digits\n", cnt);
    }

#endif

    /* test the mp_reduce_2k_l code */
#if 0
#if 0
    /* first load P with 2^1024 - 0x2A434 B9FDEC95 D8F9D550 FFFFFFFF FFFFFFFF */
    mp_2expt(&a, 1024);
    mp_read_radix(&b, "2A434B9FDEC95D8F9D550FFFFFFFFFFFFFFFF", 16);
    mp_sub(&a, &b, &a);
#elif 1
    /*  p = 2^2048 - 0x1 00000000 00000000 00000000 00000000 4945DDBF 8EA2A91D 5776399B B83E188F  */
    mp_2expt(&a, 2048);
    mp_read_radix(&b,
                  "1000000000000000000000000000000004945DDBF8EA2A91D5776399BB83E188F",
                  16);
    mp_sub(&a, &b, &a);
#endif

    mp_todecimal(&a, buf);
    printf("p==%s\n", buf);
    /* now mp_reduce_is_2k_l() should return */
    if (mp_reduce_is_2k_l(&a) != 1) {
        printf("mp_reduce_is_2k_l() return 0, should be 1\n");
        return EXIT_FAILURE;
    }
    mp_reduce_2k_setup_l(&a, &d);
    /* now do a million square+1 to see if it varies */
    mp_rand(&b, 64);
    mp_mod(&b, &a, &b);
    mp_copy(&b, &c);
    printf("testing mp_reduce_2k_l...");
    fflush(stdout);
    for (cnt = 0; cnt < (1UL << 20); cnt++) {
        mp_sqr(&b, &b);
        mp_add_d(&b, 1, &b);
        mp_reduce_2k_l(&b, &a, &d);
        mp_sqr(&c, &c);
        mp_add_d(&c, 1, &c);
        mp_mod(&c, &a, &c);
        if (mp_cmp(&b, &c) != MP_EQ) {
            printf("mp_reduce_2k_l() failed at step %lu\n", cnt);
            mp_tohex(&b, buf);
            printf("b == %s\n", buf);
            mp_tohex(&c, buf);
            printf("c == %s\n", buf);
            return EXIT_FAILURE;
        }
    }
    printf("...Passed\n");
#endif

    div2_n = mul2_n = inv_n = expt_n = lcm_n = gcd_n = add_n =
                                           sub_n = mul_n = div_n = sqr_n = mul2d_n = div2d_n = cnt = add_d_n =
                                                   sub_d_n = 0;

    /* force KARA and TOOM to enable despite cutoffs */
    KARATSUBA_SQR_CUTOFF = KARATSUBA_MUL_CUTOFF = 8;
    TOOM_SQR_CUTOFF = TOOM_MUL_CUTOFF = 16;

    for (;;) {
        /* randomly clear and re-init one variable, this has the affect of triming the alloc space */
        switch (abs(rand()) % 7) {
        case 0:
            mp_clear(&a);
            mp_init(&a);
            break;
        case 1:
            mp_clear(&b);
            mp_init(&b);
            break;
        case 2:
            mp_clear(&c);
            mp_init(&c);
            break;
        case 3:
            mp_clear(&d);
            mp_init(&d);
            break;
        case 4:
            mp_clear(&e);
            mp_init(&e);
            break;
        case 5:
            mp_clear(&f);
            mp_init(&f);
            break;
        case 6:
            break;			/* don't clear any */
        }


        printf
        ("%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu/%4lu ",
         add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n,
         expt_n, inv_n, div2_n, mul2_n, add_d_n, sub_d_n);
        fgets(cmd, 4095, stdin);
        cmd[strlen(cmd) - 1] = 0;
        printf("%s  ]\r", cmd);
        fflush(stdout);
        if (!strcmp(cmd, "mul2d")) {
            ++mul2d_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            sscanf(buf, "%d", &rr);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);

            mp_mul_2d(&a, rr, &a);
            a.sign = b.sign;
            if (mp_cmp(&a, &b) != MP_EQ) {
                printf("mul2d failed, rr == %d\n", rr);
                draw(&a);
                draw(&b);
                return 0;
            }
        } else if (!strcmp(cmd, "div2d")) {
            ++div2d_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            sscanf(buf, "%d", &rr);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);

            mp_div_2d(&a, rr, &a, &e);
            a.sign = b.sign;
            if (a.used == b.used && a.used == 0) {
                a.sign = b.sign = MP_ZPOS;
            }
            if (mp_cmp(&a, &b) != MP_EQ) {
                printf("div2d failed, rr == %d\n", rr);
                draw(&a);
                draw(&b);
                return 0;
            }
        } else if (!strcmp(cmd, "add")) {
            ++add_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_copy(&a, &d);
            mp_add(&d, &b, &d);
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("add %lu failure!\n", add_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                return 0;
            }

            /* test the sign/unsigned storage functions */

            rr = mp_signed_bin_size(&c);
            mp_to_signed_bin(&c, (unsigned char *) cmd);
            memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
            mp_read_signed_bin(&d, (unsigned char *) cmd, rr);
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("mp_signed_bin failure!\n");
                draw(&c);
                draw(&d);
                return 0;
            }


            rr = mp_unsigned_bin_size(&c);
            mp_to_unsigned_bin(&c, (unsigned char *) cmd);
            memset(cmd + rr, rand() & 255, sizeof(cmd) - rr);
            mp_read_unsigned_bin(&d, (unsigned char *) cmd, rr);
            if (mp_cmp_mag(&c, &d) != MP_EQ) {
                printf("mp_unsigned_bin failure!\n");
                draw(&c);
                draw(&d);
                return 0;
            }

        } else if (!strcmp(cmd, "sub")) {
            ++sub_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_copy(&a, &d);
            mp_sub(&d, &b, &d);
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("sub %lu failure!\n", sub_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                return 0;
            }
        } else if (!strcmp(cmd, "mul")) {
            ++mul_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_copy(&a, &d);
            mp_mul(&d, &b, &d);
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("mul %lu failure!\n", mul_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                return 0;
            }
        } else if (!strcmp(cmd, "div")) {
            ++div_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&d, buf, 64);

            mp_div(&a, &b, &e, &f);
            if (mp_cmp(&c, &e) != MP_EQ || mp_cmp(&d, &f) != MP_EQ) {
                printf("div %lu %d, %d, failure!\n", div_n, mp_cmp(&c, &e),
                       mp_cmp(&d, &f));
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                draw(&e);
                draw(&f);
                return 0;
            }

        } else if (!strcmp(cmd, "sqr")) {
            ++sqr_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            mp_copy(&a, &c);
            mp_sqr(&c, &c);
            if (mp_cmp(&b, &c) != MP_EQ) {
                printf("sqr %lu failure!\n", sqr_n);
                draw(&a);
                draw(&b);
                draw(&c);
                return 0;
            }
        } else if (!strcmp(cmd, "gcd")) {
            ++gcd_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_copy(&a, &d);
            mp_gcd(&d, &b, &d);
            d.sign = c.sign;
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("gcd %lu failure!\n", gcd_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                return 0;
            }
        } else if (!strcmp(cmd, "lcm")) {
            ++lcm_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_copy(&a, &d);
            mp_lcm(&d, &b, &d);
            d.sign = c.sign;
            if (mp_cmp(&c, &d) != MP_EQ) {
                printf("lcm %lu failure!\n", lcm_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                return 0;
            }
        } else if (!strcmp(cmd, "expt")) {
            ++expt_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&d, buf, 64);
            mp_copy(&a, &e);
            mp_exptmod(&e, &b, &c, &e);
            if (mp_cmp(&d, &e) != MP_EQ) {
                printf("expt %lu failure!\n", expt_n);
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                draw(&e);
                return 0;
            }
        } else if (!strcmp(cmd, "invmod")) {
            ++inv_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&c, buf, 64);
            mp_invmod(&a, &b, &d);
            mp_mulmod(&d, &a, &b, &e);
            if (mp_cmp_d(&e, 1) != MP_EQ) {
                printf("inv [wrong value from MPI?!] failure\n");
                draw(&a);
                draw(&b);
                draw(&c);
                draw(&d);
                mp_gcd(&a, &b, &e);
                draw(&e);
                return 0;
            }

        } else if (!strcmp(cmd, "div2")) {
            ++div2_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            mp_div_2(&a, &c);
            if (mp_cmp(&c, &b) != MP_EQ) {
                printf("div_2 %lu failure\n", div2_n);
                draw(&a);
                draw(&b);
                draw(&c);
                return 0;
            }
        } else if (!strcmp(cmd, "mul2")) {
            ++mul2_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            mp_mul_2(&a, &c);
            if (mp_cmp(&c, &b) != MP_EQ) {
                printf("mul_2 %lu failure\n", mul2_n);
                draw(&a);
                draw(&b);
                draw(&c);
                return 0;
            }
        } else if (!strcmp(cmd, "add_d")) {
            ++add_d_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            sscanf(buf, "%d", &ix);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            mp_add_d(&a, ix, &c);
            if (mp_cmp(&b, &c) != MP_EQ) {
                printf("add_d %lu failure\n", add_d_n);
                draw(&a);
                draw(&b);
                draw(&c);
                printf("d == %d\n", ix);
                return 0;
            }
        } else if (!strcmp(cmd, "sub_d")) {
            ++sub_d_n;
            fgets(buf, 4095, stdin);
            mp_read_radix(&a, buf, 64);
            fgets(buf, 4095, stdin);
            sscanf(buf, "%d", &ix);
            fgets(buf, 4095, stdin);
            mp_read_radix(&b, buf, 64);
            mp_sub_d(&a, ix, &c);
            if (mp_cmp(&b, &c) != MP_EQ) {
                printf("sub_d %lu failure\n", sub_d_n);
                draw(&a);
                draw(&b);
                draw(&c);
                printf("d == %d\n", ix);
                return 0;
            }
        }
    }
    return 0;
}
Esempio n. 11
0
/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P, 
 * Q, and R can all be identical. Uses affine coordinates. Assumes input
 * is already field-encoded using field_enc, and returns output that is
 * still field-encoded. */
mp_err
ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx,
				  const mp_int *qy, mp_int *rx, mp_int *ry,
				  const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int lambda, temp, tempx, tempy;

	MP_DIGITS(&lambda) = 0;
	MP_DIGITS(&temp) = 0;
	MP_DIGITS(&tempx) = 0;
	MP_DIGITS(&tempy) = 0;
	MP_CHECKOK(mp_init(&lambda));
	MP_CHECKOK(mp_init(&temp));
	MP_CHECKOK(mp_init(&tempx));
	MP_CHECKOK(mp_init(&tempy));
	/* if P = inf, then R = Q */
	if (ec_GFp_pt_is_inf_aff(px, py) == 0) {
		MP_CHECKOK(mp_copy(qx, rx));
		MP_CHECKOK(mp_copy(qy, ry));
		res = MP_OKAY;
		goto CLEANUP;
	}
	/* if Q = inf, then R = P */
	if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) {
		MP_CHECKOK(mp_copy(px, rx));
		MP_CHECKOK(mp_copy(py, ry));
		res = MP_OKAY;
		goto CLEANUP;
	}
	/* if px != qx, then lambda = (py-qy) / (px-qx) */
	if (mp_cmp(px, qx) != 0) {
		MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth));
		MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth));
		MP_CHECKOK(group->meth->
				   field_div(&tempy, &tempx, &lambda, group->meth));
	} else {
		/* if py != qy or qy = 0, then R = inf */
		if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) {
			mp_zero(rx);
			mp_zero(ry);
			res = MP_OKAY;
			goto CLEANUP;
		}
		/* lambda = (3qx^2+a) / (2qy) */
		MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth));
		MP_CHECKOK(mp_set_int(&temp, 3));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
		}
		MP_CHECKOK(group->meth->
				   field_mul(&tempx, &temp, &tempx, group->meth));
		MP_CHECKOK(group->meth->
				   field_add(&tempx, &group->curvea, &tempx, group->meth));
		MP_CHECKOK(mp_set_int(&temp, 2));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth));
		}
		MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth));
		MP_CHECKOK(group->meth->
				   field_div(&tempx, &tempy, &lambda, group->meth));
	}
	/* rx = lambda^2 - px - qx */
	MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth));
	MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth));
	MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth));
	/* ry = (x1-x2) * lambda - y1 */
	MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth));
	MP_CHECKOK(group->meth->
			   field_mul(&tempy, &lambda, &tempy, group->meth));
	MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth));
	MP_CHECKOK(mp_copy(&tempx, rx));
	MP_CHECKOK(mp_copy(&tempy, ry));

  CLEANUP:
	mp_clear(&lambda);
	mp_clear(&temp);
	mp_clear(&tempx);
	mp_clear(&tempy);
	return res;
}
Esempio n. 12
0
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
{
   int            err;
   ecc_point     *base;
   void          *prime, *order;
   unsigned char *buf;
   int            keysize;

   LTC_ARGCHK(key         != NULL);
   LTC_ARGCHK(ltc_mp.name != NULL);
   LTC_ARGCHK(dp          != NULL);

   /* good prng? */
   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
      return err;
   }

   key->idx = -1;
   key->dp  = dp;
   keysize  = dp->size;

   /* allocate ram */
   base = NULL;
   buf  = XMALLOC(ECC_MAXSIZE);
   if (buf == NULL) {
      return CRYPT_MEM;
   }

   /* make up random string */
   if (prng_descriptor[wprng]->read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
      err = CRYPT_ERROR_READPRNG;
      goto ERR_BUF;
   }

   /* setup the key variables */
   if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) {
      goto ERR_BUF;
   }
   base = ltc_ecc_new_point();
   if (base == NULL) {
      err = CRYPT_MEM;
      goto errkey;
   }

   /* read in the specs for this key */
   if ((err = mp_read_radix(prime,   (char *)key->dp->prime, 16)) != CRYPT_OK)                  { goto errkey; }
   if ((err = mp_read_radix(order,   (char *)key->dp->order, 16)) != CRYPT_OK)                  { goto errkey; }
   if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK)                     { goto errkey; }
   if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK)                     { goto errkey; }
   if ((err = mp_set(base->z, 1)) != CRYPT_OK)                                                  { goto errkey; }
   if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK)         { goto errkey; }

   /* the key should be smaller than the order of base point */
   if (mp_cmp(key->k, order) != LTC_MP_LT) {
       if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK)                                    { goto errkey; }
   }
   /* make the public key */
   if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK)              { goto errkey; }
   key->type = PK_PRIVATE;

   /* free up ram */
   err = CRYPT_OK;
   goto cleanup;
errkey:
   mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
cleanup:
   ltc_ecc_del_point(base);
   mp_clear_multi(prime, order, NULL);
ERR_BUF:
#ifdef LTC_CLEAN_STACK
   zeromem(buf, ECC_MAXSIZE);
#endif
   XFREE(buf);
   return err;
}
Esempio n. 13
0
SECStatus
RSA_PrivateKeyCheck(RSAPrivateKey *key)
{
    mp_int p, q, n, psub1, qsub1, e, d, d_p, d_q, qInv, res;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    MP_DIGITS(&n)    = 0;
    MP_DIGITS(&psub1)= 0;
    MP_DIGITS(&qsub1)= 0;
    MP_DIGITS(&e)    = 0;
    MP_DIGITS(&d)    = 0;
    MP_DIGITS(&d_p)  = 0;
    MP_DIGITS(&d_q)  = 0;
    MP_DIGITS(&qInv) = 0;
    MP_DIGITS(&res)  = 0;
    CHECK_MPI_OK( mp_init(&n)    );
    CHECK_MPI_OK( mp_init(&p)    );
    CHECK_MPI_OK( mp_init(&q)    );
    CHECK_MPI_OK( mp_init(&psub1));
    CHECK_MPI_OK( mp_init(&qsub1));
    CHECK_MPI_OK( mp_init(&e)    );
    CHECK_MPI_OK( mp_init(&d)    );
    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(&res)  );
    SECITEM_TO_MPINT(key->modulus,         &n);
    SECITEM_TO_MPINT(key->prime1,          &p);
    SECITEM_TO_MPINT(key->prime2,          &q);
    SECITEM_TO_MPINT(key->publicExponent,  &e);
    SECITEM_TO_MPINT(key->privateExponent, &d);
    SECITEM_TO_MPINT(key->exponent1,       &d_p);
    SECITEM_TO_MPINT(key->exponent2,       &d_q);
    SECITEM_TO_MPINT(key->coefficient,     &qInv);
    /* p > q  */
    if (mp_cmp(&p, &q) <= 0) {
	/* mind the p's and q's (and d_p's and d_q's) */
	SECItem tmp;
	mp_exch(&p, &q);
	mp_exch(&d_p,&d_q);
	tmp = key->prime1;
	key->prime1 = key->prime2;
	key->prime2 = tmp;
	tmp = key->exponent1;
	key->exponent1 = key->exponent2;
	key->exponent2 = tmp;
    }
#define VERIFY_MPI_EQUAL(m1, m2) \
    if (mp_cmp(m1, m2) != 0) {   \
	rv = SECFailure;         \
	goto cleanup;            \
    }
#define VERIFY_MPI_EQUAL_1(m)    \
    if (mp_cmp_d(m, 1) != 0) {   \
	rv = SECFailure;         \
	goto cleanup;            \
    }
    /*
     * The following errors cannot be recovered from.
     */
    /* n == p * q */
    CHECK_MPI_OK( mp_mul(&p, &q, &res) );
    VERIFY_MPI_EQUAL(&res, &n);
    /* gcd(e, p-1) == 1 */
    CHECK_MPI_OK( mp_sub_d(&p, 1, &psub1) );
    CHECK_MPI_OK( mp_gcd(&e, &psub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* gcd(e, q-1) == 1 */
    CHECK_MPI_OK( mp_sub_d(&q, 1, &qsub1) );
    CHECK_MPI_OK( mp_gcd(&e, &qsub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* d*e == 1 mod p-1 */
    CHECK_MPI_OK( mp_mulmod(&d, &e, &psub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /* d*e == 1 mod q-1 */
    CHECK_MPI_OK( mp_mulmod(&d, &e, &qsub1, &res) );
    VERIFY_MPI_EQUAL_1(&res);
    /*
     * The following errors can be recovered from.
     */
    /* d_p == d mod p-1 */
    CHECK_MPI_OK( mp_mod(&d, &psub1, &res) );
    if (mp_cmp(&d_p, &res) != 0) {
	/* swap in the correct value */
	CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent1) );
    }
    /* d_q == d mod q-1 */
    CHECK_MPI_OK( mp_mod(&d, &qsub1, &res) );
    if (mp_cmp(&d_q, &res) != 0) {
	/* swap in the correct value */
	CHECK_SEC_OK( swap_in_key_value(key->arena, &res, &key->exponent2) );
    }
    /* q * q**-1 == 1 mod p */
    CHECK_MPI_OK( mp_mulmod(&q, &qInv, &p, &res) );
    if (mp_cmp_d(&res, 1) != 0) {
	/* compute the correct value */
	CHECK_MPI_OK( mp_invmod(&q, &p, &qInv) );
	CHECK_SEC_OK( swap_in_key_value(key->arena, &qInv, &key->coefficient) );
    }
cleanup:
    mp_clear(&n);
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&psub1);
    mp_clear(&qsub1);
    mp_clear(&e);
    mp_clear(&d);
    mp_clear(&d_p);
    mp_clear(&d_q);
    mp_clear(&qInv);
    mp_clear(&res);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    return rv;
}
Esempio n. 14
0
/*
** Generate and return a new RSA public and private key.
**	Both keys are encoded in a single RSAPrivateKey structure.
**	"cx" is the random number generator context
**	"keySizeInBits" is the size of the key to be generated, in bits.
**	   512, 1024, etc.
**	"publicExponent" when not NULL is a pointer to some data that
**	   represents the public exponent to use. The data is a byte
**	   encoded integer, in "big endian" order.
*/
RSAPrivateKey *
RSA_NewKey(int keySizeInBits, SECItem *publicExponent)
{
    unsigned int primeLen;
    mp_int p, q, e;
    int kiter;
    mp_err   err = MP_OKAY;
    SECStatus rv = SECSuccess;
    int prerr = 0;
    RSAPrivateKey *key = NULL;
    PRArenaPool *arena = NULL;
    /* Require key size to be a multiple of 16 bits. */
    if (!publicExponent || keySizeInBits % 16 != 0 ||
	    BAD_RSA_KEY_SIZE(keySizeInBits/8, publicExponent->len)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return NULL;
    }
    /* 1. Allocate arena & key */
    arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE);
    if (!arena) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	return NULL;
    }
    key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey));
    if (!key) {
	PORT_SetError(SEC_ERROR_NO_MEMORY);
	PORT_FreeArena(arena, PR_TRUE);
	return NULL;
    }
    key->arena = arena;
    /* length of primes p and q (in bytes) */
    primeLen = keySizeInBits / (2 * BITS_PER_BYTE);
    MP_DIGITS(&p) = 0;
    MP_DIGITS(&q) = 0;
    MP_DIGITS(&e) = 0;
    CHECK_MPI_OK( mp_init(&p) );
    CHECK_MPI_OK( mp_init(&q) );
    CHECK_MPI_OK( mp_init(&e) );
    /* 2.  Set the version number (PKCS1 v1.5 says it should be zero) */
    SECITEM_AllocItem(arena, &key->version, 1);
    key->version.data[0] = 0;
    /* 3.  Set the public exponent */
    SECITEM_CopyItem(arena, &key->publicExponent, publicExponent);
    SECITEM_TO_MPINT(*publicExponent, &e);
    kiter = 0;
    do {
	prerr = 0;
	PORT_SetError(0);
	CHECK_SEC_OK( generate_prime(&p, primeLen) );
	CHECK_SEC_OK( generate_prime(&q, primeLen) );
	/* Assure q < p */
	if (mp_cmp(&p, &q) < 0)
	    mp_exch(&p, &q);
	/* Attempt to use these primes to generate a key */
	rv = rsa_keygen_from_primes(&p, &q, &e, key, keySizeInBits);
	if (rv == SECSuccess)
	    break; /* generated two good primes */
	prerr = PORT_GetError();
	kiter++;
	/* loop until have primes */
    } while (prerr == SEC_ERROR_NEED_RANDOM && kiter < MAX_KEY_GEN_ATTEMPTS);
    if (prerr)
	goto cleanup;
    MPINT_TO_SECITEM(&p, &key->prime1, arena);
    MPINT_TO_SECITEM(&q, &key->prime2, arena);
cleanup:
    mp_clear(&p);
    mp_clear(&q);
    mp_clear(&e);
    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }
    if (rv && arena) {
	PORT_FreeArena(arena, PR_TRUE);
	key = NULL;
    }
    return key;
}
Esempio n. 15
0
int main(int argc, char *argv[])
{
  mp_int   a, m, p, k;

  if(argc < 3) {
    fprintf(stderr, "Usage: %s <a> <m>\n", argv[0]);
    return 1;
  }

  mp_init(&a);
  mp_init(&m);
  mp_init(&p);
  mp_add_d(&p, 1, &p);

  mp_read_radix(&a, argv[1], 10);
  mp_read_radix(&m, argv[2], 10);

  mp_init_copy(&k, &a);

  signal(SIGINT, sig_catch);
#ifndef __OS2__
  signal(SIGHUP, sig_catch);
#endif
  signal(SIGTERM, sig_catch);

  while(mp_cmp(&p, &m) < 0) {
    if(g_quit) {
	int  len;
	char *buf;

	len = mp_radix_size(&p, 10);
	buf = malloc(len);
	mp_toradix(&p, buf, 10);
	
	fprintf(stderr, "Terminated at: %s\n", buf);
	free(buf);
	return 1;
    }
    if(mp_cmp_d(&k, 1) == 0) {
      int    len;
      char  *buf;

      len = mp_radix_size(&p, 10);
      buf = malloc(len);
      mp_toradix(&p, buf, 10);

      printf("%s\n", buf);

      free(buf);
      break;
    }

    mp_mulmod(&k, &a, &m, &k);
    mp_add_d(&p, 1, &p);
  }

  if(mp_cmp(&p, &m) >= 0) 
    printf("No annihilating power.\n");

  mp_clear(&p);
  mp_clear(&m);
  mp_clear(&a);
  return 0;
}
Esempio n. 16
0
int main(int argc, char *argv[])
{
  int          ix, num, prec = PRECISION;
  mp_int       a, b, c, d;
  instant_t    start, finish;
  time_t       seed;
  unsigned int d1, d2;

  seed = time(NULL);

  if(argc < 2) {
    fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
    return 1;
  }

  if((num = atoi(argv[1])) < 0)
    num = -num;

  printf("Test 5a: Euclid vs. Binary, a GCD speed test\n\n"
	 "Number of tests: %d\n"
	 "Precision:       %d digits\n\n", num, prec);

  mp_init_size(&a, prec);
  mp_init_size(&b, prec);
  mp_init(&c);
  mp_init(&d);

  printf("Verifying accuracy ... \n");
  srand((unsigned int)seed);
  for(ix = 0; ix < num; ix++) {
    mpp_random_size(&a, prec);
    mpp_random_size(&b, prec);

    mp_gcd(&a, &b, &c);
    mp_bgcd(&a, &b, &d);

    if(mp_cmp(&c, &d) != 0) {
      printf("Error!  Results not accurate:\n");
      printf("a = "); mp_print(&a, stdout); fputc('\n', stdout);
      printf("b = "); mp_print(&b, stdout); fputc('\n', stdout);
      printf("c = "); mp_print(&c, stdout); fputc('\n', stdout);
      printf("d = "); mp_print(&d, stdout); fputc('\n', stdout);

      mp_clear(&a); mp_clear(&b); mp_clear(&c); mp_clear(&d);
      return 1;
    }
  }
  mp_clear(&d);
  printf("Accuracy confirmed for the %d test samples\n", num);

  printf("Testing Euclid ... \n");
  srand((unsigned int)seed);
  start = now();
  for(ix = 0; ix < num; ix++) {
    mpp_random_size(&a, prec);
    mpp_random_size(&b, prec);
    mp_gcd(&a, &b, &c);

  }
  finish = now();

  d1 = (finish.sec - start.sec) * 1000000;
  d1 -= start.usec; d1 += finish.usec;

  printf("Testing binary ... \n");
  srand((unsigned int)seed);
  start = now();
  for(ix = 0; ix < num; ix++) {
    mpp_random_size(&a, prec);
    mpp_random_size(&b, prec);
    mp_bgcd(&a, &b, &c);
  }
  finish = now();

  d2 = (finish.sec - start.sec) * 1000000;
  d2 -= start.usec; d2 += finish.usec;

  printf("Euclidean algorithm time: %u usec\n", d1);
  printf("Binary algorithm time:    %u usec\n", d2);
  printf("Improvement:              %.2f%%\n",
         (1.0 - ((double)d2 / (double)d1)) * 100.0);

  mp_clear(&c);
  mp_clear(&b);
  mp_clear(&a);

  return 0;
}
Esempio n. 17
0
/* find the n'th root of an integer
 *
 * Result found such that (c)**b <= a and (c+1)**b > a
 *
 * This algorithm uses Newton's approximation
 * x[i+1] = x[i] - f(x[i])/f'(x[i])
 * which will find the root in log(N) time where
 * each step involves a fair bit.  This is not meant to
 * find huge roots [square and cube, etc].
 */
int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{
  mp_int  t1, t2, t3;
  int     res, neg;

  /* input must be positive if b is even */
  if ((b & 1) == 0 && a->sign == MP_NEG) {
    return MP_VAL;
  }

  if ((res = mp_init (&t1)) != MP_OKAY) {
    return res;
  }

  if ((res = mp_init (&t2)) != MP_OKAY) {
    goto LBL_T1;
  }

  if ((res = mp_init (&t3)) != MP_OKAY) {
    goto LBL_T2;
  }

  /* if a is negative fudge the sign but keep track */
  neg     = a->sign;
  a->sign = MP_ZPOS;

  /* t2 = 2 */
  mp_set (&t2, 2);

  do {
    /* t1 = t2 */
    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */

    /* t3 = t1**(b-1) */
    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* numerator */
    /* t2 = t1**b */
    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t2 = t1**b - a */
    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* denominator */
    /* t3 = t1**(b-1) * b  */
    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {
      goto LBL_T3;
    }

    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {
      goto LBL_T3;
    }

    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }
  }  while (mp_cmp (&t1, &t2) != MP_EQ);

  /* result can be off by a few so check */
  for (;;) {
    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
      goto LBL_T3;
    }

    if (mp_cmp (&t2, a) == MP_GT) {
      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
         goto LBL_T3;
      }
    } else {
      break;
    }
  }

  /* reset the sign of a first */
  a->sign = neg;

  /* set the result */
  mp_exch (&t1, c);

  /* set the sign of the result */
  c->sign = neg;

  res = MP_OKAY;

LBL_T3:mp_clear (&t3);
LBL_T2:mp_clear (&t2);
LBL_T1:mp_clear (&t1);
  return res;
}
Esempio n. 18
0
/* hac 14.61, pp608 */
int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
{
  mp_int  x, y, u, v, A, B, C, D;
  int     res;

  /* b cannot be negative */
  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
    return MP_VAL;
  }

  /* init temps */
  if ((res = mp_init_multi(&x, &y, &u, &v, 
                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
     return res;
  }

  /* x = a, y = b */
  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
      goto LBL_ERR;
  }
  if ((res = mp_copy (b, &y)) != MP_OKAY) {
    goto LBL_ERR;
  }

  /* 2. [modified] if x,y are both even then return an error! */
  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
    goto LBL_ERR;
  }
  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
    goto LBL_ERR;
  }
  mp_set (&A, 1);
  mp_set (&D, 1);

top:
  /* 4.  while u is even do */
  while (mp_iseven (&u) == 1) {
    /* 4.1 u = u/2 */
    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 4.2 if A or B is odd then */
    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
      /* A = (A+y)/2, B = (B-x)/2 */
      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* A = A/2, B = B/2 */
    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 5.  while v is even do */
  while (mp_iseven (&v) == 1) {
    /* 5.1 v = v/2 */
    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }
    /* 5.2 if C or D is odd then */
    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
      /* C = (C+y)/2, D = (D-x)/2 */
      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
         goto LBL_ERR;
      }
    }
    /* C = C/2, D = D/2 */
    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }
    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* 6.  if u >= v then */
  if (mp_cmp (&u, &v) != MP_LT) {
    /* u = u - v, A = A - C, B = B - D */
    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
      goto LBL_ERR;
    }
  } else {
    /* v - v - u, C = C - A, D = D - B */
    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
      goto LBL_ERR;
    }

    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
      goto LBL_ERR;
    }
  }

  /* if not zero goto step 4 */
  if (mp_iszero (&u) == 0)
    goto top;

  /* now a = C, b = D, gcd == g*v */

  /* if v != 1 then there is no inverse */
  if (mp_cmp_d (&v, 1) != MP_EQ) {
    res = MP_VAL;
    goto LBL_ERR;
  }

  /* if its too low */
  while (mp_cmp_d(&C, 0) == MP_LT) {
      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* too big */
  while (mp_cmp_mag(&C, b) != MP_LT) {
      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
         goto LBL_ERR;
      }
  }
  
  /* C is now the inverse */
  mp_exch (&C, c);
  res = MP_OKAY;
LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
  return res;
}
Esempio n. 19
0
File: dsa.c Progetto: agnov8/wolfssl
int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer)
{
    mp_int w, u1, u2, v, r, s;
    int    ret = 0;

    if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY)
        return MP_INIT_E;

    /* set r and s from signature */
    if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY ||
        mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY)
        ret = MP_READ_E;

    /* sanity checks */
    if (ret == 0) {
        if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES ||
                mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) {
            ret = MP_ZERO_E;
        }
    }

    /* put H into u1 from sha digest */
    if (ret == 0 && mp_read_unsigned_bin(&u1,digest,SHA_DIGEST_SIZE) != MP_OKAY)
        ret = MP_READ_E;

    /* w = s invmod q */
    if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY)
        ret = MP_INVMOD_E;

    /* u1 = (H * w) % q */
    if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* u2 = (r * w) % q */
    if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* verify v = ((g^u1 * y^u2) mod p) mod q */
    if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY)
        ret = MP_MULMOD_E;

    if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY)
        ret = MP_MULMOD_E;

    /* do they match */
    if (ret == 0 && mp_cmp(&r, &v) == MP_EQ)
        *answer = 1;
    else
        *answer = 0;

    mp_clear(&s);
    mp_clear(&r);
    mp_clear(&u1);
    mp_clear(&u2);
    mp_clear(&w);
    mp_clear(&v);

    return ret;
}
/**
   Double an ECC point
   @param P   The point to double
   @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
*/
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp)
{
   void *t1, *t2;
   int   err;

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

   if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
      return err;
   }

   if (P != R) {
      if ((err = mp_copy(P->x, R->x)) != CRYPT_OK)                                { goto done; }
      if ((err = mp_copy(P->y, R->y)) != CRYPT_OK)                                { goto done; }
      if ((err = mp_copy(P->z, R->z)) != CRYPT_OK)                                { goto done; }
   }

   /* t1 = Z * Z */
   if ((err = mp_sqr(R->z, t1)) != CRYPT_OK)                                      { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)                 { goto done; }
   /* Z = Y * Z */
   if ((err = mp_mul(R->z, R->y, R->z)) != CRYPT_OK)                              { goto done; }
   if ((err = mp_montgomery_reduce(R->z, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* Z = 2Z */
   if ((err = mp_add(R->z, R->z, R->z)) != CRYPT_OK)                              { goto done; }
   if (mp_cmp(R->z, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK)                        { goto done; }
   }
   
   /* T2 = X - T1 */
   if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
      if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                            { goto done; }
   }
   /* T1 = X + T1 */
   if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
   }
   /* T2 = T1 * T2 */
   if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK)                                    { goto done; }
   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)                 { goto done; }
   /* T1 = 2T2 */
   if ((err = mp_add(t2, t2, t1)) != CRYPT_OK)                                    { goto done; }
   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
   }
   /* T1 = T1 + T2 */
   if ((err = mp_add(t1, t2, t1)) != CRYPT_OK)                                    { goto done; }
   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                            { goto done; }
   }

   /* Y = 2Y */
   if ((err = mp_add(R->y, R->y, R->y)) != CRYPT_OK)                              { goto done; }
   if (mp_cmp(R->y, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(R->y, modulus, R->y)) != CRYPT_OK)                        { goto done; }
   }
   /* Y = Y * Y */
   if ((err = mp_sqr(R->y, R->y)) != CRYPT_OK)                                    { goto done; }
   if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* T2 = Y * Y */
   if ((err = mp_sqr(R->y, t2)) != CRYPT_OK)                                      { goto done; }
   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)                 { goto done; }
   /* T2 = T2/2 */
   if (mp_isodd(t2)) {
      if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                            { goto done; }
   }
   if ((err = mp_div_2(t2, t2)) != CRYPT_OK)                                      { goto done; }
   /* Y = Y * X */
   if ((err = mp_mul(R->y, R->x, R->y)) != CRYPT_OK)                              { goto done; }
   if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               { goto done; }

   /* X  = T1 * T1 */
   if ((err = mp_sqr(t1, R->x)) != CRYPT_OK)                                      { goto done; }
   if ((err = mp_montgomery_reduce(R->x, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* X = X - Y */
   if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK)                              { goto done; }
   if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
      if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK)                        { goto done; }
   }
   /* X = X - Y */
   if ((err = mp_sub(R->x, R->y, R->x)) != CRYPT_OK)                              { goto done; }
   if (mp_cmp_d(R->x, 0) == LTC_MP_LT) {
      if ((err = mp_add(R->x, modulus, R->x)) != CRYPT_OK)                        { goto done; }
   }

   /* Y = Y - X */     
   if ((err = mp_sub(R->y, R->x, R->y)) != CRYPT_OK)                              { goto done; }
   if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
      if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK)                        { goto done; }
   }
   /* Y = Y * T1 */
   if ((err = mp_mul(R->y, t1, R->y)) != CRYPT_OK)                                { goto done; }
   if ((err = mp_montgomery_reduce(R->y, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* Y = Y - T2 */
   if ((err = mp_sub(R->y, t2, R->y)) != CRYPT_OK)                                { goto done; }
   if (mp_cmp_d(R->y, 0) == LTC_MP_LT) {
      if ((err = mp_add(R->y, modulus, R->y)) != CRYPT_OK)                        { goto done; }
   }
 
   err = CRYPT_OK;
done:
   mp_clear_multi(t1, t2, NULL);
   return err;
}
Esempio n. 21
0
/**
   Compute an RSA modular exponentiation
   @param in         The input data to send into RSA
   @param inlen      The length of the input (octets)
   @param out        [out] The destination
   @param outlen     [in/out] The max size and resulting size of the output
   @param which      Which exponent to use, e.g. PK_PRIVATE or PK_PUBLIC
   @param key        The RSA key to use
   @return CRYPT_OK if successful
*/
int rsa_exptmod(const unsigned char *in,   unsigned long inlen,
                      unsigned char *out,  unsigned long *outlen, int which,
                      rsa_key *key)
{
   void        *tmp, *tmpa, *tmpb;
   #ifdef LTC_RSA_BLINDING
   void        *rnd = NULL, *rndi = NULL /* inverse of rnd */;
   #endif
   unsigned long x;
   int           err;

   LTC_ARGCHK(in     != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);
   LTC_ARGCHK(key    != NULL);

   /* is the key of the right type for the operation? */
   if (which == PK_PRIVATE && (key->type != PK_PRIVATE)) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   /* must be a private or public operation */
   if (which != PK_PRIVATE && which != PK_PUBLIC) {
      return CRYPT_PK_INVALID_TYPE;
   }

   /* init and copy into tmp */
   if ((err = mp_init_multi(&tmp, &tmpa, &tmpb, NULL)) != CRYPT_OK)
        { return err; }
   if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, (int)inlen)) != CRYPT_OK)
        { goto error; }


   /* sanity check on the input */
   if (mp_cmp(key->N, tmp) == LTC_MP_LT) {
      err = CRYPT_PK_INVALID_SIZE;
      goto error;
   }

   /* are we using the private exponent and is the key optimized? */
   if (which == PK_PRIVATE) {
      #ifdef LTC_RSA_BLINDING
      if ((err = mp_init_multi(&rnd, &rndi, NULL)) != CRYPT_OK)
            { goto error; }
      /* do blinding */
      err = mp_rand(rnd, mp_count_bits(key->N));
      if (err != CRYPT_OK) {
             goto error_blind;
      }

      /* rndi = 1/rnd mod N */
      err = mp_invmod(rnd, key->N, rndi);
      if (err != CRYPT_OK) {
             goto error_blind;
      }

      /* rnd = rnd^e */
      err = mp_exptmod( rnd, key->e, key->N, rnd);
      if (err != CRYPT_OK) {
             goto error_blind;
      }

      /* tmp = tmp*rnd mod N */
      err = mp_mulmod( tmp, rnd, key->N, tmp);
      if (err != CRYPT_OK) {
             goto error_blind;
      }
      #endif /* LTC_RSA_BLINDING */

      /* tmpa = tmp^dP mod p */
      if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK)                               { goto error_blind; }

      /* tmpb = tmp^dQ mod q */
      if ((err = mp_exptmod(tmp, key->dQ, key->q, tmpb)) != CRYPT_OK)                               { goto error_blind; }

      /* tmp = (tmpa - tmpb) * qInv (mod p) */
      if ((err = mp_sub(tmpa, tmpb, tmp)) != CRYPT_OK)                                              { goto error_blind; }
      if ((err = mp_mulmod(tmp, key->qP, key->p, tmp)) != CRYPT_OK)                                { goto error_blind; }

      /* tmp = tmpb + q * tmp */
      if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK)                                             { goto error_blind; }
      if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK)                                               { goto error_blind; }

      #ifdef LTC_RSA_BLINDING
      /* unblind */
      err = mp_mulmod( tmp, rndi, key->N, tmp);
      if (err != CRYPT_OK) {
             goto error_blind;
      }
      #endif
   } else {
      /* exptmod it */
      if ((err = mp_exptmod(tmp, key->e, key->N, tmp)) != CRYPT_OK)                                { goto error; }
   }

   /* read it back */
   x = (unsigned long)mp_unsigned_bin_size(key->N);
   if (x > *outlen) {
      *outlen = x;
      err = CRYPT_BUFFER_OVERFLOW;
      goto error;
   }

   /* this should never happen ... */
   if (mp_unsigned_bin_size(tmp) > mp_unsigned_bin_size(key->N)) {
      err = CRYPT_ERROR;
      goto error;
   }
   *outlen = x;

   /* convert it */
   zeromem(out, x);
   if ((err = mp_to_unsigned_bin(tmp, out+(x-mp_unsigned_bin_size(tmp)))) != CRYPT_OK)               { goto error; }

   /* clean up and return */
   err = CRYPT_OK;
error_blind:
   #ifdef LTC_RSA_BLINDING
   mp_clear_multi(rnd, rndi, NULL);
   #endif
error:
   mp_clear_multi(tmp, tmpa, tmpb, NULL);
   return err;
}
/**
  Encrypt a symmetric key with DSA
  @param in         The symmetric key you want to encrypt
  @param inlen      The length of the key to encrypt (octets)
  @param out        [out] The destination for the ciphertext
  @param outlen     [in/out] The max size and resulting size of the ciphertext
  @param prng       An active PRNG state
  @param wprng      The index of the PRNG you wish to use 
  @param hash       The index of the hash you want to use 
  @param key        The DSA key you want to encrypt to
  @return CRYPT_OK if successful
*/
int dsa_encrypt_key(const unsigned char *in,   unsigned long inlen,
                          unsigned char *out,  unsigned long *outlen, 
                          prng_state *prng, int wprng, int hash, 
                          dsa_key *key)
{
    unsigned char *expt, *skey;
    void          *g_pub, *g_priv;
    unsigned long  x, y;
    int            err, qbits;

    LTC_ARGCHK(in      != NULL);
    LTC_ARGCHK(out     != NULL);
    LTC_ARGCHK(outlen  != NULL);
    LTC_ARGCHK(key     != NULL);

    /* check that wprng/cipher/hash are not invalid */
    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
       return err;
    }

    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
       return err;
    }

    if (inlen > hash_descriptor[hash]->hashsize) {
       return CRYPT_INVALID_HASH;
    }

    /* make a random key and export the public copy */
    if ((err = mp_init_multi(&g_pub, &g_priv, NULL)) != CRYPT_OK) {
       return err;
    }
   
    expt       = XMALLOC(mp_unsigned_bin_size(key->p) + 1);
    skey       = XMALLOC(MAXBLOCKSIZE);
    if (expt == NULL  || skey == NULL) {
       if (expt != NULL) {
          XFREE(expt);
       }
       if (skey != NULL) {
          XFREE(skey);
       }
       mp_clear_multi(g_pub, g_priv, NULL);
       return CRYPT_MEM;
    }
    
    /* make a random g_priv, g_pub = g^x pair */
    qbits = mp_count_bits(key->q);
    do {
      if ((err = rand_bn_bits(g_priv, qbits, prng, wprng)) != CRYPT_OK) {
        goto LBL_ERR;
      }
      /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
    } while (mp_cmp_d(g_priv, 0) != LTC_MP_GT || mp_cmp(g_priv, key->q) != LTC_MP_LT);

    /* compute y */
    if ((err = mp_exptmod(key->g, g_priv, key->p, g_pub)) != CRYPT_OK) {
       goto LBL_ERR;
    }
    
    /* make random key */
    x        = mp_unsigned_bin_size(key->p) + 1;
    if ((err = dsa_shared_secret(g_priv, key->y, key, expt, &x)) != CRYPT_OK) {
       goto LBL_ERR;
    }

    y = MAXBLOCKSIZE;
    if ((err = hash_memory(hash, expt, x, skey, &y)) != CRYPT_OK) {
       goto LBL_ERR;
    }
    
    /* Encrypt key */
    for (x = 0; x < inlen; x++) {
      skey[x] ^= in[x];
    }

    err = der_encode_sequence_multi(out, outlen,
                                    LTC_ASN1_OBJECT_IDENTIFIER,  hash_descriptor[hash]->OIDlen,   hash_descriptor[hash]->OID,
                                    LTC_ASN1_INTEGER,            1UL,                            g_pub,
                                    LTC_ASN1_OCTET_STRING,       inlen,                          skey,
                                    LTC_ASN1_EOL,                0UL,                            NULL);

LBL_ERR:
#ifdef LTC_CLEAN_STACK
    /* clean up */
    zeromem(expt,   mp_unsigned_bin_size(key->p) + 1);
    zeromem(skey,   MAXBLOCKSIZE);
#endif

    XFREE(skey);
    XFREE(expt);
    
    mp_clear_multi(g_pub, g_priv, NULL);
    return err;
}
/**
   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
*/
int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
{
   void  *t1, *t2, *x, *y, *z;
   int    err;

   LTC_ARGCHK(P       != NULL);
   LTC_ARGCHK(Q       != NULL);
   LTC_ARGCHK(R       != NULL);
   LTC_ARGCHK(modulus != NULL);
   LTC_ARGCHK(mp      != NULL);

   if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != CRYPT_OK) {
      return err;
   }
   
   /* should we dbl instead? */
   if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK)                          { goto done; }

   if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) && 
        (Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
        (mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
        mp_clear_multi(t1, t2, x, y, z, NULL);
        return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
   }

   if ((err = mp_copy(P->x, x)) != CRYPT_OK)                                   { goto done; }
   if ((err = mp_copy(P->y, y)) != CRYPT_OK)                                   { goto done; }
   if ((err = mp_copy(P->z, z)) != CRYPT_OK)                                   { goto done; }

   /* if Z is one then these are no-operations */
   if (Q->z != NULL) {
      /* T1 = Z' * Z' */
      if ((err = mp_sqr(Q->z, t1)) != CRYPT_OK)                                { goto done; }
      if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)           { goto done; }
      /* X = X * T1 */
      if ((err = mp_mul(t1, x, x)) != CRYPT_OK)                                { goto done; }
      if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK)            { goto done; }
      /* T1 = Z' * T1 */
      if ((err = mp_mul(Q->z, t1, t1)) != CRYPT_OK)                            { goto done; }
      if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)           { goto done; }
      /* Y = Y * T1 */
      if ((err = mp_mul(t1, y, y)) != CRYPT_OK)                                { goto done; }
      if ((err = mp_montgomery_reduce(y, modulus, mp)) != CRYPT_OK)            { goto done; }
   }

   /* T1 = Z*Z */
   if ((err = mp_sqr(z, t1)) != CRYPT_OK)                                      { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* T2 = X' * T1 */
   if ((err = mp_mul(Q->x, t1, t2)) != CRYPT_OK)                               { goto done; }
   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* T1 = Z * T1 */
   if ((err = mp_mul(z, t1, t1)) != CRYPT_OK)                                  { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* T1 = Y' * T1 */
   if ((err = mp_mul(Q->y, t1, t1)) != CRYPT_OK)                               { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)              { goto done; }

   /* Y = Y - T1 */
   if ((err = mp_sub(y, t1, y)) != CRYPT_OK)                                   { goto done; }
   if (mp_cmp_d(y, 0) == LTC_MP_LT) {
      if ((err = mp_add(y, modulus, y)) != CRYPT_OK)                           { goto done; }
   }
   /* T1 = 2T1 */
   if ((err = mp_add(t1, t1, t1)) != CRYPT_OK)                                 { goto done; }
   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         { goto done; }
   }
   /* T1 = Y + T1 */
   if ((err = mp_add(t1, y, t1)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp(t1, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK)                         { goto done; }
   }
   /* X = X - T2 */
   if ((err = mp_sub(x, t2, x)) != CRYPT_OK)                                   { goto done; }
   if (mp_cmp_d(x, 0) == LTC_MP_LT) {
      if ((err = mp_add(x, modulus, x)) != CRYPT_OK)                           { goto done; }
   }
   /* T2 = 2T2 */
   if ((err = mp_add(t2, t2, t2)) != CRYPT_OK)                                 { goto done; }
   if (mp_cmp(t2, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK)                         { goto done; }
   }
   /* T2 = X + T2 */
   if ((err = mp_add(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp(t2, modulus) != LTC_MP_LT) {
      if ((err = mp_sub(t2, modulus, t2)) != CRYPT_OK)                         { goto done; }
   }

   /* if Z' != 1 */
   if (Q->z != NULL) {
      /* Z = Z * Z' */
      if ((err = mp_mul(z, Q->z, z)) != CRYPT_OK)                              { goto done; }
      if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK)            { goto done; }
   }

   /* Z = Z * X */
   if ((err = mp_mul(z, x, z)) != CRYPT_OK)                                    { goto done; }
   if ((err = mp_montgomery_reduce(z, modulus, mp)) != CRYPT_OK)               { goto done; }

   /* T1 = T1 * X  */
   if ((err = mp_mul(t1, x, t1)) != CRYPT_OK)                                  { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* X = X * X */
   if ((err = mp_sqr(x, x)) != CRYPT_OK)                                       { goto done; }
   if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* T2 = T2 * x */
   if ((err = mp_mul(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* T1 = T1 * X  */
   if ((err = mp_mul(t1, x, t1)) != CRYPT_OK)                                  { goto done; }
   if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK)              { goto done; }
 
   /* X = Y*Y */
   if ((err = mp_sqr(y, x)) != CRYPT_OK)                                       { goto done; }
   if ((err = mp_montgomery_reduce(x, modulus, mp)) != CRYPT_OK)               { goto done; }
   /* X = X - T2 */
   if ((err = mp_sub(x, t2, x)) != CRYPT_OK)                                   { goto done; }
   if (mp_cmp_d(x, 0) == LTC_MP_LT) {
      if ((err = mp_add(x, modulus, x)) != CRYPT_OK)                           { goto done; }
   }

   /* T2 = T2 - X */
   if ((err = mp_sub(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
      if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                         { goto done; }
   } 
   /* T2 = T2 - X */
   if ((err = mp_sub(t2, x, t2)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
      if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK)                         { goto done; }
   }
   /* T2 = T2 * Y */
   if ((err = mp_mul(t2, y, t2)) != CRYPT_OK)                                  { goto done; }
   if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK)              { goto done; }
   /* Y = T2 - T1 */
   if ((err = mp_sub(t2, t1, y)) != CRYPT_OK)                                  { goto done; }
   if (mp_cmp_d(y, 0) == LTC_MP_LT) {
      if ((err = mp_add(y, modulus, y)) != CRYPT_OK)                           { goto done; }
   }
   /* Y = Y/2 */
   if (mp_isodd(y)) {
      if ((err = mp_add(y, modulus, y)) != CRYPT_OK)                           { goto done; }
   }
   if ((err = mp_div_2(y, y)) != CRYPT_OK)                                     { goto done; }

   if ((err = mp_copy(x, R->x)) != CRYPT_OK)                                   { goto done; }
   if ((err = mp_copy(y, R->y)) != CRYPT_OK)                                   { goto done; }
   if ((err = mp_copy(z, R->z)) != CRYPT_OK)                                   { goto done; }

   err = CRYPT_OK;
done:
   mp_clear_multi(t1, t2, x, y, z, NULL);
   return err;
}
Esempio n. 24
0
/**
   Verify a DSA key for validity
   @param key   The key to verify
   @param stat  [out]  Result of test, 1==valid, 0==invalid
   @return CRYPT_OK if successful
*/
int dsa_verify_key(dsa_key * key, int *stat)
{
    mp_int tmp, tmp2;
    int res, err;

    LTC_ARGCHK(key != NULL);
    LTC_ARGCHK(stat != NULL);

    /* default to an invalid key */
    *stat = 0;

    /* first make sure key->q and key->p are prime */
    if ((err = mp_prime_is_prime(&key->q, 8, &res)) != CRYPT_OK) {
        return err;
    }
    if (res == 0) {
        return CRYPT_OK;
    }

    if ((err = mp_prime_is_prime(&key->p, 8, &res)) != CRYPT_OK) {
        return err;
    }
    if (res == 0) {
        return CRYPT_OK;
    }

    /* now make sure that g is not -1, 0 or 1 and <p */
    if (mp_cmp_d(&key->g, 0) == LTC_MP_EQ
            || mp_cmp_d(&key->g, 1) == LTC_MP_EQ) {
        return CRYPT_OK;
    }
    if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != CRYPT_OK) {
        return err;
    }
    if ((err = mp_sub_d(&key->p, 1, &tmp)) != CRYPT_OK) {
        goto error;
    }
    if (mp_cmp(&tmp, &key->g) == LTC_MP_EQ
            || mp_cmp(&key->g, &key->p) != LTC_MP_LT) {
        err = CRYPT_OK;
        goto error;
    }

    /* 1 < y < p-1 */
    if (!
            (mp_cmp_d(&key->y, 1) == LTC_MP_GT
             && mp_cmp(&key->y, &tmp) == LTC_MP_LT)) {
        err = CRYPT_OK;
        goto error;
    }

    /* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
    if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != CRYPT_OK) {
        goto error;
    }
    if (mp_iszero(&tmp2) != LTC_MP_YES) {
        err = CRYPT_OK;
        goto error;
    }

    if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != CRYPT_OK) {
        goto error;
    }
    if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
        err = CRYPT_OK;
        goto error;
    }

    /* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
    if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != CRYPT_OK) {
        goto error;
    }
    if (mp_cmp_d(&tmp, 1) != LTC_MP_EQ) {
        err = CRYPT_OK;
        goto error;
    }

    /* at this point we are out of tests ;-( */
    err = CRYPT_OK;
    *stat = 1;
error:
    mp_clear_multi(&tmp, &tmp2, NULL);
    return err;
}
Esempio n. 25
0
mp_err
mp_exptmod(const mp_int *inBase, const mp_int *exponent,
           const mp_int *modulus, mp_int *result)
{
    const mp_int *base;
    mp_size bits_in_exponent, i, window_bits, odd_ints;
    mp_err res;
    int nLen;
    mp_int montBase, goodBase;
    mp_mont_modulus mmm;
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
    static unsigned int max_window_bits;
#endif

    /* function for computing n0prime only works if n0 is odd */
    if (!mp_isodd(modulus))
        return s_mp_exptmod(inBase, exponent, modulus, result);

    MP_DIGITS(&montBase) = 0;
    MP_DIGITS(&goodBase) = 0;

    if (mp_cmp(inBase, modulus) < 0) {
        base = inBase;
    } else {
        MP_CHECKOK(mp_init(&goodBase));
        base = &goodBase;
        MP_CHECKOK(mp_mod(inBase, modulus, &goodBase));
    }

    nLen = MP_USED(modulus);
    MP_CHECKOK(mp_init_size(&montBase, 2 * nLen + 2));

    mmm.N = *modulus; /* a copy of the mp_int struct */

    /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
    **        where n0 = least significant mp_digit of N, the modulus.
    */
    mmm.n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(modulus, 0));

    MP_CHECKOK(s_mp_to_mont(base, &mmm, &montBase));

    bits_in_exponent = mpl_significant_bits(exponent);
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
    if (mp_using_cache_safe_exp) {
        if (bits_in_exponent > 780)
            window_bits = 6;
        else if (bits_in_exponent > 256)
            window_bits = 5;
        else if (bits_in_exponent > 20)
            window_bits = 4;
        /* RSA public key exponents are typically under 20 bits (common values
         * are: 3, 17, 65537) and a 4-bit window is inefficient
         */
        else
            window_bits = 1;
    } else
#endif
        if (bits_in_exponent > 480)
        window_bits = 6;
    else if (bits_in_exponent > 160)
        window_bits = 5;
    else if (bits_in_exponent > 20)
        window_bits = 4;
    /* RSA public key exponents are typically under 20 bits (common values
     * are: 3, 17, 65537) and a 4-bit window is inefficient
     */
    else
        window_bits = 1;

#ifdef MP_USING_CACHE_SAFE_MOD_EXP
    /*
     * clamp the window size based on
     * the cache line size.
     */
    if (!max_window_bits) {
        unsigned long cache_size = s_mpi_getProcessorLineSize();
        /* processor has no cache, use 'fast' code always */
        if (cache_size == 0) {
            mp_using_cache_safe_exp = 0;
        }
        if ((cache_size == 0) || (cache_size >= 64)) {
            max_window_bits = 6;
        } else if (cache_size >= 32) {
            max_window_bits = 5;
        } else if (cache_size >= 16) {
            max_window_bits = 4;
        } else
            max_window_bits = 1; /* should this be an assert? */
    }

    /* clamp the window size down before we caclulate bits_in_exponent */
    if (mp_using_cache_safe_exp) {
        if (window_bits > max_window_bits) {
            window_bits = max_window_bits;
        }
    }
#endif

    odd_ints = 1 << (window_bits - 1);
    i = bits_in_exponent % window_bits;
    if (i != 0) {
        bits_in_exponent += window_bits - i;
    }

#ifdef MP_USING_MONT_MULF
    if (mp_using_mont_mulf) {
        MP_CHECKOK(s_mp_pad(&montBase, nLen));
        res = mp_exptmod_f(&montBase, exponent, modulus, result, &mmm, nLen,
                           bits_in_exponent, window_bits, odd_ints);
    } else
#endif
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
        if (mp_using_cache_safe_exp) {
        res = mp_exptmod_safe_i(&montBase, exponent, modulus, result, &mmm, nLen,
                                bits_in_exponent, window_bits, 1 << window_bits);
    } else
#endif
        res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen,
                           bits_in_exponent, window_bits, odd_ints);

CLEANUP:
    mp_clear(&montBase);
    mp_clear(&goodBase);
    /* Don't mp_clear mmm.N because it is merely a copy of modulus.
    ** Just zap it.
    */
    memset(&mmm, 0, sizeof mmm);
    return res;
}
Esempio n. 26
0
static int next_prime(mp_int *N, mp_digit step)
{
    long x, s, j, total_dist;
    int res;
    mp_int n1, a, y, r;
    mp_digit dist, residues[UPPER_LIMIT];

    _ARGCHK(N != NULL);

    /* first find the residues */
    for (x = 0; x < (long)UPPER_LIMIT; x++) {
        if (mp_mod_d(N, __prime_tab[x], &residues[x]) != MP_OKAY) {
           return CRYPT_MEM;
        }
    }

    /* init variables */
    if (mp_init_multi(&r, &n1, &a, &y, NULL) != MP_OKAY) {
       return CRYPT_MEM;
    }
    
    total_dist = 0;
loop:
    /* while one of the residues is zero keep looping */
    dist = step;
    for (x = 0; (dist < (MP_DIGIT_MAX-step-1)) && (x < (long)UPPER_LIMIT); x++) {
        j = (long)residues[x] + (long)dist + total_dist;
        if (j % (long)__prime_tab[x] == 0) {
           dist += step; x = -1;
        }
    }
    
    /* recalc the total distance from where we started */
    total_dist += dist;
    
    /* add to N */
    if (mp_add_d(N, dist, N) != MP_OKAY) { goto error; }
    
    /* n1 = N - 1 */
    if (mp_sub_d(N, 1, &n1) != MP_OKAY)  { goto error; }

    /* r = N - 1 */
    if (mp_copy(&n1, &r) != MP_OKAY)     { goto error; }

    /* find s such that N-1 = (2^s)r */
    s = 0;
    while (mp_iseven(&r)) {
        ++s;
        if (mp_div_2(&r, &r) != MP_OKAY) {
           goto error;
        }
    }
    for (x = 0; x < 8; x++) {
        /* choose a */
        mp_set(&a, __prime_tab[x]);

        /* compute y = a^r mod n */
        if (mp_exptmod(&a, &r, N, &y) != MP_OKAY)             { goto error; }

        /* (y != 1) AND (y != N-1) */
        if ((mp_cmp_d(&y, 1) != 0) && (mp_cmp(&y, &n1) != 0)) {
            /* while j <= s-1 and y != n-1 */
            for (j = 1; (j <= (s-1)) && (mp_cmp(&y, &n1) != 0); j++) {
                /* y = y^2 mod N */
                if (mp_sqrmod(&y, N, &y) != MP_OKAY)          { goto error; }

                /* if y == 1 return false */
                if (mp_cmp_d(&y, 1) == 0)                     { goto loop; }
            }

            /* if y != n-1 return false */
            if (mp_cmp(&y, &n1) != 0)                         { goto loop; }
        }
    }

    res = CRYPT_OK;
    goto done;
error:
    res = CRYPT_MEM;
done:
    mp_clear_multi(&a, &y, &n1, &r, NULL);

#ifdef CLEAN_STACK
    zeromem(residues, sizeof(residues));
#endif    
    return res;
}
Esempio n. 27
0
/* integer signed division. 
 * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
 * HAC pp.598 Algorithm 14.20
 *
 * Note that the description in HAC is horribly 
 * incomplete.  For example, it doesn't consider 
 * the case where digits are removed from 'x' in 
 * the inner loop.  It also doesn't consider the 
 * case that y has fewer than three digits, etc..
 *
 * The overall algorithm is as described as 
 * 14.20 from HAC but fixed to treat these cases.
*/
int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{
	mp_int q, x, y, t1, t2;
	int res, n, t, i, norm, neg;

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

	/* if a < b then q=0, r = a */
	if (mp_cmp_mag(a, b) == MP_LT) {
		if (d != NULL) {
			res = mp_copy(a, d);
		} else {
			res = MP_OKAY;
		}
		if (c != NULL) {
			mp_zero(c);
		}
		return res;
	}

	if ((res = mp_init_size(&q, a->used + 2)) != MP_OKAY) {
		return res;
	}
	q.used = a->used + 2;

	if ((res = mp_init(&t1)) != MP_OKAY) {
		goto __Q;
	}

	if ((res = mp_init(&t2)) != MP_OKAY) {
		goto __T1;
	}

	if ((res = mp_init_copy(&x, a)) != MP_OKAY) {
		goto __T2;
	}

	if ((res = mp_init_copy(&y, b)) != MP_OKAY) {
		goto __X;
	}

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

	/* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
	norm = mp_count_bits(&y) % DIGIT_BIT;
	if (norm < (int) (DIGIT_BIT - 1)) {
		norm = (DIGIT_BIT - 1) - norm;
		if ((res = mp_mul_2d(&x, norm, &x)) != MP_OKAY) {
			goto __Y;
		}
		if ((res = mp_mul_2d(&y, norm, &y)) != MP_OKAY) {
			goto __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} } */
	if ((res = mp_lshd(&y, n - t)) != MP_OKAY) {	/* y = y*b**{n-t} */
		goto __Y;
	}

	while (mp_cmp(&x, &y) != MP_LT) {
		++(q.dp[n - t]);
		if ((res = mp_sub(&x, &y, &x)) != MP_OKAY) {
			goto __Y;
		}
	}

	/* reset y by shifting it back down */
	mp_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] =
			    ((((mp_digit) 1) << DIGIT_BIT) - 1);
		} else {
			mp_word tmp;
			tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
			tmp |= ((mp_word) x.dp[i - 1]);

			/* AxL : porting division to kernel 
			   tmp /= ((mp_word) y.dp[t]);
			 */
			if (y.dp[t] == 0)
				return MP_VAL;
			do_div(tmp, (mp_word) y.dp[t]);

			if (tmp > (mp_word) MP_MASK)
				tmp = MP_MASK;
			q.dp[i - t - 1] =
			    (mp_digit) (tmp & (mp_word) (MP_MASK));
		}

		/* 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) & MP_MASK;
		do {
			q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;

			/* find left hand */
			mp_zero(&t1);
			t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
			t1.dp[1] = y.dp[t];
			t1.used = 2;
			if ((res =
			     mp_mul_d(&t1, q.dp[i - t - 1],
				      &t1)) != MP_OKAY) {
				goto __Y;
			}

			/* 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 (mp_cmp_mag(&t1, &t2) == MP_GT);

		/* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
		if ((res = mp_mul_d(&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
			goto __Y;
		}

		if ((res = mp_lshd(&t1, i - t - 1)) != MP_OKAY) {
			goto __Y;
		}

		if ((res = mp_sub(&x, &t1, &x)) != MP_OKAY) {
			goto __Y;
		}

		/* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
		if (x.sign == MP_NEG) {
			if ((res = mp_copy(&y, &t1)) != MP_OKAY) {
				goto __Y;
			}
			if ((res = mp_lshd(&t1, i - t - 1)) != MP_OKAY) {
				goto __Y;
			}
			if ((res = mp_add(&x, &t1, &x)) != MP_OKAY) {
				goto __Y;
			}

			q.dp[i - t - 1] =
			    (q.dp[i - t - 1] - 1UL) & MP_MASK;
		}
	}

	/* now q is the quotient and x is the remainder 
	 * [which we have to normalize] 
	 */

	/* get sign before writing to c */
	x.sign = a->sign;

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

	if (d != NULL) {
		mp_div_2d(&x, norm, &x, NULL);
		mp_exch(&x, d);
	}

	res = MP_OKAY;

      __Y:mp_clear(&y);
      __X:mp_clear(&x);
      __T2:mp_clear(&t2);
      __T1:mp_clear(&t1);
      __Q:mp_clear(&q);
	return res;
}
Esempio n. 28
0
/**
  Verify a ECC signature
  @param r        ECC "r" parameter
  @param s        ECC "s" parameter
  @param hash     The hash that was signed
  @param hashlen  The length of the hash that was signed
  @param stat     [out] The result of the signature verification, 1==valid, 0==invalid
  @param key      The corresponding public DH key
  @return CRYPT_OK if successful (even if the signature is invalid)
*/
int ecc_verify_hash_raw(      void   *r, void   *s,
                        const unsigned char *hash, unsigned long hashlen,
                        int *stat, ecc_key *key)
{
   ecc_point    *mG, *mQ;
   void          *v, *w, *u1, *u2, *e, *p, *m;
   void          *mp = NULL;
   int           err;

   LTC_ARGCHK(r    != NULL);
   LTC_ARGCHK(s    != NULL);
   LTC_ARGCHK(hash != NULL);
   LTC_ARGCHK(stat != NULL);
   LTC_ARGCHK(key  != NULL);

   /* default to invalid signature */
   *stat = 0;
   mp    = NULL;

   /* is the IDX valid ?  */
   if (ltc_ecc_is_valid_idx(key->idx) != 1) {
      return CRYPT_PK_INVALID_TYPE;
   }

   /* allocate ints */
   if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
      return CRYPT_MEM;
   }

   /* allocate points */
   mG = ltc_ecc_new_point();
   mQ = ltc_ecc_new_point();
   if (mQ  == NULL || mG == NULL) {
      err = CRYPT_MEM;
      goto error;
   }

   /* get the order */
   if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK)                                { goto error; }

   /* get the modulus */
   if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK)                                { goto error; }

   /* check for zero */
   if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
      err = CRYPT_INVALID_PACKET;
      goto error;
   }

   /* read hash */
   if ((err = mp_read_unsigned_bin(e, (unsigned char *)hash, (int)hashlen)) != CRYPT_OK)                { goto error; }

   /*  w  = s^-1 mod n */
   if ((err = mp_invmod(s, p, w)) != CRYPT_OK)                                                          { goto error; }

   /* u1 = ew */
   if ((err = mp_mulmod(e, w, p, u1)) != CRYPT_OK)                                                      { goto error; }

   /* u2 = rw */
   if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK)                                                      { goto error; }

   /* find mG and mQ */
   if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK)                               { goto error; }
   if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK)                               { goto error; }
   if ((err = mp_set(mG->z, 1)) != CRYPT_OK)                                                            { goto error; }

   if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK)                                               { goto error; }
   if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK)                                               { goto error; }
   if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK)                                               { goto error; }

   /* compute u1*mG + u2*mQ = mG */
   if (ltc_mp.ecc_mul2add == NULL) {
      if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK)                                       { goto error; }
      if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK)                                       { goto error; }
  
      /* find the montgomery mp */
      if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK)                                              { goto error; }

      /* add them */
      if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK)                                      { goto error; }
   
      /* reduce */
      if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK)                                                { goto error; }
   } else {
      /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
      if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK)                                { goto error; }
   }

   /* v = X_x1 mod n */
   if ((err = mp_mod(mG->x, p, v)) != CRYPT_OK)                                                         { goto error; }

   /* does v == r */
   if (mp_cmp(v, r) == LTC_MP_EQ) {
      *stat = 1;
   }

   /* clear up and return */
   err = CRYPT_OK;
error:
   ltc_ecc_del_point(mG);
   ltc_ecc_del_point(mQ);
   mp_clear_multi(v, w, u1, u2, p, e, m, NULL);
   if (mp != NULL) { 
      mp_montgomery_free(mp);
   }
   return err;
}
Esempio n. 29
0
/* Computes the ECDSA signature (a concatenation of two values r and s)
 * on the digest using the given key and the random value kb (used in
 * computing s).
 */
SECStatus 
ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 
    const SECItem *digest, const unsigned char *kb, const int kblen)
{
    SECStatus rv = SECFailure;
#ifndef NSS_DISABLE_ECC
    mp_int x1;
    mp_int d, k;     /* private key, random integer */
    mp_int r, s;     /* tuple (r, s) is the signature */
    mp_int n;
    mp_err err = MP_OKAY;
    ECParams *ecParams = NULL;
    SECItem kGpoint = { siBuffer, NULL, 0};
    int flen = 0;    /* length in bytes of the field size */
    unsigned olen;   /* length in bytes of the base point order */
    unsigned obits;  /* length in bits  of the base point order */

#if EC_DEBUG
    char mpstr[256];
#endif

    /* Initialize MPI integers. */
    /* must happen before the first potential call to cleanup */
    MP_DIGITS(&x1) = 0;
    MP_DIGITS(&d) = 0;
    MP_DIGITS(&k) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&s) = 0;
    MP_DIGITS(&n) = 0;

    /* Check args */
    if (!key || !signature || !digest || !kb || (kblen < 0)) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	goto cleanup;
    }

    ecParams = &(key->ecParams);
    flen = (ecParams->fieldID.size + 7) >> 3;
    olen = ecParams->order.len;  
    if (signature->data == NULL) {
	/* a call to get the signature length only */
	goto finish;
    }
    if (signature->len < 2*olen) {
	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
	goto cleanup;
    }


    CHECK_MPI_OK( mp_init(&x1) );
    CHECK_MPI_OK( mp_init(&d) );
    CHECK_MPI_OK( mp_init(&k) );
    CHECK_MPI_OK( mp_init(&r) );
    CHECK_MPI_OK( mp_init(&s) );
    CHECK_MPI_OK( mp_init(&n) );

    SECITEM_TO_MPINT( ecParams->order, &n );
    SECITEM_TO_MPINT( key->privateValue, &d );

    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    /* Make sure k is in the interval [1, n-1] */
    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
#if EC_DEBUG
        printf("k is outside [1, n-1]\n");
        mp_tohex(&k, mpstr);
	printf("k : %s \n", mpstr);
        mp_tohex(&n, mpstr);
	printf("n : %s \n", mpstr);
#endif
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*
    ** We do not want timing information to leak the length of k,
    ** so we compute k*G using an equivalent scalar of fixed
    ** bit-length.
    ** Fix based on patch for ECDSA timing attack in the paper
    ** by Billy Bob Brumley and Nicola Tuveri at
    **   http://eprint.iacr.org/2011/232
    **
    ** How do we convert k to a value of a fixed bit-length?
    ** k starts off as an integer satisfying 0 <= k < n.  Hence,
    ** n <= k+n < 2n, which means k+n has either the same number
    ** of bits as n or one more bit than n.  If k+n has the same
    ** number of bits as n, the second addition ensures that the
    ** final value has exactly one more bit than n.  Thus, we
    ** always end up with a value that exactly one more bit than n.
    */
    CHECK_MPI_OK( mp_add(&k, &n, &k) );
    if (mpl_significant_bits(&k) <= mpl_significant_bits(&n)) {
	CHECK_MPI_OK( mp_add(&k, &n, &k) );
    }

    /* 
    ** ANSI X9.62, Section 5.3.2, Step 2
    **
    ** Compute kG
    */
    kGpoint.len = 2*flen + 1;
    kGpoint.data = PORT_Alloc(2*flen + 1);
    if ((kGpoint.data == NULL) ||
	(ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint)
	    != SECSuccess))
	goto cleanup;

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 1
    **
    ** Extract the x co-ordinate of kG into x1
    */
    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1, 
	                                  (mp_size) flen) );

    /* 
    ** ANSI X9.62, Section 5.3.3, Step 2
    **
    ** r = x1 mod n  NOTE: n is the order of the curve
    */
    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );

    /*
    ** ANSI X9.62, Section 5.3.3, Step 3
    **
    ** verify r != 0 
    */
    if (mp_cmp_z(&r) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

    /*                                  
    ** ANSI X9.62, Section 5.3.3, Step 4
    **
    ** s = (k**-1 * (HASH(M) + d*r)) mod n 
    */
    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */

    /* In the definition of EC signing, digests are truncated
     * to the length of n in bits. 
     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    CHECK_MPI_OK( (obits = mpl_significant_bits(&n)) );
    if (digest->len*8 > obits) {
	mpl_rsh(&s,&s,digest->len*8 - obits);
    }

#if EC_DEBUG
    mp_todecimal(&n, mpstr);
    printf("n : %s (dec)\n", mpstr);
    mp_todecimal(&d, mpstr);
    printf("d : %s (dec)\n", mpstr);
    mp_tohex(&x1, mpstr);
    printf("x1: %s\n", mpstr);
    mp_todecimal(&s, mpstr);
    printf("digest: %s (decimal)\n", mpstr);
    mp_todecimal(&r, mpstr);
    printf("r : %s (dec)\n", mpstr);
    mp_tohex(&r, mpstr);
    printf("r : %s\n", mpstr);
#endif

    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */

#if EC_DEBUG
    mp_todecimal(&s, mpstr);
    printf("s : %s (dec)\n", mpstr);
    mp_tohex(&s, mpstr);
    printf("s : %s\n", mpstr);
#endif

    /*
    ** ANSI X9.62, Section 5.3.3, Step 5
    **
    ** verify s != 0
    */
    if (mp_cmp_z(&s) == 0) {
	PORT_SetError(SEC_ERROR_NEED_RANDOM);
	goto cleanup;
    }

   /*
    **
    ** Signature is tuple (r, s)
    */
    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
finish:
    signature->len = 2*olen;

    rv = SECSuccess;
    err = MP_OKAY;
cleanup:
    mp_clear(&x1);
    mp_clear(&d);
    mp_clear(&k);
    mp_clear(&r);
    mp_clear(&s);
    mp_clear(&n);

    if (kGpoint.data) {
	PORT_ZFree(kGpoint.data, 2*flen + 1);
    }

    if (err) {
	MP_TO_SEC_ERROR(err);
	rv = SECFailure;
    }

#if EC_DEBUG
    printf("ECDSA signing with seed %s\n",
	(rv == SECSuccess) ? "succeeded" : "failed");
#endif
#else
    PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
#endif /* NSS_DISABLE_ECC */

   return rv;
}
Esempio n. 30
0
/* 4 words */
mp_err
ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
    mp_digit carry;

    switch (MP_USED(a)) {
        case 4:
            a3 = MP_DIGIT(a, 3);
        case 3:
            a2 = MP_DIGIT(a, 2);
        case 2:
            a1 = MP_DIGIT(a, 1);
        case 1:
            a0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 4:
            r3 = MP_DIGIT(b, 3);
        case 3:
            r2 = MP_DIGIT(b, 2);
        case 2:
            r1 = MP_DIGIT(b, 1);
        case 1:
            r0 = MP_DIGIT(b, 0);
    }

#ifndef MPI_AMD64_ADD
    carry = 0;
    MP_ADD_CARRY(a0, r0, r0, carry);
    MP_ADD_CARRY(a1, r1, r1, carry);
    MP_ADD_CARRY(a2, r2, r2, carry);
    MP_ADD_CARRY(a3, r3, r3, carry);
#else
    __asm__(
        "xorq   %4,%4           \n\t"
        "addq   %5,%0           \n\t"
        "adcq   %6,%1           \n\t"
        "adcq   %7,%2           \n\t"
        "adcq   %8,%3           \n\t"
        "adcq   $0,%4           \n\t"
        : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
        : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
          "0"(r0), "1"(r1), "2"(r2), "3"(r3)
        : "%cc");
#endif

    MP_CHECKOK(s_mp_pad(r, 4));
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 4;

    /* Do quick 'subract' if we've gone over
     * (add the 2's complement of the curve field) */
    a3 = MP_DIGIT(&meth->irr, 3);
    if (carry || r3 > a3 ||
        ((r3 == a3) && mp_cmp(r, &meth->irr) != MP_LT)) {
        a2 = MP_DIGIT(&meth->irr, 2);
        a1 = MP_DIGIT(&meth->irr, 1);
        a0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
        carry = 0;
        MP_SUB_BORROW(r0, a0, r0, carry);
        MP_SUB_BORROW(r1, a1, r1, carry);
        MP_SUB_BORROW(r2, a2, r2, carry);
        MP_SUB_BORROW(r3, a3, r3, carry);
#else
        __asm__(
            "subq   %4,%0           \n\t"
            "sbbq   %5,%1           \n\t"
            "sbbq   %6,%2           \n\t"
            "sbbq   %7,%3           \n\t"
            : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
            : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
              "0"(r0), "1"(r1), "2"(r2), "3"(r3)
            : "%cc");
#endif
        MP_DIGIT(r, 3) = r3;
        MP_DIGIT(r, 2) = r2;
        MP_DIGIT(r, 1) = r1;
        MP_DIGIT(r, 0) = r0;
    }