Beispiel #1
0
/**
 * \brief Finalization function of measure function
 *        measure_MPI_IO_write_file_once().
 *
 * Only one process is active. It writes once to a file.
 *
 * Remark:<br>
 * With the <tt>O_DIRECT</tt> flag set, cache effects are minimized, because I/O
 * is done directly to/from user space buffers. The operation system's page
 * cache is bypassed. Under Linux 2.6 alignment to 512-byte boundaries is
 * required for buffer and file offset. Thus the following parameters should be
 * set in a SKaMPI input file:
 * - <tt>set_send_buffert_alignment (512)</tt>
 * - <tt>set_recv_buffert_alignment (512)</tt>
 * - <tt>switch_buffer_cycling_off ()</tt><br>
 *
 * <tt>O_DIRECT</tt> is only relevant if the POSIX-API is used for I/O.
 * 
 * For more information please refer to the <tt>open ()</tt> man pages.
 *
 * \param[in] size  size of memory buffer, i.e. number of <tt>MPI_BYTE</tt>s
 * \param[in] api   POSIX-API or MPI-API for I/O accesses
 * \param[in] create_flag write into existing file (FALSE) or create it (TRUE)
 * \param[in] directio_flag open file with <tt>O_DIRECT</tt> flag to minimize
 *                          cache effects
 *
 * \return    void
 */
void finalize_MPI_IO_write_file_once (int size, char *api, int create_flag, int directio_flag){
  MPI_File_delete (io_filename, MPI_INFO_NULL);
  mpi_free (io_filename);
}
Beispiel #2
0
/* Decode the EdDSA style encoded PK and set it into RESULT.  CTX is
   the usual curve context.  If R_ENCPK is not NULL, the encoded PK is
   stored at that address; this is a new copy to be released by the
   caller.  In contrast to the supplied PK, this is not an MPI and
   thus guaranteed to be properly padded.  R_ENCPKLEN receives the
   length of that encoded key.  */
gpg_err_code_t
_gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
                             unsigned char **r_encpk, unsigned int *r_encpklen)
{
  gpg_err_code_t rc;
  unsigned char *rawmpi;
  unsigned int rawmpilen;
  int sign;

  if (mpi_is_opaque (pk))
    {
      const unsigned char *buf;

      buf = mpi_get_opaque (pk, &rawmpilen);
      if (!buf)
        return GPG_ERR_INV_OBJ;
      rawmpilen = (rawmpilen + 7)/8;

      /* Handle compression prefixes.  The size of the buffer will be
         odd in this case.  */
      if (rawmpilen > 1 && (rawmpilen%2))
        {
          /* First check whether the public key has been given in
             standard uncompressed format (SEC1).  No need to recover
             x in this case.  */
          if (buf[0] == 0x04)
            {
              gcry_mpi_t x, y;

              rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_STD,
                                   buf+1, (rawmpilen-1)/2, NULL);
              if (rc)
                return rc;
              rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_STD,
                                   buf+1+(rawmpilen-1)/2, (rawmpilen-1)/2,NULL);
              if (rc)
                {
                  mpi_free (x);
                  return rc;
                }

              if (r_encpk)
                {
                  rc = eddsa_encode_x_y (x, y, ctx->nbits/8, 0,
                                         r_encpk, r_encpklen);
                  if (rc)
                    {
                      mpi_free (x);
                      mpi_free (y);
                      return rc;
                    }
                }
              mpi_snatch (result->x, x);
              mpi_snatch (result->y, y);
              mpi_set_ui (result->z, 1);
              return 0;
            }

          /* Check whether the public key has been prefixed with a 0x40
             byte to explicitly indicate compressed format using a SEC1
             alike prefix byte.  This is a Libgcrypt extension.  */
          if (buf[0] == 0x40)
            {
              rawmpilen--;
              buf++;
            }
        }

      /* EdDSA compressed point.  */
      rawmpi = xtrymalloc (rawmpilen? rawmpilen:1);
      if (!rawmpi)
        return gpg_err_code_from_syserror ();
      memcpy (rawmpi, buf, rawmpilen);
      reverse_buffer (rawmpi, rawmpilen);
    }
  else
    {
      /* Note: Without using an opaque MPI it is not reliable possible
         to find out whether the public key has been given in
         uncompressed format.  Thus we expect native EdDSA format.  */
      rawmpi = _gcry_mpi_get_buffer (pk, ctx->nbits/8, &rawmpilen, NULL);
      if (!rawmpi)
        return gpg_err_code_from_syserror ();
    }

  if (rawmpilen)
    {
      sign = !!(rawmpi[0] & 0x80);
      rawmpi[0] &= 0x7f;
    }
  else
    sign = 0;
  _gcry_mpi_set_buffer (result->y, rawmpi, rawmpilen, 0);
  if (r_encpk)
    {
      /* Revert to little endian.  */
      if (sign && rawmpilen)
        rawmpi[0] |= 0x80;
      reverse_buffer (rawmpi, rawmpilen);
      *r_encpk = rawmpi;
      if (r_encpklen)
        *r_encpklen = rawmpilen;
    }
  else
    xfree (rawmpi);

  rc = _gcry_ecc_eddsa_recover_x (result->x, result->y, sign, ctx);
  mpi_set_ui (result->z, 1);

  return rc;
}
/*
 * Generate an RSA keypair
 */
int rsa_gen_key( rsa_context *ctx, int nbits, int exponent )
{
    int ret;
    mpi P1, Q1, H, G;

    if( ctx->f_rng == NULL || nbits < 128 || exponent < 3 )
        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );

    mpi_init( &P1, &Q1, &H, &G, NULL );

    /*
     * find primes P and Q with Q < P so that:
     * GCD( E, (P-1)*(Q-1) ) == 1
     */
    MPI_CHK( mpi_lset( &ctx->E, exponent ) );

    do
    {
        MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0,
                                ctx->f_rng, ctx->p_rng ) );

        MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0,
                                ctx->f_rng, ctx->p_rng ) );

        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
            mpi_swap( &ctx->P, &ctx->Q );

        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
            continue;

        MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
        if( mpi_msb( &ctx->N ) != nbits )
            continue;

        MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
        MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
        MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
        MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );
    }
    while( mpi_cmp_int( &G, 1 ) != 0 );

    /*
     * D  = E^-1 mod ((P-1)*(Q-1))
     * DP = D mod (P - 1)
     * DQ = D mod (Q - 1)
     * QP = Q^-1 mod P
     */
    MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
    MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
    MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
    MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );

    ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3;

cleanup:

    mpi_free( &G, &H, &Q1, &P1, NULL );

    if( ret != 0 )
    {
        rsa_free( ctx );
        return( POLARSSL_ERR_RSA_KEY_GEN_FAILED | ret );
    }

    return( 0 );
}
Beispiel #4
0
/*
 * Check a private RSA key
 */
int rsa_check_privkey( const rsa_context *ctx )
{
    int ret;
    mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP;

    if( ( ret = rsa_check_pubkey( ctx ) ) != 0 )
        return( ret );

    if( !ctx->P.p || !ctx->Q.p || !ctx->D.p )
        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED );

    mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 );
    mpi_init( &H  ); mpi_init( &I  ); mpi_init( &G  ); mpi_init( &G2 );
    mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ );
    mpi_init( &QP );

    MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) );
    MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) );
    MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
    MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
    MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
    MPI_CHK( mpi_gcd( &G, &ctx->E, &H  ) );

    MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) );
    MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) );
    MPI_CHK( mpi_mod_mpi( &I, &DE, &L1  ) );

    MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) );
    MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) );
    MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) );
    /*
     * Check for a valid PKCS1v2 private key
     */
    if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 ||
        mpi_cmp_mpi( &DP, &ctx->DP ) != 0 ||
        mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 ||
        mpi_cmp_mpi( &QP, &ctx->QP ) != 0 ||
        mpi_cmp_int( &L2, 0 ) != 0 ||
        mpi_cmp_int( &I, 1 ) != 0 ||
        mpi_cmp_int( &G, 1 ) != 0 )
    {
        ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED;
    }

cleanup:
    mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 );
    mpi_free( &H  ); mpi_free( &I  ); mpi_free( &G  ); mpi_free( &G2 );
    mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ );
    mpi_free( &QP );

    if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED )
        return( ret );

    if( ret != 0 )
        return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret );

    return( 0 );
}
Beispiel #5
0
/*
 * Generate a deterministic secret exponent K less than DSA_Q.  H1 is
 * the to be signed digest with a length of HLEN bytes.  HALGO is the
 * algorithm used to create the hash.  On success the value for K is
 * stored at R_K.
 */
gpg_err_code_t
_gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                         gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
                         const unsigned char *h1, unsigned int hlen,
                         int halgo, unsigned int extraloops)
{
  gpg_err_code_t rc;
  unsigned char *V = NULL;
  unsigned char *K = NULL;
  unsigned char *x_buf = NULL;
  unsigned char *h1_buf = NULL;
  gcry_md_hd_t hd = NULL;
  unsigned char *t = NULL;
  gcry_mpi_t k = NULL;
  unsigned int tbits, qbits;
  int i;

  qbits = mpi_get_nbits (dsa_q);

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

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

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

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

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

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

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

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

  /* Step e:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

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

  /* Step g:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

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

 again:
  for (tbits = 0; tbits < qbits;)
    {
      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

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

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

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

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

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

      /* K = HMAC_K(V || 0x00) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      gcry_md_write (hd, "", 1);
      memcpy (K, gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

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

 leave:
  gcry_free (t);
  gcry_md_close (hd);
  gcry_free (h1_buf);
  gcry_free (x_buf);
  gcry_free (K);
  gcry_free (V);

  if (rc)
    mpi_free (k);
  else
    *r_k = k;
  return rc;
}
Beispiel #6
0
/****************
 * RES = (BASE[0] ^ EXP[0]) *  (BASE[1] ^ EXP[1]) * ... * mod M
 */
void
_gcry_mpi_mulpowm( gcry_mpi_t res, gcry_mpi_t *basearray, gcry_mpi_t *exparray, gcry_mpi_t m)
{
    int k;	/* number of elements */
    int t;	/* bit size of largest exponent */
    int i, j, idx;
    gcry_mpi_t *G;	/* table with precomputed values of size 2^k */
    gcry_mpi_t tmp;
#ifdef USE_BARRETT
    gcry_mpi_t barrett_y, barrett_r1, barrett_r2;
    int barrett_k;
#endif

    for(k=0; basearray[k]; k++ )
	;
    gcry_assert(k);
    for(t=0, i=0; (tmp=exparray[i]); i++ ) {
	/*log_mpidump("exp: ", tmp );*/
	j = mpi_get_nbits(tmp);
	if( j > t )
	    t = j;
    }
    /*log_mpidump("mod: ", m );*/
    gcry_assert (i==k);
    gcry_assert (t);
    gcry_assert (k < 10);

    G = xcalloc( (1<<k) , sizeof *G );
#ifdef USE_BARRETT
    barrett_y = init_barrett( m, &barrett_k, &barrett_r1, &barrett_r2 );
#endif
    /* and calculate */
    tmp =  mpi_alloc( mpi_get_nlimbs(m)+1 );
    mpi_set_ui( res, 1 );
    for(i = 1; i <= t; i++ ) {
	barrett_mulm(tmp, res, res, m, barrett_y, barrett_k,
				       barrett_r1, barrett_r2 );
	idx = build_index( exparray, k, i, t );
	gcry_assert (idx >= 0 && idx < (1<<k));
	if( !G[idx] ) {
	    if( !idx )
		 G[0] = mpi_alloc_set_ui( 1 );
	    else {
		for(j=0; j < k; j++ ) {
		    if( (idx & (1<<j) ) ) {
			if( !G[idx] )
			    G[idx] = mpi_copy( basearray[j] );
			else
			    barrett_mulm( G[idx], G[idx], basearray[j],
					       m, barrett_y, barrett_k, barrett_r1, barrett_r2	);
		    }
		}
		if( !G[idx] )
		    G[idx] = mpi_alloc(0);
	    }
	}
	barrett_mulm(res, tmp, G[idx], m, barrett_y, barrett_k, barrett_r1, barrett_r2	);
    }

    /* cleanup */
    mpi_free(tmp);
#ifdef USE_BARRETT
    mpi_free(barrett_y);
    mpi_free(barrett_r1);
    mpi_free(barrett_r2);
#endif
    for(i=0; i < (1<<k); i++ )
	mpi_free(G[i]);
    xfree(G);
}
Beispiel #7
0
int main()
{
	int ret = 0;

	size_t len = STR_LEN;
	char E[STR_LEN], D[STR_LEN], N[STR_LEN];

	uchar source[MSG_LEN];
	uchar encrypted[MSG_LEN], decrypted[MSG_LEN];		// Buffers

	public_key pub;
	private_key priv;

	MPI_CHK(rsa_generate_keys(65537, pub, priv, 1024));

	MPI_CHK(mpi_write_string(&pub.e, 10, E, &len));
	len = STR_LEN;

	MPI_CHK(mpi_write_string(&pub.n, 10, N, &len));
	len = STR_LEN;

	MPI_CHK(mpi_write_string(&priv.d, 10, D, &len));

	printf("e = %s\nd = %s\nn = %s\n", E, D, N);

	printf("Enter message to encrypt:\n");
	scanf("%[^\n]", source);

	len = strnlen((const char *)source, MSG_LEN) + 1;			// Length of string + zero-char

	try
	{
		MPI_CHK(rsa_encrypt_block(source, len, encrypted, MSG_LEN, pub));
		print_buffer("Encrypted", encrypted, MSG_LEN);

		MPI_CHK(rsa_decrypt_block(encrypted, MSG_LEN, decrypted, MSG_LEN, priv));
		print_buffer("Decrypted", decrypted, MSG_LEN);

		MPI_CHK(rsa_sign_block(source, len, encrypted, MSG_LEN, priv));
		print_buffer("Signature", encrypted, MSG_LEN);

		MPI_CHK(rsa_check_block(encrypted, MSG_LEN, decrypted, MSG_LEN, pub));
		print_buffer("Preimage", decrypted, MSG_LEN);

		source[0] = InvertBit(source[0], 2);
		printf("Corrupted:\n%s\n\n", source);

		MPI_CHK(rsa_sign_block(source, len, encrypted, MSG_LEN, priv));
		print_buffer("Signature of corrupted", encrypted, MSG_LEN);
	}
	catch (char *e)
	{
		printf("Error: %s\n", e);
	}

cleanup:
	mpi_free(&pub.e);
	mpi_free(&priv.d);
	mpi_free(&priv.n);

	return ret;
}
Beispiel #8
0
/* Helper to extract a point from key parameters.  If no parameter
   with NAME is found, the functions tries to find a non-encoded point
   by appending ".x", ".y" and ".z" to NAME.  ".z" is in this case
   optional and defaults to 1.  EC is the context which at this point
   may not be fully initialized. */
static gpg_err_code_t
point_from_keyparam (gcry_mpi_point_t *r_a,
                     gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
{
  gcry_err_code_t rc;
  gcry_sexp_t l1;
  gcry_mpi_point_t point;

  l1 = sexp_find_token (keyparam, name, 0);
  if (l1)
    {
      gcry_mpi_t a;

      a = sexp_nth_mpi (l1, 1, GCRYMPI_FMT_OPAQUE);
      sexp_release (l1);
      if (!a)
        return GPG_ERR_INV_OBJ;

      point = mpi_point_new (0);
      if (ec && ec->dialect == ECC_DIALECT_ED25519)
        rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
      else
        rc = _gcry_ecc_os2ec (point, a);
      mpi_free (a);
      if (rc)
        {
          mpi_point_release (point);
          return rc;
        }
    }
  else
    {
      char *tmpname;
      gcry_mpi_t x = NULL;
      gcry_mpi_t y = NULL;
      gcry_mpi_t z = NULL;

      tmpname = xtrymalloc (strlen (name) + 2 + 1);
      if (!tmpname)
        return gpg_err_code_from_syserror ();
      strcpy (stpcpy (tmpname, name), ".x");
      rc = mpi_from_keyparam (&x, keyparam, tmpname);
      if (rc)
        {
          xfree (tmpname);
          return rc;
        }
      strcpy (stpcpy (tmpname, name), ".y");
      rc = mpi_from_keyparam (&y, keyparam, tmpname);
      if (rc)
        {
          mpi_free (x);
          xfree (tmpname);
          return rc;
        }
      strcpy (stpcpy (tmpname, name), ".z");
      rc = mpi_from_keyparam (&z, keyparam, tmpname);
      if (rc)
        {
          mpi_free (y);
          mpi_free (x);
          xfree (tmpname);
          return rc;
        }
      if (!z)
        z = mpi_set_ui (NULL, 1);
      if (x && y)
        point = mpi_point_snatch_set (NULL, x, y, z);
      else
        {
          mpi_free (x);
          mpi_free (y);
          mpi_free (z);
          point = NULL;
        }
      xfree (tmpname);
    }

  if (point)
    *r_a = point;
  return 0;
}
Beispiel #9
0
/* This function creates a new context for elliptic curve operations.
   Either KEYPARAM or CURVENAME must be given.  If both are given and
   KEYPARAM has no curve parameter, CURVENAME is used to add missing
   parameters.  On success 0 is returned and the new context stored at
   R_CTX.  On error NULL is stored at R_CTX and an error code is
   returned.  The context needs to be released using
   gcry_ctx_release.  */
gpg_err_code_t
_gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
                  gcry_sexp_t keyparam, const char *curvename)
{
  gpg_err_code_t errc;
  gcry_ctx_t ctx = NULL;
  enum gcry_mpi_ec_models model = MPI_EC_WEIERSTRASS;
  enum ecc_dialects dialect = ECC_DIALECT_STANDARD;
  gcry_mpi_t p = NULL;
  gcry_mpi_t a = NULL;
  gcry_mpi_t b = NULL;
  gcry_mpi_point_t G = NULL;
  gcry_mpi_t n = NULL;
  gcry_mpi_point_t Q = NULL;
  gcry_mpi_t d = NULL;
  int flags = 0;
  gcry_sexp_t l1;

  *r_ctx = NULL;

  if (keyparam)
    {
      /* Parse an optional flags list.  */
      l1 = sexp_find_token (keyparam, "flags", 0);
      if (l1)
        {
          errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
          sexp_release (l1);
          l1 = NULL;
          if (errc)
            goto leave;
        }

      /* Check whether a curve name was given.  */
      l1 = sexp_find_token (keyparam, "curve", 5);

      /* If we don't have a curve name or if override parameters have
         explicitly been requested, parse them.  */
      if (!l1 || (flags & PUBKEY_FLAG_PARAM))
        {
          errc = mpi_from_keyparam (&p, keyparam, "p");
          if (errc)
            goto leave;
          errc = mpi_from_keyparam (&a, keyparam, "a");
          if (errc)
            goto leave;
          errc = mpi_from_keyparam (&b, keyparam, "b");
          if (errc)
            goto leave;
          errc = point_from_keyparam (&G, keyparam, "g", NULL);
          if (errc)
            goto leave;
          errc = mpi_from_keyparam (&n, keyparam, "n");
          if (errc)
            goto leave;
        }
    }
  else
    l1 = NULL; /* No curvename.  */

  /* Check whether a curve parameter is available and use that to fill
     in missing values.  If no curve parameter is available try an
     optional provided curvename.  If only the curvename has been
     given use that one. */
  if (l1 || curvename)
    {
      char *name;
      elliptic_curve_t *E;

      if (l1)
        {
          name = sexp_nth_string (l1, 1);
          sexp_release (l1);
          if (!name)
            {
              errc = GPG_ERR_INV_OBJ; /* Name missing or out of core. */
              goto leave;
            }
        }
      else
        name = NULL;

      E = xtrycalloc (1, sizeof *E);
      if (!E)
        {
          errc = gpg_err_code_from_syserror ();
          xfree (name);
          goto leave;
        }

      errc = _gcry_ecc_fill_in_curve (0, name? name : curvename, E, NULL);
      xfree (name);
      if (errc)
        {
          xfree (E);
          goto leave;
        }

      model = E->model;
      dialect = E->dialect;

      if (!p)
        {
          p = E->p;
          E->p = NULL;
        }
      if (!a)
        {
          a = E->a;
          E->a = NULL;
        }
      if (!b)
        {
          b = E->b;
          E->b = NULL;
        }
      if (!G)
        {
          G = mpi_point_snatch_set (NULL, E->G.x, E->G.y, E->G.z);
          E->G.x = NULL;
          E->G.y = NULL;
          E->G.z = NULL;
        }
      if (!n)
        {
          n = E->n;
          E->n = NULL;
        }
      _gcry_ecc_curve_free (E);
      xfree (E);
    }


  errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
  if (!errc)
    {
      mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);

      if (b)
        {
          mpi_free (ec->b);
          ec->b = b;
          b = NULL;
        }
      if (G)
        {
          ec->G = G;
          G = NULL;
        }
      if (n)
        {
          ec->n = n;
          n = NULL;
        }

      /* Now that we know the curve name we can look for the public key
         Q.  point_from_keyparam needs to know the curve parameters so
         that it is able to use the correct decompression.  Parsing
         the private key D could have been done earlier but it is less
         surprising if we do it here as well.  */
      if (keyparam)
        {
          errc = point_from_keyparam (&Q, keyparam, "q", ec);
          if (errc)
            goto leave;
          errc = mpi_from_keyparam (&d, keyparam, "d");
          if (errc)
            goto leave;
        }

      if (Q)
        {
          ec->Q = Q;
          Q = NULL;
        }
      if (d)
        {
          ec->d = d;
          d = NULL;
        }

      *r_ctx = ctx;
      ctx = NULL;
    }

 leave:
  _gcry_ctx_release (ctx);
  mpi_free (p);
  mpi_free (a);
  mpi_free (b);
  _gcry_mpi_point_release (G);
  mpi_free (n);
  _gcry_mpi_point_release (Q);
  mpi_free (d);
  return errc;
}
Beispiel #10
0
/****************
 * Generate a random secret exponent k from prime p, so that k is
 * relatively prime to p-1.  With SMALL_K set, k will be selected for
 * better encryption performance - this must never be used signing!
 */
static gcry_mpi_t
gen_k( gcry_mpi_t p, int small_k )
{
  gcry_mpi_t k = mpi_alloc_secure( 0 );
  gcry_mpi_t temp = mpi_alloc( mpi_get_nlimbs(p) );
  gcry_mpi_t p_1 = mpi_copy(p);
  unsigned int orig_nbits = mpi_get_nbits(p);
  unsigned int nbits, nbytes;
  char *rndbuf = NULL;

  if (small_k)
    {
      /* Using a k much lesser than p is sufficient for encryption and
       * it greatly improves the encryption performance.  We use
       * Wiener's table and add a large safety margin. */
      nbits = wiener_map( orig_nbits ) * 3 / 2;
      if( nbits >= orig_nbits )
        BUG();
    }
  else
    nbits = orig_nbits;


  nbytes = (nbits+7)/8;
  if( DBG_CIPHER )
    log_debug("choosing a random k ");
  mpi_sub_ui( p_1, p, 1);
  for(;;)
    {
      if( !rndbuf || nbits < 32 )
        {
          gcry_free(rndbuf);
          rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM );
        }
      else
        {
          /* Change only some of the higher bits.  We could improve
             this by directly requesting more memory at the first call
             to get_random_bytes() and use this the here maybe it is
             easier to do this directly in random.c Anyway, it is
             highly inlikely that we will ever reach this code. */
          char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM );
          memcpy( rndbuf, pp, 4 );
          gcry_free(pp);
	}
      _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 );

      for(;;)
        {
          if( !(mpi_cmp( k, p_1 ) < 0) )  /* check: k < (p-1) */
            {
              if( DBG_CIPHER )
                progress('+');
              break; /* no  */
            }
          if( !(mpi_cmp_ui( k, 0 ) > 0) )  /* check: k > 0 */
            {
              if( DBG_CIPHER )
                progress('-');
              break; /* no */
            }
          if (gcry_mpi_gcd( temp, k, p_1 ))
            goto found;  /* okay, k is relative prime to (p-1) */
          mpi_add_ui( k, k, 1 );
          if( DBG_CIPHER )
            progress('.');
	}
    }
 found:
  gcry_free(rndbuf);
  if( DBG_CIPHER )
    progress('\n');
  mpi_free(p_1);
  mpi_free(temp);

  return k;
}
Beispiel #11
0
/* Return the name matching the parameters in PKEY.  This works only
   with curves described by the Weierstrass equation. */
const char *
_gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits)
{
  gpg_err_code_t rc;
  const char *result = NULL;
  elliptic_curve_t E;
  gcry_mpi_t mpi_g = NULL;
  gcry_mpi_t tmp = NULL;
  int idx;

  memset (&E, 0, sizeof E);

  if (r_nbits)
    *r_nbits = 0;

  if (!keyparms)
    {
      idx = iterator;
      if (idx >= 0 && idx < DIM (domain_parms))
        {
          result = domain_parms[idx].desc;
          if (r_nbits)
            *r_nbits = domain_parms[idx].nbits;
        }
      return result;
    }


  /*
   * Extract the curve parameters..
   */
  rc = gpg_err_code (sexp_extract_param (keyparms, NULL, "-pabgn",
                                         &E.p, &E.a, &E.b, &mpi_g, &E.n,
                                         NULL));
  if (rc == GPG_ERR_NO_OBJ)
    {
      /* This might be the second use case of checking whether a
         specific curve given by name is supported.  */
      gcry_sexp_t l1;
      char *name;

      l1 = sexp_find_token (keyparms, "curve", 5);
      if (!l1)
        goto leave;  /* No curve name parameter.  */

      name = sexp_nth_string (l1, 1);
      sexp_release (l1);
      if (!name)
        goto leave;  /* Name missing or out of core. */

      idx = find_domain_parms_idx (name);
      xfree (name);
      if (idx >= 0)  /* Curve found.  */
        {
          result = domain_parms[idx].desc;
          if (r_nbits)
            *r_nbits = domain_parms[idx].nbits;
        }
      return result;
    }

  if (rc)
    goto leave;

  if (mpi_g)
    {
      _gcry_mpi_point_init (&E.G);
      if (_gcry_ecc_os2ec (&E.G, mpi_g))
        goto leave;
    }

  for (idx = 0; domain_parms[idx].desc; idx++)
    {
      mpi_free (tmp);
      tmp = scanval (domain_parms[idx].p);
      if (!mpi_cmp (tmp, E.p))
        {
          mpi_free (tmp);
          tmp = scanval (domain_parms[idx].a);
          if (!mpi_cmp (tmp, E.a))
            {
              mpi_free (tmp);
              tmp = scanval (domain_parms[idx].b);
              if (!mpi_cmp (tmp, E.b))
                {
                  mpi_free (tmp);
                  tmp = scanval (domain_parms[idx].n);
                  if (!mpi_cmp (tmp, E.n))
                    {
                      mpi_free (tmp);
                      tmp = scanval (domain_parms[idx].g_x);
                      if (!mpi_cmp (tmp, E.G.x))
                        {
                          mpi_free (tmp);
                          tmp = scanval (domain_parms[idx].g_y);
                          if (!mpi_cmp (tmp, E.G.y))
                            {
                              result = domain_parms[idx].desc;
                              if (r_nbits)
                                *r_nbits = domain_parms[idx].nbits;
                              goto leave;
                            }
                        }
                    }
                }
            }
        }
    }

 leave:
  _gcry_mpi_release (tmp);
  _gcry_mpi_release (E.p);
  _gcry_mpi_release (E.a);
  _gcry_mpi_release (E.b);
  _gcry_mpi_release (mpi_g);
  _gcry_mpi_point_free_parts (&E.G);
  _gcry_mpi_release (E.n);
  return result;
}
Beispiel #12
0
result_t X509Req::sign(const char *issuer, PKey_base *key,
                       v8::Local<v8::Object> opts, obj_ptr<X509Cert_base> &retVal,
                       exlib::AsyncEvent *ac)
{
    result_t hr;
    bool priv;

    hr = key->isPrivate(priv);
    if (hr < 0)
        return hr;

    if (!priv)
        return CHECK_ERROR(CALL_E_INVALIDARG);

    int ret;
    std::string subject;
    pk_context *pk;
    int32_t hash;
    std::string buf;
    obj_ptr<X509Cert> cert;

    if (!ac)
    {
        mpi serial;
        v8::Local<v8::Value> v;

        x509write_crt_init(&m_crt);

        hr = GetConfigValue(opts, "hash", hash);
        if (hr == CALL_E_PARAMNOTOPTIONAL)
            hash = m_csr.sig_md;
        else if (hr < 0)
            goto exit;

        if (hash < POLARSSL_MD_MD2 || hash > POLARSSL_MD_RIPEMD160)
        {
            hr = CALL_E_INVALIDARG;
            goto exit;
        }

        x509write_crt_set_md_alg(&m_crt, POLARSSL_MD_SHA1);

        v = opts->Get(v8::String::NewFromUtf8(isolate, "serial",
                                              v8::String::kNormalString, 6));
        if (!IsEmpty(v))
        {
            v8::String::Utf8Value str(v);

            if (!*str)
            {
                hr = CHECK_ERROR(_ssl::setError(POLARSSL_ERR_MPI_BAD_INPUT_DATA));
                goto exit;
            }

            mpi_init(&serial);
            ret = mpi_read_string(&serial, 10, *str);
            if (ret != 0)
            {
                mpi_free(&serial);
                hr = CHECK_ERROR(_ssl::setError(ret));
                goto exit;
            }
        }
        else
        {
            mpi_init(&serial);
            mpi_lset(&serial, 1);
        }

        ret = x509write_crt_set_serial(&m_crt, &serial);
        if (ret != 0)
        {
            mpi_free(&serial);
            hr = CHECK_ERROR(_ssl::setError(ret));
            goto exit;
        }

        mpi_free(&serial);

        date_t d1, d2;
        std::string s1, s2;

        hr = GetConfigValue(opts, "notBefore", d1);
        if (hr == CALL_E_PARAMNOTOPTIONAL)
            d1.now();
        else if (hr < 0)
            goto exit;
        d1.toX509String(s1);


        hr = GetConfigValue(opts, "notAfter", d2);
        if (hr == CALL_E_PARAMNOTOPTIONAL)
        {
            d2 = d1;
            d2.add(1, date_t::_YEAR);
        }
        else if (hr < 0)
            goto exit;
        d2.toX509String(s2);

        ret = x509write_crt_set_validity(&m_crt, s1.c_str(), s2.c_str());
        if (ret != 0)
        {
            hr = CHECK_ERROR(_ssl::setError(ret));
            goto exit;
        }

        bool is_ca = false;
        hr = GetConfigValue(opts, "ca", is_ca);
        if (hr < 0 && hr != CALL_E_PARAMNOTOPTIONAL)
            goto exit;

        int32_t pathlen = -1;
        hr = GetConfigValue(opts, "pathlen", pathlen);
        if (hr < 0 && hr != CALL_E_PARAMNOTOPTIONAL)
            goto exit;

        if (pathlen < -1 || pathlen > 127)
        {
            hr = CALL_E_INVALIDARG;
            goto exit;
        }

        ret = x509write_crt_set_basic_constraints(&m_crt, is_ca ? 1 : 0, pathlen);
        if (ret != 0)
        {
            hr = CHECK_ERROR(_ssl::setError(ret));
            goto exit;
        }

        int key_usage = parseString(opts->Get(v8::String::NewFromUtf8(isolate, "usage",
                                              v8::String::kNormalString, 5)), X509Cert::g_usages);
        if (key_usage < 0)
        {
            hr = key_usage;
            goto exit;
        }
        else if (key_usage)
        {
            ret = x509write_crt_set_key_usage(&m_crt, key_usage);
            if (ret != 0)
            {
                hr = CHECK_ERROR(_ssl::setError(ret));
                goto exit;
            }
        }

        int cert_type = parseString(opts->Get(v8::String::NewFromUtf8(isolate, "type",
                                              v8::String::kNormalString, 4)), X509Cert::g_types);
        if (cert_type < 0)
        {
            hr = cert_type;
            goto exit;
        }
        else if (cert_type)
        {
            ret = x509write_crt_set_ns_cert_type(&m_crt, cert_type);
            if (ret != 0)
            {
                hr = CHECK_ERROR(_ssl::setError(ret));
                goto exit;
            }
        }

        return CHECK_ERROR(CALL_E_NOSYNC);
    }

    pk = &((PKey *)key)->m_key;

    x509write_crt_set_subject_key(&m_crt, &m_csr.pk);
    x509write_crt_set_issuer_key(&m_crt, pk);

    hr = X509Req::get_subject(subject);
    if (hr < 0)
        goto exit;

    ret = x509write_crt_set_subject_name(&m_crt, subject.c_str());
    if (ret != 0)
    {
        hr = CHECK_ERROR(_ssl::setError(ret));
        goto exit;
    }

    ret = x509write_crt_set_issuer_name(&m_crt, issuer);
    if (ret != 0)
    {
        hr = CHECK_ERROR(_ssl::setError(ret));
        goto exit;
    }

    ret = x509write_crt_set_subject_key_identifier(&m_crt);
    if (ret != 0)
    {
        hr = CHECK_ERROR(_ssl::setError(ret));
        goto exit;
    }

    ret = x509write_crt_set_authority_key_identifier(&m_crt);
    if (ret != 0)
    {
        hr = CHECK_ERROR(_ssl::setError(ret));
        goto exit;
    }

    buf.resize(pk_get_size(pk) * 8 + 128);

    ret = x509write_crt_pem(&m_crt, (unsigned char *)&buf[0], buf.length(),
                            ctr_drbg_random, &g_ssl.ctr_drbg);
    if (ret < 0)
    {
        hr = CHECK_ERROR(_ssl::setError(ret));
        goto exit;
    }

    cert = new X509Cert();
    hr = cert->load(buf.c_str());
    if (hr < 0)
        goto exit;

    retVal = cert;

exit:
    x509write_crt_free(&m_crt);

    return hr;
}
Beispiel #13
0
/**
 * \brief Finalization function of measure function
 *        measure_MPI_IO_write_large_file_once().
 *
 * Only one process is active. It writes once to a file.
 *
 * Since SKaMPI measurement functions are not allowed to use MPI_Offset
 * parameters, it is impossible to tell an init_-routine to create a file
 * which is larger than \f$2^{\mbox{\texttt{sizeof(int)}}-1}-1\f$ directly. As
 * a preliminary solution we use a parameter (<tt>power</tt>) which commits the
 * power to 2 as an indicator for the file size.
 *
 * Remark concerning the <em>HP XC6000</em>:<br>
 * Measurements showed that there is no significant difference between MPI-API
 * and POSIX-API I/O accesses, if files are larger than 1MB. Thus there is no
 * choice between these two modes like in measure_MPI_IO_read_file_once(),
 * which makes type compatibilty problems much easier. Only MPI-API is
 * supported.
 *        
 * \param[in] power       size of memory buffer; 2 to the power of `power' <tt>MPI_BYTE</tt>s
 * \param[in] create_flag write into existing file (FALSE) or create it (TRUE)
 *
 * \return    void
 */
void finalize_MPI_IO_write_large_file_once (int power, int create_flag){
  MPI_File_delete (io_filename, MPI_INFO_NULL);
  mpi_free (io_filename);
}
Beispiel #14
0
/**
 * \brief Finalization function of measure function
 *        measure_MPI_IO_read_large_file_once().
 *
 * Only one process is active. It writes once to a file.
 *
 * Since SKaMPI measurement functions are not allowed to use MPI_Offset
 * parameters, it is impossible to tell an init_-routine to create a file
 * which is larger than \f$2^{\mbox{\texttt{sizeof(int)}}-1}-1\f$ directly. As
 * a preliminary solution we use a parameter (<tt>power</tt>) which commits the
 * power to 2 as an indicator for the file size.
 *
 * Remark concerning the <em>HP XC6000</em>:<br>
 * Measurements showed that there is no significant difference between MPI-API
 * and POSIX-API I/O accesses, if files are larger than 1MB. Thus there is no
 * choice between these two modes like in measure_MPI_IO_read_file_once(),
 * which makes type compatibilty problems much easier. Only MPI-API is
 * supported.
 *        
 * \param[in] power size of memory buffer; 2 to the power of `power' <tt>MPI_BYTE</tt>s
 *
 * \return    void
 */
void finalize_MPI_IO_read_large_file_once (int power){
  MPI_File_delete (io_filename, MPI_INFO_NULL);
  mpi_free (io_filename);
}
Beispiel #15
0
/* Compute an ECDSA signature.
 * Return the signature struct (r,s) from the message hash.  The caller
 * must have allocated R and S.
 */
gpg_err_code_t
_gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
                      gcry_mpi_t r, gcry_mpi_t s,
                      int flags, int hashalgo)
{
  gpg_err_code_t rc = 0;
  int extraloops = 0;
  gcry_mpi_t k, dr, sum, k_1, x;
  mpi_point_struct I;
  gcry_mpi_t hash;
  const void *abuf;
  unsigned int abits, qbits;
  mpi_ec_t ctx;

  if (DBG_CIPHER)
    log_mpidump ("ecdsa sign hash  ", input );

  qbits = mpi_get_nbits (skey->E.n);

  /* Convert the INPUT into an MPI if needed.  */
  rc = _gcry_dsa_normalize_hash (input, &hash, qbits);
  if (rc)
    return rc;

  k = NULL;
  dr = mpi_alloc (0);
  sum = mpi_alloc (0);
  k_1 = mpi_alloc (0);
  x = mpi_alloc (0);
  point_init (&I);

  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
                                     skey->E.p, skey->E.a, skey->E.b);

  /* Two loops to avoid R or S are zero.  This is more of a joke than
     a real demand because the probability of them being zero is less
     than any hardware failure.  Some specs however require it.  */
  do
    {
      do
        {
          mpi_free (k);
          k = NULL;
          if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
            {
              /* Use Pornin's method for deterministic DSA.  If this
                 flag is set, it is expected that HASH is an opaque
                 MPI with the to be signed hash.  That hash is also
                 used as h1 from 3.2.a.  */
              if (!mpi_is_opaque (input))
                {
                  rc = GPG_ERR_CONFLICT;
                  goto leave;
                }

              abuf = mpi_get_opaque (input, &abits);
              rc = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
                                            abuf, (abits+7)/8,
                                            hashalgo, extraloops);
              if (rc)
                goto leave;
              extraloops++;
            }
          else
            k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);

          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
            {
              if (DBG_CIPHER)
                log_debug ("ecc sign: Failed to get affine coordinates\n");
              rc = GPG_ERR_BAD_SIGNATURE;
              goto leave;
            }
          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
        }
      while (!mpi_cmp_ui (r, 0));

      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
      mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
    }
  while (!mpi_cmp_ui (s, 0));

  if (DBG_CIPHER)
    {
      log_mpidump ("ecdsa sign result r ", r);
      log_mpidump ("ecdsa sign result s ", s);
    }

 leave:
  _gcry_mpi_ec_free (ctx);
  point_free (&I);
  mpi_free (x);
  mpi_free (k_1);
  mpi_free (sum);
  mpi_free (dr);
  mpi_free (k);

  if (hash != input)
    mpi_free (hash);

  return rc;
}
Beispiel #16
0
/*
    Free the components of an RSA key
 */
void rsa_free(rsa_context *ctx)
{
    mpi_free(&ctx->RQ, &ctx->RP, &ctx->RN, &ctx->QP, &ctx->DQ, &ctx->DP, &ctx->Q, &ctx->P, &ctx->D, &ctx->E, &ctx->N, NULL);
}
Beispiel #17
0
/*
 * Free the components of a DHM key
 */
void dhm_free( dhm_context *ctx )
{
    mpi_free( &ctx->RP, &ctx->K, &ctx->GY,
              &ctx->GX, &ctx->X, &ctx->G,
              &ctx->P, NULL );    
}
Beispiel #18
0
void cmd_sign(char *conf, char *key)
{
    rsa_sig_t sign;
    rsa_key_t pubkey;
    rsa_key_t seckey;
    rsa_context *ctx;
    sigstruct_t *sigstruct;

    // Load sigstruct from file
    sigstruct = load_sigstruct(conf);

    // Ignore fields don't need to sign
    memset(sigstruct->modulus, 0, 384);
    sigstruct->exponent = 0;
    memset(sigstruct->signature, 0, 384);
    memset(sigstruct->q1, 0, 384);
    memset(sigstruct->q2, 0, 384);

    // Load rsa keys from file
	ctx = load_rsa_keys(key, pubkey, seckey, KEY_LENGTH_BITS);
#if 0
    {
        char *pubkey_str = fmt_bytes(pubkey, KEY_LENGTH);
        char *seckey_str = fmt_bytes(seckey, KEY_LENGTH);

        printf("PUBKEY: %.40s..\n", pubkey_str);
        printf("SECKEY: %.40s..\n", seckey_str);

        free(pubkey_str);
        free(seckey_str);
    }
#endif

    // Generate rsa sign on sigstruct with private key
    rsa_sign(ctx, sign, (unsigned char *)sigstruct, sizeof(sigstruct_t));

    // Compute q1, q2
    unsigned char *q1, *q2;
    q1 = malloc(384);
    q2 = malloc(384);
    memset(q1, 0, 384);
    memset(q2, 0, 384);

    mpi Q1, Q2, S, M, T1, T2, R;
    mpi_init(&Q1);
    mpi_init(&Q2);
    mpi_init(&S);
    mpi_init(&M);
    mpi_init(&T1);
    mpi_init(&T2);
    mpi_init(&R);

    // q1 = signature ^ 2 / modulus
    mpi_read_binary(&S, sign, 384);
    mpi_read_binary(&M, pubkey, 384);
    mpi_mul_mpi(&T1, &S, &S);
    mpi_div_mpi(&Q1, &R, &T1, &M);

    // q2 = (signature ^ 3 - q1 * signature * modulus) / modulus
    mpi_init(&R);
    mpi_mul_mpi(&T1, &T1, &S);
    mpi_mul_mpi(&T2, &Q1, &S);
    mpi_mul_mpi(&T2, &T2, &M);
    mpi_sub_mpi(&Q2, &T1, &T2);
    mpi_div_mpi(&Q2, &R, &Q2, &M);

    mpi_write_binary(&Q1, q1, 384);
    mpi_write_binary(&Q2, q2, 384);

    mpi_free(&Q1);
    mpi_free(&Q2);
    mpi_free(&S);
    mpi_free(&M);
    mpi_free(&T1);
    mpi_free(&T2);
    mpi_free(&R);

    sigstruct = load_sigstruct(conf);
    sigstruct->exponent = 3;
    memcpy(sigstruct->modulus, pubkey, 384);
    memcpy(sigstruct->signature, sign, 384);
    memcpy(sigstruct->q1, q1, 384);
    memcpy(sigstruct->q2, q2, 384);

    char *msg = dump_sigstruct(sigstruct);
    printf("# SIGSTRUCT START\n");
    printf("%s\n", msg);
    printf("# SIGSTRUCT END\n");

    /*unsigned char exp[4] = { 0x00, 0x00, 0x00, 0x03 };
    char *mod_str = fmt_bytes(pubkey, 384);
    char *exp_str = fmt_bytes(exp, 4);
    char *sign_str = fmt_bytes(sign, 384);
    char *q1_str = fmt_bytes(q1, 384);
    char *q2_str = fmt_bytes(q2, 384);

    printf("# sign information\n");
    printf("MODULUS       : %s\n", mod_str);
    printf("EXPONENT      : %s\n", exp_str);
    printf("SIGNATURE     : %s\n", sign_str);
    printf("Q1            : %s\n", q1_str);
    printf("Q2            : %s\n", q2_str);

    free(mod_str);
    free(exp_str);
    free(sign_str);

    unsigned char signer[32];
    sha256(pubkey, KEY_LENGTH, signer, 0);
    char *signer_str = fmt_bytes(pubkey, 32);
    printf("# hash of public key\n");
    printf("MRSIGNER      : %s\n", signer_str);*/
}
Beispiel #19
0
/* RESULT must have been initialized and is set on success to the
   point given by VALUE.  */
gcry_err_code_t
_gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
{
  gcry_err_code_t rc;
  size_t n;
  const unsigned char *buf;
  unsigned char *buf_memory;
  gcry_mpi_t x, y;

  if (mpi_is_opaque (value))
    {
      unsigned int nbits;

      buf = mpi_get_opaque (value, &nbits);
      if (!buf)
        return GPG_ERR_INV_OBJ;
      n = (nbits + 7)/8;
      buf_memory = NULL;
    }
  else
    {
      n = (mpi_get_nbits (value)+7)/8;
      buf_memory = xmalloc (n);
      rc = _gcry_mpi_print (GCRYMPI_FMT_USG, buf_memory, n, &n, value);
      if (rc)
        {
          xfree (buf_memory);
          return rc;
        }
      buf = buf_memory;
    }

  if (n < 1)
    {
      xfree (buf_memory);
      return GPG_ERR_INV_OBJ;
    }
  if (*buf != 4)
    {
      xfree (buf_memory);
      return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression.  */
    }
  if ( ((n-1)%2) )
    {
      xfree (buf_memory);
      return GPG_ERR_INV_OBJ;
    }
  n = (n-1)/2;
  rc = _gcry_mpi_scan (&x, GCRYMPI_FMT_USG, buf+1, n, NULL);
  if (rc)
    {
      xfree (buf_memory);
      return rc;
    }
  rc = _gcry_mpi_scan (&y, GCRYMPI_FMT_USG, buf+1+n, n, NULL);
  xfree (buf_memory);
  if (rc)
    {
      mpi_free (x);
      return rc;
    }

  mpi_set (result->x, x);
  mpi_set (result->y, y);
  mpi_set_ui (result->z, 1);

  mpi_free (x);
  mpi_free (y);

  return 0;
}
Beispiel #20
0
static int
get_it( PKT_pubkey_enc *k, DEK *dek, PKT_secret_key *sk, u32 *keyid )
{
    int rc;
    MPI plain_dek  = NULL;
    byte *frame = NULL;
    unsigned n, nframe;
    u16 csum, csum2;

    rc = pubkey_decrypt(sk->pubkey_algo, &plain_dek, k->data, sk->skey );
    if( rc )
	goto leave;
    frame = mpi_get_buffer( plain_dek, &nframe, NULL );
    mpi_free( plain_dek ); plain_dek = NULL;

    /* Now get the DEK (data encryption key) from the frame
     *
     * Old versions encode the DEK in in this format (msb is left):
     *
     *	   0  1  DEK(16 bytes)	CSUM(2 bytes)  0  RND(n bytes) 2
     *
     * Later versions encode the DEK like this:
     *
     *	   0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
     *
     * (mpi_get_buffer already removed the leading zero).
     *
     * RND are non-zero randow bytes.
     * A   is the cipher algorithm
     * DEK is the encryption key (session key) with length k
     * CSUM
     */
    if( DBG_CIPHER )
	log_hexdump("DEK frame:", frame, nframe );
    n=0;
    if( n + 7 > nframe )
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }
    if( frame[n] == 1 && frame[nframe-1] == 2 ) {
	log_info(_("old encoding of the DEK is not supported\n"));
	rc = G10ERR_CIPHER_ALGO;
	goto leave;
    }
    if( frame[n] != 2 )  /* somethink is wrong */
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }
    for(n++; n < nframe && frame[n]; n++ ) /* skip the random bytes */
	;
    n++; /* and the zero byte */
    if( n + 4 > nframe )
	{ rc = G10ERR_WRONG_SECKEY; goto leave; }

    dek->keylen = nframe - (n+1) - 2;
    dek->algo = frame[n++];
    if( dek->algo ==  CIPHER_ALGO_IDEA )
	write_status(STATUS_RSA_OR_IDEA);
    rc = check_cipher_algo( dek->algo );
    if( rc ) {
	if( !opt.quiet && rc == G10ERR_CIPHER_ALGO ) {
	    log_info(_("cipher algorithm %d is unknown or disabled\n"),
							    dek->algo);
	}
	dek->algo = 0;
	goto leave;
    }
    if( (dek->keylen*8) != cipher_get_keylen( dek->algo ) ) {
	rc = G10ERR_WRONG_SECKEY;
	goto leave;
    }

    /* copy the key to DEK and compare the checksum */
    csum  = frame[nframe-2] << 8;
    csum |= frame[nframe-1];
    memcpy( dek->key, frame+n, dek->keylen );
    for( csum2=0, n=0; n < dek->keylen; n++ )
	csum2 += dek->key[n];
    if( csum != csum2 ) {
	rc = G10ERR_WRONG_SECKEY;
	goto leave;
    }
    if( DBG_CIPHER )
	log_hexdump("DEK is:", dek->key, dek->keylen );
    /* check that the algo is in the preferences and whether it has expired */
    {
	PKT_public_key *pk = m_alloc_clear( sizeof *pk );
	if( (rc = get_pubkey( pk, keyid )) )
	    log_error("public key problem: %s\n", g10_errstr(rc) );
	else if( !pk->local_id && query_trust_record(pk) )
	    log_error("can't check algorithm against preferences\n");
	else if( dek->algo != CIPHER_ALGO_3DES
	    && !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM, dek->algo ) ) {
	    /* Don't print a note while we are not on verbose mode,
	     * the cipher is blowfish and the preferences have twofish
	     * listed */
	    if( opt.verbose || dek->algo != CIPHER_ALGO_BLOWFISH
		|| !is_algo_in_prefs( pk->local_id, PREFTYPE_SYM,
						    CIPHER_ALGO_TWOFISH ) )
		log_info(_(
		    "NOTE: cipher algorithm %d not found in preferences\n"),
								 dek->algo );
	}


	if( !rc && pk->expiredate && pk->expiredate <= make_timestamp() ) {
	    log_info(_("NOTE: secret key %08lX expired at %s\n"),
			   (ulong)keyid[1], asctimestamp( pk->expiredate) );
	}

	/* FIXME: check wheter the key has been revoked and display
	 * the revocation reason.  Actually the user should know this himself,
	 * but the sender might not know already and therefor the user
	 * should get a notice that an revoked key has been used to decode
	 * the message.  The user can than watch out for snakes send by
	 * one of those Eves outside his paradise :-)
	 */
	free_public_key( pk );
	rc = 0;
    }


  leave:
    mpi_free(plain_dek);
    m_free(frame);
    return rc;
}
Beispiel #21
0
/*
 * Free the components of an RSA key
 */
void rsa_free( rsa_context *ctx )
{
#if !defined(POLARSSL_RSA_NO_CRT)
    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
#endif
    mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
    mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
    mpi_free( &ctx->Q  ); mpi_free( &ctx->P  ); mpi_free( &ctx->D );
    mpi_free( &ctx->E  ); mpi_free( &ctx->N  );

#if defined(POLARSSL_THREADING_C)
    polarssl_mutex_free( &ctx->mutex );
#endif
}
Beispiel #22
0
/*
 * Free the components of an RSA key
 */
void rsa_free( rsa_context *ctx )
{
    mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN );
    mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP );
    mpi_free( &ctx->Q  ); mpi_free( &ctx->P  ); mpi_free( &ctx->D );
    mpi_free( &ctx->E  ); mpi_free( &ctx->N  );
}
Beispiel #23
0
/*
 * Do an RSA private key operation
 */
int rsa_private( rsa_context *ctx,
                 int (*f_rng)(void *, unsigned char *, size_t),
                 void *p_rng,
                 const unsigned char *input,
                 unsigned char *output )
{
    int ret;
    size_t olen;
    mpi T, T1, T2;
#if !defined(POLARSSL_RSA_NO_CRT)
    mpi *Vi, *Vf;

    /*
     * When using the Chinese Remainder Theorem, we use blinding values.
     * Without threading, we just read them directly from the context,
     * otherwise we make a local copy in order to reduce locking contention.
     */
#if defined(POLARSSL_THREADING_C)
    mpi Vi_copy, Vf_copy;

    mpi_init( &Vi_copy ); mpi_init( &Vf_copy );
    Vi = &Vi_copy;
    Vf = &Vf_copy;
#else
    Vi = &ctx->Vi;
    Vf = &ctx->Vf;
#endif
#endif /* !POLARSSL_RSA_NO_CRT */

    mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );

    MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
    {
        mpi_free( &T );
        return( POLARSSL_ERR_RSA_BAD_INPUT_DATA );
    }

#if defined(POLARSSL_RSA_NO_CRT)
    ((void) f_rng);
    ((void) p_rng);
    MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
#else
    if( f_rng != NULL )
    {
        /*
         * Blinding
         * T = T * Vi mod N
         */
        MPI_CHK( rsa_prepare_blinding( ctx, Vi, Vf, f_rng, p_rng ) );
        MPI_CHK( mpi_mul_mpi( &T, &T, Vi ) );
        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
    }

    /*
     * faster decryption using the CRT
     *
     * T1 = input ^ dP mod P
     * T2 = input ^ dQ mod Q
     */
    MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
    MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );

    /*
     * T = (T1 - T2) * (Q^-1 mod P) mod P
     */
    MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
    MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );

    /*
     * T = T2 + T * Q
     */
    MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
    MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) );

    if( f_rng != NULL )
    {
        /*
         * Unblind
         * T = T * Vf mod N
         */
        MPI_CHK( mpi_mul_mpi( &T, &T, Vf ) );
        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
    }
#endif /* POLARSSL_RSA_NO_CRT */

    olen = ctx->len;
    MPI_CHK( mpi_write_binary( &T, output, olen ) );

cleanup:
    mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
#if !defined(POLARSSL_RSA_NO_CRT) && defined(POLARSSL_THREADING_C)
    mpi_free( &Vi_copy ); mpi_free( &Vf_copy );
#endif

    if( ret != 0 )
        return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );

    return( 0 );
}
Beispiel #24
0
int main( void )
{
    int ret;
    mpi E, P, Q, N, H, D, X, Y, Z;

    mpi_init( &E ); mpi_init( &P ); mpi_init( &Q ); mpi_init( &N );
    mpi_init( &H ); mpi_init( &D ); mpi_init( &X ); mpi_init( &Y );
    mpi_init( &Z );

    MPI_CHK( mpi_read_string( &P, 10, "2789" ) );
    MPI_CHK( mpi_read_string( &Q, 10, "3203" ) );
    MPI_CHK( mpi_read_string( &E, 10,  "257" ) );
    MPI_CHK( mpi_mul_mpi( &N, &P, &Q ) );

    polarssl_printf( "\n  Public key:\n\n" );
    MPI_CHK( mpi_write_file( "  N = ", &N, 10, NULL ) );
    MPI_CHK( mpi_write_file( "  E = ", &E, 10, NULL ) );

    polarssl_printf( "\n  Private key:\n\n" );
    MPI_CHK( mpi_write_file( "  P = ", &P, 10, NULL ) );
    MPI_CHK( mpi_write_file( "  Q = ", &Q, 10, NULL ) );

#if defined(POLARSSL_GENPRIME)
    MPI_CHK( mpi_sub_int( &P, &P, 1 ) );
    MPI_CHK( mpi_sub_int( &Q, &Q, 1 ) );
    MPI_CHK( mpi_mul_mpi( &H, &P, &Q ) );
    MPI_CHK( mpi_inv_mod( &D, &E, &H ) );

    mpi_write_file( "  D = E^-1 mod (P-1)*(Q-1) = ",
                    &D, 10, NULL );
#else
    polarssl_printf("\nTest skipped (POLARSSL_GENPRIME not defined).\n\n");
#endif
    MPI_CHK( mpi_read_string( &X, 10, "55555" ) );
    MPI_CHK( mpi_exp_mod( &Y, &X, &E, &N, NULL ) );
    MPI_CHK( mpi_exp_mod( &Z, &Y, &D, &N, NULL ) );

    polarssl_printf( "\n  RSA operation:\n\n" );
    MPI_CHK( mpi_write_file( "  X (plaintext)  = ", &X, 10, NULL ) );
    MPI_CHK( mpi_write_file( "  Y (ciphertext) = X^E mod N = ", &Y, 10, NULL ) );
    MPI_CHK( mpi_write_file( "  Z (decrypted)  = Y^D mod N = ", &Z, 10, NULL ) );
    polarssl_printf( "\n" );

cleanup:
    mpi_free( &E ); mpi_free( &P ); mpi_free( &Q ); mpi_free( &N );
    mpi_free( &H ); mpi_free( &D ); mpi_free( &X ); mpi_free( &Y );
    mpi_free( &Z );

    if( ret != 0 )
    {
        polarssl_printf( "\nAn error occurred.\n" );
        ret = 1;
    }

#if defined(_WIN32)
    polarssl_printf( "  Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}
Beispiel #25
0
/* Recover X from Y and SIGN (which actually is a parity bit).  */
gpg_err_code_t
_gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
{
  gpg_err_code_t rc = 0;
  gcry_mpi_t u, v, v3, t;
  static gcry_mpi_t p58, seven;

  if (ec->dialect != ECC_DIALECT_ED25519)
    return GPG_ERR_NOT_IMPLEMENTED;

  if (!p58)
    p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD");
  if (!seven)
    seven = mpi_set_ui (NULL, 7);

  u   = mpi_new (0);
  v   = mpi_new (0);
  v3  = mpi_new (0);
  t   = mpi_new (0);

  /* Compute u and v */
  /* u = y^2    */
  mpi_mulm (u, y, y, ec->p);
  /* v = b*y^2   */
  mpi_mulm (v, ec->b, u, ec->p);
  /* u = y^2-1  */
  mpi_sub_ui (u, u, 1);
  /* v = b*y^2+1 */
  mpi_add_ui (v, v, 1);

  /* Compute sqrt(u/v) */
  /* v3 = v^3 */
  mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p);
  /* t = v3 * v3 * u * v = u * v^7 */
  mpi_powm (t, v, seven, ec->p);
  mpi_mulm (t, t, u, ec->p);
  /* t = t^((p-5)/8) = (u * v^7)^((p-5)/8)  */
  mpi_powm (t, t, p58, ec->p);
  /* x = t * u * v^3 = (u * v^3) * (u * v^7)^((p-5)/8) */
  mpi_mulm (t, t, u, ec->p);
  mpi_mulm (x, t, v3, ec->p);

  /* Adjust if needed.  */
  /* t = v * x^2  */
  mpi_mulm (t, x, x, ec->p);
  mpi_mulm (t, t, v, ec->p);
  /* -t == u ? x = x * sqrt(-1) */
  mpi_neg (t, t);
  if (!mpi_cmp (t, u))
    {
      static gcry_mpi_t m1;  /* Fixme: this is not thread-safe.  */
      if (!m1)
        m1 = scanval ("2B8324804FC1DF0B2B4D00993DFBD7A7"
                      "2F431806AD2FE478C4EE1B274A0EA0B0");
      mpi_mulm (x, x, m1, ec->p);
      /* t = v * x^2  */
      mpi_mulm (t, x, x, ec->p);
      mpi_mulm (t, t, v, ec->p);
      /* -t == u ? x = x * sqrt(-1) */
      mpi_neg (t, t);
      if (!mpi_cmp (t, u))
        rc = GPG_ERR_INV_OBJ;
    }

  /* Choose the desired square root according to parity */
  if (mpi_test_bit (x, 0) != !!sign)
    mpi_sub (x, ec->p, x);

  mpi_free (t);
  mpi_free (v3);
  mpi_free (v);
  mpi_free (u);

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

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

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

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

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


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

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

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

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

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

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

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

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

    mpi_free(u);
    mpi_free(v);
#endif
    return 1;
}
Beispiel #27
0
/*
 * Free the components of a DHM key
 */
void dhm_free( dhm_context *ctx )
{
    mpi_free( &ctx->RP ); mpi_free( &ctx->K ); mpi_free( &ctx->GY );
    mpi_free( &ctx->GX ); mpi_free( &ctx->X ); mpi_free( &ctx->G );
    mpi_free( &ctx->P );
}
Beispiel #28
0
/* Verify an ECDSA signature.
 * Check if R and S verifies INPUT.
 */
gpg_err_code_t
_gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
                        gcry_mpi_t r, gcry_mpi_t s)
{
  gpg_err_code_t err = 0;
  gcry_mpi_t hash, h, h1, h2, x;
  mpi_point_struct Q, Q1, Q2;
  mpi_ec_t ctx;
  unsigned int nbits;

  if( !(mpi_cmp_ui (r, 0) > 0 && mpi_cmp (r, pkey->E.n) < 0) )
    return GPG_ERR_BAD_SIGNATURE; /* Assertion	0 < r < n  failed.  */
  if( !(mpi_cmp_ui (s, 0) > 0 && mpi_cmp (s, pkey->E.n) < 0) )
    return GPG_ERR_BAD_SIGNATURE; /* Assertion	0 < s < n  failed.  */

  nbits = mpi_get_nbits (pkey->E.n);
  err = _gcry_dsa_normalize_hash (input, &hash, nbits);
  if (err)
    return err;

  h  = mpi_alloc (0);
  h1 = mpi_alloc (0);
  h2 = mpi_alloc (0);
  x = mpi_alloc (0);
  point_init (&Q);
  point_init (&Q1);
  point_init (&Q2);

  ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
                                     pkey->E.p, pkey->E.a, pkey->E.b);

  /* h  = s^(-1) (mod n) */
  mpi_invm (h, s, pkey->E.n);
  /* h1 = hash * s^(-1) (mod n) */
  mpi_mulm (h1, hash, h, pkey->E.n);
  /* Q1 = [ hash * s^(-1) ]G  */
  _gcry_mpi_ec_mul_point (&Q1, h1, &pkey->E.G, ctx);
  /* h2 = r * s^(-1) (mod n) */
  mpi_mulm (h2, r, h, pkey->E.n);
  /* Q2 = [ r * s^(-1) ]Q */
  _gcry_mpi_ec_mul_point (&Q2, h2, &pkey->Q, ctx);
  /* Q  = ([hash * s^(-1)]G) + ([r * s^(-1)]Q) */
  _gcry_mpi_ec_add_points (&Q, &Q1, &Q2, ctx);

  if (!mpi_cmp_ui (Q.z, 0))
    {
      if (DBG_CIPHER)
          log_debug ("ecc verify: Rejected\n");
      err = GPG_ERR_BAD_SIGNATURE;
      goto leave;
    }
  if (_gcry_mpi_ec_get_affine (x, NULL, &Q, ctx))
    {
      if (DBG_CIPHER)
        log_debug ("ecc verify: Failed to get affine coordinates\n");
      err = GPG_ERR_BAD_SIGNATURE;
      goto leave;
    }
  mpi_mod (x, x, pkey->E.n); /* x = x mod E_n */
  if (mpi_cmp (x, r))   /* x != r */
    {
      if (DBG_CIPHER)
        {
          log_mpidump ("     x", x);
          log_mpidump ("     r", r);
          log_mpidump ("     s", s);
        }
      err = GPG_ERR_BAD_SIGNATURE;
      goto leave;
    }

 leave:
  _gcry_mpi_ec_free (ctx);
  point_free (&Q2);
  point_free (&Q1);
  point_free (&Q);
  mpi_free (x);
  mpi_free (h2);
  mpi_free (h1);
  mpi_free (h);
  if (hash != input)
    mpi_free (hash);

  return err;
}
Beispiel #29
0
/* Store the MPI NEWVALUE into the context EC under NAME. */
gpg_err_code_t
_gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
{
  gpg_err_code_t rc = 0;

  if (!*name)
    ;
  else if (!strcmp (name, "p"))
    {
      mpi_free (ec->p);
      ec->p = mpi_copy (newvalue);
      _gcry_mpi_ec_get_reset (ec);
    }
  else if (!strcmp (name, "a"))
    {
      mpi_free (ec->a);
      ec->a = mpi_copy (newvalue);
      _gcry_mpi_ec_get_reset (ec);
    }
  else if (!strcmp (name, "b"))
    {
      mpi_free (ec->b);
      ec->b = mpi_copy (newvalue);
    }
  else if (!strcmp (name, "n"))
    {
      mpi_free (ec->n);
      ec->n = mpi_copy (newvalue);
    }
  else if (*name == 'q' && (!name[1] || name[1] == '@'))
    {
      if (newvalue)
        {
          if (!ec->Q)
            ec->Q = mpi_point_new (0);
          if (ec->dialect == ECC_DIALECT_ED25519)
            rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
          else
            rc = _gcry_ecc_os2ec (ec->Q, newvalue);
        }
      if (rc || !newvalue)
        {
          _gcry_mpi_point_release (ec->Q);
          ec->Q = NULL;
        }
      /* Note: We assume that Q matches d and thus do not reset d.  */
    }
  else if (!strcmp (name, "d"))
    {
      mpi_free (ec->d);
      ec->d = mpi_copy (newvalue);
      if (ec->d)
        {
          /* We need to reset the public key because it may not
             anymore match.  */
          _gcry_mpi_point_release (ec->Q);
          ec->Q = NULL;
        }
    }
  else
   rc = GPG_ERR_UNKNOWN_NAME;

  return rc;
}
Beispiel #30
0
int main( int argc, char *argv[] )
{
    int ret = 0;
    x509_crt issuer_crt;
    pk_context loaded_issuer_key, loaded_subject_key;
    pk_context *issuer_key = &loaded_issuer_key,
                *subject_key = &loaded_subject_key;
    char buf[1024];
    char issuer_name[128];
    int i, j, n;
    char *p, *q, *r;
#if defined(POLARSSL_X509_CSR_PARSE_C)
    char subject_name[128];
    x509_csr csr;
#endif
    x509write_cert crt;
    mpi serial;
    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    const char *pers = "crt example app";

    /*
     * Set to sane values
     */
    x509write_crt_init( &crt );
    x509write_crt_set_md_alg( &crt, POLARSSL_MD_SHA1 );
    pk_init( &loaded_issuer_key );
    pk_init( &loaded_subject_key );
    mpi_init( &serial );
#if defined(POLARSSL_X509_CSR_PARSE_C)
    x509_csr_init( &csr );
#endif
    x509_crt_init( &issuer_crt );
    memset( buf, 0, 1024 );

    if( argc == 0 )
    {
    usage:
        printf( USAGE );
        ret = 1;
        goto exit;
    }

    opt.issuer_crt          = DFL_ISSUER_CRT;
    opt.request_file        = DFL_REQUEST_FILE;
    opt.request_file        = DFL_REQUEST_FILE;
    opt.subject_key         = DFL_SUBJECT_KEY;
    opt.issuer_key          = DFL_ISSUER_KEY;
    opt.subject_pwd         = DFL_SUBJECT_PWD;
    opt.issuer_pwd          = DFL_ISSUER_PWD;
    opt.output_file         = DFL_OUTPUT_FILENAME;
    opt.subject_name        = DFL_SUBJECT_NAME;
    opt.issuer_name         = DFL_ISSUER_NAME;
    opt.not_before          = DFL_NOT_BEFORE;
    opt.not_after           = DFL_NOT_AFTER;
    opt.serial              = DFL_SERIAL;
    opt.selfsign            = DFL_SELFSIGN;
    opt.is_ca               = DFL_IS_CA;
    opt.max_pathlen         = DFL_MAX_PATHLEN;
    opt.key_usage           = DFL_KEY_USAGE;
    opt.ns_cert_type        = DFL_NS_CERT_TYPE;

    for( i = 1; i < argc; i++ )
    {

        p = argv[i];
        if( ( q = strchr( p, '=' ) ) == NULL )
            goto usage;
        *q++ = '\0';

        n = strlen( p );
        for( j = 0; j < n; j++ )
        {
            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
                argv[i][j] |= 0x20;
        }

        if( strcmp( p, "request_file" ) == 0 )
            opt.request_file = q;
        else if( strcmp( p, "subject_key" ) == 0 )
            opt.subject_key = q;
        else if( strcmp( p, "issuer_key" ) == 0 )
            opt.issuer_key = q;
        else if( strcmp( p, "subject_pwd" ) == 0 )
            opt.subject_pwd = q;
        else if( strcmp( p, "issuer_pwd" ) == 0 )
            opt.issuer_pwd = q;
        else if( strcmp( p, "issuer_crt" ) == 0 )
            opt.issuer_crt = q;
        else if( strcmp( p, "output_file" ) == 0 )
            opt.output_file = q;
        else if( strcmp( p, "subject_name" ) == 0 )
        {
            opt.subject_name = q;
        }
        else if( strcmp( p, "issuer_name" ) == 0 )
        {
            opt.issuer_name = q;
        }
        else if( strcmp( p, "not_before" ) == 0 )
        {
            opt.not_before = q;
        }
        else if( strcmp( p, "not_after" ) == 0 )
        {
            opt.not_after = q;
        }
        else if( strcmp( p, "serial" ) == 0 )
        {
            opt.serial = q;
        }
        else if( strcmp( p, "selfsign" ) == 0 )
        {
            opt.selfsign = atoi( q );
            if( opt.selfsign < 0 || opt.selfsign > 1 )
                goto usage;
        }
        else if( strcmp( p, "is_ca" ) == 0 )
        {
            opt.is_ca = atoi( q );
            if( opt.is_ca < 0 || opt.is_ca > 1 )
                goto usage;
        }
        else if( strcmp( p, "max_pathlen" ) == 0 )
        {
            opt.max_pathlen = atoi( q );
            if( opt.max_pathlen < -1 || opt.max_pathlen > 127 )
                goto usage;
        }
        else if( strcmp( p, "key_usage" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "digital_signature" ) == 0 )
                    opt.key_usage |= KU_DIGITAL_SIGNATURE;
                else if( strcmp( q, "non_repudiation" ) == 0 )
                    opt.key_usage |= KU_NON_REPUDIATION;
                else if( strcmp( q, "key_encipherment" ) == 0 )
                    opt.key_usage |= KU_KEY_ENCIPHERMENT;
                else if( strcmp( q, "data_encipherment" ) == 0 )
                    opt.key_usage |= KU_DATA_ENCIPHERMENT;
                else if( strcmp( q, "key_agreement" ) == 0 )
                    opt.key_usage |= KU_KEY_AGREEMENT;
                else if( strcmp( q, "key_cert_sign" ) == 0 )
                    opt.key_usage |= KU_KEY_CERT_SIGN;
                else if( strcmp( q, "crl_sign" ) == 0 )
                    opt.key_usage |= KU_CRL_SIGN;
                else
                    goto usage;

                q = r;
            }
        }
        else if( strcmp( p, "ns_cert_type" ) == 0 )
        {
            while( q != NULL )
            {
                if( ( r = strchr( q, ',' ) ) != NULL )
                    *r++ = '\0';

                if( strcmp( q, "ssl_client" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_SSL_CLIENT;
                else if( strcmp( q, "ssl_server" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_SSL_SERVER;
                else if( strcmp( q, "email" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_EMAIL;
                else if( strcmp( q, "object_signing" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING;
                else if( strcmp( q, "ssl_ca" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_SSL_CA;
                else if( strcmp( q, "email_ca" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_EMAIL_CA;
                else if( strcmp( q, "object_signing_ca" ) == 0 )
                    opt.ns_cert_type |= NS_CERT_TYPE_OBJECT_SIGNING_CA;
                else
                    goto usage;

                q = r;
            }
        }
        else
            goto usage;
    }

    printf("\n");

    /*
     * 0. Seed the PRNG
     */
    printf( "  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
    if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  ctr_drbg_init returned %d - %s\n", ret, buf );
        goto exit;
    }

    printf( " ok\n" );

    // Parse serial to MPI
    //
    printf( "  . Reading serial number..." );
    fflush( stdout );

    if( ( ret = mpi_read_string( &serial, 10, opt.serial ) ) != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  mpi_read_string returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );

    // Parse issuer certificate if present
    //
    if( !opt.selfsign && strlen( opt.issuer_crt ) )
    {
        /*
         * 1.0.a. Load the certificates
         */
        printf( "  . Loading the issuer certificate ..." );
        fflush( stdout );

        if( ( ret = x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509_crt_parse_file returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        ret = x509_dn_gets( issuer_name, sizeof(issuer_name),
                                 &issuer_crt.issuer );
        if( ret < 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        opt.issuer_name = issuer_name;

        printf( " ok\n" );
    }

#if defined(POLARSSL_X509_CSR_PARSE_C)
    // Parse certificate request if present
    //
    if( !opt.selfsign && strlen( opt.request_file ) )
    {
        /*
         * 1.0.b. Load the CSR
         */
        printf( "  . Loading the certificate request ..." );
        fflush( stdout );

        if( ( ret = x509_csr_parse_file( &csr, opt.request_file ) ) != 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509_csr_parse_file returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        ret = x509_dn_gets( subject_name, sizeof(subject_name),
                                 &csr.subject );
        if( ret < 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509_dn_gets returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        opt.subject_name = subject_name;
        subject_key = &csr.pk;

        printf( " ok\n" );
    }
#endif /* POLARSSL_X509_CSR_PARSE_C */

    /*
     * 1.1. Load the keys
     */
    if( !opt.selfsign && !strlen( opt.request_file ) )
    {
        printf( "  . Loading the subject key ..." );
        fflush( stdout );

        ret = pk_parse_keyfile( &loaded_subject_key, opt.subject_key,
                                 opt.subject_pwd );
        if( ret != 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  pk_parse_keyfile returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        printf( " ok\n" );
    }

    printf( "  . Loading the issuer key ..." );
    fflush( stdout );

    ret = pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key,
                             opt.issuer_pwd );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  pk_parse_keyfile returned -x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    // Check if key and issuer certificate match
    //
    if( strlen( opt.issuer_crt ) )
    {
        if( !pk_can_do( &issuer_crt.pk, POLARSSL_PK_RSA ) ||
            mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->N,
                         &pk_rsa( *issuer_key )->N ) != 0 ||
            mpi_cmp_mpi( &pk_rsa( issuer_crt.pk )->E,
                         &pk_rsa( *issuer_key )->E ) != 0 )
        {
            printf( " failed\n  !  issuer_key does not match issuer certificate\n\n" );
            ret = -1;
            goto exit;
        }
    }

    printf( " ok\n" );

    if( opt.selfsign )
    {
        opt.subject_name = opt.issuer_name;
        subject_key = issuer_key;
    }

    x509write_crt_set_subject_key( &crt, subject_key );
    x509write_crt_set_issuer_key( &crt, issuer_key );

    /*
     * 1.0. Check the names for validity
     */
    if( ( ret = x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_subject_name returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    if( ( ret = x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_issuer_name returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( "  . Setting certificate values ..." );
    fflush( stdout );

    ret = x509write_crt_set_serial( &crt, &serial );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_serial returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    ret = x509write_crt_set_validity( &crt, opt.not_before, opt.not_after );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_validity returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );

    printf( "  . Adding the Basic Constraints extension ..." );
    fflush( stdout );

    ret = x509write_crt_set_basic_constraints( &crt, opt.is_ca,
                                               opt.max_pathlen );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_basic_contraints returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );

#if defined(POLARSSL_SHA1_C)
    printf( "  . Adding the Subject Key Identifier ..." );
    fflush( stdout );

    ret = x509write_crt_set_subject_key_identifier( &crt );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_subject_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );

    printf( "  . Adding the Authority Key Identifier ..." );
    fflush( stdout );

    ret = x509write_crt_set_authority_key_identifier( &crt );
    if( ret != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  x509write_crt_set_authority_key_identifier returned -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );
#endif /* POLARSSL_SHA1_C */

    if( opt.key_usage )
    {
        printf( "  . Adding the Key Usage extension ..." );
        fflush( stdout );

        ret = x509write_crt_set_key_usage( &crt, opt.key_usage );
        if( ret != 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509write_crt_set_key_usage returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        printf( " ok\n" );
    }

    if( opt.ns_cert_type )
    {
        printf( "  . Adding the NS Cert Type extension ..." );
        fflush( stdout );

        ret = x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type );
        if( ret != 0 )
        {
            error_strerror( ret, buf, 1024 );
            printf( " failed\n  !  x509write_crt_set_ns_cert_type returned -0x%02x - %s\n\n", -ret, buf );
            goto exit;
        }

        printf( " ok\n" );
    }

    /*
     * 1.2. Writing the request
     */
    printf( "  . Writing the certificate..." );
    fflush( stdout );

    if( ( ret = write_certificate( &crt, opt.output_file,
                                   ctr_drbg_random, &ctr_drbg ) ) != 0 )
    {
        error_strerror( ret, buf, 1024 );
        printf( " failed\n  !  write_certifcate -0x%02x - %s\n\n", -ret, buf );
        goto exit;
    }

    printf( " ok\n" );

exit:
    x509write_crt_free( &crt );
    pk_free( &loaded_subject_key );
    pk_free( &loaded_issuer_key );
    mpi_free( &serial );
    entropy_free( &entropy );

#if defined(_WIN32)
    printf( "  + Press Enter to exit this program.\n" );
    fflush( stdout ); getchar();
#endif

    return( ret );
}