Пример #1
0
/* flatten RsaKey structure into individual elements (e, n) */
int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n,
                           word32* nSz)
{
    int sz, ret;

    if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL)
       return BAD_FUNC_ARG;

    sz = mp_unsigned_bin_size(&key->e);
    if ((word32)sz > *nSz)
        return RSA_BUFFER_E;
    ret = mp_to_unsigned_bin(&key->e, e);
    if (ret != MP_OKAY)
        return ret;
    *eSz = (word32)sz;

    sz = mp_unsigned_bin_size(&key->n);
    if ((word32)sz > *nSz)
        return RSA_BUFFER_E;
    ret = mp_to_unsigned_bin(&key->n, n);
    if (ret != MP_OKAY)
        return ret;
    *nSz = (word32)sz;

    return 0;
}
Пример #2
0
uint8_t *rsa_serialize_pair(rsa_keypair_t *pair, size_t *len) {
	uint32_t bytes_m, bytes_e, bytes_d;
	uint32_t bytes_p, bytes_q, bytes_dp, bytes_dq, bytes_qi;
	size_t offs = 0;
	uint8_t *out;

	if(pair == NULL) return NULL;
	if((pair->public == NULL) || (pair->secret == NULL) || (pair->modulus == NULL))
		return NULL;

	bytes_m = mp_unsigned_bin_size(pair->modulus);
	bytes_e = mp_unsigned_bin_size(pair->public);
	bytes_d = mp_unsigned_bin_size(pair->secret);
	*len = bytes_e + bytes_d + bytes_m + 3 * INT_SIZE;

	if((pair->p == NULL) || (pair->q == NULL) || (pair->dp == NULL) || (pair->dq == NULL) || (pair->qi == NULL)) {
		if((out = malloc(*len)) == NULL)
			return NULL;

		memcpy(out + offs, &bytes_m, INT_SIZE);		offs += INT_SIZE;
		mp_to_unsigned_bin(pair->modulus, out + offs); 	offs += bytes_m;
		memcpy(out + offs, &bytes_e, INT_SIZE);		offs += INT_SIZE;
		mp_to_unsigned_bin(pair->public, out + offs);	offs += bytes_e;
		memcpy(out + offs, &bytes_d, INT_SIZE);		offs += INT_SIZE;
		mp_to_unsigned_bin(pair->secret, out + offs);	offs += bytes_d;
		
	} else {
/** ECC X9.63 (Sec. 4.3.6) uncompressed export
   @param key     Key to export
   @param out     [out] destination of export
   @param outlen  [in/out]  Length of destination and final output size
   Return CRYPT_OK on success
 */
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen) {
    unsigned char buf[ECC_BUF_SIZE];
    unsigned long numlen;

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

    if (ltc_ecc_is_valid_idx(key->idx) == 0) {
        return CRYPT_INVALID_ARG;
    }
    numlen = key->dp->size;

    if (*outlen < (1 + 2 * numlen)) {
        *outlen = 1 + 2 * numlen;
        return CRYPT_BUFFER_OVERFLOW;
    }

    /* store byte 0x04 */
    out[0] = 0x04;

    /* pad and store x */
    zeromem(buf, sizeof(buf));
    mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
    XMEMCPY(out + 1, buf, numlen);

    /* pad and store y */
    zeromem(buf, sizeof(buf));
    mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - mp_unsigned_bin_size(key->pubkey.y)));
    XMEMCPY(out + 1 + numlen, buf, numlen);

    *outlen = 1 + 2 * numlen;
    return CRYPT_OK;
}
Пример #4
0
uint8_t *rsa_serialize_public(rsa_keypair_t *pair, size_t *len) {
	uint32_t bytes_m, bytes_e;
	size_t offs = 0;
	uint8_t *out;

	if(pair == NULL)
		return NULL;

	if((pair->public == NULL) || (pair->modulus == NULL))
		return NULL;

	bytes_m = mp_unsigned_bin_size(pair->modulus);
	bytes_e = mp_unsigned_bin_size(pair->public);
	*len = bytes_m + bytes_e + 2 * INT_SIZE;

	if((out = malloc(*len)) == NULL)
		return NULL;

	memcpy(out + offs, &bytes_m, INT_SIZE);		offs += INT_SIZE;
	mp_to_unsigned_bin(pair->modulus, out + offs);	offs += bytes_m;
	memcpy(out + offs, &bytes_e, INT_SIZE);		offs += INT_SIZE;
	mp_to_unsigned_bin(pair->public, out + offs);	offs += bytes_e;

	return out;
}
Пример #5
0
/**
   Convert data from a specific radix to binary

      The default MPI descriptors #ltm_desc, #tfm_desc and #gmp_desc
      have the following restrictions on parameters:

        \p in    - NUL-terminated char buffer

        \p radix - 2..64

   @param in    The input
   @param radix The radix of the input
   @param out   The output buffer
   @param len   [in/out] The length of the output buffer

   @return CRYPT_OK on success.
*/
int radix_to_bin(const void *in, int radix, void *out, unsigned long *len)
{
   unsigned long l;
   void* mpi;
   int err;

   LTC_ARGCHK(in  != NULL);
   LTC_ARGCHK(len != NULL);

   if ((err = mp_init(&mpi)) != CRYPT_OK) return err;
   if ((err = mp_read_radix(mpi, in, radix)) != CRYPT_OK) goto LBL_ERR;

   if ((l = mp_unsigned_bin_size(mpi)) > *len) {
      *len = l;
      err = CRYPT_BUFFER_OVERFLOW;
      goto LBL_ERR;
   }
   *len = l;

   if ((err = mp_to_unsigned_bin(mpi, out)) != CRYPT_OK) goto LBL_ERR;

LBL_ERR:
   mp_clear(mpi);
   return err;
}
Пример #6
0
int 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 (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;
}
Пример #7
0
static int GeneratePublic(DhKey* key, const byte* priv, word32 privSz,
                          byte* pub, word32* pubSz)
{
    int ret = 0;

    mp_int x; 
    mp_int y;

    if (mp_init_multi(&x, &y, 0, 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_exptmod(&key->g, &x, &key->p, &y) != MP_OKAY)
        ret = MP_EXPTMOD_E;

    if (ret == 0 && mp_to_unsigned_bin(&y, pub) != MP_OKAY)
        ret = MP_TO_E;

    if (ret == 0)
        *pubSz = mp_unsigned_bin_size(&y);

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

    return ret;
}
Пример #8
0
int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size)
{
    mp_int v;
    int r;

    if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE)
        return BAD_FUNC_ARG;

    if (mp_iszero(&srp->auth) == MP_YES)
        return SRP_CALL_ORDER_E;

    r = mp_init(&v);
    if (r != MP_OKAY)
        return MP_INIT_E;

    /* v = g ^ x % N */
    if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v);
    if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY;
    if (!r) r = mp_to_unsigned_bin(&v, verifier);
    if (!r) *size = mp_unsigned_bin_size(&v);

    mp_clear(&v);

    return r;
}
/* store in unsigned [big endian] format */
int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
{
   if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
      return MP_VAL;
   }
   *outlen = mp_unsigned_bin_size(a);
   return mp_to_unsigned_bin(a, b);
}
Пример #10
0
/**
  Create an ECC shared secret between two keys
  @param private_key      The private ECC key
  @param public_key       The public key
  @param out              [out] Destination of the shared secret (Conforms to EC-DH from ANSI X9.63)
  @param outlen           [in/out] The max size and resulting size of the shared secret
  @return CRYPT_OK if successful
*/
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
                      unsigned char *out, unsigned long *outlen)
{
   unsigned long  x;
   ecc_point     *result;
   void          *prime;
   int            err;

   LTC_ARGCHK(private_key != NULL);
   LTC_ARGCHK(public_key  != NULL);
   LTC_ARGCHK(out         != NULL);
   LTC_ARGCHK(outlen      != NULL);

   /* type valid? */
   if (private_key->type != PK_PRIVATE) {
      return CRYPT_PK_NOT_PRIVATE;
   }

   if (ltc_ecc_is_valid_idx(private_key->idx) == 0 || ltc_ecc_is_valid_idx(public_key->idx) == 0) {
      return CRYPT_INVALID_ARG;
   }

   if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
      return CRYPT_PK_TYPE_MISMATCH;
   }

   /* make new point */
   result = ltc_ecc_new_point();
   if (result == NULL) {
      return CRYPT_MEM;
   }

   if ((err = mp_init(&prime)) != CRYPT_OK) {
      ltc_ecc_del_point(result);
      return err;
   }

   if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK)                               { goto done; }
   if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK)                { goto done; }

   x = (unsigned long)mp_unsigned_bin_size(prime);
   if (*outlen < x) {
      *outlen = x;
      err = CRYPT_BUFFER_OVERFLOW;
      goto done;
   }
   zeromem(out, x);
   if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x))))   != CRYPT_OK)           { goto done; }

   err     = CRYPT_OK;
   *outlen = x;
done:
   mp_clear(prime);
   ltc_ecc_del_point(result);
   return err;
}
Пример #11
0
/* store in signed [big endian] format */
int mp_to_signed_bin(const mp_int *a, unsigned char *b)
{
   int     res;

   if ((res = mp_to_unsigned_bin(a, b + 1)) != MP_OKAY) {
      return res;
   }
   b[0] = (a->sign == MP_ZPOS) ? (unsigned char)0 : (unsigned char)1;
   return MP_OKAY;
}
/* store in signed [big endian] format */
int mp_to_signed_bin (mp_int * a, unsigned char *b)
{
    int     res;

    if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
        return res;
    }
    b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
    return MP_OKAY;
}
/**
   LTC_PKCS #1 Integer to binary
   @param n             The integer to store
   @param modulus_len   The length of the RSA modulus
   @param out           [out] The destination for the integer
   @return CRYPT_OK if successful
 */
int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out) {
    unsigned long size;

    size = mp_unsigned_bin_size(n);

    if (size > modulus_len) {
        return CRYPT_BUFFER_OVERFLOW;
    }

    /* store it */
    zeromem(out, modulus_len);
    return mp_to_unsigned_bin(n, out + (modulus_len - size));
}
Пример #14
0
/**
 * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum
 * @n: Bignum from bignum_init()
 * @buf: Buffer for the binary number
 * @len: Length of the buffer, can be %NULL if buffer is known to be long
 * enough. Set to used buffer length on success if not %NULL.
 * Returns: 0 on success, -1 on failure
 */
int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) {
    size_t need = mp_unsigned_bin_size((mp_int *) n);
    if (len && need > *len) {
        *len = need;
        return -1;
    }
    if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) {
        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
        return -1;
    }
    if (len)
        *len = need;
    return 0;
}
Пример #15
0
int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst)
{
    int err;
    word32 sz;

    if (src == NULL || dst == NULL)
        return BAD_FUNC_ARG;

    sz = mp_unsigned_bin_size(src);
    err = wc_bigint_alloc(dst, sz);
    if (err == MP_OKAY)
        err = mp_to_unsigned_bin(src, dst->buf);

    return err;
}
Пример #16
0
static BIGNUM *
mpz2BN(mp_int *s)
{
    size_t size;
    BIGNUM *bn;
    void *p;

    size = mp_unsigned_bin_size(s);
    p = malloc(size);
    if (p == NULL && size != 0)
	return NULL;
    mp_to_unsigned_bin(s, p);

    bn = BN_bin2bn(p, size, NULL);
    free(p);
    return bn;
}
Пример #17
0
/* always stores the same # of bytes, pads with leading zero bytes
   as required
 */
int pkcs_1_i2osp(mp_int *n, unsigned long modulus_len, unsigned char *out)
{
   int err;
   unsigned long size;

   size = mp_unsigned_bin_size(n);

   if (size > modulus_len) {
      return CRYPT_BUFFER_OVERFLOW;
   }

   /* store it */
   zeromem(out, modulus_len);
   if ((err = mp_to_unsigned_bin(n, out+(modulus_len-size))) != MP_OKAY) {
      return mpi_to_ltc_error(err);
   }
   return CRYPT_OK;
}
Пример #18
0
mp_err   mp_i2osp(mp_int *x, char *out, int len)
{
  int    xlen;

  ARGCHK(x != NULL && out != NULL && len > 0, MP_BADARG);

  if((xlen = mp_unsigned_bin_size(x)) > len) {
    return MP_RANGE;
  }

  xlen -= len;
  if(xlen > 0)
    memset(out, 0, xlen);

  mp_to_unsigned_bin(x, (unsigned char *)out + xlen);

  return MP_OKAY;
 
} /* end mp_i2osp() */
Пример #19
0
/* for our purposes we only need positive (or 0) numbers, so will
 * fail if we get negative numbers */
void buf_putmpint(buffer* buf, mp_int * mp) {

	unsigned int len, pad = 0;
	TRACE2(("enter buf_putmpint"))

	dropbear_assert(mp != NULL);

	if (SIGN(mp) == MP_NEG) {
		dropbear_exit("negative bignum");
	}

	/* zero check */
	if (USED(mp) == 1 && DIGIT(mp, 0) == 0) {
		len = 0;
	} else {
		/* SSH spec requires padding for mpints with the MSB set, this code
		 * implements it */
		len = mp_count_bits(mp);
		/* if the top bit of MSB is set, we need to pad */
		pad = (len%8 == 0) ? 1 : 0;
		len = len / 8 + 1; /* don't worry about rounding, we need it for
							  padding anyway when len%8 == 0 */

	}

	/* store the length */
	buf_putint(buf, len);
	
	/* store the actual value */
	if (len > 0) {
		if (pad) {
			buf_putbyte(buf, 0x00);
		}
		if (mp_to_unsigned_bin(mp, buf_getwriteptr(buf, len-pad)) != MP_OKAY) {
			dropbear_exit("mpint error");
		}
		buf_incrwritepos(buf, len-pad);
	}

	TRACE2(("leave buf_putmpint"))
}
Пример #20
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;
}
Пример #21
0
/**
  Create a DSA shared secret between two keys
  @param private_key      The private DSA key (the exponent)
  @param base             The base of the exponentiation (allows this to be used for both encrypt and decrypt) 
  @param public_key       The public key
  @param out              [out] Destination of the shared secret
  @param outlen           [in/out] The max size and resulting size of the shared secret
  @return CRYPT_OK if successful
*/
int dsa_shared_secret(void          *private_key, void *base,
                      dsa_key       *public_key,
                      unsigned char *out,         unsigned long *outlen)
{
   unsigned long  x;
   void          *res;
   int            err;

   LTC_ARGCHK(private_key != NULL);
   LTC_ARGCHK(public_key  != NULL);
   LTC_ARGCHK(out         != NULL);
   LTC_ARGCHK(outlen      != NULL);

   /* make new point */
   if ((err = mp_init(&res)) != CRYPT_OK) {
      return err;
   }

   if ((err = mp_exptmod(base, private_key, public_key->p, res)) != CRYPT_OK) {
      mp_clear(res);
      return err;
   }
   
   x = (unsigned long)mp_unsigned_bin_size(res);
   if (*outlen < x) {
      *outlen = x;
      err = CRYPT_BUFFER_OVERFLOW;
      goto done;
   }
   zeromem(out, x);
   if ((err = mp_to_unsigned_bin(res, out + (x - mp_unsigned_bin_size(res))))   != CRYPT_OK)          { goto done; }

   err     = CRYPT_OK;
   *outlen = x;
done:
   mp_clear(res);
   return err;
}
Пример #22
0
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;
}
Пример #23
0
	void BigInteger::getBytes(Firebird::UCharBuffer& bytes) const
	{
		CHECK_MP(mp_to_unsigned_bin(const_cast<mp_int*>(&t), bytes.getBuffer(length())));
	}
Пример #24
0
int ecc_export_full(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
  int           err;
  void *prime, *order, *a, *b, *gx, *gy;
  unsigned char bin_a[256], bin_b[256], bin_k[256], bin_g[512], bin_xy[512];
  unsigned long len_a, len_b, len_k, len_g, len_xy;
  unsigned long cofactor, one = 1;
  oid_st oid;
  ltc_asn1_list seq_fieldid[2], seq_curve[2], seq_ecparams[6], seq_priv[4];

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

  if (key->type != PK_PRIVATE && type == PK_PRIVATE)                                   return CRYPT_PK_TYPE_MISMATCH;
  if (ltc_ecc_is_valid_idx(key->idx) == 0)                                             return CRYPT_INVALID_ARG;

  if ((err = mp_init_multi(&prime, &order, &a, &b, &gx, &gy, NULL)) != CRYPT_OK)       return err;

  if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK)                    goto error;
  if ((err = mp_read_radix(order, key->dp->order, 16)) != CRYPT_OK)                    goto error;
  if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK)                            goto error;
  if ((err = mp_read_radix(a, key->dp->A, 16)) != CRYPT_OK)                            goto error;
  if ((err = mp_read_radix(gx, key->dp->Gx, 16)) != CRYPT_OK)                          goto error;
  if ((err = mp_read_radix(gy, key->dp->Gy, 16)) != CRYPT_OK)                          goto error;

  /* curve param a */
  len_a = mp_unsigned_bin_size(a);
  if (len_a > sizeof(bin_a))                                                           { err = CRYPT_BUFFER_OVERFLOW; goto error; }
  if ((err = mp_to_unsigned_bin(a, bin_a)) != CRYPT_OK)                                goto error;
  if (len_a == 0) { len_a = 1; bin_a[0] = 0; } /* XXX-TODO hack to handle case a == 0 */

  /* curve param b */
  len_b = mp_unsigned_bin_size(b);
  if (len_b > sizeof(bin_b))                                                           { err = CRYPT_BUFFER_OVERFLOW; goto error; }
  if ((err = mp_to_unsigned_bin(b, bin_b)) != CRYPT_OK)                                goto error;
  if (len_b == 0) { len_b = 1; bin_b[0] = 0; } /* XXX-TODO hack to handle case b == 0 */

  /* base point - we export uncompressed form */
  len_g = sizeof(bin_g);
  if ((err = ecc_export_point(bin_g, &len_g, gx, gy, key->dp->size, 0)) != CRYPT_OK)   goto error;

  /* public key */
  len_xy = sizeof(bin_xy);
  if ((err = ecc_export_point(bin_xy, &len_xy, key->pubkey.x, key->pubkey.y, key->dp->size, 0)) != CRYPT_OK)    goto error;

  /* co-factor */
  cofactor = key->dp->cofactor;

  /* we support only prime-field EC */
  if ((err = pk_get_oid(EC_PRIME_FIELD, &oid)) != CRYPT_OK)                            goto error;

  /* FieldID SEQUENCE */
  LTC_SET_ASN1(seq_fieldid,  0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID,     oid.OIDlen);
  LTC_SET_ASN1(seq_fieldid,  1, LTC_ASN1_INTEGER,           prime,       1UL);

  /* Curve SEQUENCE */
  LTC_SET_ASN1(seq_curve,    0, LTC_ASN1_OCTET_STRING,      bin_a,       len_a);
  LTC_SET_ASN1(seq_curve,    1, LTC_ASN1_OCTET_STRING,      bin_b,       len_b);

  /* ECParameters SEQUENCE */
  LTC_SET_ASN1(seq_ecparams, 0, LTC_ASN1_SHORT_INTEGER,     &one,        1UL);
  LTC_SET_ASN1(seq_ecparams, 1, LTC_ASN1_SEQUENCE,          seq_fieldid, 2UL);
  LTC_SET_ASN1(seq_ecparams, 2, LTC_ASN1_SEQUENCE,          seq_curve,   2UL);
  LTC_SET_ASN1(seq_ecparams, 3, LTC_ASN1_OCTET_STRING,      bin_g,       len_g);
  LTC_SET_ASN1(seq_ecparams, 4, LTC_ASN1_INTEGER,           order,       1UL);
  LTC_SET_ASN1(seq_ecparams, 5, LTC_ASN1_SHORT_INTEGER,     &cofactor,   1UL);

  if (type == PK_PRIVATE) {
      /* private key format: http://tools.ietf.org/html/rfc5915

          ECPrivateKey ::= SEQUENCE {                                    # SEQUENCE
           version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),  # INTEGER       :01
           privateKey     OCTET STRING,                                  # OCTET STRING
           [0] ECParameters ::= SEQUENCE {                               # SEQUENCE
                version         INTEGER { ecpVer1(1) } (ecpVer1),        # INTEGER       :01
                FieldID ::= SEQUENCE {                                   # SEQUENCE
                    fieldType       FIELD-ID.&id({IOSet}),               # OBJECT        :prime-field
                    parameters      FIELD-ID.&Type({IOSet}{@fieldType})  # INTEGER
                }
                Curve ::= SEQUENCE {                                     # SEQUENCE
                    a               FieldElement ::= OCTET STRING        # OCTET STRING
                    b               FieldElement ::= OCTET STRING        # OCTET STRING
                    seed            BIT STRING      OPTIONAL
                }
                base            ECPoint ::= OCTET STRING                 # OCTET STRING
                order           INTEGER,                                 # INTEGER
                cofactor        INTEGER OPTIONAL                         # INTEGER
            }
            [1] publicKey                                                # BIT STRING
          }
      */

      /* private key */
      len_k = mp_unsigned_bin_size(key->k);
      if (len_k > sizeof(bin_k))                                                       { err = CRYPT_BUFFER_OVERFLOW; goto error; }
      if ((err = mp_to_unsigned_bin(key->k, bin_k)) != CRYPT_OK)                       goto error;

      LTC_SET_ASN1(seq_priv, 0, LTC_ASN1_SHORT_INTEGER,   &one,         1UL);
      LTC_SET_ASN1(seq_priv, 1, LTC_ASN1_OCTET_STRING,    bin_k,        len_k);
      LTC_SET_ASN1(seq_priv, 2, LTC_ASN1_SEQUENCE,        seq_ecparams, 6UL);
      LTC_SET_ASN1(seq_priv, 3, LTC_ASN1_RAW_BIT_STRING,  bin_xy,       8*len_xy);
      seq_priv[2].tag = 0xA0;
      seq_priv[3].tag = 0xA1;

      err = der_encode_sequence(seq_priv, 4, out, outlen);
  }
  else {
      /* public key format: http://tools.ietf.org/html/rfc5480

          SubjectPublicKeyInfo ::= SEQUENCE  {                           # SEQUENCE
            AlgorithmIdentifier ::= SEQUENCE  {                          # SEQUENCE
              algorithm OBJECT IDENTIFIER                                # OBJECT        :id-ecPublicKey
              ECParameters ::= SEQUENCE {                                # SEQUENCE
                  version INTEGER { ecpVer1(1) } (ecpVer1),              # INTEGER       :01
                  FieldID ::= SEQUENCE {                                 # SEQUENCE
                      fieldType   FIELD-ID.&id({IOSet}),                 # OBJECT        :prime-field
                      parameters  FIELD-ID.&Type({IOSet}{@fieldType})    # INTEGER
                  }
                  Curve ::= SEQUENCE {                                   # SEQUENCE
                      a           FieldElement ::= OCTET STRING          # OCTET STRING
                      b           FieldElement ::= OCTET STRING          # OCTET STRING
                      seed        BIT STRING      OPTIONAL
                  }
                  base            ECPoint ::= OCTET STRING               # OCTET STRING
                  order           INTEGER,                               # INTEGER
                  cofactor        INTEGER OPTIONAL                       # INTEGER
              }
            }
            subjectPublicKey  BIT STRING                                 # BIT STRING
          }
      */

      err = der_encode_subject_public_key_info( out, outlen,
                                                PKA_EC, bin_xy, len_xy,
                                                LTC_ASN1_SEQUENCE, seq_ecparams, 6 );
  }

error:
  mp_clear_multi(prime, order, a, b, gx, gy, NULL);
  return err;
}
Пример #25
0
/**
  Create DSA parameters (INTERNAL ONLY, not part of public API)
  @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 p             [out] bignum where generated 'p' is stored (must be initialized by caller)
  @param q             [out] bignum where generated 'q' is stored (must be initialized by caller)
  @param g             [out] bignum where generated 'g' is stored (must be initialized by caller)
  @return CRYPT_OK if successful, upon error this function will free all allocated memory
*/
static int _dsa_make_params(prng_state *prng, int wprng, int group_size, int modulus_size, void *p, void *q, void *g)
{
  unsigned long L, N, n, outbytes, seedbytes, counter, j, i;
  int err, res, mr_tests_q, mr_tests_p, found_p, found_q, hash;
  unsigned char *wbuf, *sbuf, digest[MAXBLOCKSIZE];
  void *t2L1, *t2N1, *t2q, *t2seedlen, *U, *W, *X, *c, *h, *e, *seedinc;

  /* check size */
  if (group_size >= LTC_MDSA_MAX_GROUP || group_size < 1 || group_size >= modulus_size) {
    return CRYPT_INVALID_ARG;
  }

 /* FIPS-186-4 A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
  *
  * L = The desired length of the prime p (in bits e.g. L = 1024)
  * N = The desired length of the prime q (in bits e.g. N = 160)
  * seedlen = The desired bit length of the domain parameter seed; seedlen shallbe equal to or greater than N
  * outlen  = The bit length of Hash function
  *
  * 1.  Check that the (L, N)
  * 2.  If (seedlen <N), then return INVALID.
  * 3.  n = ceil(L / outlen) - 1
  * 4.  b = L- 1 - (n * outlen)
  * 5.  domain_parameter_seed = an arbitrary sequence of seedlen bits
  * 6.  U = Hash (domain_parameter_seed) mod 2^(N-1)
  * 7.  q = 2^(N-1) + U + 1 - (U mod 2)
  * 8.  Test whether or not q is prime as specified in Appendix C.3
  * 9.  If qis not a prime, then go to step 5.
  * 10. offset = 1
  * 11. For counter = 0 to (4L- 1) do {
  *       For j=0 to n do {
  *         Vj = Hash ((domain_parameter_seed+ offset + j) mod 2^seedlen
  *       }
  *       W = V0 + (V1 *2^outlen) + ... + (Vn-1 * 2^((n-1) * outlen)) + ((Vn mod 2^b) * 2^(n * outlen))
  *       X = W + 2^(L-1)           Comment: 0 <= W < 2^(L-1); hence 2^(L-1) <= X < 2^L
  *       c = X mod 2*q
  *       p = X - (c - 1)           Comment: p ~ 1 (mod 2*q)
  *       If (p >= 2^(L-1)) {
  *         Test whether or not p is prime as specified in Appendix C.3.
  *         If p is determined to be prime, then return VALID and the values of p, qand (optionally) the values of domain_parameter_seed and counter
  *       }
  *       offset = offset + n + 1   Comment: Increment offset
  *     }
  */

  seedbytes = group_size;
  L = (unsigned long)modulus_size * 8;
  N = (unsigned long)group_size * 8;

  /* XXX-TODO no Lucas test */
#ifdef LTC_MPI_HAS_LUCAS_TEST
  /* M-R tests (when followed by one Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
  mr_tests_p = (L <= 2048) ? 3 : 2;
  if      (N <= 160)  { mr_tests_q = 19; }
  else if (N <= 224)  { mr_tests_q = 24; }
  else                { mr_tests_q = 27; }
#else
  /* M-R tests (without Lucas test) according FIPS-186-4 - Appendix C.3 - table C.1 */
  if      (L <= 1024) { mr_tests_p = 40; }
  else if (L <= 2048) { mr_tests_p = 56; }
  else                { mr_tests_p = 64; }

  if      (N <= 160)  { mr_tests_q = 40; }
  else if (N <= 224)  { mr_tests_q = 56; }
  else                { mr_tests_q = 64; }
#endif

  if (N <= 256) {
    hash = register_hash(&sha256_desc);
  }
  else if (N <= 384) {
    hash = register_hash(&sha384_desc);
  }
  else if (N <= 512) {
    hash = register_hash(&sha512_desc);
  }
  else {
    return CRYPT_INVALID_ARG; /* group_size too big */
  }

  if ((err = hash_is_valid(hash)) != CRYPT_OK)                                   { return err; }
  outbytes = hash_descriptor[hash].hashsize;

  n = ((L + outbytes*8 - 1) / (outbytes*8)) - 1;

  if ((wbuf = XMALLOC((n+1)*outbytes)) == NULL)                                  { err = CRYPT_MEM; goto cleanup3; }
  if ((sbuf = XMALLOC(seedbytes)) == NULL)                                       { err = CRYPT_MEM; goto cleanup2; }

  err = mp_init_multi(&t2L1, &t2N1, &t2q, &t2seedlen, &U, &W, &X, &c, &h, &e, &seedinc, NULL);
  if (err != CRYPT_OK)                                                           { goto cleanup1; }

  if ((err = mp_2expt(t2L1, L-1)) != CRYPT_OK)                                   { goto cleanup; }
  /* t2L1 = 2^(L-1) */
  if ((err = mp_2expt(t2N1, N-1)) != CRYPT_OK)                                   { goto cleanup; }
  /* t2N1 = 2^(N-1) */
  if ((err = mp_2expt(t2seedlen, seedbytes*8)) != CRYPT_OK)                      { goto cleanup; }
  /* t2seedlen = 2^seedlen */

  for(found_p=0; !found_p;) {
    /* q */
    for(found_q=0; !found_q;) {
      if (prng_descriptor[wprng].read(sbuf, seedbytes, prng) != seedbytes)       { err = CRYPT_ERROR_READPRNG; goto cleanup; }
      i = outbytes;
      if ((err = hash_memory(hash, sbuf, seedbytes, digest, &i)) != CRYPT_OK)    { goto cleanup; }
      if ((err = mp_read_unsigned_bin(U, digest, outbytes)) != CRYPT_OK)         { goto cleanup; }
      if ((err = mp_mod(U, t2N1, U)) != CRYPT_OK)                                { goto cleanup; }
      if ((err = mp_add(t2N1, U, q)) != CRYPT_OK)                                { goto cleanup; }
      if (!mp_isodd(q)) mp_add_d(q, 1, q);
      if ((err = mp_prime_is_prime(q, mr_tests_q, &res)) != CRYPT_OK)            { goto cleanup; }
      if (res == LTC_MP_YES) found_q = 1;
    }

    /* p */
    if ((err = mp_read_unsigned_bin(seedinc, sbuf, seedbytes)) != CRYPT_OK)      { goto cleanup; }
    if ((err = mp_add(q, q, t2q)) != CRYPT_OK)                                   { goto cleanup; }
    for(counter=0; counter < 4*L && !found_p; counter++) {
      for(j=0; j<=n; j++) {
        if ((err = mp_add_d(seedinc, 1, seedinc)) != CRYPT_OK)                   { goto cleanup; }
        if ((err = mp_mod(seedinc, t2seedlen, seedinc)) != CRYPT_OK)             { goto cleanup; }
        /* seedinc = (seedinc+1) % 2^seed_bitlen */
        if ((i = mp_unsigned_bin_size(seedinc)) > seedbytes)                     { err = CRYPT_INVALID_ARG; goto cleanup; }
        zeromem(sbuf, seedbytes);
        if ((err = mp_to_unsigned_bin(seedinc, sbuf + seedbytes-i)) != CRYPT_OK) { goto cleanup; }
        i = outbytes;
        err = hash_memory(hash, sbuf, seedbytes, wbuf+(n-j)*outbytes, &i);
        if (err != CRYPT_OK)                                                     { goto cleanup; }
      }
      if ((err = mp_read_unsigned_bin(W, wbuf, (n+1)*outbytes)) != CRYPT_OK)     { goto cleanup; }
      if ((err = mp_mod(W, t2L1, W)) != CRYPT_OK)                                { goto cleanup; }
      if ((err = mp_add(W, t2L1, X)) != CRYPT_OK)                                { goto cleanup; }
      if ((err = mp_mod(X, t2q, c))  != CRYPT_OK)                                { goto cleanup; }
      if ((err = mp_sub_d(c, 1, p))  != CRYPT_OK)                                { goto cleanup; }
      if ((err = mp_sub(X, p, p))    != CRYPT_OK)                                { goto cleanup; }
      if (mp_cmp(p, t2L1) != LTC_MP_LT) {
        /* p >= 2^(L-1) */
        if ((err = mp_prime_is_prime(p, mr_tests_p, &res)) != CRYPT_OK)          { goto cleanup; }
        if (res == LTC_MP_YES) {
          found_p = 1;
        }
      }
    }
  }

 /* FIPS-186-4 A.2.1 Unverifiable Generation of the Generator g
  * 1. e = (p - 1)/q
  * 2. h = any integer satisfying: 1 < h < (p - 1)
  *    h could be obtained from a random number generator or from a counter that changes after each use
  * 3. g = h^e mod p
  * 4. if (g == 1), then go to step 2.
  *
  */

  if ((err = mp_sub_d(p, 1, e)) != CRYPT_OK)                                     { goto cleanup; }
  if ((err = mp_div(e, q, e, c)) != CRYPT_OK)                                    { goto cleanup; }
  /* e = (p - 1)/q */
  i = mp_count_bits(p);
  do {
    do {
      if ((err = rand_bn_bits(h, i, prng, wprng)) != CRYPT_OK)                   { goto cleanup; }
    } while (mp_cmp(h, p) != LTC_MP_LT || mp_cmp_d(h, 2) != LTC_MP_GT);
    if ((err = mp_sub_d(h, 1, h)) != CRYPT_OK)                                   { goto cleanup; }
    /* h is randon and 1 < h < (p-1) */
    if ((err = mp_exptmod(h, e, p, g)) != CRYPT_OK)                              { goto cleanup; }
  } while (mp_cmp_d(g, 1) == LTC_MP_EQ);

  err = CRYPT_OK;
cleanup:
  mp_clear_multi(t2L1, t2N1, t2q, t2seedlen, U, W, X, c, h, e, seedinc, NULL);
cleanup1:
  XFREE(sbuf);
cleanup2:
  XFREE(wbuf);
cleanup3:
  return err;
}
Пример #26
0
static int _set_test(void)
{
   dh_key k1, k2, k3;
   unsigned char buf[4096];
   unsigned long len;
   int i;
   unsigned char gbin[] = { 0x02 };
   unsigned char pbin[] = {
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
   };
   unsigned char xbin[] = {
      0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE, 0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C,
      0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98, 0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F,
      0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1
   };
   unsigned char ybin[] = {
      0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA, 0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14,
      0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3, 0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07,
      0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8, 0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0,
      0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD, 0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40,
      0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7, 0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08,
      0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC, 0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0,
      0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80, 0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81,
      0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B, 0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7,
      0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5, 0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1,
      0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E, 0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97,
      0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64, 0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53,
      0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36, 0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41,
      0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32, 0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99,
      0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6, 0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9,
      0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A, 0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B,
      0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C, 0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C
   };

   struct {
     int radix;
     void* g; int glen;
     void* p; int plen;
     void* x; int xlen;
     void* y; int ylen;
   } test[1] = {
      { 256, gbin, sizeof(gbin),   pbin, sizeof(pbin),   xbin, sizeof(xbin),   ybin, sizeof(ybin)   }
   };

   unsigned char export_private[] = {
      0x30, 0x82, 0x01, 0x3A, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x80, 0x02, 0x82, 0x01, 0x01, 0x00,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0x02, 0x01, 0x02, 0x02, 0x29, 0x00, 0xA6, 0x68, 0x1A, 0xDC, 0x38, 0x6C, 0xE9, 0x44, 0xC3, 0xDE,
      0xD9, 0xA7, 0x30, 0x1D, 0xCC, 0x9C, 0x51, 0x82, 0x50, 0xE3, 0xED, 0xB6, 0x2F, 0x95, 0x91, 0x98,
      0xF8, 0xDC, 0x00, 0x57, 0xDD, 0x6F, 0xB5, 0x7A, 0xBA, 0xFD, 0x78, 0x81, 0x98, 0xB1
   };
   unsigned char export_public[] = {
      0x30, 0x82, 0x02, 0x13, 0x02, 0x01, 0x00, 0x03, 0x02, 0x07, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
      0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
      0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
      0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
      0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
      0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
      0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
      0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
      0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
      0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
      0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
      0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
      0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0x02, 0x01, 0x02, 0x02, 0x82, 0x01, 0x00, 0x39, 0x04, 0x66, 0x32, 0xC8, 0x34, 0x41, 0x8D, 0xFA,
      0x07, 0xB3, 0x09, 0x15, 0x38, 0xB6, 0x14, 0xD1, 0xFB, 0x5D, 0xBB, 0x78, 0x5C, 0x0F, 0xBE, 0xA3,
      0xB9, 0x8B, 0x29, 0x5B, 0xC0, 0xCD, 0x07, 0x6A, 0x88, 0xD9, 0x45, 0x21, 0x41, 0xA2, 0x69, 0xE8,
      0xBA, 0xEB, 0x1D, 0xD6, 0x54, 0xEB, 0xA0, 0x3A, 0x57, 0x05, 0x31, 0x8D, 0x12, 0x97, 0x54, 0xCD,
      0xF4, 0x00, 0x3A, 0x8C, 0x39, 0x92, 0x40, 0xFB, 0xB8, 0xF1, 0x62, 0x49, 0x0F, 0x6F, 0x0D, 0xC7,
      0x0E, 0x41, 0x4B, 0x6F, 0xEE, 0x88, 0x08, 0x6A, 0xFA, 0xA4, 0x8E, 0x9F, 0x3A, 0x24, 0x8E, 0xDC,
      0x09, 0x34, 0x52, 0x66, 0x3D, 0x34, 0xE0, 0xE8, 0x09, 0xD4, 0xF6, 0xBA, 0xDB, 0xB3, 0x6F, 0x80,
      0xB6, 0x81, 0x3E, 0xBF, 0x7C, 0x32, 0x81, 0xB8, 0x62, 0x20, 0x9E, 0x56, 0x04, 0xBD, 0xEA, 0x8B,
      0x8F, 0x5F, 0x7B, 0xFD, 0xC3, 0xEE, 0xB7, 0xAD, 0xB7, 0x30, 0x48, 0x28, 0x9B, 0xCE, 0xA0, 0xF5,
      0xA5, 0xCD, 0xEE, 0x7D, 0xF9, 0x1C, 0xD1, 0xF0, 0xBA, 0x63, 0x2F, 0x06, 0xDB, 0xE9, 0xBA, 0x7E,
      0xF0, 0x14, 0xB8, 0x4B, 0x02, 0xD4, 0x97, 0xCA, 0x7D, 0x0C, 0x60, 0xF7, 0x34, 0x75, 0x2A, 0x64,
      0x9D, 0xA4, 0x96, 0x94, 0x6B, 0x4E, 0x53, 0x1B, 0x30, 0xD9, 0xF8, 0x2E, 0xDD, 0x85, 0x56, 0x36,
      0xC0, 0xB0, 0xF2, 0xAE, 0x23, 0x2E, 0x41, 0x86, 0x45, 0x4E, 0x88, 0x87, 0xBB, 0x42, 0x3E, 0x32,
      0xA5, 0xA2, 0x49, 0x5E, 0xAC, 0xBA, 0x99, 0x62, 0x0A, 0xCD, 0x03, 0xA3, 0x83, 0x45, 0xEB, 0xB6,
      0x73, 0x5E, 0x62, 0x33, 0x0A, 0x8E, 0xE9, 0xAA, 0x6C, 0x83, 0x70, 0x41, 0x0F, 0x5C, 0xD4, 0x5A,
      0xF3, 0x7E, 0xE9, 0x0A, 0x0D, 0xA9, 0x5B, 0xE9, 0x6F, 0xC9, 0x39, 0xE8, 0x8F, 0xE0, 0xBD, 0x2C,
      0xD0, 0x9F, 0xC8, 0xF5, 0x24, 0x20, 0x8C
   };

   for (i = 0; i < 1; i++) {
      DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k1));
      DO(dh_set_key(test[i].x, test[i].xlen, PK_PRIVATE, &k1));

      len = sizeof(buf);
      DO(dh_export(buf, &len, PK_PRIVATE, &k1));
      if (compare_testvector(buf, len, export_private, sizeof(export_private), "radix_test", i*10 + 0)) {
         printf("radix_test: dh_export+PK_PRIVATE mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      len = sizeof(buf);
      DO(dh_export(buf, &len, PK_PUBLIC, &k1));
      if (compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test", i*10 + 1)) {
         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      len = sizeof(buf);
      DO(dh_export_key(buf, &len, PK_PRIVATE, &k1));
      if (compare_testvector(buf, len, xbin, sizeof(xbin), "radix_test", i*10 + 2)) {
         printf("radix_test: dh_export+PK_PRIVATE mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      len = sizeof(buf);
      DO(dh_export_key(buf, &len, PK_PUBLIC, &k1));
      if (compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test", i*10 + 3)) {
         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      dh_free(&k1);

      DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k1));
      DO(dh_set_key(test[i].x, test[i].xlen, PK_PRIVATE, &k1));

      len = sizeof(buf);
      DO(dh_export(buf, &len, PK_PRIVATE, &k1));
      if (compare_testvector(buf, len, export_private, sizeof(export_private), "radix_test", i*10 + 4)) {
         printf("radix_test: dh_export+PK_PRIVATE mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      len = sizeof(buf);
      DO(dh_export(buf, &len, PK_PUBLIC, &k1));
      if (compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test", i*10 + 5)) {
         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
         dh_free(&k1);
         return CRYPT_ERROR;
      }
      dh_free(&k1);

      DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k2));
      DO(dh_set_key(test[i].y, test[i].ylen, PK_PUBLIC, &k2));

      len = sizeof(buf);
      DO(dh_export(buf, &len, PK_PUBLIC, &k2));
      if (compare_testvector(buf, len, export_public, sizeof(export_public), "radix_test", i*10 + 6)) {
         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
         dh_free(&k2);
         return CRYPT_ERROR;
      }
      len = sizeof(buf);
      DO(dh_export_key(buf, &len, PK_PUBLIC, &k2));
      if (compare_testvector(buf, len, ybin, sizeof(ybin), "radix_test", i*10 + 7)) {
         printf("radix_test: dh_export+PK_PUBLIC mismatch\n");
         dh_free(&k2);
         return CRYPT_ERROR;
      }
      dh_free(&k2);

      DO(dh_set_pg(test[i].p, test[i].plen, test[i].g, test[i].glen, &k3));
      DO(dh_generate_key(&yarrow_prng, find_prng("yarrow"), &k3));

      len = mp_unsigned_bin_size(k3.prime);
      DO(mp_to_unsigned_bin(k3.prime, buf));
      if (compare_testvector(buf, len, pbin, sizeof(pbin), "radix_test", i*10 + 8)) {
         printf("radix_test: dh_make_key_ex prime mismatch\n");
         dh_free(&k3);
         return CRYPT_ERROR;
      }
      len = mp_unsigned_bin_size(k3.base);
      DO(mp_to_unsigned_bin(k3.base, buf));
      if (compare_testvector(buf, len, gbin, sizeof(gbin), "radix_test", i*10 + 9)) {
         printf("radix_test: dh_make_key_ex base mismatch\n");
         dh_free(&k3);
         return CRYPT_ERROR;
      }
      dh_free(&k3);
   }

   return CRYPT_OK;
}
Пример #27
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;
}
Пример #28
0
/* store */
static int unsigned_write(void *a, unsigned char *b)
{
   LTC_ARGCHK(a != NULL);
   LTC_ARGCHK(b != NULL);
   return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
}
Пример #29
0
static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
                       int type, RsaKey* key)
{
    #define ERROR_OUT(x) { ret = x; goto done;}

    mp_int tmp;
    int    ret = 0;
    word32 keyLen, len;

    if (mp_init(&tmp) != MP_OKAY)
        return MP_INIT_E;

    if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
        ERROR_OUT(MP_READ_E);

    if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
        #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
            if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
                ERROR_OUT(MP_EXPTMOD_E);
        #else
            #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }

            mp_int tmpa, tmpb;

            if (mp_init(&tmpa) != MP_OKAY)
                ERROR_OUT(MP_INIT_E);

            if (mp_init(&tmpb) != MP_OKAY) {
                mp_clear(&tmpa);
                ERROR_OUT(MP_INIT_E);
            }

            /* tmpa = tmp^dP mod p */
            if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
                INNER_ERROR_OUT(MP_EXPTMOD_E);

            /* tmpb = tmp^dQ mod q */
            if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
                INNER_ERROR_OUT(MP_EXPTMOD_E);

            /* tmp = (tmpa - tmpb) * qInv (mod p) */
            if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_SUB_E);

            if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_MULMOD_E);

            /* tmp = tmpb + q * tmp */
            if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_MUL_E);

            if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
                INNER_ERROR_OUT(MP_ADD_E);

        inner_done:
            mp_clear(&tmpa);
            mp_clear(&tmpb);

            if (ret != 0) return ret;

        #endif   /* RSA_LOW_MEM */
    }
    else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
        if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
            ERROR_OUT(MP_EXPTMOD_E);
    }
    else
        ERROR_OUT(RSA_WRONG_TYPE_E);

    keyLen = mp_unsigned_bin_size(&key->n);
    if (keyLen > *outLen)
        ERROR_OUT(RSA_BUFFER_E);

    len = mp_unsigned_bin_size(&tmp);

    /* pad front w/ zeros to match key length */
    while (len < keyLen) {
        *out++ = 0x00;
        len++;
    }

    *outLen = keyLen;

    /* convert */
    if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
        ERROR_OUT(MP_TO_E);
   
done: 
    mp_clear(&tmp);
    return ret;
}
Пример #30
0
static int _dhparam_test(void)
{
   dh_key k;
   unsigned char buf[1024];
   /* generated by: openssl dhparam -outform der -out dhparam.der 2048 */
   unsigned char dhparam_der[] = {
      0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7,
      0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95, 0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0,
      0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f, 0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43,
      0x55, 0x08, 0xb4, 0x20, 0x60, 0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7,
      0x00, 0x44, 0xc2, 0x5e, 0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c,
      0xac, 0x64, 0x13, 0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91,
      0xa4, 0x6e, 0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1,
      0xdb, 0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0,
      0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65, 0x99,
      0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52, 0x4c, 0xd4,
      0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06, 0xd2, 0x0f, 0x2d,
      0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa, 0x67, 0x26, 0xe2, 0x89,
      0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc, 0x70, 0x7e, 0x4f, 0x0e, 0xd3,
      0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b, 0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23,
      0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e, 0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d,
      0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71, 0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86,
      0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1, 0x98, 0xcb, 0x02, 0x01, 0x02
   };
   /* text dump: openssl dh -inform DER -in dhparam.der -text
      DH Parameters: (2048 bit)
          prime:
              00:ae:fe:78:ce:80:d5:d7:8e:cc:4f:0c:1b:b0:95:
              10:e1:41:15:53:4d:0e:68:b0:f8:5a:41:0e:65:2f:
              9f:ac:9c:30:b0:76:ec:02:e9:43:55:08:b4:20:60:
              d9:52:da:2d:ab:9a:ba:e6:cf:11:a7:00:44:c2:5e:
              d1:ba:9b:aa:fe:03:dd:dc:ef:41:89:9c:ac:64:13:
              d9:6a:8a:55:a0:5b:ff:12:92:37:52:6a:91:a4:6e:
              9e:61:b7:fe:b0:17:8e:67:0f:88:46:a7:9e:b1:db:
              68:77:70:b5:77:f2:7e:33:b1:3e:10:c4:63:36:d0:
              13:27:d3:29:c3:b6:5d:f6:5d:a7:d8:25:5c:0b:65:
              99:fa:f9:5f:1d:ee:d1:86:64:7c:44:cb:a0:12:52:
              4c:d4:46:81:ae:07:db:c7:13:29:ce:9b:cf:1c:06:
              d2:0f:2d:bb:12:33:b9:b1:0f:67:5d:3f:0c:e4:fa:
              67:26:e2:89:a2:d5:66:29:1c:e2:8e:bb:7b:cb:cc:
              70:7e:4f:0e:d3:5d:64:64:1b:27:bb:da:a9:08:2b:
              62:d4:ca:c3:3a:23:39:58:57:af:7b:8b:0c:5b:2e:
              fc:42:57:59:39:2e:6d:39:97:db:5b:5c:b9:59:71:
              42:f3:cd:ea:da:86:54:86:61:8d:93:66:c7:65:d1:
              98:cb
          generator: 2 (0x2)
   */
   unsigned char prime[] = {
            0xae, 0xfe, 0x78, 0xce, 0x80, 0xd5, 0xd7, 0x8e, 0xcc, 0x4f, 0x0c, 0x1b, 0xb0, 0x95,
      0x10, 0xe1, 0x41, 0x15, 0x53, 0x4d, 0x0e, 0x68, 0xb0, 0xf8, 0x5a, 0x41, 0x0e, 0x65, 0x2f,
      0x9f, 0xac, 0x9c, 0x30, 0xb0, 0x76, 0xec, 0x02, 0xe9, 0x43, 0x55, 0x08, 0xb4, 0x20, 0x60,
      0xd9, 0x52, 0xda, 0x2d, 0xab, 0x9a, 0xba, 0xe6, 0xcf, 0x11, 0xa7, 0x00, 0x44, 0xc2, 0x5e,
      0xd1, 0xba, 0x9b, 0xaa, 0xfe, 0x03, 0xdd, 0xdc, 0xef, 0x41, 0x89, 0x9c, 0xac, 0x64, 0x13,
      0xd9, 0x6a, 0x8a, 0x55, 0xa0, 0x5b, 0xff, 0x12, 0x92, 0x37, 0x52, 0x6a, 0x91, 0xa4, 0x6e,
      0x9e, 0x61, 0xb7, 0xfe, 0xb0, 0x17, 0x8e, 0x67, 0x0f, 0x88, 0x46, 0xa7, 0x9e, 0xb1, 0xdb,
      0x68, 0x77, 0x70, 0xb5, 0x77, 0xf2, 0x7e, 0x33, 0xb1, 0x3e, 0x10, 0xc4, 0x63, 0x36, 0xd0,
      0x13, 0x27, 0xd3, 0x29, 0xc3, 0xb6, 0x5d, 0xf6, 0x5d, 0xa7, 0xd8, 0x25, 0x5c, 0x0b, 0x65,
      0x99, 0xfa, 0xf9, 0x5f, 0x1d, 0xee, 0xd1, 0x86, 0x64, 0x7c, 0x44, 0xcb, 0xa0, 0x12, 0x52,
      0x4c, 0xd4, 0x46, 0x81, 0xae, 0x07, 0xdb, 0xc7, 0x13, 0x29, 0xce, 0x9b, 0xcf, 0x1c, 0x06,
      0xd2, 0x0f, 0x2d, 0xbb, 0x12, 0x33, 0xb9, 0xb1, 0x0f, 0x67, 0x5d, 0x3f, 0x0c, 0xe4, 0xfa,
      0x67, 0x26, 0xe2, 0x89, 0xa2, 0xd5, 0x66, 0x29, 0x1c, 0xe2, 0x8e, 0xbb, 0x7b, 0xcb, 0xcc,
      0x70, 0x7e, 0x4f, 0x0e, 0xd3, 0x5d, 0x64, 0x64, 0x1b, 0x27, 0xbb, 0xda, 0xa9, 0x08, 0x2b,
      0x62, 0xd4, 0xca, 0xc3, 0x3a, 0x23, 0x39, 0x58, 0x57, 0xaf, 0x7b, 0x8b, 0x0c, 0x5b, 0x2e,
      0xfc, 0x42, 0x57, 0x59, 0x39, 0x2e, 0x6d, 0x39, 0x97, 0xdb, 0x5b, 0x5c, 0xb9, 0x59, 0x71,
      0x42, 0xf3, 0xcd, 0xea, 0xda, 0x86, 0x54, 0x86, 0x61, 0x8d, 0x93, 0x66, 0xc7, 0x65, 0xd1,
      0x98, 0xcb
   };

   DO(dh_set_pg_dhparam(dhparam_der, sizeof(dhparam_der), &k));
   DO(dh_generate_key(&yarrow_prng, find_prng ("yarrow"), &k));
   if (mp_unsigned_bin_size(k.prime) > sizeof(buf)) {
      printf("dhparam_test: short buf\n");
      dh_free(&k);
      return CRYPT_ERROR;
   }
   DO(mp_to_unsigned_bin(k.prime, buf));
   if (compare_testvector(buf, sizeof(prime), prime, sizeof(prime), "dhparam_test", 1)) {
      printf("dhparam_test: prime mismatch\n");
      dh_free(&k);
      return CRYPT_ERROR;
   }
   if (mp_cmp_d(k.base, 2) != LTC_MP_EQ) {
      printf("dhparam_test: base mismatch\n");
      dh_free(&k);
      return CRYPT_ERROR;
   }
   dh_free(&k);
   return CRYPT_OK;
}