コード例 #1
0
/**
   Allocate a new ECC point
   @return A newly allocated point or NULL on error 
*/
ecc_point *ltc_ecc_new_point(void)
{
   ecc_point *p;
   p = XCALLOC(1, sizeof(*p));
   if (p == NULL) {
      return NULL;
   }
   if (mp_init_multi(&p->x, &p->y, &p->z, NULL) != CRYPT_OK) {
      XFREE(p);
      return NULL;
   }
   return p;
}
コード例 #2
0
ファイル: crtmgr.c プロジェクト: LZ-SecurityTeam/clamav-devel
int cli_crt_init(cli_crt *x509) {
    int ret;
    if((ret = mp_init_multi(&x509->n, &x509->e, &x509->sig, NULL))) {
	cli_errmsg("cli_crt_init: mp_init_multi failed with %d\n", ret);
	return 1;
    }
    x509->name = NULL;
    x509->isBlacklisted = 0;
    x509->not_before = x509->not_after = 0;
    x509->prev = x509->next = NULL;
    x509->certSign = x509->codeSign = x509->timeSign = 0;
    return 0;
}
コード例 #3
0
int pkcs_1_pss_test(void)
{
  struct ltc_prng_descriptor* no_prng_desc = no_prng_desc_get();
  int prng_idx = register_prng(no_prng_desc);
  int hash_idx = find_hash("sha1");
  unsigned int i;
  unsigned int j;

  DO(prng_is_valid(prng_idx));
  DO(hash_is_valid(hash_idx));

  for (i = 0; i < sizeof(testcases_pss)/sizeof(testcases_pss[0]); ++i) {
    testcase_t* t = &testcases_pss[i];
    rsa_key k, *key = &k;
    DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
                       &key->dP, &key->qP, &key->p, &key->q, NULL), t->name);

    DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name);
    DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name);
    DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name);
    DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name);
    DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name);
    DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name);
    DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name);
    DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name);
    key->type = PK_PRIVATE;

    for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) {
        rsaData_t* s = &t->data[j];
        unsigned char buf[20], obuf[256];
        unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf);
        int stat;
        prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (prng_state*)no_prng_desc);
        DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name);
        DOX(rsa_sign_hash(buf, buflen, obuf, &obuflen, (prng_state*)no_prng_desc, prng_idx, hash_idx, s->o2_l, key), s->name);
        DOX(obuflen == (unsigned long)s->o3_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(memcmp(s->o3, obuf, s->o3_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(rsa_verify_hash(obuf, obuflen, buf, buflen, hash_idx, s->o2_l, &stat, key), s->name);
        DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
    } /* for */

    mp_clear_multi(key->d,  key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
  } /* for */

  unregister_prng(no_prng_desc);
  no_prng_desc_free(no_prng_desc);

  return 0;
}
コード例 #4
0
int ltc_ecc_is_point(const ltc_ecc_set_type *dp, void *x, void *y)
{
  void *prime, *a, *b, *t1, *t2;
  int err;

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

  /* load prime, a and b */
  if ((err = mp_read_radix(prime, dp->prime, 16)) != CRYPT_OK)         goto cleanup;
  if ((err = mp_read_radix(b, dp->B, 16)) != CRYPT_OK)                 goto cleanup;
  if ((err = mp_read_radix(a, dp->A, 16)) != CRYPT_OK)                 goto cleanup;

  /* compute y^2 */
  if ((err = mp_sqr(y, t1)) != CRYPT_OK)                               goto cleanup;

  /* compute x^3 */
  if ((err = mp_sqr(x, t2)) != CRYPT_OK)                               goto cleanup;
  if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK)                       goto cleanup;
  if ((err = mp_mul(x, t2, t2)) != CRYPT_OK)                           goto cleanup;

  /* compute y^2 - x^3 */
  if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK)                          goto cleanup;

  /* compute y^2 - x^3 - a*x */
  if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK)              goto cleanup;
  if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK)                 goto cleanup;
  if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK)                goto cleanup;

  /* adjust range (0, prime) */
  while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
     if ((err = mp_add(t1, prime, t1)) != CRYPT_OK)                    goto cleanup;
  }
  while (mp_cmp(t1, prime) != LTC_MP_LT) {
     if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK)                    goto cleanup;
  }

  /* compare to b */
  if (mp_cmp(t1, b) != LTC_MP_EQ) {
     err = CRYPT_INVALID_PACKET;
  } else {
     err = CRYPT_OK;
  }

cleanup:
  mp_clear_multi(prime, b, t1, t2, NULL);
  return err;
}
コード例 #5
0
ファイル: katja_import.c プロジェクト: FirebirdSQL/firebird
/**
  Import an KatjaPublicKey or KatjaPrivateKey [two-prime only, only support >= 1024-bit keys, defined in 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 katja_import(const unsigned char *in, unsigned long inlen, katja_key *key)
{
   int           err;
   void         *zero;

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

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

   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) {
      /* 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->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_INTEGER, 1UL, key->pq,
                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
         goto LBL_ERR;
      }
      key->type = PK_PRIVATE;
   } else {
      /* public we have N */
      key->type = PK_PUBLIC;
   }
   mp_clear(zero);
   return CRYPT_OK;
LBL_ERR:
   mp_clear_multi(zero,    key->d, key->N, key->dQ, key->dP,
                  key->qP, key->p, key->q, key->pq, NULL);
   return err;
}
コード例 #6
0
ファイル: mpa_desc.c プロジェクト: MrTomasz/optee_os
static int mulmod(void *a, void *b, void *c, void *d)
{
	LTC_ARGCHK(a != NULL);
	LTC_ARGCHK(b != NULL);
	LTC_ARGCHK(c != NULL);
	LTC_ARGCHK(d != NULL);
	void *tmpa, *tmpb;

	mp_init_multi(&tmpa, &tmpb, NULL);

	mod(a, c, tmpa);
	mod(b, c, tmpb);
	mpa_mul_mod((mpanum) d, (const mpanum) tmpa, (const mpanum) tmpb, (const mpanum) c, external_mem_pool);
	mp_clear_multi(tmpa, tmpb, NULL);
	return CRYPT_OK;
}
コード例 #7
0
/*
   Allocate a new ECC point
   @return A newly allocated point or NULL on error
*/
ecc_point *
ecc_new_point (void)
{
  ecc_point *p;
  p = calloc (1, sizeof (*p));
  if (p == NULL)
    {
      return NULL;
    }
  if (mp_init_multi (&p->x, &p->y, &p->z, NULL) != 0)
    {
      free (p);
      return NULL;
    }
  return p;
}
コード例 #8
0
ファイル: ecc_import.c プロジェクト: 4lextg/libtomcrypt
static int is_point(ecc_key *key)
{
   void *prime, *b, *t1, *t2;
   int err;
   
   if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) {
      return err;
   }
   
   /* load prime and b */
   if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK)                          { goto error; }
   if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK)                                  { goto error; }
   
   /* compute y^2 */
   if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK)                                         { goto error; }
   
   /* compute x^3 */
   if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK)                                         { goto error; }
   if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK)                                             { goto error; }
   if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK)                                     { goto error; }
   
   /* compute y^2 - x^3 */
   if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK)                                                { goto error; }
   
   /* compute y^2 - x^3 + 3x */
   if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK)                                     { goto error; }
   if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK)                                     { goto error; }
   if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK)                                     { goto error; }
   if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK)                                             { goto error; }
   while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
      if ((err = mp_add(t1, prime, t1)) != CRYPT_OK)                                          { goto error; }
   }
   while (mp_cmp(t1, prime) != LTC_MP_LT) {
      if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK)                                          { goto error; }
   }
   
   /* compare to b */
   if (mp_cmp(t1, b) != LTC_MP_EQ) {
      err = CRYPT_INVALID_PACKET;
   } else {
      err = CRYPT_OK;
   }
   
error:
   mp_clear_multi(prime, b, t1, t2, NULL);
   return err;
}
コード例 #9
0
int pkcs_1_eme_test(void)
{
  int prng_idx = register_prng(&no_prng_desc);
  int hash_idx = find_hash("sha1");
  unsigned int i;

  DO(prng_is_valid(prng_idx));
  DO(hash_is_valid(hash_idx));

  for (i = 0; i < sizeof(testcases_eme)/sizeof(testcases_eme[0]); ++i) {
    testcase_t* t = &testcases_eme[i];
    rsa_key k, *key = &k;
    DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
                       &key->dP, &key->qP, &key->p, &key->q, NULL), t->name);

    DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name);
    DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name);
    DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name);
    DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name);
    DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name);
    DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name);
    DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name);
    DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name);
    key->type = PK_PRIVATE;

    unsigned int j;
    for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) {
        rsaData_t* s = &t->data[j];
        unsigned char buf[256], obuf[256];
        unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf);
        int stat;
        prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, NULL);
        DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, NULL, prng_idx, -1, LTC_PKCS_1_V1_5, key), s->name);
        DOX(obuflen == (unsigned long)s->o3_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(memcmp(s->o3, obuf, s->o3_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name);
        DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
    } /* for */

    mp_clear_multi(key->d,  key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
  } /* for */

  unregister_prng(&no_prng_desc);

  return 0;
}
コード例 #10
0
ファイル: dsa_verify_key.c プロジェクト: dyemanov/firebird
/**
   Non-complex part (no primality testing) of the validation
   of DSA params (p, q, g)

   @param key   The key to validate
   @param stat  [out]  Result of test, 1==valid, 0==invalid
   @return CRYPT_OK if successful
*/
int dsa_int_validate_pqg(dsa_key *key, int *stat)
{
   void *tmp1, *tmp2;
   int  err;

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

   /* check q-order */
   if ( key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
        (unsigned long)key->qord >= mp_unsigned_bin_size(key->p) ||
        (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA ) {
      return CRYPT_OK;
   }

   /* FIPS 186-4 chapter 4.1: 1 < g < p */
   if (mp_cmp_d(key->g, 1) != LTC_MP_GT || mp_cmp(key->g, key->p) != LTC_MP_LT) {
      return CRYPT_OK;
   }

   if ((err = mp_init_multi(&tmp1, &tmp2, NULL)) != CRYPT_OK)        { return err; }

   /* FIPS 186-4 chapter 4.1: q is a divisor of (p - 1) */
   if ((err = mp_sub_d(key->p, 1, tmp1)) != CRYPT_OK)                { goto error; }
   if ((err = mp_div(tmp1, key->q, tmp1, tmp2)) != CRYPT_OK)         { goto error; }
   if (mp_iszero(tmp2) != LTC_MP_YES) {
      err = CRYPT_OK;
      goto error;
   }

   /* FIPS 186-4 chapter 4.1: g is a generator of a subgroup of order q in
    * the multiplicative group of GF(p) - so we make sure that g^q mod p = 1
    */
   if ((err = mp_exptmod(key->g, key->q, key->p, tmp1)) != CRYPT_OK) { goto error; }
   if (mp_cmp_d(tmp1, 1) != LTC_MP_EQ) {
      err = CRYPT_OK;
      goto error;
   }

   err   = CRYPT_OK;
   *stat = 1;
error:
   mp_clear_multi(tmp2, tmp1, NULL);
   return err;
}
コード例 #11
0
ファイル: ecc_verify_key.c プロジェクト: FGasper/perl-CryptX
int ecc_verify_key(ecc_key *key)
{
  int err;
  void *prime = NULL;
  void *order = NULL;
  void *a = NULL;
  ecc_point *test_output = NULL;
  test_output = malloc(sizeof(ecc_point));

  if (mp_init_multi(&(test_output->x), &(test_output->y), &(test_output->z), &order, &prime, NULL) != CRYPT_OK) {
    return CRYPT_MEM;
  }

  /* Test 1: Are the x amd y points of the public key in the field? */
  if((err = ltc_mp.read_radix(prime, key->dp->prime, 16)) != CRYPT_OK)                  { goto error;}

  if(ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) {
    if(
       (ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT)
       || (ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT)
       || (ltc_mp.compare_d(key->pubkey.x, 0) != LTC_MP_GT)
       || (ltc_mp.compare_d(key->pubkey.y, 0) != LTC_MP_GT) )
      {
        err = CRYPT_INVALID_PACKET;
        goto error;
      }
  }

  /* Test 2: is the public key on the curve? */
  if((err = ltc_ecc_is_point(key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK)       { goto error;}

  /* Test 3: does nG = O? (n = order, 0 = point at infinity, G = public key) */
  if((err = ltc_mp.read_radix(order, key->dp->order, 16)) != CRYPT_OK)                  { goto error;}
  if((err = ltc_mp.read_radix(a, key->dp->A, 16)) != CRYPT_OK)                          { goto error;}
  if((err = ltc_ecc_mulmod(order, &(key->pubkey), test_output, a, prime, 1)) != CRYPT_OK) {
    goto error;
  }

  err = CRYPT_OK;
error:
  mp_clear_multi(prime, order, test_output->z, test_output->y, test_output->x, NULL);
  return err;
}
コード例 #12
0
ファイル: pkcs_1_emsa_test.c プロジェクト: libtom/libtomcrypt
int pkcs_1_emsa_test(void)
{
  int hash_idx = find_hash("sha1");
  unsigned int i;
  unsigned int j;

  DO(hash_is_valid(hash_idx));

  for (i = 0; i < sizeof(testcases_emsa)/sizeof(testcases_emsa[0]); ++i) {
    testcase_t* t = &testcases_emsa[i];
    rsa_key k, *key = &k;
    DOX(mp_init_multi(&key->e, &key->d, &key->N, &key->dQ,
                       &key->dP, &key->qP, &key->p, &key->q, NULL), t->name);

    DOX(mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name);
    DOX(mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name);
    DOX(mp_read_unsigned_bin(key->N, t->rsa.n, t->rsa.n_l), t->name);
    DOX(mp_read_unsigned_bin(key->dQ, t->rsa.dQ, t->rsa.dQ_l), t->name);
    DOX(mp_read_unsigned_bin(key->dP, t->rsa.dP, t->rsa.dP_l), t->name);
    DOX(mp_read_unsigned_bin(key->qP, t->rsa.qInv, t->rsa.qInv_l), t->name);
    DOX(mp_read_unsigned_bin(key->q, t->rsa.q, t->rsa.q_l), t->name);
    DOX(mp_read_unsigned_bin(key->p, t->rsa.p, t->rsa.p_l), t->name);
    key->type = PK_PRIVATE;

    for (j = 0; j < sizeof(t->data)/sizeof(t->data[0]); ++j) {
        rsaData_t* s = &t->data[j];
        unsigned char buf[20], obuf[256];
        unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf);
        int stat;
        DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name);
        DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name);
        DOX(obuflen == (unsigned long)s->o2_l?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(memcmp(s->o2, obuf, s->o2_l)==0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
        DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name);
        DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name);
    } /* for */

    mp_clear_multi(key->d,  key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
  } /* for */

  return 0;
}
コード例 #13
0
ファイル: dsa_make_key.c プロジェクト: OP-TEE/optee_os
/**
  Create a DSA key (with given params)
  @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
  @param p_hex         Hexadecimal string 'p'
  @param q_hex         Hexadecimal string 'q'
  @param g_hex         Hexadecimal string 'g'
  @return CRYPT_OK if successful, upon error this function will free all allocated memory
*/
static int dsa_make_key_ex(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key, char* p_hex, char* q_hex, char* g_hex)
{
  int err, qbits;

  LTC_ARGCHK(key  != NULL);

  /* init mp_ints */
  if ((err = mp_init_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) {
    return err;
  }

  if (p_hex == NULL || q_hex == NULL || g_hex == NULL) {
    /* generate params */
    err = dsa_make_params(prng, wprng, group_size, modulus_size, key->p, key->q, key->g);
    if (err != CRYPT_OK)                                                         { goto cleanup; }
  }
  else {
    /* read params */
    if ((err = mp_read_radix(key->p, p_hex, 16)) != CRYPT_OK)                    { goto cleanup; }
    if ((err = mp_read_radix(key->q, q_hex, 16)) != CRYPT_OK)                    { goto cleanup; }
    if ((err = mp_read_radix(key->g, g_hex, 16)) != CRYPT_OK)                    { goto cleanup; }
    /* XXX-TODO maybe do some validity check for p, q, 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
   */
  qbits = mp_count_bits(key->q);
  do {
     if ((err = rand_bn_bits(key->x, qbits, prng, wprng)) != CRYPT_OK)                  { goto cleanup; }
     /* private key x should be from range: 1 <= x <= q-1 (see FIPS 186-4 B.1.2) */
  } while (mp_cmp_d(key->x, 0) != LTC_MP_GT || mp_cmp(key->x, key->q) != LTC_MP_LT);
  if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK)                   { goto cleanup; }
  key->type = PK_PRIVATE;
  key->qord = group_size;

  return CRYPT_OK;

cleanup:
  mp_clear_multi(key->g, key->q, key->p, key->x, key->y, NULL);
  return err;
}
コード例 #14
0
int __private_eccdh_shared_secret(const ltc_ecc_set_type *dp, const char *pub_key_x, const char *pub_key_y, const char *pub_key_z, const char *priv_key, unsigned char *out, unsigned long *outlen) {
    int err;
 
    ecc_key public_key;
    ecc_key private_key;

    memset(&public_key, 0, sizeof(ecc_key));
    memset(&private_key, 0, sizeof(ecc_key));

    if (mp_init_multi(&public_key.pubkey.x, &public_key.pubkey.y, &public_key.pubkey.z, &private_key.k, NULL))
        return -1;
    
    if ((err = mp_read_radix(public_key.pubkey.x, pub_key_x, 16)) != 0) {
        mp_clear_multi(public_key.pubkey.x, public_key.pubkey.y, public_key.pubkey.z, private_key.k, NULL);
        return -1;
    }
    if ((err = mp_read_radix(public_key.pubkey.y, pub_key_y, 16)) != 0) {
        mp_clear_multi(public_key.pubkey.x, public_key.pubkey.y, public_key.pubkey.z, private_key.k, NULL);
        return -1;
    }
    if ((err = mp_read_radix(public_key.pubkey.z, pub_key_z, 16)) != 0) {
        mp_clear_multi(public_key.pubkey.x, public_key.pubkey.y, public_key.pubkey.z, private_key.k, NULL);
        return -1;
    }
    if ((err = mp_read_radix(private_key.k, priv_key, 16)) != 0) {
        mp_clear_multi(public_key.pubkey.x, public_key.pubkey.y, public_key.pubkey.z, private_key.k, NULL);
        return -1;
    }

    public_key.idx = -1;
    public_key.dp = dp;
    public_key.type = PK_PUBLIC;

    private_key.idx = -1;
    private_key.dp = dp;
    private_key.type = PK_PRIVATE;

    err = ecc_shared_secret(&private_key, &public_key, out, outlen);
    mp_clear_multi(public_key.pubkey.x, public_key.pubkey.y, public_key.pubkey.z, private_key.k, NULL);
    return err;
}
コード例 #15
0
ファイル: dh_test.c プロジェクト: mkj/dropbear
static int _prime_test(void)
{
   void *p, *g, *tmp;
   int x, err, primality;

   if ((err = mp_init_multi(&p, &g, &tmp, NULL)) != CRYPT_OK)               { goto error; }

   for (x = 0; ltc_dh_sets[x].size != 0; x++) {
      if ((err = mp_read_radix(g, ltc_dh_sets[x].base, 16)) != CRYPT_OK)    { goto error; }
      if ((err = mp_read_radix(p, ltc_dh_sets[x].prime, 16)) != CRYPT_OK)   { goto error; }

      /* ensure p is prime */
      if ((err = mp_prime_is_prime(p, 8, &primality)) != CRYPT_OK)          { goto done; }
      if (primality != LTC_MP_YES ) {
         err = CRYPT_FAIL_TESTVECTOR;
         goto done;
      }

      if ((err = mp_sub_d(p, 1, tmp)) != CRYPT_OK)                          { goto error; }
      if ((err = mp_div_2(tmp, tmp)) != CRYPT_OK)                           { goto error; }

      /* ensure (p-1)/2 is prime */
      if ((err = mp_prime_is_prime(tmp, 8, &primality)) != CRYPT_OK)        { goto done; }
      if (primality == 0) {
         err = CRYPT_FAIL_TESTVECTOR;
         goto done;
      }

      /* now see if g^((p-1)/2) mod p is in fact 1 */
      if ((err = mp_exptmod(g, tmp, p, tmp)) != CRYPT_OK)                   { goto error; }
      if (mp_cmp_d(tmp, 1)) {
         err = CRYPT_FAIL_TESTVECTOR;
         goto done;
      }
   }
   err = CRYPT_OK;
error:
done:
   mp_clear_multi(tmp, g, p, NULL);
   return err;
}
コード例 #16
0
ファイル: dh.c プロジェクト: shihrer/wolfssl
/* Check DH Public Key for invalid numbers
 *
 * key   DH key group parameters.
 * pub   Public Key.
 * pubSz Public Key size.
 *
 *  returns 0 on success or error code
 */
int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz)
{
    int ret = 0;

    mp_int x;
    mp_int y;

    if (key == NULL || pub == NULL) {
        return BAD_FUNC_ARG;
    }

    if (mp_init_multi(&x, &y, NULL, NULL, NULL, NULL) != MP_OKAY) {
        return MP_INIT_E;
    }

    if (mp_read_unsigned_bin(&x, pub, pubSz) != MP_OKAY) {
        ret = MP_READ_E;
    }

    /* pub should not be 0 or 1 */
    if (ret == 0 && mp_cmp_d(&x, 2) == MP_LT) {
        ret = MP_CMP_E;
    }

    /* pub shouldn't be greater than or equal to p - 1 */
    if (ret == 0 && mp_copy(&key->p, &y) != MP_OKAY) {
        ret = MP_INIT_E;
    }
    if (ret == 0 && mp_sub_d(&y, 2, &y) != MP_OKAY) {
        ret = MP_SUB_E;
    }
    if (ret == 0 && mp_cmp(&x, &y) == MP_GT) {
        ret = MP_CMP_E;
    }

    mp_clear(&y);
    mp_clear(&x);

    return ret;
}
コード例 #17
0
static int
ltm_dh_compute_key(unsigned char *shared, const BIGNUM * pub, DH *dh)
{
    mp_int s, priv_key, p, peer_pub;
    int ret;

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

    mp_init_multi(&s, &priv_key, &p, &peer_pub, NULL);
    BN2mpz(&p, dh->p);
    BN2mpz(&peer_pub, pub);

    /* check if peers pubkey is reasonable */
    if (mp_isneg(&peer_pub)
	|| mp_cmp(&peer_pub, &p) >= 0
	|| mp_cmp_d(&peer_pub, 1) <= 0)
    {
	ret = -1;
	goto out;
    }

    BN2mpz(&priv_key, dh->priv_key);

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

    if (ret != 0) {
	ret = -1;
	goto out;
    }

    ret = mp_unsigned_bin_size(&s);
    mp_to_unsigned_bin(&s, shared);

 out:
    mp_clear_multi(&s, &priv_key, &p, &peer_pub, NULL);

    return ret;
}
コード例 #18
0
/**
  Import DSA's p, q & g from dsaparam

      dsaparam data: openssl dsaparam -outform DER -out dsaparam.der 2048

  @param dsaparam    The DSA param DER encoded data
  @param dsaparamlen The length of dhparam data
  @param key         [out] the destination for the imported key
  @return CRYPT_OK if successful.
*/
int dsa_set_pqg_dsaparam(const unsigned char *dsaparam, unsigned long dsaparamlen,
                         dsa_key *key)
{
   int err, stat;

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

   /* init key */
   err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
   if (err != CRYPT_OK) return err;

   if ((err = der_decode_sequence_multi(dsaparam, dsaparamlen,
                                        LTC_ASN1_INTEGER, 1UL, key->p,
                                        LTC_ASN1_INTEGER, 1UL, key->q,
                                        LTC_ASN1_INTEGER, 1UL, key->g,
                                        LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
      goto LBL_ERR;
   }

   key->qord = mp_unsigned_bin_size(key->q);

   /* quick p, q, g validation, without primality testing */
   if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK) {
      goto LBL_ERR;
   }
   if (stat == 0) {
      err = CRYPT_INVALID_PACKET;
      goto LBL_ERR;
   }

   return CRYPT_OK;

LBL_ERR:
   dsa_free(key);
   return err;
}
コード例 #19
0
ファイル: mont.c プロジェクト: DavidMulder/heimdal
int main(void)
{
   mp_int modulus, R, p, pp;
   mp_digit mp;
   long x, y;

   srand(time(NULL));
   mp_init_multi(&modulus, &R, &p, &pp, NULL);

   /* loop through various sizes */
   for (x = 4; x < 256; x++) {
       printf("DIGITS == %3ld...", x); fflush(stdout);

       /* make up the odd modulus */
       mp_rand(&modulus, x);
       modulus.dp[0] |= 1;

       /* now find the R value */
       mp_montgomery_calc_normalization(&R, &modulus);
       mp_montgomery_setup(&modulus, &mp);

       /* now run through a bunch tests */
       for (y = 0; y < 1000; y++) {
           mp_rand(&p, x/2);        /* p = random */
           mp_mul(&p, &R, &pp);     /* pp = R * p */
           mp_montgomery_reduce(&pp, &modulus, mp);

           /* should be equal to p */
           if (mp_cmp(&pp, &p) != MP_EQ) {
              printf("FAILURE!\n");
              exit(-1);
           }
       }
       printf("PASSED\n");
    }

    return 0;
}
コード例 #20
0
ファイル: dh.c プロジェクト: shihrer/wolfssl
int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv,
            word32 privSz, const byte* otherPub, word32 pubSz)
{
    int ret = 0;

    mp_int x;
    mp_int y;
    mp_int z;

    if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) {
        WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed");
        return DH_CHECK_PUB_E;
    }

    if (mp_init_multi(&x, &y, &z, 0, 0, 0) != MP_OKAY)
        return MP_INIT_E;

    if (mp_read_unsigned_bin(&x, priv, privSz) != MP_OKAY)
        ret = MP_READ_E;

    if (ret == 0 && mp_read_unsigned_bin(&y, otherPub, pubSz) != MP_OKAY)
        ret = MP_READ_E;

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

    if (ret == 0 && mp_to_unsigned_bin(&z, agree) != MP_OKAY)
        ret = MP_TO_E;

    if (ret == 0)
        *agreeSz = mp_unsigned_bin_size(&z);

    mp_clear(&z);
    mp_clear(&y);
    mp_clear(&x);

    return ret;
}
コード例 #21
0
ファイル: dh_set.c プロジェクト: ybendan/libtomcrypt
/**
  Import DH key parts p and g from built-in DH groups

  @param groupsize  The size of the DH group to use
  @param key        [out] Where the newly created DH key will be stored
  @return CRYPT_OK if successful, note: on error all allocated memory will be freed automatically.
*/
int dh_set_pg_groupsize(int groupsize, dh_key *key)
{
   int err, i;

   LTC_ARGCHK(key         != NULL);
   LTC_ARGCHK(ltc_mp.name != NULL);
   LTC_ARGCHK(groupsize   > 0);

   for (i = 0; (groupsize > ltc_dh_sets[i].size) && (ltc_dh_sets[i].size != 0); i++);
   if (ltc_dh_sets[i].size == 0) return CRYPT_INVALID_KEYSIZE;

   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
      return err;
   }
   if ((err = mp_read_radix(key->base, ltc_dh_sets[i].base, 16)) != CRYPT_OK)  { goto LBL_ERR; }
   if ((err = mp_read_radix(key->prime, ltc_dh_sets[i].prime, 16)) != CRYPT_OK) { goto LBL_ERR; }

   return CRYPT_OK;

LBL_ERR:
   dh_free(key);
   return err;
}
コード例 #22
0
ファイル: lnc_dh.c プロジェクト: peterwankman/libnetcrypt
lnc_key_t *lnc_gen_client_key(const size_t size, int *status) {
	lnc_key_t *out = malloc(sizeof(lnc_key_t));

	if(!out) {
		*status = LNC_ERR_MALLOC;
		return NULL;
	}

	mp_init_multi(&(out->generator), &(out->modulus), &(out->secret_key), &(out->public_key), NULL);

	if(mp_random(&(out->secret_key), size) != MP_OKAY) {
		*status = LNC_ERR_LTM;
		free(out);
		return NULL;
	}

	mp_set(&(out->generator), 0);
	mp_set(&(out->modulus), 0);
	mp_set(&(out->public_key), 0);
		
	*status = LNC_OK;
	return out;
}
コード例 #23
0
ファイル: dsa_utils.cpp プロジェクト: bdbcat/s63_pi
int _dsa_verify_hash (mp_int *r, mp_int *s, mp_int *hash,
                mp_int *keyG, mp_int *keyP, mp_int *keyQ, mp_int *keyY)
{
        mp_int w, v, u1, u2;
        int ret;
        
        MP_OP(mp_init_multi(&w, &v, &u1, &u2, NULL));
        
        // neither r or s can be 0 or >q
        if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || mp_cmp(r, keyQ) != MP_LT || mp_cmp(s, keyQ) != MP_LT) {
           ret = -1;
           goto error;
        }
        
        // w = 1/s mod q
        MP_OP(mp_invmod(s, keyQ, &w));
        
        // u1 = m * w mod q
        MP_OP(mp_mulmod(hash, &w, keyQ, &u1));
        
        // u2 = r*w mod q
        MP_OP(mp_mulmod(r, &w, keyQ, &u2));
        
        // v = g^u1 * y^u2 mod p mod q
        MP_OP(mp_exptmod(keyG, &u1, keyP, &u1));
        MP_OP(mp_exptmod(keyY, &u2, keyP, &u2));
        MP_OP(mp_mulmod(&u1, &u2, keyP, &v));
        MP_OP(mp_mod(&v, keyQ, &v));
        
        // if r = v then we're set
        ret = 0;
        if (mp_cmp(r, &v) == MP_EQ) ret = 1;
        
error:
        mp_clear_multi(&w, &v, &u1, &u2, NULL);
        return ret;
}
コード例 #24
0
ファイル: ltc_ecc_map.c プロジェクト: aegoroff/linq2hash
/**
  Map a projective jacbobian point back to affine space
  @param P        [in/out] The point to map
  @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_map(ecc_point *P, void *modulus, void *mp)
{
   void *t1, *t2;
   int   err;

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

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

   /* first map z back to normal */
   if ((err = mp_montgomery_reduce(P->z, modulus, mp)) != CRYPT_OK)           { goto done; }

   /* get 1/z */
   if ((err = mp_invmod(P->z, modulus, t1)) != CRYPT_OK)                      { goto done; }
 
   /* get 1/z^2 and 1/z^3 */
   if ((err = mp_sqr(t1, t2)) != CRYPT_OK)                                    { goto done; }
   if ((err = mp_mod(t2, modulus, t2)) != CRYPT_OK)                           { goto done; }
   if ((err = mp_mul(t1, t2, t1)) != CRYPT_OK)                                { goto done; }
   if ((err = mp_mod(t1, modulus, t1)) != CRYPT_OK)                           { goto done; }

   /* multiply against x/y */
   if ((err = mp_mul(P->x, t2, P->x)) != CRYPT_OK)                            { goto done; }
   if ((err = mp_montgomery_reduce(P->x, modulus, mp)) != CRYPT_OK)           { goto done; }
   if ((err = mp_mul(P->y, t1, P->y)) != CRYPT_OK)                            { goto done; }
   if ((err = mp_montgomery_reduce(P->y, modulus, mp)) != CRYPT_OK)           { goto done; }
   if ((err = mp_set(P->z, 1)) != CRYPT_OK)                                   { goto done; }

   err = CRYPT_OK;
done:
   mp_clear_multi(t1, t2, NULL);
   return err;
}
コード例 #25
0
/*
  Map a projective jacobian point back to affine space
  @param P        [in/out] The point to map
  @param modulus  The modulus of the field the ECC curve is in
  @param mp       The "b" value from montgomery_setup()
  @return 0 on success
*/
int
ecc_map (ecc_point * P, mpz_t modulus)
{
  mpz_t t1, t2;
  int err;

  if (P == NULL)
    return -1;

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

  mpz_mod (P->z, P->z, modulus);

  /* get 1/z */
  mpz_invert (t1, P->z, modulus);

  /* get 1/z^2 and 1/z^3 */
  mpz_mul (t2, t1, t1);
  mpz_mod (t2, t2, modulus);
  mpz_mul (t1, t1, t2);
  mpz_mod (t1, t1, modulus);

  /* multiply against x/y */
  mpz_mul (P->x, P->x, t2);
  mpz_mod (P->x, P->x, modulus);
  mpz_mul (P->y, P->y, t1);
  mpz_mod (P->y, P->y, modulus);
  mpz_set_ui (P->z, 1);

  err = 0;

  mp_clear_multi (&t1, &t2, NULL);
  return err;
}
コード例 #26
0
ファイル: bn_mp_lcm.c プロジェクト: libtom/libtommath
/* computes least common multiple as |a*b|/(a, b) */
int mp_lcm(const mp_int *a, const mp_int *b, mp_int *c)
{
   int     res;
   mp_int  t1, t2;


   if ((res = mp_init_multi(&t1, &t2, NULL)) != MP_OKAY) {
      return res;
   }

   /* t1 = get the GCD of the two inputs */
   if ((res = mp_gcd(a, b, &t1)) != MP_OKAY) {
      goto LBL_T;
   }

   /* divide the smallest by the GCD */
   if (mp_cmp_mag(a, b) == MP_LT) {
      /* store quotient in t2 such that t2 * b is the LCM */
      if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
         goto LBL_T;
      }
      res = mp_mul(b, &t2, c);
   } else {
      /* store quotient in t2 such that t2 * a is the LCM */
      if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
         goto LBL_T;
      }
      res = mp_mul(a, &t2, c);
   }

   /* fix the sign to positive */
   c->sign = MP_ZPOS;

LBL_T:
   mp_clear_multi(&t1, &t2, NULL);
   return res;
}
コード例 #27
0
ファイル: dsa_set.c プロジェクト: FirebirdSQL/firebird
/**
  Import DSA's p, q & g from raw numbers
  @param p       DSA's p  in binary representation
  @param plen    The length of p
  @param q       DSA's q  in binary representation
  @param qlen    The length of q
  @param g       DSA's g  in binary representation
  @param glen    The length of g
  @param key     [out] the destination for the imported key
  @return CRYPT_OK if successful.
*/
int dsa_set_pqg(const unsigned char *p,  unsigned long plen,
                const unsigned char *q,  unsigned long qlen,
                const unsigned char *g,  unsigned long glen,
                dsa_key *key)
{
   int err, stat;

   LTC_ARGCHK(p           != NULL);
   LTC_ARGCHK(q           != NULL);
   LTC_ARGCHK(g           != NULL);
   LTC_ARGCHK(key         != NULL);
   LTC_ARGCHK(ltc_mp.name != NULL);

   /* init key */
   err = mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
   if (err != CRYPT_OK) return err;

   if ((err = mp_read_unsigned_bin(key->p, (unsigned char *)p , plen)) != CRYPT_OK) { goto LBL_ERR; }
   if ((err = mp_read_unsigned_bin(key->g, (unsigned char *)g , glen)) != CRYPT_OK) { goto LBL_ERR; }
   if ((err = mp_read_unsigned_bin(key->q, (unsigned char *)q , qlen)) != CRYPT_OK) { goto LBL_ERR; }

   key->qord = mp_unsigned_bin_size(key->q);

   /* do only a quick validation, without primality testing */
   if ((err = dsa_int_validate_pqg(key, &stat)) != CRYPT_OK)                        { goto LBL_ERR; }
   if (stat == 0) {
      err = CRYPT_INVALID_PACKET;
      goto LBL_ERR;
   }

   return CRYPT_OK;

LBL_ERR:
   dsa_free(key);
   return err;
}
コード例 #28
0
ファイル: bignum-tommath.c プロジェクト: Meijuh/ltsmin
void
bn_double2int (double a, mp_int *b)
{
    const unsigned int  FRAC_BITS = 52;
    int                 ret,
                        exp;
    long int            val;
    double              frac;
    mp_int              upper,
                        number;

    assert (a >= 0);
    ret = mp_init_multi (b, &number, &upper, NULL);
    if (ret != MP_OKAY)
        Fatal (1, error, "Error initializing number");
    mp_set (&upper, 1);
    frac = frexp (a, &exp);
    ret = mp_mul_2d (&upper, exp, &upper);
    if (ret != MP_OKAY)
        Fatal (1, error, "Error initializing number");
    for (unsigned int i = 0; i < FRAC_BITS; i++) {
        frac = frac * 2;
        val = lround (floor (frac));
        assert (val == 0 || val == 1);
        frac = frac - lround (floor (frac));
        if (val == 1) {
            mp_div_2d (&upper, i + 1, &number, NULL);
            if (ret != MP_OKAY)
                Fatal (1, error, "Error dividing numbers");
            mp_add (b, &number, b);
            if (ret != MP_OKAY)
                Fatal (1, error, "Error adding numbers");
        }
    }
    mp_clear_multi (&number, &upper, NULL);
}
コード例 #29
0
ファイル: dh_set.c プロジェクト: ybendan/libtomcrypt
/**
  Import DH key parts p and g from raw numbers

  @param p       DH's p (prime)
  @param plen    DH's p's length
  @param g       DH's g (group)
  @param glen    DH's g's length
  @param key     [out] the destination for the imported key
  @return CRYPT_OK if successful
*/
int dh_set_pg(const unsigned char *p, unsigned long plen,
              const unsigned char *g, unsigned long glen,
              dh_key *key)
{
   int err;

   LTC_ARGCHK(key         != NULL);
   LTC_ARGCHK(p           != NULL);
   LTC_ARGCHK(g           != NULL);
   LTC_ARGCHK(ltc_mp.name != NULL);

   if ((err = mp_init_multi(&key->x, &key->y, &key->base, &key->prime, NULL)) != CRYPT_OK) {
      return err;
   }

   if ((err = mp_read_unsigned_bin(key->base, (unsigned char*)g, glen)) != CRYPT_OK)     { goto LBL_ERR; }
   if ((err = mp_read_unsigned_bin(key->prime, (unsigned char*)p, plen)) != CRYPT_OK)  { goto LBL_ERR; }

   return CRYPT_OK;

LBL_ERR:
   dh_free(key);
   return err;
}
コード例 #30
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;
}