Beispiel #1
0
static int
ltm_rsa_private_encrypt(int flen, const unsigned char* from,
			unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *ptr, *ptr0;
    int res;
    int size;
    mp_int in, out, n, e;
    mp_int bi, b;
    int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
    int do_unblind = 0;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

    mp_init_multi(&e, &n, &in, &out, &b, &bi, NULL);

    size = RSA_size(rsa);

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

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

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

    if (mp_cmp_d(&e, 3) == MP_LT) {
	size = -3;
	goto out;
    }

    mp_read_unsigned_bin(&in, ptr0, size);
    free(ptr0);

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

    if (blinding) {
	setup_blind(&n, &b, &bi);
	blind(&in, &b, &e, &n);
	do_unblind = 1;
    }

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

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

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

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

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

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

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

    if (do_unblind)
	unblind(&out, &bi, &n);

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

 out:
    mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);

    return size;
}
/* 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) == MP_YES)) {
    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) == MP_YES) && (mp_iseven (&y) == MP_YES)) {
    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) == MP_YES) {
    /* 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) == MP_YES) || (mp_isodd (&B) == MP_YES)) {
      /* 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) == MP_YES) {
    /* 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) == MP_YES) || (mp_isodd (&D) == MP_YES)) {
      /* 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) == MP_NO)
    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;
}
/* 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;
}
/*
   Double an ECC point
   @param P         The point to double
   @param R   [out] The destination of the double
   @param a         Curve's a value
   @param modulus   The modulus of the field the ECC curve is in
   @return          GNUTLS_E_SUCCESS on success
*/
int
ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a,
                              mpz_t modulus)
{
   /* Using "dbl-2004-hmv" algorithm.
    * It costs 4M + 4S + half. */
   mpz_t t1, t2;
   int err;

   if (P == NULL || R == NULL || modulus == NULL)
     return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;

   if ( (err = ecc_projective_isneutral(P, modulus)) == 1 ) {

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

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

     if (mpz_cmp_ui (P->z, 1) != 0) {
         /* t1 = Z * Z */
         mpz_mul(t1, R->z, R->z);
         mpz_mod(t1, t1, modulus);
         /* Z = Y * Z */
         mpz_mul(R->z, R->y, R->z);
         mpz_mod(R->z, R->z, modulus);
         /* Z = 2Z */
         mpz_add(R->z, R->z, R->z);
         if (mpz_cmp(R->z, modulus) >= 0) {
            mpz_sub(R->z, R->z, modulus);
         }
     } else {
         /* t1 = 1 */
         mpz_set(t1, P->z);
         /* Z = 2Y */
         mpz_add(R->z, R->y, R->y);
         if (mpz_cmp(R->z, modulus) >= 0) {
            mpz_sub(R->z, R->z, modulus);
         }
     }

     /* T2 = X - T1 */
     mpz_sub(t2, R->x, t1);
     if (mpz_cmp_ui(t2, 0) < 0) {
        mpz_add(t2, t2, modulus);
     }
     /* T1 = X + T1 */
     mpz_add(t1, t1, R->x);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }
     /* T2 = T1 * T2 */
     mpz_mul(t2, t1, t2);
     mpz_mod(t2, t2, modulus);
     /* T1 = 2T2 */
     mpz_add(t1, t2, t2);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }
     /* T1 = T1 + T2 */
     mpz_add(t1, t1, t2);
     if (mpz_cmp(t1, modulus) >= 0) {
        mpz_sub(t1, t1, modulus);
     }

     /* Y = 2Y */
     mpz_add(R->y, R->y, R->y);
     if (mpz_cmp(R->y, modulus) >= 0) {
        mpz_sub(R->y, R->y, modulus);
     }
     /* Y = Y * Y */
     mpz_mul(R->y, R->y, R->y);
     mpz_mod(R->y, R->y, modulus);
     /* T2 = Y * Y */
     mpz_mul(t2, R->y, R->y);
     mpz_mod(t2, t2, modulus);
     /* T2 = T2/2 */
     if (mpz_odd_p(t2)) {
        mpz_add(t2, t2, modulus);
     }
     mpz_divexact_ui(t2, t2, 2);
     /* Y = Y * X */
     mpz_mul(R->y, R->y, R->x);
     mpz_mod(R->y, R->y, modulus);

     /* X  = T1 * T1 */
     mpz_mul(R->x, t1, t1);
     mpz_mod(R->x, R->x, modulus);
     /* X = X - Y */
     mpz_sub(R->x, R->x, R->y);
     if (mpz_cmp_ui(R->x, 0) < 0) {
        mpz_add(R->x, R->x, modulus);
     }
     /* X = X - Y */
     mpz_sub(R->x, R->x, R->y);
     if (mpz_cmp_ui(R->x, 0) < 0) {
        mpz_add(R->x, R->x, modulus);
     }

     /* Y = Y - X */
     mpz_sub(R->y, R->y, R->x);
     if (mpz_cmp_ui(R->y, 0) < 0) {
        mpz_add(R->y, R->y, modulus);
     }
     /* Y = Y * T1 */
     mpz_mul(R->y, R->y, t1);
     mpz_mod(R->y, R->y, modulus);
     /* Y = Y - T2 */
     mpz_sub(R->y, R->y, t2);
     if (mpz_cmp_ui(R->y, 0) < 0) {
        mpz_add( R->y, R->y, modulus);
     }

     err = GNUTLS_E_SUCCESS;

     mp_clear_multi(&t1, &t2, NULL);
     return err;
   } else if (err == 0) {
     /* 2*neutral = neutral */
     mpz_set_ui(R->x, 1);
     mpz_set_ui(R->y, 1);
     mpz_set_ui(R->z, 0);

     return GNUTLS_E_SUCCESS;
   } else {
     return err;
   }
}
Beispiel #5
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;
}
Beispiel #6
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;
   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) {
      /* tmpa = tmp^dP mod p */
      if ((err = mp_exptmod(tmp, key->dP, key->p, tmpa)) != CRYPT_OK)                               { goto error; }

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

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

      /* tmp = tmpb + q * tmp */
      if ((err = mp_mul(tmp, key->q, tmp)) != CRYPT_OK)                                             { goto error; }
      if ((err = mp_add(tmp, tmpb, tmp)) != CRYPT_OK)                                               { goto error; }
   } 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:
   mp_clear_multi(tmp, tmpa, tmpb, NULL);
   return err;
}
Beispiel #7
0
/**
  Free an RSA key from memory
  @param key   The RSA key to free
*/
void rsa_free(rsa_key * key)
{
	LTC_ARGCHKVD(key != NULL);
	mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
		       &key->p, &key->q, NULL);
}
Beispiel #8
0
/**
  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;

    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 x, g^x pair */
    x = mp_unsigned_bin_size(key->q);
    if (prng_descriptor[wprng].read(expt, x, prng) != x) {
       err = CRYPT_ERROR_READPRNG;
       goto LBL_ERR;
    }
    
    /* load x */
    if ((err = mp_read_unsigned_bin(g_priv, expt, x)) != CRYPT_OK) {
       goto LBL_ERR;
    }
    
    /* 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;
}
Beispiel #9
0
/**
   Verify an ECC signature
   @param sig         The signature to verify
   @param siglen      The length of the signature (octets)
   @param hash        The hash (message digest) that was signed
   @param hashlen     The length of the hash (octets)
   @param stat        Result of signature, 1==valid, 0==invalid
   @param key         The corresponding public ECC key
   @return CRYPT_OK if successful (even if the signature is not valid)
*/
int ecc_verify_hash(const unsigned char *sig,  unsigned long siglen,
                    const unsigned char *hash, unsigned long hashlen, 
                    int *stat, ecc_key *key)
{
   ecc_point    *mG, *mQ;
   void          *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
   void          *mp;
   int           err;

   LTC_ARGCHK(sig  != 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(&r, &s, &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;
   }

   /* parse header */
   if ((err = der_decode_sequence_multi(sig, siglen,
                                  LTC_ASN1_INTEGER, 1UL, r,
                                  LTC_ASN1_INTEGER, 1UL, s,
                                  LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
      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(r, s, v, w, u1, u2, p, e, m, NULL);
   if (mp != NULL) { 
      mp_montgomery_free(mp);
   }
   return err;
}
Beispiel #10
0
/**
   Verify the signature given
   @param sig        The signature
   @param siglen     The length of the signature (octets)
   @param hash       The hash that was signed
   @param hashlen    The length of the hash (octets)
   @param stat       [out] Result of signature comparison, 1==valid, 0==invalid
   @param key        The public DH key that signed the hash
   @return CRYPT_OK if succsessful (even if signature is invalid)
*/
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
                   const unsigned char *hash, unsigned long hashlen, 
                         int *stat, dh_key *key)
{
   mp_int        a, b, p, g, m, tmp;
   unsigned long x, y;
   int           err;

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

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

   /* check initial input length */
   if (siglen < PACKET_SIZE+4+4) {
      return CRYPT_INVALID_PACKET;
   } 

   /* header ok? */
   if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
      return err;
   }
   
   /* get hash out of packet */
   y = PACKET_SIZE;

   /* init all bignums */
   if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) { 
      return mpi_to_ltc_error(err);
   }

   /* load a and b */
   INPUT_BIGNUM(&a, sig, x, y, siglen);
   INPUT_BIGNUM(&b, sig, x, y, siglen);

   /* load p and g */
   if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)              { goto error1; }
   if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)               { goto error1; }

   /* load m */
   if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; }

   /* find g^m mod p */
   if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY)                { goto error1; } /* m = g^m mod p */

   /* find y^a * a^b */
   if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY)         { goto error1; } /* tmp = y^a mod p */
   if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY)                { goto error1; } /* a = a^b mod p */
   if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY)               { goto error1; } /* a = y^a * a^b mod p */

   /* y^a * a^b == g^m ??? */
   if (mp_cmp(&a, &m) == 0) {
      *stat = 1;
   }

   /* clean up */
   err = CRYPT_OK;
   goto done;
error1:
   err = mpi_to_ltc_error(err);
error:
done:
   mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
   return err;
}
Beispiel #11
0
/**
  Sign a hash with DSA
  @param in       The hash to sign
  @param inlen    The length of the hash to sign
  @param r        The "r" integer of the signature (caller must initialize with mp_init() first)
  @param s        The "s" integer of the signature (caller must initialize with mp_init() first)
  @param key      A private DSA key
  @return CRYPT_OK if successful
*/
int dsa_sign_hash_raw(const unsigned char *in, unsigned long inlen,
		      mp_int_t r, mp_int_t s, dsa_key * key)
{
	mp_int k, kinv, tmp;
	unsigned char *buf;
	int err;

	LTC_ARGCHK(in != NULL);
	LTC_ARGCHK(r != NULL);
	LTC_ARGCHK(s != NULL);
	LTC_ARGCHK(key != NULL);

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

	/* check group order size  */
	if (key->qord >= LTC_MDSA_MAX_GROUP) {
		return CRYPT_INVALID_ARG;
	}

	buf = XMALLOC(LTC_MDSA_MAX_GROUP);
	if (buf == NULL) {
		return CRYPT_MEM;
	}

	/* Init our temps */
	if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK) {
		goto ERRBUF;
	}

retry:

	do {
		/* gen random k */
		get_random_bytes(buf, key->qord);

		/* read k */
		if ((err =
		     mp_read_unsigned_bin(&k, buf, key->qord)) != CRYPT_OK) {
			goto error;
		}

		/* k > 1 ? */
		if (mp_cmp_d(&k, 1) != LTC_MP_GT) {
			goto retry;
		}

		/* test gcd */
		if ((err = mp_gcd(&k, &key->q, &tmp)) != CRYPT_OK) {
			goto error;
		}
	} while (mp_cmp_d(&tmp, 1) != LTC_MP_EQ);

	/* now find 1/k mod q */
	if ((err = mp_invmod(&k, &key->q, &kinv)) != CRYPT_OK) {
		goto error;
	}

	/* now find r = g^k mod p mod q */
	if ((err = mp_exptmod(&key->g, &k, &key->p, r)) != CRYPT_OK) {
		goto error;
	}
	if ((err = mp_mod(r, &key->q, r)) != CRYPT_OK) {
		goto error;
	}

	if (mp_iszero(r) == LTC_MP_YES) {
		goto retry;
	}

	/* now find s = (in + xr)/k mod q */
	if ((err =
	     mp_read_unsigned_bin(&tmp, (unsigned char *)in,
				  inlen)) != CRYPT_OK) {
		goto error;
	}
	if ((err = mp_mul(&key->x, r, s)) != CRYPT_OK) {
		goto error;
	}
	if ((err = mp_add(s, &tmp, s)) != CRYPT_OK) {
		goto error;
	}
	if ((err = mp_mulmod(s, &kinv, &key->q, s)) != CRYPT_OK) {
		goto error;
	}

	if (mp_iszero(s) == LTC_MP_YES) {
		goto retry;
	}

	err = CRYPT_OK;
error:
	mp_clear_multi(&k, &kinv, &tmp, NULL);
ERRBUF:
#ifdef LTC_CLEAN_STACK
	zeromem(buf, LTC_MDSA_MAX_GROUP);
#endif
	XFREE(buf);
	return err;
}
Beispiel #12
0
/**
  Sign a message digest using a DH private key 
  @param in      The data to sign
  @param inlen   The length of the input (octets)
  @param out     [out] The destination of the signature
  @param outlen  [in/out] The max size and resulting size of the output
  @param prng    An active PRNG state
  @param wprng   The index of the PRNG desired
  @param key     A private DH key
  @return CRYPT_OK if successful
*/
int dh_sign_hash(const unsigned char *in,  unsigned long inlen,
                       unsigned char *out, unsigned long *outlen,
                       prng_state *prng, int wprng, dh_key *key)
{
   mp_int         a, b, k, m, g, p, p1, tmp;
   unsigned char *buf;
   unsigned long  x, y;
   int            err;

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

   /* check parameters */
   if (key->type != PK_PRIVATE) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
      return err;
   }

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

   /* allocate ram for buf */
   buf = XMALLOC(520);

   /* make up a random value k,
    * since the order of the group is prime
    * we need not check if gcd(k, r) is 1 
    */
   if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) != 
       (unsigned long)(sets[key->idx].size)) {
      err = CRYPT_ERROR_READPRNG;
      goto LBL_ERR;
   }

   /* init bignums */
   if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) { 
      err = mpi_to_ltc_error(err);
      goto LBL_ERR;
   }

   /* load k and m */
   if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY)        { goto error; }
   if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY)          { goto error; }

   /* load g, p and p1 */
   if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY)               { goto error; }
   if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY)              { goto error; }
   if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY)                                     { goto error; }
   if ((err = mp_div_2(&p1, &p1)) != MP_OKAY)                                       { goto error; } /* p1 = (p-1)/2 */

   /* now get a = g^k mod p */
   if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY)                               { goto error; }

   /* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
   if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY)                                   { goto error; } /* k = 1/k mod p1 */
   if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY)                        { goto error; } /* tmp = xa */
   if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY)                           { goto error; } /* tmp = M - xa */
   if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY)                             { goto error; } /* b = (M - xa)/k */
   
   /* check for overflow */
   if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
      err = CRYPT_BUFFER_OVERFLOW;
      goto LBL_ERR;
   }
   
   /* store header  */
   y = PACKET_SIZE;

   /* now store them both (a,b) */
   x = (unsigned long)mp_unsigned_bin_size(&a);
   STORE32L(x, out+y);  y += 4;
   if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY)                            { goto error; }
   y += x;

   x = (unsigned long)mp_unsigned_bin_size(&b);
   STORE32L(x, out+y);  y += 4;
   if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY)                            { goto error; }
   y += x;

   /* check if size too big */
   if (*outlen < y) {
      err = CRYPT_BUFFER_OVERFLOW;
      goto LBL_ERR;
   }

   /* store header */
   packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
   *outlen = y;

   err = CRYPT_OK;
   goto LBL_ERR;
error:
   err = mpi_to_ltc_error(err);
LBL_ERR:
   mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);

   XFREE(buf);

   return err;
}
Beispiel #13
0
static int
ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
{
    mp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
    int counter, ret, bitsp;

    if (bits < 789)
	return -1;

    bitsp = (bits + 1) / 2;

    ret = -1;

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

    BN2mpz(&el, e);

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

	mp_sub_d(&p, 1, &t1);
	mp_gcd(&t1, &el, &t2);
    } while(mp_cmp_d(&t2, 1) != 0);

    BN_GENCB_call(cb, 3, 0);

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

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

	mp_sub_d(&q, 1, &t1);
	mp_gcd(&t1, &el, &t2);
    } while(mp_cmp_d(&t2, 1) != 0);

    /* make p > q */
    if (mp_cmp(&p, &q) < 0) {
	mp_int c;
	c = p;
	p = q;
	q = c;
    }

    BN_GENCB_call(cb, 3, 1);

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

    /* calculate d, 		d = 1/e mod (p - 1)(q - 1) */
    mp_sub_d(&p, 1, &t1);
    mp_sub_d(&q, 1, &t2);
    mp_mul(&t1, &t2, &t3);
    mp_invmod(&el, &t3, &d);

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

    /* fill in RSA key */

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

    ret = 1;

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

    return ret;
}
Beispiel #14
0
static int
ltm_rsa_private_decrypt(int flen, const unsigned char* from,
			unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *ptr;
    int res, size;
    mp_int in, out, n, e, b, bi;
    int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
    int do_unblind = 0;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

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

    mp_init_multi(&in, &n, &e, &out, &b, &bi, NULL);

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

    if (mp_cmp_d(&e, 3) == MP_LT) {
	size = -2;
	goto out;
    }

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

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

    if (blinding) {
	setup_blind(&n, &b, &bi);
	blind(&in, &b, &e, &n);
	do_unblind = 1;
    }

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

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

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

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

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

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

    } else {
	mp_int d;

	if(mp_isneg(&in) || mp_cmp(&in, &n) >= 0)
	    return -4;

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

    if (do_unblind)
	unblind(&out, &bi, &n);

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

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

    memmove(to, ptr, size);

 out:
    mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);

    return size;
}
Beispiel #15
0
int ecc_test_shamir(void)
{
    void *modulus, *mp, *kA, *kB, *rA, *rB, *a;
    ecc_point *G, *A, *B, *C1, *C2;
    int x, y, z;
    unsigned char buf[ECC_BUF_SIZE];

    DO(mp_init_multi(&kA, &kB, &rA, &rB, &modulus, &a, NULL));
    LTC_ARGCHK((G  = ltc_ecc_new_point()) != NULL);
    LTC_ARGCHK((A  = ltc_ecc_new_point()) != NULL);
    LTC_ARGCHK((B  = ltc_ecc_new_point()) != NULL);
    LTC_ARGCHK((C1 = ltc_ecc_new_point()) != NULL);
    LTC_ARGCHK((C2 = ltc_ecc_new_point()) != NULL);

    for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) {
        /* get the base point */
        for (z = 0; ltc_ecc_sets[z].name; z++) {
            if (sizes[z] < ltc_ecc_sets[z].size) break;
        }
        LTC_ARGCHK(ltc_ecc_sets[z].name != NULL);

        /* load it */
        DO(mp_read_radix(G->x, ltc_ecc_sets[z].Gx, 16));
        DO(mp_read_radix(G->y, ltc_ecc_sets[z].Gy, 16));
        DO(mp_set(G->z, 1));
        DO(mp_read_radix(modulus, ltc_ecc_sets[z].prime, 16));
        DO(mp_read_radix(a,       ltc_ecc_sets[z].A,     16));
        DO(mp_montgomery_setup(modulus, &mp));

        /* do 100 random tests */
        for (y = 0; y < 100; y++) {
            /* pick a random r1, r2 */
            LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
            DO(mp_read_unsigned_bin(rA, buf, sizes[x]));
            LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
            DO(mp_read_unsigned_bin(rB, buf, sizes[x]));

            /* compute rA * G = A */
            DO(ltc_mp.ecc_ptmul(rA, G, A, modulus, a, 1));

            /* compute rB * G = B */
            DO(ltc_mp.ecc_ptmul(rB, G, B, modulus, a, 1));

            /* pick a random kA, kB */
            LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
            DO(mp_read_unsigned_bin(kA, buf, sizes[x]));
            LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
            DO(mp_read_unsigned_bin(kB, buf, sizes[x]));

            /* now, compute kA*A + kB*B = C1 using the older method */
            DO(ltc_mp.ecc_ptmul(kA, A, C1, modulus, a, 0));
            DO(ltc_mp.ecc_ptmul(kB, B, C2, modulus, a, 0));
            DO(ltc_mp.ecc_ptadd(C1, C2, C1, modulus, a, mp));
            DO(ltc_mp.ecc_map(C1, modulus, mp));

            /* now compute using mul2add */
            DO(ltc_mp.ecc_mul2add(A, kA, B, kB, C2, modulus, a));

            /* is they the sames?  */
            if ((mp_cmp(C1->x, C2->x) != LTC_MP_EQ) || (mp_cmp(C1->y, C2->y) != LTC_MP_EQ) || (mp_cmp(C1->z, C2->z) != LTC_MP_EQ)) {
                fprintf(stderr, "ECC failed shamir test: size=%d, testno=%d\n", sizes[x], y);
                return 1;
            }
        }
        mp_montgomery_free(mp);
    }
    ltc_ecc_del_point(C2);
    ltc_ecc_del_point(C1);
    ltc_ecc_del_point(B);
    ltc_ecc_del_point(A);
    ltc_ecc_del_point(G);
    mp_clear_multi(kA, kB, rA, rB, modulus, NULL);
    return 0;
}
int mp_toom_cook_5_mul(mp_int *a, mp_int *b, mp_int *c)
{
   mp_int w1, w2, w3, w4, w5, w6, w7, w8, w9;
   mp_int tmp1, tmp2;
   mp_int a0, a1, a2, a3, a4;
   mp_int b0, b1, b2, b3, b4;
   int e = MP_OKAY;
   int B, count, sign;

   B = (MAX(a->used, b->used)) / 5;


   sign = (a->sign != b->sign) ? MP_NEG : MP_ZPOS;
   if (MIN(a->used, b->used) < TOOM_COOK_5_MUL_CO) {
      if ((e = mp_mul(a, b, c)) != MP_OKAY) {
         return e;
      }
      c->sign = sign;
      return MP_OKAY;
   }



   if ((e =
           mp_init_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                         //&a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                         NULL)) != MP_OKAY) {
      goto ERR0;
      //goto ERR;
   }

   if ((e = mp_init_size(&a0, B)) != MP_OKAY) {
      goto ERRa0;
   }
   if ((e = mp_init_size(&a1, B)) != MP_OKAY) {
      goto ERRa1;
   }
   if ((e = mp_init_size(&a2, B)) != MP_OKAY) {
      goto ERRa2;
   }
   if ((e = mp_init_size(&a3, B)) != MP_OKAY) {
      goto ERRa3;
   }
   if ((e = mp_init_size(&a4, B)) != MP_OKAY) {
      goto ERRa4;
   }

   if ((e = mp_init_size(&b0, B)) != MP_OKAY) {
      goto ERRb0;
   }
   if ((e = mp_init_size(&b1, B)) != MP_OKAY) {
      goto ERRb1;
   }
   if ((e = mp_init_size(&b2, B)) != MP_OKAY) {
      goto ERRb2;
   }
   if ((e = mp_init_size(&b3, B)) != MP_OKAY) {
      goto ERRb3;
   }
   if ((e = mp_init_size(&b4, B)) != MP_OKAY) {
      goto ERRb4;
   }
   // A = a4*x^4 + a3*x^3 + a2*x^2 + a1*x + a0
   for (count = 0; count < a->used; count++) {
      switch (count / B) {
      case 0:
         a0.dp[count] = a->dp[count];
         a0.used++;
         break;
      case 1:
         a1.dp[count - B] = a->dp[count];
         a1.used++;
         break;
      case 2:
         a2.dp[count - 2 * B] = a->dp[count];
         a2.used++;
         break;
      case 3:
         a3.dp[count - 3 * B] = a->dp[count];
         a3.used++;
         break;
      case 4:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      default:
         a4.dp[count - 4 * B] = a->dp[count];
         a4.used++;
         break;
      }
   }
   mp_clamp(&a0);
   mp_clamp(&a1);
   mp_clamp(&a2);
   mp_clamp(&a3);
   mp_clamp(&a4);
   // B = b4*x^4 + b3*x^3 + b2*x^2 + b1*x + b0
   for (count = 0; count < b->used; count++) {
      switch (count / B) {
      case 0:
         b0.dp[count] = b->dp[count];
         b0.used++;
         break;
      case 1:
         b1.dp[count - B] = b->dp[count];
         b1.used++;
         break;
      case 2:
         b2.dp[count - 2 * B] = b->dp[count];
         b2.used++;
         break;
      case 3:
         b3.dp[count - 3 * B] = b->dp[count];
         b3.used++;
         break;
      case 4:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      default:
         b4.dp[count - 4 * B] = b->dp[count];
         b4.used++;
         break;
      }
   }
   mp_clamp(&b0);
   mp_clamp(&b1);
   mp_clamp(&b2);
   mp_clamp(&b3);
   mp_clamp(&b4);


   /*
     if ((e = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a1, B);
     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

     if ((e = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a2, B * 2);
     mp_mod_2d(&a2, DIGIT_BIT * B, &a2);

     if ((e = mp_copy(a, &a3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a3, B * 3);

     mp_mod_2d(&a3, DIGIT_BIT * B, &a3);

     if ((e = mp_copy(a, &a4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&a4, B * 4);



     if ((e = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
     }

     if ((e = mp_copy(a, &b1)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b1, B);
     mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

     if ((e = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b2, B * 2);
     mp_mod_2d(&b2, DIGIT_BIT * B, &b2);

     if ((e = mp_copy(b, &b3)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b3, B * 3);

     mp_mod_2d(&b3, DIGIT_BIT * B, &b3);

     if ((e = mp_copy(b, &b4)) != MP_OKAY) {
       goto ERR;
     }
     mp_rshd(&b4, B * 4);
   */

// S1 = a4*b4
   if ((e = mp_mul(&a4, &b4, &w1)) != MP_OKAY) {
      goto ERR;
   }
// S9 = a0*b0
   if ((e = mp_mul(&a0, &b0, &w9)) != MP_OKAY) {
      goto ERR;
   }

// S2 = (a0- 2*a1 +4*a2 -8*a3 +16*a4)

   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 2*a1     = tmp1
   if ((e = mp_sub(&a0, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 = a0 - tmp1 = w2
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 4*a2     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 = w2 + tmp1 = w2
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 8*a3     = tmp1
   if ((e = mp_sub(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 = w2 - tmp1 = w2
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }            // 16*a4     = tmp1
   if ((e = mp_add(&w2, &tmp1, &w2)) != MP_OKAY) {
      goto ERR;
   }            // a0- 2*a1 +4*a2 -8*a3 +16*a4 = w2 + tmp1 = w2

//    * (b0- 2*b1 +4*b2 -8*b3 +16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S5 = (a0+ 2*a1+ 4*a2+ 8*a3+ 16*a4)
   if ((e = mp_mul_2d(&a1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// *(b0+ 2*b1+ 4*b2+ 8*b3+ 16*b4)
   if ((e = mp_mul_2d(&b1, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w5, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 = (a4+ 2*a3+ 4*a2+ 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a4, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// *    (b4+ 2*b3+ 4*b2+ 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 = (a4- 2*a3+ 4*a2- 8*a1+ 16*a0)
   if ((e = mp_mul_2d(&a3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&a4, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
//*     (b4- 2*b3+ 4*b2- 8*b1+ 16*b0)
   if ((e = mp_mul_2d(&b3, 1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&b4, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b1, 3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b0, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S4 = (a0+ 4*a1+ 16*a2+ 64*a3+ 256*a4)
   if ((e = mp_mul_2d(&a1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&a0, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&a4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
//*     (b0+ 4*b1+ 16*b2+ 64*b3+ 256*b4)
   if ((e = mp_mul_2d(&b1, 2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&b0, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b2, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b3, 6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_mul_2d(&b4, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp2, &tmp1, &tmp2)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp2, &w4, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 = (a0- a1+ a2- a3 +a4)
   if ((e = mp_sub(&a0, &a1, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a2, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w6, &a3, &w6)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w6, &a4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0- b1+ b2- b3+ b4)
   if ((e = mp_sub(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S7 = (a0+ a1+ a2+ a3+ a4)
   if ((e = mp_add(&a0, &a1, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a2, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a3, &w7)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w7, &a4, &w7)) != MP_OKAY) {
      goto ERR;
   }
// *    (b0+ b1+ b2+ b3+ b4)
   if ((e = mp_add(&b0, &b1, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &b4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_mul(&tmp1, &w7, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S7
   if ((e = mp_sub(&w6, &w7, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 -= S5
   if ((e = mp_sub(&w2, &w5, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S9
   if ((e = mp_sub(&w4, &w9, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (2^16*S1)
   if ((e = mp_mul_2d(&w1, 16, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S3
   if ((e = mp_sub(&w8, &w3, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S6 /= 2
   if ((e = mp_div_2d(&w6, 1, &w6, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 *= 2
   if ((e = mp_mul_2d(&w5, 1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S2
   if ((e = mp_add(&w5, &w2, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 = -S2
   if ((e = mp_neg(&w2, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S8 = -S8
   if ((e = mp_neg(&w8, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S7 += S6
   if ((e = mp_add(&w7, &w6, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S6 = -S6
   if ((e = mp_neg(&w6, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S7
   if ((e = mp_sub(&w3, &w7, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S5 -= (512*S7)
   if ((e = mp_mul_2d(&w7, 9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 2
   if ((e = mp_mul_2d(&w3, 1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S8
   if ((e = mp_sub(&w3, &w8, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S1
   if ((e = mp_sub(&w7, &w1, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S9
   if ((e = mp_sub(&w7, &w9, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S8 += S2
   if ((e = mp_add(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S5 += S3
   if ((e = mp_add(&w5, &w3, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= (80*S6)
   if ((e = mp_mul_d(&w6, 80, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w8, &tmp1, &w8)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= (510*S9)
   if ((e = mp_mul_d(&w9, 510, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= S2
   if ((e = mp_sub(&w4, &w2, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 *= 3
   if ((e = mp_mul_d(&w3, 3, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S3 += S5
   if ((e = mp_add(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S8 /= 180 \\ division by 180
   if ((e = mp_div_d(&w8, 180, &w8, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S5 += (378*S7)
   if ((e = mp_mul_d(&w7, 378, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w5, &tmp1, &w5)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 4
   if ((e = mp_div_2d(&w2, 2, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S6 -= S2
   if ((e = mp_sub(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S5 /= (-72) \\ division by -72
   if ((e = mp_div_d(&w5, 72, &w5, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w5.sign == MP_ZPOS)
      (&w5)->sign = MP_NEG;
   (&w5)->sign = MP_ZPOS;
// S3 /= (-360) \\ division by -360
   if ((e = mp_div_d(&w3, 360, &w3, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w3.sign == MP_ZPOS)
      (&w3)->sign = MP_NEG;
   (&w3)->sign = MP_ZPOS;
// S2 -= S8
   if ((e = mp_sub(&w2, &w8, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S7 -= S3
   if ((e = mp_sub(&w7, &w3, &w7)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (256*S5)
   if ((e = mp_mul_2d(&w5, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S3 -= S5
   if ((e = mp_sub(&w3, &w5, &w3)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (4096*S3)
   if ((e = mp_mul_2d(&w3, 12, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 -= (16*S7)
   if ((e = mp_mul_2d(&w7, 4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_sub(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (256*S6)
   if ((e = mp_mul_2d(&w6, 8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S6 += S2
   if ((e = mp_add(&w6, &w2, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S2 *= 180
   if ((e = mp_mul_d(&w2, 180, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 += S4
   if ((e = mp_add(&w2, &w4, &w2)) != MP_OKAY) {
      goto ERR;
   }
// S2 /= 11340 \\ division by 11340
   if ((e = mp_div_d(&w2, 11340, &w2, NULL)) != MP_OKAY) {
      goto ERR;
   }
// S4 += (720*S6)
   if ((e = mp_mul_d(&w6, 720, &tmp1)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&w4, &tmp1, &w4)) != MP_OKAY) {
      goto ERR;
   }
// S4 /= (-2160) \\ division by -2160
   if ((e = mp_div_d(&w4, 2160, &w4, NULL)) != MP_OKAY) {
      goto ERR;
   }
   if (&w4.sign == MP_ZPOS)
      (&w4)->sign = MP_NEG;
   (&w4)->sign = MP_ZPOS;
// S6 -= S4
   if ((e = mp_sub(&w6, &w4, &w6)) != MP_OKAY) {
      goto ERR;
   }
// S8 -= S2
   if ((e = mp_sub(&w8, &w2, &w8)) != MP_OKAY) {
      goto ERR;
   }
// P = S1*x^8 + S2*x^7 + S3*x^6 + S4*x^5 + S5*x^4 + S6*x^3 + S7*x^2 + S8*x + S9
   if ((e = mp_copy(&w9, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w8, B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w8, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w7, 2 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w7, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w6, 3 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w6, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w5, 4 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w5, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w4, 5 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w4, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w3, 6 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w3, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w2, 7 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w2, &tmp1)) != MP_OKAY) {
      goto ERR;
   }

   if ((e = mp_lshd(&w1, 8 * B)) != MP_OKAY) {
      goto ERR;
   }
   if ((e = mp_add(&tmp1, &w1, c)) != MP_OKAY) {
      goto ERR;
   }
// P - A*B \\ == zero
   c->sign = sign;
ERR:

ERRb4:
   mp_clear(&b4);
ERRb3:
   mp_clear(&b3);
ERRb2:
   mp_clear(&b2);
ERRb1:
   mp_clear(&b1);
ERRb0:
   mp_clear(&b0);
ERRa4:
   mp_clear(&a4);
ERRa3:
   mp_clear(&a3);
ERRa2:
   mp_clear(&a2);
ERRa1:
   mp_clear(&a1);
ERRa0:
   mp_clear(&a0);

ERR0:

   mp_clear_multi(&w1, &w2, &w3, &w4, &w5, &w6, &w7, &w8, &w9, &tmp1, &tmp2,
                  // &a0, &a1, &a2, &a3, &a4, &b0, &b1, &b2, &b3, &b4,
                  NULL);
   return e;
}
Beispiel #17
0
/**
  Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in LTC_PKCS #1 v2.1]
  @param in      The packet to import from
  @param inlen   It's length (octets)
  @param key     [out] Destination for newly imported key
  @return CRYPT_OK if successful, upon error allocated memory is freed
*/
int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
   int           err;
   void         *zero;
   unsigned char *tmpbuf;
   unsigned long  t, x, y, z, tmpoid[16];
   ltc_asn1_list ssl_pubkey_hashoid[2];
   ltc_asn1_list ssl_pubkey[2];

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

   /* init key */
   if ((err = mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, 
                            &key->dP, &key->qP, &key->p, &key->q, NULL)) != CRYPT_OK) {
      return err;
   }

   /* see if the OpenSSL DER format RSA public key will work */
   tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
   if (tmpbuf == NULL) {
       err = CRYPT_MEM;
       goto LBL_ERR;
   }

   /* this includes the internal hash ID and optional params (NULL in this case) */
   LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid,                sizeof(tmpoid)/sizeof(tmpoid[0]));   
   LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL,              NULL,                  0);

   /* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
      then proceed to convert bit to octet 
    */
   LTC_SET_ASN1(ssl_pubkey, 0,         LTC_ASN1_SEQUENCE,          &ssl_pubkey_hashoid,   2);
   LTC_SET_ASN1(ssl_pubkey, 1,         LTC_ASN1_BIT_STRING,        tmpbuf,                MAX_RSA_SIZE*8);

   if (der_decode_sequence(in, inlen,
                           ssl_pubkey, 2UL) == CRYPT_OK) {

      /* ok now we have to reassemble the BIT STRING to an OCTET STRING.  Thanks OpenSSL... */
      for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) {
          y = (y << 1) | tmpbuf[x];
          if (++z == 8) {
             tmpbuf[t++] = (unsigned char)y;
             y           = 0;
             z           = 0;
          }
      }

      /* now it should be SEQUENCE { INTEGER, INTEGER } */
      if ((err = der_decode_sequence_multi(tmpbuf, t,
                                           LTC_ASN1_INTEGER, 1UL, key->N, 
                                           LTC_ASN1_INTEGER, 1UL, key->e, 
                                           LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
         XFREE(tmpbuf);
         goto LBL_ERR;
      }
      XFREE(tmpbuf);
      key->type = PK_PUBLIC;
      return CRYPT_OK;
   }
   XFREE(tmpbuf);

   /* not SSL public key, try to match against LTC_PKCS #1 standards */
   if ((err = der_decode_sequence_multi(in, inlen, 
                                  LTC_ASN1_INTEGER, 1UL, key->N, 
                                  LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
      goto LBL_ERR;
   }

   if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
      if ((err = mp_init(&zero)) != CRYPT_OK) { 
         goto LBL_ERR;
      }
      /* it's a private key */
      if ((err = der_decode_sequence_multi(in, inlen, 
                          LTC_ASN1_INTEGER, 1UL, zero, 
                          LTC_ASN1_INTEGER, 1UL, key->N, 
                          LTC_ASN1_INTEGER, 1UL, key->e,
                          LTC_ASN1_INTEGER, 1UL, key->d, 
                          LTC_ASN1_INTEGER, 1UL, key->p, 
                          LTC_ASN1_INTEGER, 1UL, key->q, 
                          LTC_ASN1_INTEGER, 1UL, key->dP,
                          LTC_ASN1_INTEGER, 1UL, key->dQ, 
                          LTC_ASN1_INTEGER, 1UL, key->qP, 
                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
         mp_clear(zero);
         goto LBL_ERR;
      }
      mp_clear(zero);
      key->type = PK_PRIVATE;
   } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
      /* we don't support multi-prime RSA */
      err = CRYPT_PK_INVALID_TYPE;
      goto LBL_ERR;
   } else {
      /* it's a public key and we lack e */
      if ((err = der_decode_sequence_multi(in, inlen, 
                                     LTC_ASN1_INTEGER, 1UL, key->N, 
                                     LTC_ASN1_INTEGER, 1UL, key->e, 
                                     LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
         goto LBL_ERR;
      }
      key->type = PK_PUBLIC;
   }
   return CRYPT_OK;
LBL_ERR:
   mp_clear_multi(key->d,  key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
   return err;
}
/**
   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;
}
Beispiel #19
0
void cli_crt_clear(cli_crt *x509) {
    mp_clear_multi(&x509->n, &x509->e, &x509->sig, NULL);
}
/**
   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;
}
Beispiel #21
0
// http://www.jjj.de/fxt/#fxtbook
static int machin_ln_10(mp_float * a)
{
    int err;
    long oldeps, eps;
    mp_int c1, c2, c3, a1, a2, a3, sum, zero, t1, t2, P, Q, R, EPS;

    oldeps = a->radix;
    eps = (oldeps + MP_DIGIT_BIT);

    // TODO: error calculation!

    err = MP_OKAY;
    if ((err =
	 mp_init_multi(&c1, &c2, &c3, &a1, &a2, &a3, &sum, &zero, &t1, &t2,
		       &EPS, &P, &Q, &R, NULL)) != MP_OKAY) {
	return err;
    }

    if ((err = mp_set_int(&EPS, (unsigned long) (eps))) != MP_OKAY) {
	goto _ERR;
    }
    // using acoth instead of atanh to make things simpler 
    // atanh(x) = acoth(1/x) for x > 1

    // coefficients due to P. Sebah "Machin like formulae for logarithm" (1997)
    // http://numbers.computation.free.fr/Constants/PiProgram/userconstants.html
    mp_set(&c1, 46);
    mp_set(&c2, 34);
    mp_set(&c3, 20);

    mp_set(&a1, 31);
    mp_set(&a2, 49);
    mp_set(&a3, 161); // http://oeis.org/A175607

    mp_zero(&sum);
    mp_zero(&zero);

    if ((err =
	 mp_acoth_binary_splitting(&a1, &zero, &EPS, &P, &Q, &R)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&P, &Q, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul_2d(&t1, eps, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&Q, &a1, &t2)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_div(&t1, &t2, &t1, NULL)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&t1, &c1, &sum)) != MP_OKAY) {
	goto _ERR;
    }

    if ((err =
	 mp_acoth_binary_splitting(&a2, &zero, &EPS, &P, &Q, &R)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&P, &Q, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul_2d(&t1, eps, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&Q, &a2, &t2)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_div(&t1, &t2, &t1, NULL)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&t1, &c2, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&sum, &t1, &sum)) != MP_OKAY) {
	goto _ERR;
    }


    if ((err =
	 mp_acoth_binary_splitting(&a3, &zero, &EPS, &P, &Q, &R)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&P, &Q, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul_2d(&t1, eps, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&Q, &a3, &t2)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_div(&t1, &t2, &t1, NULL)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_mul(&t1, &c3, &t1)) != MP_OKAY) {
	goto _ERR;
    }
    if ((err = mp_add(&sum, &t1, &sum)) != MP_OKAY) {
	goto _ERR;
    }

    if ((err = mpf_from_mp_int(&sum, a)) != MP_OKAY) {
	goto _ERR;
    }
    a->exp -= eps;

_ERR:
    mp_clear_multi(&c1, &c2, &c3, &a1, &a2, &a3, &sum, &zero, &t1, &t2, &EPS,
		   &P, &Q, &R, NULL);
    return err;
}
/*
    Strong Lucas-Selfridge test.
    returns MP_YES if it is a strong L-S prime, MP_NO if it is composite

    Code ported from  Thomas Ray Nicely's implementation of the BPSW test
    at http://www.trnicely.net/misc/bpsw.html

    Freeware copyright (C) 2016 Thomas R. Nicely <http://www.trnicely.net>.
    Released into the public domain by the author, who disclaims any legal
    liability arising from its use

    The multi-line comments are made by Thomas R. Nicely and are copied verbatim.
    Additional comments marked "CZ" (without the quotes) are by the code-portist.

    (If that name sounds familiar, he is the guy who found the fdiv bug in the
     Pentium (P5x, I think) Intel processor)
*/
int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result)
{
   /* CZ TODO: choose better variable names! */
   mp_int Dz, gcd, Np1, Uz, Vz, U2mz, V2mz, Qmz, Q2mz, Qkdz, T1z, T2z, T3z, T4z, Q2kdz;
   /* CZ TODO: Some of them need the full 32 bit, hence the (temporary) exclusion of MP_8BIT */
   int32_t D, Ds, J, sign, P, Q, r, s, u, Nbits;
   int e;
   int isset;

   *result = MP_NO;

   /*
   Find the first element D in the sequence {5, -7, 9, -11, 13, ...}
   such that Jacobi(D,N) = -1 (Selfridge's algorithm). Theory
   indicates that, if N is not a perfect square, D will "nearly
   always" be "small." Just in case, an overflow trap for D is
   included.
   */

   if ((e = mp_init_multi(&Dz, &gcd, &Np1, &Uz, &Vz, &U2mz, &V2mz, &Qmz, &Q2mz, &Qkdz, &T1z, &T2z, &T3z, &T4z, &Q2kdz,
                          NULL)) != MP_OKAY) {
      return e;
   }

   D = 5;
   sign = 1;

   for (;;) {
      Ds   = sign * D;
      sign = -sign;
      if ((e = mp_set_long(&Dz, (unsigned long)D)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_gcd(a, &Dz, &gcd)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* if 1 < GCD < N then N is composite with factor "D", and
         Jacobi(D,N) is technically undefined (but often returned
         as zero). */
      if ((mp_cmp_d(&gcd, 1uL) == MP_GT) && (mp_cmp(&gcd, a) == MP_LT)) {
         goto LBL_LS_ERR;
      }
      if (Ds < 0) {
         Dz.sign = MP_NEG;
      }
      if ((e = mp_kronecker(&Dz, a, &J)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }

      if (J == -1) {
         break;
      }
      D += 2;

      if (D > (INT_MAX - 2)) {
         e = MP_VAL;
         goto LBL_LS_ERR;
      }
   }

   P = 1;              /* Selfridge's choice */
   Q = (1 - Ds) / 4;   /* Required so D = P*P - 4*Q */

   /* NOTE: The conditions (a) N does not divide Q, and
      (b) D is square-free or not a perfect square, are included by
      some authors; e.g., "Prime numbers and computer methods for
      factorization," Hans Riesel (2nd ed., 1994, Birkhauser, Boston),
      p. 130. For this particular application of Lucas sequences,
      these conditions were found to be immaterial. */

   /* Now calculate N - Jacobi(D,N) = N + 1 (even), and calculate the
      odd positive integer d and positive integer s for which
      N + 1 = 2^s*d (similar to the step for N - 1 in Miller's test).
      The strong Lucas-Selfridge test then returns N as a strong
      Lucas probable prime (slprp) if any of the following
      conditions is met: U_d=0, V_d=0, V_2d=0, V_4d=0, V_8d=0,
      V_16d=0, ..., etc., ending with V_{2^(s-1)*d}=V_{(N+1)/2}=0
      (all equalities mod N). Thus d is the highest index of U that
      must be computed (since V_2m is independent of U), compared
      to U_{N+1} for the standard Lucas-Selfridge test; and no
      index of V beyond (N+1)/2 is required, just as in the
      standard Lucas-Selfridge test. However, the quantity Q^d must
      be computed for use (if necessary) in the latter stages of
      the test. The result is that the strong Lucas-Selfridge test
      has a running time only slightly greater (order of 10 %) than
      that of the standard Lucas-Selfridge test, while producing
      only (roughly) 30 % as many pseudoprimes (and every strong
      Lucas pseudoprime is also a standard Lucas pseudoprime). Thus
      the evidence indicates that the strong Lucas-Selfridge test is
      more effective than the standard Lucas-Selfridge test, and a
      Baillie-PSW test based on the strong Lucas-Selfridge test
      should be more reliable. */

   if ((e = mp_add_d(a, 1uL, &Np1)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }
   s = mp_cnt_lsb(&Np1);

   /* CZ
    * This should round towards zero because
    * Thomas R. Nicely used GMP's mpz_tdiv_q_2exp()
    * and mp_div_2d() is equivalent. Additionally:
    * dividing an even number by two does not produce
    * any leftovers.
    */
   if ((e = mp_div_2d(&Np1, s, &Dz, NULL)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }
   /* We must now compute U_d and V_d. Since d is odd, the accumulated
      values U and V are initialized to U_1 and V_1 (if the target
      index were even, U and V would be initialized instead to U_0=0
      and V_0=2). The values of U_2m and V_2m are also initialized to
      U_1 and V_1; the FOR loop calculates in succession U_2 and V_2,
      U_4 and V_4, U_8 and V_8, etc. If the corresponding bits
      (1, 2, 3, ...) of t are on (the zero bit having been accounted
      for in the initialization of U and V), these values are then
      combined with the previous totals for U and V, using the
      composition formulas for addition of indices. */

   mp_set(&Uz, 1uL);    /* U=U_1 */
   mp_set(&Vz, (mp_digit)P);    /* V=V_1 */
   mp_set(&U2mz, 1uL);  /* U_1 */
   mp_set(&V2mz, (mp_digit)P);  /* V_1 */

   if (Q < 0) {
      Q = -Q;
      if ((e = mp_set_long(&Qmz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Initializes calculation of Q^d */
      if ((e = mp_set_long(&Qkdz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      Qmz.sign = MP_NEG;
      Q2mz.sign = MP_NEG;
      Qkdz.sign = MP_NEG;
      Q = -Q;
   } else {
      if ((e = mp_set_long(&Qmz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Initializes calculation of Q^d */
      if ((e = mp_set_long(&Qkdz, (unsigned long)Q)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
   }

   Nbits = mp_count_bits(&Dz);
   for (u = 1; u < Nbits; u++) { /* zero bit off, already accounted for */
      /* Formulas for doubling of indices (carried out mod N). Note that
       * the indices denoted as "2m" are actually powers of 2, specifically
       * 2^(ul-1) beginning each loop and 2^ul ending each loop.
       *
       * U_2m = U_m*V_m
       * V_2m = V_m*V_m - 2*Q^m
       */

      if ((e = mp_mul(&U2mz, &V2mz, &U2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&U2mz, a, &U2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sqr(&V2mz, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sub(&V2mz, &Q2mz, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&V2mz, a, &V2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* Must calculate powers of Q for use in V_2m, also for Q^d later */
      if ((e = mp_sqr(&Qmz, &Qmz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      /* prevents overflow */ /* CZ  still necessary without a fixed prealloc'd mem.? */
      if ((e = mp_mod(&Qmz, a, &Qmz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mul_2(&Qmz, &Q2mz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }

      if ((isset = mp_get_bit(&Dz, u)) == MP_VAL) {
         e = isset;
         goto LBL_LS_ERR;
      }
      if (isset == MP_YES) {
         /* Formulas for addition of indices (carried out mod N);
          *
          * U_(m+n) = (U_m*V_n + U_n*V_m)/2
          * V_(m+n) = (V_m*V_n + D*U_m*U_n)/2
          *
          * Be careful with division by 2 (mod N)!
          */

         if ((e = mp_mul(&U2mz, &Vz, &T1z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&Uz, &V2mz, &T2z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&V2mz, &Vz, &T3z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul(&U2mz, &Uz, &T4z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = s_mp_mul_si(&T4z, (long)Ds, &T4z)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_add(&T1z, &T2z, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if (mp_isodd(&Uz) != MP_NO) {
            if ((e = mp_add(&Uz, a, &Uz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         /* CZ
          * This should round towards negative infinity because
          * Thomas R. Nicely used GMP's mpz_fdiv_q_2exp().
          * But mp_div_2() does not do so, it is truncating instead.
          */
         if ((e = mp_div_2(&Uz, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((Uz.sign == MP_NEG) && (mp_isodd(&Uz) != MP_NO)) {
            if ((e = mp_sub_d(&Uz, 1uL, &Uz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_add(&T3z, &T4z, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if (mp_isodd(&Vz) != MP_NO) {
            if ((e = mp_add(&Vz, a, &Vz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_div_2(&Vz, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((Vz.sign == MP_NEG) && (mp_isodd(&Vz) != MP_NO)) {
            if ((e = mp_sub_d(&Vz, 1uL, &Vz)) != MP_OKAY) {
               goto LBL_LS_ERR;
            }
         }
         if ((e = mp_mod(&Uz, a, &Uz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Vz, a, &Vz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         /* Calculating Q^d for later use */
         if ((e = mp_mul(&Qkdz, &Qmz, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
      }
   }

   /* If U_d or V_d is congruent to 0 mod N, then N is a prime or a
      strong Lucas pseudoprime. */
   if ((mp_iszero(&Uz) != MP_NO) || (mp_iszero(&Vz) != MP_NO)) {
      *result = MP_YES;
      goto LBL_LS_ERR;
   }

   /* NOTE: Ribenboim ("The new book of prime number records," 3rd ed.,
      1995/6) omits the condition V0 on p.142, but includes it on
      p. 130. The condition is NECESSARY; otherwise the test will
      return false negatives---e.g., the primes 29 and 2000029 will be
      returned as composite. */

   /* Otherwise, we must compute V_2d, V_4d, V_8d, ..., V_{2^(s-1)*d}
      by repeated use of the formula V_2m = V_m*V_m - 2*Q^m. If any of
      these are congruent to 0 mod N, then N is a prime or a strong
      Lucas pseudoprime. */

   /* Initialize 2*Q^(d*2^r) for V_2m */
   if ((e = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) {
      goto LBL_LS_ERR;
   }

   for (r = 1; r < s; r++) {
      if ((e = mp_sqr(&Vz, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_sub(&Vz, &Q2kdz, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if ((e = mp_mod(&Vz, a, &Vz)) != MP_OKAY) {
         goto LBL_LS_ERR;
      }
      if (mp_iszero(&Vz) != MP_NO) {
         *result = MP_YES;
         goto LBL_LS_ERR;
      }
      /* Calculate Q^{d*2^r} for next r (final iteration irrelevant). */
      if (r < (s - 1)) {
         if ((e = mp_sqr(&Qkdz, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mod(&Qkdz, a, &Qkdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
         if ((e = mp_mul_2(&Qkdz, &Q2kdz)) != MP_OKAY) {
            goto LBL_LS_ERR;
         }
      }
   }
LBL_LS_ERR:
   mp_clear_multi(&Q2kdz, &T4z, &T3z, &T2z, &T1z, &Qkdz, &Q2mz, &Qmz, &V2mz, &U2mz, &Vz, &Uz, &Np1, &gcd, &Dz, NULL);
   return e;
}
Beispiel #23
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)
{
   void   *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;
}
Beispiel #24
0
/**
  Create a DSA key
  @param prng          An active PRNG state
  @param wprng         The index of the PRNG desired
  @param group_size    Size of the multiplicative group (octets)
  @param modulus_size  Size of the modulus (octets)
  @param key           [out] Where to store the created key
  @return CRYPT_OK if successful, upon error this function will free all allocated memory
*/
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
{
   mp_int         tmp, tmp2;
   int            err, res;
   unsigned char *buf;

   LTC_ARGCHK(key  != NULL);

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

   /* check size */
   if (group_size >= MDSA_MAX_GROUP || group_size <= 15 || 
       group_size >= modulus_size || (modulus_size - group_size) >= MDSA_DELTA) {
      return CRYPT_INVALID_ARG;
   }

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

   /* init mp_ints  */
   if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
      err = mpi_to_ltc_error(err);
      goto LBL_ERR;
   }

   /* make our prime q */
   if ((err = rand_prime(&key->q, group_size*8, prng, wprng)) != CRYPT_OK)             { goto LBL_ERR; }

   /* double q  */
   if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY)                                     { goto error; }

   /* now make a random string and multply it against q */
   if (prng_descriptor[wprng].read(buf+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
      err = CRYPT_ERROR_READPRNG;
      goto LBL_ERR;
   }

   /* force magnitude */
   buf[0] = 1;

   /* force even */
   buf[modulus_size - group_size] &= ~1;

   if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size+1)) != MP_OKAY) { goto error; }
   if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY)                             { goto error; }
   if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY)                               { goto error; }
   
   /* now loop until p is prime */
   for (;;) {
       if ((err = is_prime(&key->p, &res)) != CRYPT_OK)                                { goto LBL_ERR; }
       if (res == MP_YES) break;

       /* add 2q to p and 2 to tmp2 */
       if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY)                          { goto error; }
       if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY)                               { goto error; }
   }

   /* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
   mp_set(&key->g, 1);

   do {
      if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY)                            { goto error; }
      if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY)                { goto error; }
   } while (mp_cmp_d(&tmp, 1) == MP_EQ);

   /* at this point tmp generates a group of order q mod p */
   mp_exch(&tmp, &key->g);

   /* so now we have our DH structure, generator g, order q, modulus p 
      Now we need a random exponent [mod q] and it's power g^x mod p 
    */
   do {
      if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
         err = CRYPT_ERROR_READPRNG;
         goto LBL_ERR;
      }
      if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY)           { goto error; }
   } while (mp_cmp_d(&key->x, 1) != MP_GT);
   if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY)              { goto error; }
   
   key->type = PK_PRIVATE;
   key->qord = group_size;

   /* shrink the ram required */
   if ((err = mp_shrink(&key->g)) != MP_OKAY)                                          { goto error; }
   if ((err = mp_shrink(&key->p)) != MP_OKAY)                                          { goto error; }
   if ((err = mp_shrink(&key->q)) != MP_OKAY)                                          { goto error; }
   if ((err = mp_shrink(&key->x)) != MP_OKAY)                                          { goto error; }
   if ((err = mp_shrink(&key->y)) != MP_OKAY)                                          { goto error; }

#ifdef LTC_CLEAN_STACK
   zeromem(buf, MDSA_DELTA);
#endif

   err = CRYPT_OK;
   goto done;
error: 
    err = mpi_to_ltc_error(err);
LBL_ERR: 
    mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
done: 
    mp_clear_multi(&tmp, &tmp2, NULL);

    XFREE(buf);
    return err;
}
Beispiel #25
0
/* multiplication using the Toom-Cook 3-way algorithm 
 *
 * Much more complicated than Karatsuba but has a lower 
 * asymptotic running time of O(N**1.464).  This algorithm is 
 * only particularly useful on VERY large inputs 
 * (we're talking 1000s of digits here...).
*/
int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
{
    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
    int res, B;
        
    /* init temps */
    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
                             &a0, &a1, &a2, &b0, &b1, 
                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
       return res;
    }
    
    /* B */
    B = MIN(USED(a), USED(b)) / 3;
    
    /* a = a2 * B**2 + a1 * B + a0 */
    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a1, B);
    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);

    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&a2, B*2);
    
    /* b = b2 * B**2 + b1 * B + b0 */
    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
       goto ERR;
    }

    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b1, B);
    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);

    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
       goto ERR;
    }
    mp_rshd(&b2, B*2);
    
    /* w0 = a0*b0 */
    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w4 = a2 * b2 */
    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
       goto ERR;
    }
    
    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    
    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
       goto ERR;
    }
    

    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
       goto ERR;
    }
    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
       goto ERR;
    }
    
    /* now solve the matrix 
    
       0  0  0  0  1
       1  2  4  8  16
       1  1  1  1  1
       16 8  4  2  1
       1  0  0  0  0
       
       using 12 subtractions, 4 shifts, 
              2 small divisions and 1 small multiplication 
     */
     
     /* r1 - r4 */
     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r0 */
     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/2 */
     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/2 */
     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r2 - r0 - r4 */
     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - 8r0 */
     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - 8r4 */
     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* 3r2 - r1 - r3 */
     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
        goto ERR;
     }
     /* r1 - r2 */
     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
        goto ERR;
     }
     /* r3 - r2 */
     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
        goto ERR;
     }
     /* r1/3 */
     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
        goto ERR;
     }
     /* r3/3 */
     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
        goto ERR;
     }
     
     /* at this point shift W[n] by B*n */
     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
        goto ERR;
     }     
     
     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
        goto ERR;
     }
     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
        goto ERR;
     }     
     
ERR:
     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
                    &a0, &a1, &a2, &b0, &b1, 
                    &b2, &tmp1, &tmp2, NULL);
     return res;
}     
Beispiel #26
0
/* this is a shell function that calls either the normal or Montgomery
 * exptmod functions.  Originally the call to the montgomery code was
 * embedded in the normal function but that wasted alot of stack space
 * for nothing (since 99% of the time the Montgomery code would be called)
 */
int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{
  int dr;

  /* modulus P must be positive */
  if (P->sign == MP_NEG) {
     return MP_VAL;
  }

  /* if exponent X is negative we have to recurse */
  if (X->sign == MP_NEG) {
#ifdef BN_MP_INVMOD_C
     mp_int tmpG, tmpX;
     int err;

     /* first compute 1/G mod P */
     if ((err = mp_init(&tmpG)) != MP_OKAY) {
        return err;
     }
     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }

     /* now get |X| */
     if ((err = mp_init(&tmpX)) != MP_OKAY) {
        mp_clear(&tmpG);
        return err;
     }
     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
        mp_clear_multi(&tmpG, &tmpX, NULL);
        return err;
     }

     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
     err = mp_exptmod(&tmpG, &tmpX, P, Y);
     mp_clear_multi(&tmpG, &tmpX, NULL);
     return err;
#else
     /* no invmod */
     return MP_VAL;
#endif
  }

/* modified diminished radix reduction */
#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
  if (mp_reduce_is_2k_l(P) == MP_YES) {
     return s_mp_exptmod(G, X, P, Y, 1);
  }
#endif

#ifdef BN_MP_DR_IS_MODULUS_C
  /* is it a DR modulus? */
  dr = mp_dr_is_modulus(P);
#else
  /* default to no */
  dr = 0;
#endif

#ifdef BN_MP_REDUCE_IS_2K_C
  /* if not, is it a unrestricted DR modulus? */
  if (dr == 0) {
     dr = mp_reduce_is_2k(P) << 1;
  }
#endif

  /* if the modulus is odd or dr != 0 use the montgomery method */
#ifdef BN_MP_EXPTMOD_FAST_C
  if (mp_isodd (P) == 1 || dr !=  0) {
    return mp_exptmod_fast (G, X, P, Y, dr);
  } else {
#endif
#ifdef BN_S_MP_EXPTMOD_C
    /* otherwise use the generic Barrett reduction technique */
    return s_mp_exptmod (G, X, P, Y, 0);
#else
    /* no exptmod for evens */
    return MP_VAL;
#endif
#ifdef BN_MP_EXPTMOD_FAST_C
  }
#endif
}
/* 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;
}
Beispiel #28
0
/**
  Sign a hash with DSA
  @param in       The hash to sign
  @param inlen    The length of the hash to sign
  @param r        The "r" integer of the signature (caller must initialize with mp_init() first)
  @param s        The "s" integer of the signature (caller must initialize with mp_init() first)
  @param prng     An active PRNG state
  @param wprng    The index of the PRNG desired
  @param key      A private DSA key
  @return CRYPT_OK if successful
*/
int dsa_sign_hash_raw(const unsigned char *in,  unsigned long inlen,
                                   void   *r,   void *s,
                               prng_state *prng, int wprng, dsa_key *key)
{
   void         *k, *kinv, *tmp;
   unsigned char *buf;
   int            err, qbits;

   LTC_ARGCHK(in  != NULL);
   LTC_ARGCHK(r   != NULL);
   LTC_ARGCHK(s   != NULL);
   LTC_ARGCHK(key != NULL);

   if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
      return err;
   }
   if (key->type != PK_PRIVATE) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   /* check group order size  */
   if (key->qord >= LTC_MDSA_MAX_GROUP) {
      return CRYPT_INVALID_ARG;
   }

   buf = XMALLOC(LTC_MDSA_MAX_GROUP);
   if (buf == NULL) {
      return CRYPT_MEM;
   }

   /* Init our temps */
   if ((err = mp_init_multi(&k, &kinv, &tmp, NULL)) != CRYPT_OK)                       { goto ERRBUF; }

   qbits = mp_count_bits(key->q);
retry:

   do {
      /* gen random k */
      if ((err = rand_bn_bits(k, qbits, prng, wprng)) != CRYPT_OK)                     { goto error; }

      /* k should be from range: 1 <= k <= q-1 (see FIPS 186-4 B.2.2) */
      if (mp_cmp_d(k, 0) != LTC_MP_GT || mp_cmp(k, key->q) != LTC_MP_LT)               { goto retry; }

      /* test gcd */
      if ((err = mp_gcd(k, key->q, tmp)) != CRYPT_OK)                                  { goto error; }
   } while (mp_cmp_d(tmp, 1) != LTC_MP_EQ);

   /* now find 1/k mod q */
   if ((err = mp_invmod(k, key->q, kinv)) != CRYPT_OK)                                 { goto error; }

   /* now find r = g^k mod p mod q */
   if ((err = mp_exptmod(key->g, k, key->p, r)) != CRYPT_OK)                           { goto error; }
   if ((err = mp_mod(r, key->q, r)) != CRYPT_OK)                                       { goto error; }

   if (mp_iszero(r) == LTC_MP_YES)                                                     { goto retry; }

   /* FIPS 186-4 4.6: use leftmost min(bitlen(q), bitlen(hash)) bits of 'hash'*/
   inlen = MIN(inlen, (unsigned long)(key->qord));

   /* now find s = (in + xr)/k mod q */
   if ((err = mp_read_unsigned_bin(tmp, (unsigned char *)in, inlen)) != CRYPT_OK)      { goto error; }
   if ((err = mp_mul(key->x, r, s)) != CRYPT_OK)                                       { goto error; }
   if ((err = mp_add(s, tmp, s)) != CRYPT_OK)                                          { goto error; }
   if ((err = mp_mulmod(s, kinv, key->q, s)) != CRYPT_OK)                              { goto error; }

   if (mp_iszero(s) == LTC_MP_YES)                                                     { goto retry; }

   err = CRYPT_OK;
error:
   mp_clear_multi(k, kinv, tmp, NULL);
ERRBUF:
#ifdef LTC_CLEAN_STACK
   zeromem(buf, LTC_MDSA_MAX_GROUP);
#endif
   XFREE(buf);
   return err;
}
Beispiel #29
0
/**
  Free an ECC key from memory
  @param key   The key you wish to free
*/
void ecc_free(ecc_key *key)
{
   LTC_ARGCHKVD(key != NULL);
   mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
}
Beispiel #30
0
static int
ltm_rsa_public_decrypt(int flen, const unsigned char* from,
		       unsigned char* to, RSA* rsa, int padding)
{
    unsigned char *p;
    int res;
    size_t size;
    mp_int s, us, n, e;

    if (padding != RSA_PKCS1_PADDING)
	return -1;

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

    mp_init_multi(&e, &n, &s, &us, NULL);

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

    if (mp_cmp_d(&e, 3) == MP_LT) {
	mp_clear_multi(&e, &n, &s, &us, NULL);
	return -3;
    }

    mp_read_unsigned_bin(&s, rk_UNCONST(from), flen);

    if (mp_cmp(&s, &n) >= 0) {
	mp_clear_multi(&e, &n, &s, &us, NULL);
	return -4;
    }

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

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

    if (res != 0) {
	mp_clear(&us);
	return -5;
    }
    p = to;


    size = mp_unsigned_bin_size(&us);
    assert(size <= RSA_size(rsa));
    mp_to_unsigned_bin(&us, p);

    mp_clear(&us);

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

    memmove(to, p, size);

    return size;
}