Пример #1
0
result_t PKey::copy(const pk_context &key)
{
    pk_type_t type = pk_get_type(&key);
    int ret;

    if (type == POLARSSL_PK_RSA)
    {
        rsa_context *rsa = pk_rsa(key);

        ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_RSA));
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        rsa_context *rsa1 = pk_rsa(m_key);

        ret = rsa_copy(rsa1, rsa);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        return 0;
    }

    if (type == POLARSSL_PK_ECKEY)
    {
        ecp_keypair *ecp = pk_ec(key);

        ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_ECKEY));
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ecp_keypair *ecp1 = pk_ec(m_key);

        ret = ecp_group_copy(&ecp1->grp, &ecp->grp);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ret = mpi_copy(&ecp1->d, &ecp->d);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ret = ecp_copy(&ecp1->Q, &ecp->Q);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        return 0;
    }

    return CHECK_ERROR(CALL_E_INVALID_CALL);
}
Пример #2
0
result_t PKey::genEcKey(const char *curve, exlib::AsyncEvent *ac)
{
    if (switchToAsync(ac))
        return CHECK_ERROR(CALL_E_NOSYNC);

    const ecp_curve_info *curve_info;
    curve_info = ecp_curve_info_from_name(curve);
    if (curve_info == NULL)
        return CHECK_ERROR(Runtime::setError("PKey: Unknown curve"));

    int ret;

    clear();

    ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_ECKEY));
    if (ret != 0)
        return CHECK_ERROR(_ssl::setError(ret));

    ret = ecp_gen_key(curve_info->grp_id, pk_ec(m_key),
                      ctr_drbg_random, &g_ssl.ctr_drbg);

    if (ret != 0)
        return CHECK_ERROR(_ssl::setError(ret));

    return 0;
}
Пример #3
0
/*
 *  SubjectPublicKeyInfo  ::=  SEQUENCE  {
 *       algorithm            AlgorithmIdentifier,
 *       subjectPublicKey     BIT STRING }
 */
int pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
                        pk_context *pk )
{
    int ret;
    size_t len;
    asn1_buf alg_params;
    pk_type_t pk_alg = POLARSSL_PK_NONE;
    const pk_info_t *pk_info;

    if( ( ret = asn1_get_tag( p, end, &len,
                    ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
    {
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
    }

    end = *p + len;

    if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 )
        return( ret );

    if( ( ret = asn1_get_bitstring_null( p, end, &len ) ) != 0 )
        return( POLARSSL_ERR_PK_INVALID_PUBKEY + ret );

    if( *p + len != end )
        return( POLARSSL_ERR_PK_INVALID_PUBKEY +
                POLARSSL_ERR_ASN1_LENGTH_MISMATCH );

    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
        return( ret );

#if defined(POLARSSL_RSA_C)
    if( pk_alg == POLARSSL_PK_RSA )
    {
        ret = pk_get_shrsapubkey( p, end, pk_rsa( *pk ) );
    } else
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECP_C)
    if( pk_alg == POLARSSL_PK_ECKEY_DH || pk_alg == POLARSSL_PK_ECKEY )
    {
        ret = pk_use_ecparams( &alg_params, &pk_ec( *pk )->grp );
        if( ret == 0 )
            ret = pk_get_ecpubkey( p, end, pk_ec( *pk ) );
    } else
#endif /* POLARSSL_ECP_C */
        ret = POLARSSL_ERR_PK_UNKNOWN_PK_ALG;

    if( ret == 0 && *p != end )
        ret = POLARSSL_ERR_PK_INVALID_PUBKEY
              POLARSSL_ERR_ASN1_LENGTH_MISMATCH;

    if( ret != 0 )
        pk_free( pk );

    return( ret );
}
Пример #4
0
		cPubKey(rsa_context * a_Rsa) :
			m_IsValid(false)
		{
			pk_init(&m_Key);
			if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0)
			{
				ASSERT(!"Cannot init PrivKey context");
				return;
			}
			if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0)
			{
				ASSERT(!"Cannot copy PrivKey to PK context");
				return;
			}
			m_IsValid = true;
		}
Пример #5
0
result_t PKey::genRsaKey(int32_t size, exlib::AsyncEvent *ac)
{
    if (size < 128 || size > 8192)
        return CHECK_ERROR(Runtime::setError("PKey: Invalid key size"));

    if (switchToAsync(ac))
        return CHECK_ERROR(CALL_E_NOSYNC);

    int ret;

    clear();

    ret = pk_init_ctx(&m_key, pk_info_from_type(POLARSSL_PK_RSA));
    if (ret != 0)
        return CHECK_ERROR(_ssl::setError(ret));

    ret = rsa_gen_key(pk_rsa(m_key), ctr_drbg_random, &g_ssl.ctr_drbg,
                      size, 65537);

    if (ret != 0)
        return CHECK_ERROR(_ssl::setError(ret));

    return 0;
}
Пример #6
0
/*
 * Parse an unencrypted PKCS#8 encoded private key
 */
static int pk_parse_key_pkcs8_unencrypted_der(
                                    pk_context *pk,
                                    const unsigned char* key,
                                    size_t keylen )
{
    int ret, version;
    size_t len;
    asn1_buf params;
    unsigned char *p = (unsigned char *) key;
    unsigned char *end = p + keylen;
    pk_type_t pk_alg = POLARSSL_PK_NONE;
    const pk_info_t *pk_info;

    /*
     * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208)
     *
     *    PrivateKeyInfo ::= SEQUENCE {
     *      version                   Version,
     *      privateKeyAlgorithm       PrivateKeyAlgorithmIdentifier,
     *      privateKey                PrivateKey,
     *      attributes           [0]  IMPLICIT Attributes OPTIONAL }
     *
     *    Version ::= INTEGER
     *    PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
     *    PrivateKey ::= OCTET STRING
     *
     *  The PrivateKey OCTET STRING is a SEC1 ECPrivateKey
     */

    if( ( ret = asn1_get_tag( &p, end, &len,
            ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 )
    {
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );
    }

    end = p + len;

    if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 )
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );

    if( version != 0 )
        return( POLARSSL_ERR_PK_KEY_INVALID_VERSION + ret );

    if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &params ) ) != 0 )
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );

    if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 )
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret );

    if( len < 1 )
        return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT +
                POLARSSL_ERR_ASN1_OUT_OF_DATA );

    if( ( pk_info = pk_info_from_type( pk_alg ) ) == NULL )
        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

    if( ( ret = pk_init_ctx( pk, pk_info ) ) != 0 )
        return( ret );

#if defined(POLARSSL_RSA_C)
    if( pk_alg == POLARSSL_PK_RSA )
    {
        if( ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), p, len ) ) != 0 )
        {
            pk_free( pk );
            return( ret );
        }
    } else
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECP_C)
    if( pk_alg == POLARSSL_PK_ECKEY || pk_alg == POLARSSL_PK_ECKEY_DH )
    {
        if( ( ret = pk_use_ecparams( &params, &pk_ec( *pk )->grp ) ) != 0 ||
            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), p, len )  ) != 0 )
        {
            pk_free( pk );
            return( ret );
        }
    } else
#endif /* POLARSSL_ECP_C */
        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

    return( 0 );
}
Пример #7
0
/*
 * Parse a private key
 */
int pk_parse_key( pk_context *pk,
                  const unsigned char *key, size_t keylen,
                  const unsigned char *pwd, size_t pwdlen )
{
    int ret;
    const pk_info_t *pk_info;

#if defined(POLARSSL_PEM_PARSE_C)
    size_t len;
    pem_context pem;

    pem_init( &pem );

#if defined(POLARSSL_RSA_C)
    ret = pem_read_buffer( &pem,
                           "-----BEGIN RSA PRIVATE KEY-----",
                           "-----END RSA PRIVATE KEY-----",
                           key, pwd, pwdlen, &len );
    if( ret == 0 )
    {
        if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

        if( ( ret = pk_init_ctx( pk, pk_info                    ) ) != 0 ||
            ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ),
                                            pem.buf, pem.buflen ) ) != 0 )
        {
            pk_free( pk );
        }

        pem_free( &pem );
        return( ret );
    }
    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
        return( ret );
#endif /* POLARSSL_RSA_C */

#if defined(POLARSSL_ECP_C)
    ret = pem_read_buffer( &pem,
                           "-----BEGIN EC PRIVATE KEY-----",
                           "-----END EC PRIVATE KEY-----",
                           key, pwd, pwdlen, &len );
    if( ret == 0 )
    {
        if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
            return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

        if( ( ret = pk_init_ctx( pk, pk_info                   ) ) != 0 ||
            ( ret = pk_parse_key_sec1_der( pk_ec( *pk ),
                                           pem.buf, pem.buflen ) ) != 0 )
        {
            pk_free( pk );
        }

        pem_free( &pem );
        return( ret );
    }
    else if( ret == POLARSSL_ERR_PEM_PASSWORD_MISMATCH )
        return( POLARSSL_ERR_PK_PASSWORD_MISMATCH );
    else if( ret == POLARSSL_ERR_PEM_PASSWORD_REQUIRED )
        return( POLARSSL_ERR_PK_PASSWORD_REQUIRED );
    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
        return( ret );
#endif /* POLARSSL_ECP_C */

    ret = pem_read_buffer( &pem,
                           "-----BEGIN PRIVATE KEY-----",
                           "-----END PRIVATE KEY-----",
                           key, NULL, 0, &len );
    if( ret == 0 )
    {
        if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk,
                                                pem.buf, pem.buflen ) ) != 0 )
        {
            pk_free( pk );
        }

        pem_free( &pem );
        return( ret );
    }
    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
        return( ret );

#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C)
    ret = pem_read_buffer( &pem,
                           "-----BEGIN ENCRYPTED PRIVATE KEY-----",
                           "-----END ENCRYPTED PRIVATE KEY-----",
                           key, NULL, 0, &len );
    if( ret == 0 )
    {
        if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk,
                                                      pem.buf, pem.buflen,
                                                      pwd, pwdlen ) ) != 0 )
        {
            pk_free( pk );
        }

        pem_free( &pem );
        return( ret );
    }
    else if( ret != POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
        return( ret );
#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */
#else
    ((void) pwd);
    ((void) pwdlen);
#endif /* POLARSSL_PEM_PARSE_C */

    /*
    * At this point we only know it's not a PEM formatted key. Could be any
    * of the known DER encoded private key formats
    *
    * We try the different DER format parsers to see if one passes without
    * error
    */
#if defined(POLARSSL_PKCS12_C) || defined(POLARSSL_PKCS5_C)
    if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen,
                                                  pwd, pwdlen ) ) == 0 )
    {
        return( 0 );
    }

    pk_free( pk );

    if( ret == POLARSSL_ERR_PK_PASSWORD_MISMATCH )
    {
        return( ret );
    }
#endif /* POLARSSL_PKCS12_C || POLARSSL_PKCS5_C */

    if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 )
        return( 0 );

    pk_free( pk );

#if defined(POLARSSL_RSA_C)
    if( ( pk_info = pk_info_from_type( POLARSSL_PK_RSA ) ) == NULL )
        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

    if( ( ret = pk_init_ctx( pk, pk_info                           ) ) != 0 ||
        ( ret = pk_parse_key_pkcs1_der( pk_rsa( *pk ), key, keylen ) ) == 0 )
    {
        return( 0 );
    }

    pk_free( pk );
#endif /* POLARSSL_RSA_C */

#if defined(POLARSSL_ECP_C)
    if( ( pk_info = pk_info_from_type( POLARSSL_PK_ECKEY ) ) == NULL )
        return( POLARSSL_ERR_PK_UNKNOWN_PK_ALG );

    if( ( ret = pk_init_ctx( pk, pk_info                         ) ) != 0 ||
        ( ret = pk_parse_key_sec1_der( pk_ec( *pk ), key, keylen ) ) == 0 )
    {
        return( 0 );
    }

    pk_free( pk );
#endif /* POLARSSL_ECP_C */

    return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT );
}
Пример #8
0
result_t PKey::get_publicKey(obj_ptr<PKey_base> &retVal)
{
    result_t hr;
    bool priv;

    hr = isPrivate(priv);
    if (hr < 0)
        return hr;

    if (!priv)
        return CALL_RETURN_NULL;

    pk_type_t type = pk_get_type(&m_key);
    int ret;

    if (type == POLARSSL_PK_RSA)
    {
        rsa_context *rsa = pk_rsa(m_key);
        obj_ptr<PKey> pk1 = new PKey();

        ret = pk_init_ctx(&pk1->m_key, pk_info_from_type(POLARSSL_PK_RSA));
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        rsa_context *rsa1 = pk_rsa(pk1->m_key);

        rsa1->len = rsa->len;
        rsa1->padding = rsa->padding;
        rsa1->hash_id = rsa->hash_id;

        ret = mpi_copy(&rsa1->N, &rsa->N);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ret = mpi_copy(&rsa1->E, &rsa->E);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        retVal = pk1;

        return 0;
    }

    if (type == POLARSSL_PK_ECKEY)
    {
        ecp_keypair *ecp = pk_ec(m_key);

        obj_ptr<PKey> pk1 = new PKey();

        ret = pk_init_ctx(&pk1->m_key, pk_info_from_type(POLARSSL_PK_ECKEY));
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ecp_keypair *ecp1 = pk_ec(pk1->m_key);

        ret = ecp_group_copy(&ecp1->grp, &ecp->grp);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        ret = ecp_copy(&ecp1->Q, &ecp->Q);
        if (ret != 0)
            return CHECK_ERROR(_ssl::setError(ret));

        retVal = pk1;

        return 0;
    }

    return CHECK_ERROR(CALL_E_INVALID_CALL);
}
Пример #9
0
void attacker_send_keys(havege_state *havege_state, void* socket)
  //@ requires attacker_invariant(?pub, ?pred, ?kc, havege_state, socket, ?attacker);
  //@ ensures  attacker_invariant(pub, pred, kc, havege_state, socket, attacker);
{
  pk_context context;
  pk_context context_pub;
  pk_context context_priv;
  unsigned int key_size;

  //@ open attacker_invariant(pub, pred, kc, havege_state, socket, attacker);

  unsigned int temp;
  //@ close_havege_util(pub, pred, attacker);
  r_u_int_with_bounds(havege_state, &temp, 1024, 8192);
  //@ open_havege_util(pub, pred, attacker);
  key_size = temp;
  char* key = malloc((int) key_size);
  if ((key) == 0) abort();
  char* pub_key = malloc((int) key_size);
  if ((pub_key) == 0) abort();
  char* priv_key = malloc((int) key_size);
  if ((priv_key) == 0) abort();

  //@ close random_request(attacker, temp, true);
  if (havege_random(havege_state, key, key_size) != 0) abort();

  //@ close pk_context(&context);
  pk_init(&context);
  //@ close pk_context(&context_pub);
  pk_init(&context_pub);
  //@ close pk_context(&context_priv);
  pk_init(&context_priv);

  if (pk_init_ctx(&context, pk_info_from_type(POLARSSL_PK_RSA)) != 0)
    abort();
  //@ close rsa_key_request(attacker, 0);
  //@ close random_state_predicate(havege_state_initialized);
  /*@ produce_function_pointer_chunk random_function(
                      attacker_key_item_havege_random_stub)
                     (havege_state_initialized)(state, out, len) { call(); } @*/
  if (rsa_gen_key(context.pk_ctx, attacker_key_item_havege_random_stub,
                  havege_state, key_size, 65537) != 0) abort();

  if (pk_write_pubkey_pem(&context, pub_key, key_size) != 0) abort();
  if (pk_write_key_pem(&context, priv_key, key_size) != 0) abort();
  if (pk_parse_public_key(&context_pub, pub_key, key_size) != 0) abort();
  if (pk_parse_key(&context_priv, priv_key, key_size, NULL, 0) != 0) abort();

  //@ assert is_bad_key_is_public(?proof1, pub, pred);
  //@ assert cryptogram(key, key_size, ?key_ccs, ?key_cg);
  //@ proof1(key_cg);
  //@ public_cryptogram(key, key_cg);
  net_send(socket, key, key_size);

  //@ assert is_public_key_is_public(?proof2, pub, pred);
  //@ assert cryptogram(pub_key, key_size, ?pub_key_ccs, ?pub_key_cg);
  //@ proof2(pub_key_cg);
  //@ public_cryptogram(pub_key, pub_key_cg);
  net_send(socket, pub_key, key_size);

  //@ assert is_bad_private_key_is_public(?proof3, pub, pred);
  //@ assert cryptogram(priv_key, key_size, ?priv_key_ccs, ?priv_key_cg);
  //@ proof3(priv_key_cg);
  //@ public_cryptogram(priv_key, priv_key_cg);
  net_send(socket, priv_key, key_size);

  //@ open random_state_predicate(havege_state_initialized);
  //@ pk_release_context_with_keys(&context);
  pk_free(&context);
  //@ open pk_context(&context);
  //@ pk_release_context_with_key(&context_pub);
  pk_free(&context_pub);
  //@ open pk_context(&context_pub);
  //@ pk_release_context_with_key(&context_priv);
  pk_free(&context_priv);
  //@ open pk_context(&context_priv);
  free(key);
  free(pub_key);
  free(priv_key);

  //@ close attacker_invariant(pub, pred, kc, havege_state, socket, attacker);
}
Пример #10
0
int main( int argc, char *argv[] )
{
    int ret = 0;
    pk_context key;
    char buf[1024];
    int i;
    char *p, *q;
    entropy_context entropy;
    ctr_drbg_context ctr_drbg;
    const char *pers = "gen_key";
#if defined(POLARSSL_ECP_C)
    const ecp_curve_info *curve_info;
#endif

    /*
     * Set to sane values
     */
    pk_init( &key );
    memset( buf, 0, sizeof( buf ) );

    if( argc == 0 )
    {
    usage:
        ret = 1;
        printf( USAGE );
#if defined(POLARSSL_ECP_C)
        printf( " availabled ec_curve values:\n" );
        curve_info = ecp_curve_list();
        printf( "    %s (default)\n", curve_info->name );
        while( ( ++curve_info )->name != NULL )
            printf( "    %s\n", curve_info->name );
#endif
        goto exit;
    }

    opt.type                = DFL_TYPE;
    opt.rsa_keysize         = DFL_RSA_KEYSIZE;
    opt.ec_curve            = DFL_EC_CURVE;
    opt.filename            = DFL_FILENAME;
    opt.format              = DFL_FORMAT;
    opt.use_dev_random      = DFL_USE_DEV_RANDOM;

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

        if( strcmp( p, "type" ) == 0 )
        {
            if( strcmp( q, "rsa" ) == 0 )
                opt.type = POLARSSL_PK_RSA;
            else if( strcmp( q, "ec" ) == 0 )
                opt.type = POLARSSL_PK_ECKEY;
            else
                goto usage;
        }
        else if( strcmp( p, "format" ) == 0 )
        {
            if( strcmp( q, "pem" ) == 0 )
                opt.format = FORMAT_PEM;
            else if( strcmp( q, "der" ) == 0 )
                opt.format = FORMAT_DER;
            else
                goto usage;
        }
        else if( strcmp( p, "rsa_keysize" ) == 0 )
        {
            opt.rsa_keysize = atoi( q );
            if( opt.rsa_keysize < 1024 || opt.rsa_keysize > 8192 )
                goto usage;
        }
        else if( strcmp( p, "ec_curve" ) == 0 )
        {
            if( ( curve_info = ecp_curve_info_from_name( q ) ) == NULL )
                goto usage;
            opt.ec_curve = curve_info->grp_id;
        }
        else if( strcmp( p, "filename" ) == 0 )
            opt.filename = q;
        else if( strcmp( p, "use_dev_random" ) == 0 )
        {
            opt.use_dev_random = atoi( q );
            if( opt.use_dev_random < 0 || opt.use_dev_random > 1 )
                goto usage;
        }
        else
            goto usage;
    }

    printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    entropy_init( &entropy );
#if !defined(_WIN32) && defined(POLARSSL_FS_IO)
    if( opt.use_dev_random )
    {
        if( ( ret = entropy_add_source( &entropy, dev_random_entropy_poll,
                                        NULL, DEV_RANDOM_THRESHOLD ) ) != 0 )
        {
            printf( " failed\n  ! entropy_add_source returned -0x%04x\n", -ret );
            goto exit;
        }

        printf("\n    Using /dev/random, so can take a long time! " );
        fflush( stdout );
    }
#endif /* !_WIN32 && POLARSSL_FS_IO */

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

    /*
     * 1.1. Generate the key
     */
    printf( "\n  . Generating the private key ..." );
    fflush( stdout );

    if( ( ret = pk_init_ctx( &key, pk_info_from_type( opt.type ) ) ) != 0 )
    {
        printf( " failed\n  !  pk_init_ctx returned -0x%04x", -ret );
        goto exit;
    }

#if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
    if( opt.type == POLARSSL_PK_RSA )
    {
        ret = rsa_gen_key( pk_rsa( key ), ctr_drbg_random, &ctr_drbg,
                           opt.rsa_keysize, 65537 );
        if( ret != 0 )
        {
            printf( " failed\n  !  rsa_gen_key returned -0x%04x", -ret );
            goto exit;
        }
    }
    else
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECP_C)
    if( opt.type == POLARSSL_PK_ECKEY )
    {
        ret = ecp_gen_key( opt.ec_curve, pk_ec( key ),
                          ctr_drbg_random, &ctr_drbg );
        if( ret != 0 )
        {
            printf( " failed\n  !  rsa_gen_key returned -0x%04x", -ret );
            goto exit;
        }
    }
    else
#endif /* POLARSSL_ECP_C */
    {
        printf( " failed\n  !  key type not supported\n" );
        goto exit;
    }

    /*
     * 1.2 Print the key
     */
    printf( " ok\n  . Key information:\n" );

#if defined(POLARSSL_RSA_C)
    if( pk_get_type( &key ) == POLARSSL_PK_RSA )
    {
        rsa_context *rsa = pk_rsa( key );
        mpi_write_file( "N:  ",  &rsa->N,  16, NULL );
        mpi_write_file( "E:  ",  &rsa->E,  16, NULL );
        mpi_write_file( "D:  ",  &rsa->D,  16, NULL );
        mpi_write_file( "P:  ",  &rsa->P,  16, NULL );
        mpi_write_file( "Q:  ",  &rsa->Q,  16, NULL );
        mpi_write_file( "DP: ",  &rsa->DP, 16, NULL );
        mpi_write_file( "DQ:  ", &rsa->DQ, 16, NULL );
        mpi_write_file( "QP:  ", &rsa->QP, 16, NULL );
    }
    else
#endif
#if defined(POLARSSL_ECP_C)
    if( pk_get_type( &key ) == POLARSSL_PK_ECKEY )
    {
        ecp_keypair *ecp = pk_ec( key );
        printf( "curve: %s\n",
                ecp_curve_info_from_grp_id( ecp->grp.id )->name );
        mpi_write_file( "X_Q:   ", &ecp->Q.X, 16, NULL );
        mpi_write_file( "Y_Q:   ", &ecp->Q.Y, 16, NULL );
        mpi_write_file( "D:     ", &ecp->d  , 16, NULL );
    }
    else
#endif
        printf("  ! key type not supported\n");

    write_private_key( &key, opt.filename );

exit:

    if( ret != 0 && ret != 1)
    {
#ifdef POLARSSL_ERROR_C
        polarssl_strerror( ret, buf, sizeof( buf ) );
        printf( " - %s\n", buf );
#else
        printf("\n");
#endif
    }

    pk_free( &key );
    ctr_drbg_free( &ctr_drbg );
    entropy_free( &entropy );

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

    return( ret );
}