Example #1
0
/* Connert the bit string BITS of length NBITS into an octet string
   with a length of (QBITS+7)/8 bytes.  On success store the result at
   R_FRAME.  */
static gpg_err_code_t
bits2octets (unsigned char **r_frame,
             const void *bits, unsigned int nbits,
             gcry_mpi_t q, unsigned int qbits)
{
  gpg_err_code_t rc;
  gcry_mpi_t z1;

  /* z1 = bits2int (b) */
  rc = _gcry_mpi_scan (&z1, GCRYMPI_FMT_USG, bits, (nbits+7)/8, NULL);
  if (rc)
    return rc;
  if (nbits > qbits)
    mpi_rshift (z1, z1, nbits - qbits);

  /* z2 - z1 mod q */
  if (mpi_cmp (z1, q) >= 0)
    mpi_sub (z1, z1, q);

  /* Convert to an octet string.  */
  rc = int2octets (r_frame, z1, (qbits+7)/8);

  mpi_free (z1);
  return rc;
}
Example #2
0
/*
 * Truncate opaque hash value to qbits for DSA.
 * Non-opaque input is not truncated, in hope that user
 * knows what is passed. It is not possible to correctly
 * trucate non-opaque inputs.
 */
gpg_err_code_t
_gcry_dsa_normalize_hash (gcry_mpi_t input,
                          gcry_mpi_t *out,
                          unsigned int qbits)
{
  gpg_err_code_t rc = 0;
  const void *abuf;
  unsigned int abits;
  gcry_mpi_t hash;

  if (mpi_is_opaque (input))
    {
      abuf = mpi_get_opaque (input, &abits);
      rc = _gcry_mpi_scan (&hash, GCRYMPI_FMT_USG, abuf, (abits+7)/8, NULL);
      if (rc)
        return rc;
      if (abits > qbits)
        mpi_rshift (hash, hash, abits - qbits);
    }
  else
    hash = input;

  *out = hash;

  return rc;
}
Example #3
0
File: mpi.c Project: ifzz/weecrypt
/* < 0 means right shift, > 0 means left shift */
void
mpi_shift(const mpi *p, int bits, mpi *q)
{
    if (bits < 0)
        mpi_rshift(p, -bits, q);
    else if (bits > 0)
        mpi_lshift(p, +bits, q);
}
Example #4
0
static void
do_rshift(void)
{
    if( stackidx < 1 ) {
	fputs("stack underflow\n", stderr);
	return;
    }
    mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
}
Example #5
0
/* Compute binomial coefficient N choose K. */
void
mpi_binomial(uint64_t n, uint64_t k, mpi *coeff)
{
    ASSERT(coeff != NULL);

    /* Trivial cases */
    if (k > n) {
	mpi_zero(coeff);
	return;
    } else if (k == 0 || k == n) {
	mpi_set_u32(coeff, 1);
	return;
    } else if (k == 1 || k == n-1) {
	mpi_set_u64(coeff, n);
	return;
    }

    /*             (N-K+1) x (N-K+2) x ... x N
		   N choose K = ---------------------------
		   1 x 2 x ... x K       */
    mpi_t num, den;
    mpi_init_u64(num, n - k + 1);
    mpi_init_u32(den, 1);
    for (uint64_t i = 2; i <= k; ++i) {
	mpi_mul_u64(num, n - k + i, num);
	mpi_mul_u64(den, i, den);
	if ((i & 31) == 0) {
	    unsigned digits = 0;
	    while ((num->digits[digits] | den->digits[digits]) == 0)
		++digits;
	    unsigned shift = mp_digit_lsb_shift(num->digits[digits] |
						den->digits[digits]);
	    if (digits || shift) {
		mpi_rshift(num, digits * MP_DIGIT_BITS + shift, num);
		mpi_rshift(den, digits * MP_DIGIT_BITS + shift, den);
	    }
	}
    }
    mpi_divexact(num, den, coeff);
    mpi_free(num);
    mpi_free(den);
}
Example #6
0
/*
 * Generate a deterministic secret exponent K less than DSA_Q.  H1 is
 * the to be signed digest with a length of HLEN bytes.  HALGO is the
 * algorithm used to create the hash.  On success the value for K is
 * stored at R_K.
 */
gpg_err_code_t
_gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                         gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
                         const unsigned char *h1, unsigned int hlen,
                         int halgo, unsigned int extraloops)
{
  gpg_err_code_t rc;
  unsigned char *V = NULL;
  unsigned char *K = NULL;
  unsigned char *x_buf = NULL;
  unsigned char *h1_buf = NULL;
  gcry_md_hd_t hd = NULL;
  unsigned char *t = NULL;
  gcry_mpi_t k = NULL;
  unsigned int tbits, qbits;
  int i;

  qbits = mpi_get_nbits (dsa_q);

  if (!qbits || !h1 || !hlen)
    return GPG_ERR_EINVAL;

  if (_gcry_md_get_algo_dlen (halgo) != hlen)
    return GPG_ERR_DIGEST_ALGO;

  /* Step b:  V = 0x01 0x01 0x01 ... 0x01 */
  V = xtrymalloc (hlen);
  if (!V)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }
  for (i=0; i < hlen; i++)
    V[i] = 1;

  /* Step c:  K = 0x00 0x00 0x00 ... 0x00 */
  K = xtrycalloc (1, hlen);
  if (!K)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

  rc = int2octets (&x_buf, dsa_x, (qbits+7)/8);
  if (rc)
    goto leave;

  rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits);
  if (rc)
    goto leave;

  /* Create a handle to compute the HMACs.  */
  rc = _gcry_md_open (&hd, halgo, (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC));
  if (rc)
    goto leave;

  /* Step d:  K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */
  rc = _gcry_md_setkey (hd, K, hlen);
  if (rc)
    goto leave;
  _gcry_md_write (hd, V, hlen);
  _gcry_md_write (hd, "", 1);
  _gcry_md_write (hd, x_buf, (qbits+7)/8);
  _gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, _gcry_md_read (hd, 0), hlen);

  /* Step e:  V = HMAC_K(V) */
  rc = _gcry_md_setkey (hd, K, hlen);
  if (rc)
    goto leave;
  _gcry_md_write (hd, V, hlen);
  memcpy (V, _gcry_md_read (hd, 0), hlen);

  /* Step f:  K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */
  rc = _gcry_md_setkey (hd, K, hlen);
  if (rc)
    goto leave;
  _gcry_md_write (hd, V, hlen);
  _gcry_md_write (hd, "\x01", 1);
  _gcry_md_write (hd, x_buf, (qbits+7)/8);
  _gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, _gcry_md_read (hd, 0), hlen);

  /* Step g:  V = HMAC_K(V) */
  rc = _gcry_md_setkey (hd, K, hlen);
  if (rc)
    goto leave;
  _gcry_md_write (hd, V, hlen);
  memcpy (V, _gcry_md_read (hd, 0), hlen);

  /* Step h. */
  t = xtrymalloc ((qbits+7)/8+hlen);
  if (!t)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

 again:
  for (tbits = 0; tbits < qbits;)
    {
      /* V = HMAC_K(V) */
      rc = _gcry_md_setkey (hd, K, hlen);
      if (rc)
        goto leave;
      _gcry_md_write (hd, V, hlen);
      memcpy (V, _gcry_md_read (hd, 0), hlen);

      /* T = T || V */
      memcpy (t+(tbits+7)/8, V, hlen);
      tbits += 8*hlen;
    }

  /* k = bits2int (T) */
  mpi_free (k);
  k = NULL;
  rc = _gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL);
  if (rc)
    goto leave;
  if (tbits > qbits)
    mpi_rshift (k, k, tbits - qbits);

  /* Check: k < q and k > 1 */
  if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
    {
      /* K = HMAC_K(V || 0x00) */
      rc = _gcry_md_setkey (hd, K, hlen);
      if (rc)
        goto leave;
      _gcry_md_write (hd, V, hlen);
      _gcry_md_write (hd, "", 1);
      memcpy (K, _gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = _gcry_md_setkey (hd, K, hlen);
      if (rc)
        goto leave;
      _gcry_md_write (hd, V, hlen);
      memcpy (V, _gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* The caller may have requested that we introduce some extra loops.
     This is for example useful if the caller wants another value for
     K because the last returned one yielded an R of 0.  Because this
     is very unlikely we implement it in a straightforward way.  */
  if (extraloops)
    {
      extraloops--;

      /* K = HMAC_K(V || 0x00) */
      rc = _gcry_md_setkey (hd, K, hlen);
      if (rc)
        goto leave;
      _gcry_md_write (hd, V, hlen);
      _gcry_md_write (hd, "", 1);
      memcpy (K, _gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = _gcry_md_setkey (hd, K, hlen);
      if (rc)
        goto leave;
      _gcry_md_write (hd, V, hlen);
      memcpy (V, _gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* log_mpidump ("  k", k); */

 leave:
  xfree (t);
  _gcry_md_close (hd);
  xfree (h1_buf);
  xfree (x_buf);
  xfree (K);
  xfree (V);

  if (rc)
    mpi_free (k);
  else
    *r_k = k;
  return rc;
}
/****************
 * Calculate the multiplicative inverse X of A mod N
 * That is: Find the solution x for
 *		1 = (a*x) mod n
 */
int mpi_invm(MPI x, const MPI a, const MPI n)
{
	/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
	 * modified according to Michael Penk's solution for Exercice 35
	 * with further enhancement */
	MPI u = NULL, v = NULL;
	MPI u1 = NULL, u2 = NULL, u3 = NULL;
	MPI v1 = NULL, v2 = NULL, v3 = NULL;
	MPI t1 = NULL, t2 = NULL, t3 = NULL;
	unsigned k;
	int sign;
	int odd = 0;
	int rc = -ENOMEM;

	if (mpi_copy(&u, a) < 0)
		goto cleanup;
	if (mpi_copy(&v, n) < 0)
		goto cleanup;

	for (k = 0; !mpi_test_bit(u, 0) && !mpi_test_bit(v, 0); k++) {
		if (mpi_rshift(u, u, 1) < 0)
			goto cleanup;
		if (mpi_rshift(v, v, 1) < 0)
			goto cleanup;
	}
	odd = mpi_test_bit(v, 0);

	u1 = mpi_alloc_set_ui(1);
	if (!u1)
		goto cleanup;
	if (!odd) {
		u2 = mpi_alloc_set_ui(0);
		if (!u2)
			goto cleanup;
	}
	if (mpi_copy(&u3, u) < 0)
		goto cleanup;
	if (mpi_copy(&v1, v) < 0)
		goto cleanup;
	if (!odd) {
		v2 = mpi_alloc(mpi_get_nlimbs(u));
		if (!v2)
			goto cleanup;
		if (mpi_sub(v2, u1, u) < 0)
			goto cleanup;	/* U is used as const 1 */
	}
	if (mpi_copy(&v3, v) < 0)
		goto cleanup;
	if (mpi_test_bit(u, 0)) {	/* u is odd */
		t1 = mpi_alloc_set_ui(0);
		if (!t1)
			goto cleanup;
		if (!odd) {
			t2 = mpi_alloc_set_ui(1);
			if (!t2)
				goto cleanup;
			t2->sign = 1;
		}
		if (mpi_copy(&t3, v) < 0)
			goto cleanup;
		t3->sign = !t3->sign;
		goto Y4;
	} else {
		t1 = mpi_alloc_set_ui(1);
		if (!t1)
			goto cleanup;
		if (!odd) {
			t2 = mpi_alloc_set_ui(0);
			if (!t2)
				goto cleanup;
		}
		if (mpi_copy(&t3, u) < 0)
			goto cleanup;
	}
	do {
		do {
			if (!odd) {
				if (mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0)) {	/* one is odd */
					if (mpi_add(t1, t1, v) < 0)
						goto cleanup;
					if (mpi_sub(t2, t2, u) < 0)
						goto cleanup;
				}
				if (mpi_rshift(t1, t1, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t2, t2, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t3, t3, 1) < 0)
					goto cleanup;
			} else {
				if (mpi_test_bit(t1, 0))
					if (mpi_add(t1, t1, v) < 0)
						goto cleanup;
				if (mpi_rshift(t1, t1, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t3, t3, 1) < 0)
					goto cleanup;
			}
Y4:
			;
		} while (!mpi_test_bit(t3, 0));	/* while t3 is even */

		if (!t3->sign) {
			if (mpi_set(u1, t1) < 0)
				goto cleanup;
			if (!odd)
				if (mpi_set(u2, t2) < 0)
					goto cleanup;
			if (mpi_set(u3, t3) < 0)
				goto cleanup;
		} else {
			if (mpi_sub(v1, v, t1) < 0)
				goto cleanup;
			sign = u->sign;
			u->sign = !u->sign;
			if (!odd)
				if (mpi_sub(v2, u, t2) < 0)
					goto cleanup;
			u->sign = sign;
			sign = t3->sign;
			t3->sign = !t3->sign;
			if (mpi_set(v3, t3) < 0)
				goto cleanup;
			t3->sign = sign;
		}
		if (mpi_sub(t1, u1, v1) < 0)
			goto cleanup;
		if (!odd)
			if (mpi_sub(t2, u2, v2) < 0)
				goto cleanup;
		if (mpi_sub(t3, u3, v3) < 0)
			goto cleanup;
		if (t1->sign) {
			if (mpi_add(t1, t1, v) < 0)
				goto cleanup;
			if (!odd)
				if (mpi_sub(t2, t2, u) < 0)
					goto cleanup;
		}
	} while (mpi_cmp_ui(t3, 0));	/* while t3 != 0 */
	/* mpi_lshift( u3, k ); */
	rc = mpi_set(x, u1);

cleanup:
	mpi_free(u1);
	mpi_free(v1);
	mpi_free(t1);
	if (!odd) {
		mpi_free(u2);
		mpi_free(v2);
		mpi_free(t2);
	}
	mpi_free(u3);
	mpi_free(v3);
	mpi_free(t3);

	mpi_free(u);
	mpi_free(v);
	return rc;
}
Example #8
0
/****************
 * Calculate the multiplicative inverse X of A mod N
 * That is: Find the solution x for
 *		1 = (a*x) mod n
 */
int
_gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
{
#if 0
    gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
    gcry_mpi_t ta, tb, tc;

    u = mpi_copy(a);
    v = mpi_copy(n);
    u1 = mpi_alloc_set_ui(1);
    u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_alloc_set_ui(0);
    v2 = mpi_alloc_set_ui(1);
    v3 = mpi_copy(v);
    q  = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    while( mpi_cmp_ui( v3, 0 ) ) {
	mpi_fdiv_q( q, u3, v3 );
	mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
	mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
	mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
	mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
    }
    /*	log_debug("result:\n");
	log_mpidump("q =", q );
	log_mpidump("u1=", u1);
	log_mpidump("u2=", u2);
	log_mpidump("u3=", u3);
	log_mpidump("v1=", v1);
	log_mpidump("v2=", v2); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(u2);
    mpi_free(u3);
    mpi_free(v1);
    mpi_free(v2);
    mpi_free(v3);
    mpi_free(q);
    mpi_free(t1);
    mpi_free(t2);
    mpi_free(t3);
    mpi_free(u);
    mpi_free(v);
#elif 0
    /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
     * modified according to Michael Penk's solution for Exercise 35 */

    /* FIXME: we can simplify this in most cases (see Knuth) */
    gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
    unsigned k;
    int sign;

    u = mpi_copy(a);
    v = mpi_copy(n);
    for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
	mpi_rshift(u, u, 1);
	mpi_rshift(v, v, 1);
    }


    u1 = mpi_alloc_set_ui(1);
    u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_copy(v);				   /* !-- used as const 1 */
    v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u );
    v3 = mpi_copy(v);
    if( mpi_test_bit(u, 0) ) { /* u is odd */
	t1 = mpi_alloc_set_ui(0);
	t2 = mpi_alloc_set_ui(1); t2->sign = 1;
	t3 = mpi_copy(v); t3->sign = !t3->sign;
	goto Y4;
    }
    else {
	t1 = mpi_alloc_set_ui(1);
	t2 = mpi_alloc_set_ui(0);
	t3 = mpi_copy(u);
    }
    do {
	do {
	    if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
		mpi_add(t1, t1, v);
		mpi_sub(t2, t2, u);
	    }
	    mpi_rshift(t1, t1, 1);
	    mpi_rshift(t2, t2, 1);
	    mpi_rshift(t3, t3, 1);
	  Y4:
	    ;
	} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */

	if( !t3->sign ) {
	    mpi_set(u1, t1);
	    mpi_set(u2, t2);
	    mpi_set(u3, t3);
	}
	else {
	    mpi_sub(v1, v, t1);
	    sign = u->sign; u->sign = !u->sign;
	    mpi_sub(v2, u, t2);
	    u->sign = sign;
	    sign = t3->sign; t3->sign = !t3->sign;
	    mpi_set(v3, t3);
	    t3->sign = sign;
	}
	mpi_sub(t1, u1, v1);
	mpi_sub(t2, u2, v2);
	mpi_sub(t3, u3, v3);
	if( t1->sign ) {
	    mpi_add(t1, t1, v);
	    mpi_sub(t2, t2, u);
	}
    } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
    /* mpi_lshift( u3, k ); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(u2);
    mpi_free(u3);
    mpi_free(v1);
    mpi_free(v2);
    mpi_free(v3);
    mpi_free(t1);
    mpi_free(t2);
    mpi_free(t3);
#else
    /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
     * modified according to Michael Penk's solution for Exercise 35
     * with further enhancement */
    gcry_mpi_t u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3;
    unsigned k;
    int sign;
    int odd ;

    if (!mpi_cmp_ui (a, 0))
        return 0; /* Inverse does not exists.  */
    if (!mpi_cmp_ui (n, 1))
        return 0; /* Inverse does not exists.  */

    u = mpi_copy(a);
    v = mpi_copy(n);

    for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
	mpi_rshift(u, u, 1);
	mpi_rshift(v, v, 1);
    }
    odd = mpi_test_bit(v,0);

    u1 = mpi_alloc_set_ui(1);
    if( !odd )
	u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_copy(v);
    if( !odd ) {
	v2 = mpi_alloc( mpi_get_nlimbs(u) );
	mpi_sub( v2, u1, u ); /* U is used as const 1 */
    }
    v3 = mpi_copy(v);
    if( mpi_test_bit(u, 0) ) { /* u is odd */
	t1 = mpi_alloc_set_ui(0);
	if( !odd ) {
	    t2 = mpi_alloc_set_ui(1); t2->sign = 1;
	}
	t3 = mpi_copy(v); t3->sign = !t3->sign;
	goto Y4;
    }
    else {
	t1 = mpi_alloc_set_ui(1);
	if( !odd )
	    t2 = mpi_alloc_set_ui(0);
	t3 = mpi_copy(u);
    }
    do {
	do {
	    if( !odd ) {
		if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
		    mpi_add(t1, t1, v);
		    mpi_sub(t2, t2, u);
		}
		mpi_rshift(t1, t1, 1);
		mpi_rshift(t2, t2, 1);
		mpi_rshift(t3, t3, 1);
	    }
	    else {
		if( mpi_test_bit(t1, 0) )
		    mpi_add(t1, t1, v);
		mpi_rshift(t1, t1, 1);
		mpi_rshift(t3, t3, 1);
	    }
	  Y4:
	    ;
	} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */

	if( !t3->sign ) {
	    mpi_set(u1, t1);
	    if( !odd )
		mpi_set(u2, t2);
	    mpi_set(u3, t3);
	}
	else {
	    mpi_sub(v1, v, t1);
	    sign = u->sign; u->sign = !u->sign;
	    if( !odd )
		mpi_sub(v2, u, t2);
	    u->sign = sign;
	    sign = t3->sign; t3->sign = !t3->sign;
	    mpi_set(v3, t3);
	    t3->sign = sign;
	}
	mpi_sub(t1, u1, v1);
	if( !odd )
	    mpi_sub(t2, u2, v2);
	mpi_sub(t3, u3, v3);
	if( t1->sign ) {
	    mpi_add(t1, t1, v);
	    if( !odd )
		mpi_sub(t2, t2, u);
	}
    } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
    /* mpi_lshift( u3, k ); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(v1);
    mpi_free(t1);
    if( !odd ) {
	mpi_free(u2);
	mpi_free(v2);
	mpi_free(t2);
    }
    mpi_free(u3);
    mpi_free(v3);
    mpi_free(t3);

    mpi_free(u);
    mpi_free(v);
#endif
    return 1;
}