Ejemplo n.º 1
1
	void finish() {
		av_lockmgr_register(nullptr);

		CRYPTO_cleanup_all_ex_data();
		FIPS_mode_set(0);
		ENGINE_cleanup();
		CONF_modules_unload(1);
		ERR_remove_state(0);
		ERR_free_strings();
		ERR_remove_thread_state(nullptr);
		EVP_cleanup();

		delete[] _sslLocks;
		_sslLocks = nullptr;

		Platform::ThirdParty::finish();
	}
Ejemplo n.º 2
1
static void SQBIND_Exit_curl()
{
	oexAutoLock ll( _g_curl_lock );
	if ( !ll.IsLocked() ) 
		return;
	
	// Cleanup curl
	curl_global_cleanup();

	// SSL cleanup sequence
	ERR_remove_state( 0 );
//	ENGINE_cleanup();
	CONF_modules_unload( 1 );
	ERR_free_strings();
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
}
Ejemplo n.º 3
0
static void
openssl_shutdown(void)
{
	CONF_modules_unload(1);
	destroy_ui();
	OBJ_cleanup();
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_remove_thread_state(NULL);
	ERR_free_strings();
}
Ejemplo n.º 4
0
static int luaclose_openssl(lua_State *L)
{
  if(atomic_fetch_sub(&init, 1) > 1)
    return 0;

#if !defined(LIBRESSL_VERSION_NUMBER)
  FIPS_mode_set(0);
#endif

  OBJ_cleanup();
  EVP_cleanup();
  ENGINE_cleanup();
  RAND_cleanup();

#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
  SSL_COMP_free_compression_methods();
#endif
  COMP_zlib_cleanup();


#if OPENSSL_VERSION_NUMBER < 0x10000000L
  ERR_remove_state(0);
#elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  ERR_remove_thread_state(NULL);
#endif
#if defined(OPENSSL_THREADS)
  CRYPTO_thread_cleanup();
#endif
  CRYPTO_set_locking_callback(NULL);
  CRYPTO_set_id_callback(NULL);

  CRYPTO_cleanup_all_ex_data();
  ERR_free_strings();

  CONF_modules_free();
  CONF_modules_unload(1);
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
#if !(defined(OPENSSL_NO_STDIO) || defined(OPENSSL_NO_FP_API))
#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L
  CRYPTO_mem_leaks_fp(stderr);
#else
  if(CRYPTO_mem_leaks_fp(stderr)!=1)
  {
    fprintf(stderr,
            "Please report a bug on https://github.com/zhaozg/lua-openssl."
            "And if can, please provide a reproduce method and minimal code.\n"
            "\n\tThank You.");
  }
#endif
#endif /* OPENSSL_NO_STDIO or OPENSSL_NO_FP_API */
#endif /* OPENSSL_NO_CRYPTO_MDEBUG */
  return 0;
}
Ejemplo n.º 5
0
static void _scallion_cleanupOpenSSL() {
	EVP_cleanup();
	ERR_remove_state(0);
	ERR_free_strings();

	#ifndef DISABLE_ENGINES
	  ENGINE_cleanup();
	#endif

	CONF_modules_unload(1);
	CRYPTO_cleanup_all_ex_data();
}
Ejemplo n.º 6
0
ASocketLibrary_SSL::~ASocketLibrary_SSL()
{
  // Have to make all these calls until OpenSSL adds one function to do it all
  // This accounts for memory leaks inherent in the library on shutdown
  // Not really essential since process is exiting but allows better tracking of other
  //  leaks without getting a flood of leaks from OpenSSL on shutdown
  ERR_remove_state(0);
  ENGINE_cleanup();
  CONF_modules_unload(1);
  ERR_free_strings();
  EVP_cleanup();
  CRYPTO_cleanup_all_ex_data();
}
Ejemplo n.º 7
0
void ape_ssl_library_destroy()
{
    return;
    FIPS_mode_set(0);
    ENGINE_cleanup();
    CONF_modules_unload(1);
    CONF_modules_free();
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
    sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
    ERR_remove_state(0);
    ERR_free_strings();
}
Ejemplo n.º 8
0
void free_ssl(void)
{
	/* free context */
	if(ssl_ctx != NULL) {
		SSL_CTX_free(ssl_ctx);
		ssl_ctx = NULL;
	}
	ERR_remove_state(0);
	ENGINE_cleanup();
	CONF_modules_unload(1);
	ERR_free_strings();
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
}
Ejemplo n.º 9
0
static void SQBIND_ffmpeg_cleanup()
{
	// SSL cleanup sequence
	ERR_remove_state( 0 );
#ifndef OPENSSL_NO_ENGINE
	ENGINE_cleanup();
#endif
	CONF_modules_unload( 1 );
	
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_thread_state(NULL);
	EVP_cleanup();
}
Ejemplo n.º 10
0
void tls_engine_stop()
{
    SSL_CTX* ctx = get_tls_ctx();

    SSL_CTX_free(ctx);
    ctx = NULL;

    ERR_remove_state(0);
    ENGINE_cleanup();
    CONF_modules_unload(1);
    ERR_free_strings();
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
}
Ejemplo n.º 11
0
void
dst__openssl_destroy() {

	/*
	 * Sequence taken from apps_shutdown() in <apps/apps.h>.
	 */
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
	CONF_modules_unload(1);
#endif
	EVP_cleanup();
#if defined(USE_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
	ENGINE_cleanup();
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
	CRYPTO_cleanup_all_ex_data();
#endif
	ERR_clear_error();
	ERR_free_strings();
	ERR_remove_state(0);

#ifdef  DNS_CRYPTO_LEAKS
	CRYPTO_mem_leaks_fp(stderr);
#endif

#if 0
	/*
	 * The old error sequence that leaked.  Remove for 9.4.1 if
	 * there are no issues by then.
	 */
	ERR_clear_error();
#ifdef USE_ENGINE
	if (e != NULL) {
		ENGINE_free(e);
		e = NULL;
	}
#endif
#endif
	if (rm != NULL) {
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
		RAND_cleanup();
#endif
		mem_free(rm);
	}
	if (locks != NULL) {
		CRYPTO_set_locking_callback(NULL);
		DESTROYMUTEXBLOCK(locks, nlocks);
		mem_free(locks);
	}
}
Ejemplo n.º 12
0
Archivo: openssl.c Proyecto: Tilka/uhub
int net_ssl_library_shutdown()
{
	ERR_clear_error();
	ERR_remove_state(0);

	ENGINE_cleanup();
	CONF_modules_unload(1);

        ERR_free_strings();
	EVP_cleanup();
        CRYPTO_cleanup_all_ex_data();

	// sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
	return 1;
}
Ejemplo n.º 13
0
static void
openssl_shutdown(void)
{
	CONF_modules_unload(1);
	destroy_ui_method();
	OBJ_cleanup();
	EVP_cleanup();

#ifndef OPENSSL_NO_ENGINE
	ENGINE_cleanup();
#endif

	CRYPTO_cleanup_all_ex_data();
	ERR_remove_thread_state(NULL);
	RAND_cleanup();
	ERR_free_strings();
}
Ejemplo n.º 14
0
static void apps_shutdown()
{
#ifndef OPENSSL_NO_ENGINE
    ENGINE_cleanup();
#endif
    destroy_ui_method();
    CONF_modules_unload(1);
#ifndef OPENSSL_NO_COMP
    COMP_zlib_cleanup();
    SSL_COMP_free_compression_methods();
#endif
    OBJ_cleanup();
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
    ERR_remove_thread_state(NULL);
    RAND_cleanup();
    ERR_free_strings();
}
Ejemplo n.º 15
0
/**
 * oh_ssl_finit
 *
 * Finalizes the OpenSSL library. The calls used in this routine releases global
 * data created/initialized by the OpenSSL library.
 *
 * Note that it is the responisbility of the caller of this function to make
 * sure that no other threads are making the OpenSSL library calls. The openhpid
 * should close all the threads and call this function from the main (single)
 * thread.
 *
 * Return value: None
 **/
void oh_ssl_finit(void)
{
        /* TODO: Check whether any other SSL library cleanup should be called */
        thread_cleanup();
        ENGINE_cleanup();
        CONF_modules_unload(0);
        ERR_free_strings();
        EVP_cleanup();
        CRYPTO_cleanup_all_ex_data();
        /* The valgrind is showing possible memory leak by
         * SSL_COMP_get_compression_methods() call.
         *
         * Call to SSL_free_comp_methods() may resolve the memory leak.
         * But not able to find this call in the openssl 0.9.8e
         * TODO: Find whether its a real problem or not
         */

}
Ejemplo n.º 16
0
// .. c:function::
ch_error_t
ch_en_openssl_uninit(void)
//    :noindex:
//
//    see: :c:func:`ch_en_openssl_uninit`
//
// .. code-block:: cpp
//
{
    FIPS_mode_set(0);
    ENGINE_cleanup();
    CONF_modules_unload(1);
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
    ERR_free_strings();
    CONF_modules_free();
    return CH_SUCCESS;
}
Ejemplo n.º 17
0
	void finish() {
		av_lockmgr_register(nullptr);

		CRYPTO_cleanup_all_ex_data();
#ifndef LIBRESSL_VERSION_NUMBER
		FIPS_mode_set(0);
#endif
		ENGINE_cleanup();
		CONF_modules_unload(1);
		ERR_remove_state(0);
		ERR_free_strings();
		ERR_remove_thread_state(nullptr);
		EVP_cleanup();

		delete[] base::take(_sslLocks);

		Platform::ThirdParty::finish();
	}
Ejemplo n.º 18
0
void _mosquitto_net_cleanup(void)
{
#ifdef WITH_TLS
	ERR_remove_state(0);
	ENGINE_cleanup();
	CONF_modules_unload(1);
	ERR_free_strings();
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();
#endif

#ifdef WITH_SRV
	ares_library_cleanup();
#endif

#ifdef WIN32
	WSACleanup();
#endif
}
Ejemplo n.º 19
0
/*
   Release SSL and free resources
   Will be automatically executed by 
   mysql_server_end() function

   SYNOPSIS
     my_ssl_end()
       void

   RETURN VALUES
     void
*/
void my_ssl_end()
{
  DBUG_ENTER("my_ssl_end");
  pthread_mutex_lock(&LOCK_ssl_config);
  if (my_ssl_initialized)
  {
    int i;

    if (LOCK_crypto)
    {
      CRYPTO_set_locking_callback(NULL);
      CRYPTO_set_id_callback(NULL);

      for (i=0; i < CRYPTO_num_locks(); i++)
        pthread_mutex_destroy(&LOCK_crypto[i]);

      my_free(LOCK_crypto);
      LOCK_crypto= NULL;
    }

    if (SSL_context)
    {
      SSL_CTX_free(SSL_context);
      SSL_context= FALSE;
    }
    if (mariadb_deinitialize_ssl)
    {
#if OPENSSL_VERSION_NUMBER < 0x10100000
      ERR_remove_state(0);
#endif
      EVP_cleanup();
      CRYPTO_cleanup_all_ex_data();
      ERR_free_strings();
      CONF_modules_free();
      CONF_modules_unload(1);
    }
    my_ssl_initialized= FALSE;
  }
  pthread_mutex_unlock(&LOCK_ssl_config);
  pthread_mutex_destroy(&LOCK_ssl_config);
  DBUG_VOID_RETURN;
}
Ejemplo n.º 20
0
void cleanup_openssl(global_data_t *global_data)
{
	SSL_CTX_free(global_data->ssl_ctx);
	CRYPTO_set_locking_callback(NULL);
	CRYPTO_set_id_callback(NULL);
	CRYPTO_set_dynlock_create_callback(NULL);
	CRYPTO_set_dynlock_destroy_callback(NULL);
	CRYPTO_set_dynlock_lock_callback(NULL);
	ERR_remove_state(0);
	ERR_free_strings();
	CONF_modules_unload(1);
	EVP_cleanup();
	CRYPTO_cleanup_all_ex_data();

	for (size_t i = 0; i < openssl_global_data.num_lock; i++)
		CHECK_ERROR(pthread_mutex_destroy, openssl_global_data.lock + i);

	free(openssl_global_data.lock);
	CHECK_ERROR(pthread_mutexattr_destroy, &openssl_global_data.lock_attr);
}
Ejemplo n.º 21
0
void Stop(int signo)
{
    printf("oops! stop by ctrl+c or kill!!!----------------------------------------\n");
    if(flock(fileno(fd_pid_conf),LOCK_UN) != 0)
    {
        DEBUG_printf("unlock fd_pid_conf failed!\n");
    }
    else
    {
        DEBUG_printf("unlock fd_pid_conf succeed!\n");
    }
    fclose(fd_pid_conf);

    DeleteList(L_cmd);

    p_n_over = false;
    //sleep(5);
    pthread_join(thread_id,NULL);
    //pthread_join(thread_rev,NULL);
    pthread_join(thread_deal_cmd_id,NULL);
    pthread_join(thread_deal_response_id,NULL);

    DestroyQueue(&Q_cmd);
    DestroyQueue(&Q_respond);
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);

    CONF_modules_free();
    ERR_remove_state(0);
    ENGINE_cleanup();
    CONF_modules_unload(1);
    ERR_free_strings();
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
    sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
    exit(0);
}
Ejemplo n.º 22
0
/*
   Release SSL and free resources
   Will be automatically executed by 
   mysql_server_end() function

   SYNOPSIS
     my_ssl_end()
       void

   RETURN VALUES
     void
*/
void ma_tls_end()
{
  if (ma_tls_initialized)
  {
    pthread_mutex_lock(&LOCK_openssl_config);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
    CRYPTO_set_locking_callback(NULL);
    CRYPTO_set_id_callback(NULL);
    {
      int i;
      for (i=0; i < CRYPTO_num_locks(); i++)
        pthread_mutex_destroy(&LOCK_crypto[i]);
    }
    ma_free((gptr)LOCK_crypto);
    LOCK_crypto= NULL;
#endif

    if (SSL_context)
    {
      SSL_CTX_free(SSL_context);
      SSL_context= NULL;
    }
    if (mariadb_deinitialize_ssl)
    {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
      ERR_remove_state(0);
#endif
      EVP_cleanup();
      CRYPTO_cleanup_all_ex_data();
      ERR_free_strings();
      CONF_modules_free();
      CONF_modules_unload(1);
    }
    ma_tls_initialized= FALSE;
    pthread_mutex_unlock(&LOCK_openssl_config);
    pthread_mutex_destroy(&LOCK_openssl_config);
  }
  return;
}
Ejemplo n.º 23
0
/*
 *  the various processing hooks
 */
static apr_status_t ssl_cleanup_pre_config(void *data)
{
    /*
     * Try to kill the internals of the SSL library.
     */
#ifdef HAVE_OPENSSL
#if OPENSSL_VERSION_NUMBER >= 0x00907001
    /* Corresponds to OPENSSL_load_builtin_modules():
     * XXX: borrowed from apps.h, but why not CONF_modules_free()
     * which also invokes CONF_modules_finish()?
     */
    CONF_modules_unload(1);
#endif
#endif
    /* Corresponds to SSL_library_init: */
    EVP_cleanup();
#if HAVE_ENGINE_LOAD_BUILTIN_ENGINES
    ENGINE_cleanup();
#endif
    ERR_remove_state(0);

    /* Don't call ERR_free_strings here; ERR_load_*_strings only
     * actually load the error strings once per process due to static
     * variable abuse in OpenSSL. */

    /* Also don't call CRYPTO_cleanup_all_ex_data here; any registered
     * ex_data indices may have been cached in static variables in
     * OpenSSL; removing them may cause havoc.  Notably, with OpenSSL
     * versions >= 0.9.8f, COMP_CTX cleanups would not be run, which
     * could result in a per-connection memory leak (!). */

    /*
     * TODO: determine somewhere we can safely shove out diagnostics
     *       (when enabled) at this late stage in the game:
     * CRYPTO_mem_leaks_fp(stderr);
     */
    return APR_SUCCESS;
}
Ejemplo n.º 24
0
void OpenSSLSession::Stop()
{
	if(!m_bStarted)
	{
		return;
	}

	if(m_ConnectionCtx)
	{
		SSL_CTX_free(m_ConnectionCtx);
		m_ConnectionCtx = 0;
	}

	ERR_remove_state(0);
	ENGINE_cleanup();
	CONF_modules_unload(1);
	ERR_free_strings();
	EVP_cleanup();
	sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
	CRYPTO_cleanup_all_ex_data();

	m_bStarted = false;
}
Ejemplo n.º 25
0
/*
   Release SSL and free resources
   Will be automatically executed by 
   mysql_server_end() function

   SYNOPSIS
     my_ssl_end()
       void

   RETURN VALUES
     void
*/
void ma_tls_end()
{
  if (ma_tls_initialized)
  {
    int i;
    pthread_mutex_lock(&LOCK_openssl_config);
    CRYPTO_set_locking_callback(NULL);
    CRYPTO_set_id_callback(NULL);

    for (i=0; i < CRYPTO_num_locks(); i++)
      pthread_mutex_destroy(&LOCK_crypto[i]);

    ma_free((gptr)LOCK_crypto);
    LOCK_crypto= NULL;

    if (SSL_context)
    {
      SSL_CTX_free(SSL_context);
      SSL_context= NULL;
    }
    if (mariadb_deinitialize_ssl)
    {
      ERR_remove_state(0);
      EVP_cleanup();
      CRYPTO_cleanup_all_ex_data();
      ERR_free_strings();
      CONF_modules_free();
      CONF_modules_unload(1);
      sk_SSL_COMP_free(SSL_COMP_get_compression_methods());
    }
    ma_tls_initialized= FALSE;
    pthread_mutex_unlock(&LOCK_openssl_config);
    pthread_mutex_destroy(&LOCK_openssl_config);
  }
  return;
}
Ejemplo n.º 26
0
Archivo: tor.c Proyecto: postfix/libtor
void
tor_cleanup (void)
{
	if (!initialized) {
		return;
	}

	EVP_cleanup();
	ERR_remove_state(0);
	ERR_free_strings();

	ENGINE_cleanup();

	CONF_modules_unload(1);
	CRYPTO_cleanup_all_ex_data();

	// cleanup multithreading
	for (size_t i = 0; i < locks.length; i++) {
		uv_mutex_destroy(&locks.item[i]);
	}

	free(locks.item);
	locks.length = 0;
}
Ejemplo n.º 27
0
/*
 * OpenSSL provides SSL, TLS and general purpose cryptography.  It wraps the
 * OpenSSL[http://www.openssl.org/] library.
 *
 * = Examples
 *
 * All examples assume you have loaded OpenSSL with:
 *
 *   require 'openssl'
 *
 * These examples build atop each other.  For example the key created in the
 * next is used in throughout these examples.
 *
 * == Keys
 *
 * === Creating a Key
 *
 * This example creates a 2048 bit RSA keypair and writes it to the current
 * directory.
 *
 *   key = OpenSSL::PKey::RSA.new 2048
 *
 *   open 'private_key.pem', 'w' do |io| io.write key.to_pem end
 *   open 'public_key.pem', 'w' do |io| io.write key.public_key.to_pem end
 *
 * === Exporting a Key
 *
 * Keys saved to disk without encryption are not secure as anyone who gets
 * ahold of the key may use it unless it is encrypted.  In order to securely
 * export a key you may export it with a pass phrase.
 *
 *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
 *   pass_phrase = 'my secure pass phrase goes here'
 *
 *   key_secure = key.export cipher, pass_phrase
 *
 *   open 'private.secure.pem', 'w' do |io|
 *     io.write key_secure
 *   end
 *
 * OpenSSL::Cipher.ciphers returns a list of available ciphers.
 *
 * === Loading a Key
 *
 * A key can also be loaded from a file.
 *
 *   key2 = OpenSSL::PKey::RSA.new File.read 'private_key.pem'
 *   key2.public? # => true
 *
 * or
 *
 *   key3 = OpenSSL::PKey::RSA.new File.read 'public_key.pem'
 *   key3.private? # => false
 *
 * === Loading an Encrypted Key
 *
 * OpenSSL will prompt you for your pass phrase when loading an encrypted key.
 * If you will not be able to type in the pass phrase you may provide it when
 * loading the key:
 *
 *   key4_pem = File.read 'private.secure.pem'
 *   key4 = OpenSSL::PKey::RSA.new key4_pem, pass_phrase
 *
 * == RSA Encryption
 *
 * RSA provides encryption and decryption using the public and private keys.
 * You can use a variety of padding methods depending upon the intended use of
 * encrypted data.
 *
 * === Encryption & Decryption
 *
 * Asymmetric public/private key encryption is slow and victim to attack in
 * cases where it is used without padding or directly to encrypt larger chunks
 * of data. Typical use cases for RSA encryption involve "wrapping" a symmetric
 * key with the public key of the recipient who would "unwrap" that symmetric
 * key again using their private key.
 * The following illustrates a simplified example of such a key transport
 * scheme. It shouldn't be used in practice, though, standardized protocols
 * should always be preferred.
 *
 *   wrapped_key = key.public_encrypt key
 *
 * A symmetric key encrypted with the public key can only be decrypted with
 * the corresponding private key of the recipient.
 *
 *   original_key = key.private_decrypt wrapped_key
 *
 * By default PKCS#1 padding will be used, but it is also possible to use
 * other forms of padding, see PKey::RSA for further details.
 *
 * === Signatures
 *
 * Using "private_encrypt" to encrypt some data with the private key is
 * equivalent to applying a digital signature to the data. A verifying
 * party may validate the signature by comparing the result of decrypting
 * the signature with "public_decrypt" to the original data. However,
 * OpenSSL::PKey already has methods "sign" and "verify" that handle
 * digital signatures in a standardized way - "private_encrypt" and
 * "public_decrypt" shouldn't be used in practice.
 *
 * To sign a document, a cryptographically secure hash of the document is
 * computed first, which is then signed using the private key.
 *
 *   digest = OpenSSL::Digest::SHA256.new
 *   signature = key.sign digest, document
 *
 * To validate the signature, again a hash of the document is computed and
 * the signature is decrypted using the public key. The result is then
 * compared to the hash just computed, if they are equal the signature was
 * valid.
 *
 *   digest = OpenSSL::Digest::SHA256.new
 *   if key.verify digest, signature, document
 *     puts 'Valid'
 *   else
 *     puts 'Invalid'
 *   end
 *
 * == PBKDF2 Password-based Encryption
 *
 * If supported by the underlying OpenSSL version used, Password-based
 * Encryption should use the features of PKCS5. If not supported or if
 * required by legacy applications, the older, less secure methods specified
 * in RFC 2898 are also supported (see below).
 *
 * PKCS5 supports PBKDF2 as it was specified in PKCS#5
 * v2.0[http://www.rsa.com/rsalabs/node.asp?id=2127]. It still uses a
 * password, a salt, and additionally a number of iterations that will
 * slow the key derivation process down. The slower this is, the more work
 * it requires being able to brute-force the resulting key.
 *
 * === Encryption
 *
 * The strategy is to first instantiate a Cipher for encryption, and
 * then to generate a random IV plus a key derived from the password
 * using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
 * the number of iterations largely depends on the hardware being used.
 *
 *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
 *   cipher.encrypt
 *   iv = cipher.random_iv
 *
 *   pwd = 'some hopefully not to easily guessable password'
 *   salt = OpenSSL::Random.random_bytes 16
 *   iter = 20000
 *   key_len = cipher.key_len
 *   digest = OpenSSL::Digest::SHA256.new
 *
 *   key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
 *   cipher.key = key
 *
 *   Now encrypt the data:
 *
 *   encrypted = cipher.update document
 *   encrypted << cipher.final
 *
 * === Decryption
 *
 * Use the same steps as before to derive the symmetric AES key, this time
 * setting the Cipher up for decryption.
 *
 *   cipher = OpenSSL::Cipher.new 'AES-128-CBC'
 *   cipher.decrypt
 *   cipher.iv = iv # the one generated with #random_iv
 *
 *   pwd = 'some hopefully not to easily guessable password'
 *   salt = ... # the one generated above
 *   iter = 20000
 *   key_len = cipher.key_len
 *   digest = OpenSSL::Digest::SHA256.new
 *
 *   key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
 *   cipher.key = key
 *
 *   Now decrypt the data:
 *
 *   decrypted = cipher.update encrypted
 *   decrypted << cipher.final
 *
 * == PKCS #5 Password-based Encryption
 *
 * PKCS #5 is a password-based encryption standard documented at
 * RFC2898[http://www.ietf.org/rfc/rfc2898.txt].  It allows a short password or
 * passphrase to be used to create a secure encryption key. If possible, PBKDF2
 * as described above should be used if the circumstances allow it.
 *
 * PKCS #5 uses a Cipher, a pass phrase and a salt to generate an encryption
 * key.
 *
 *   pass_phrase = 'my secure pass phrase goes here'
 *   salt = '8 octets'
 *
 * === Encryption
 *
 * First set up the cipher for encryption
 *
 *   encrypter = OpenSSL::Cipher.new 'AES-128-CBC'
 *   encrypter.encrypt
 *   encrypter.pkcs5_keyivgen pass_phrase, salt
 *
 * Then pass the data you want to encrypt through
 *
 *   encrypted = encrypter.update 'top secret document'
 *   encrypted << encrypter.final
 *
 * === Decryption
 *
 * Use a new Cipher instance set up for decryption
 *
 *   decrypter = OpenSSL::Cipher.new 'AES-128-CBC'
 *   decrypter.decrypt
 *   decrypter.pkcs5_keyivgen pass_phrase, salt
 *
 * Then pass the data you want to decrypt through
 *
 *   plain = decrypter.update encrypted
 *   plain << decrypter.final
 *
 * == X509 Certificates
 *
 * === Creating a Certificate
 *
 * This example creates a self-signed certificate using an RSA key and a SHA1
 * signature.
 *
 *   name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
 *
 *   cert = OpenSSL::X509::Certificate.new
 *   cert.version = 2
 *   cert.serial = 0
 *   cert.not_before = Time.now
 *   cert.not_after = Time.now + 3600
 *
 *   cert.public_key = key.public_key
 *   cert.subject = name
 *
 * === Certificate Extensions
 *
 * You can add extensions to the certificate with
 * OpenSSL::SSL::ExtensionFactory to indicate the purpose of the certificate.
 *
 *   extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
 *
 *   cert.add_extension \
 *     extension_factory.create_extension('basicConstraints', 'CA:FALSE', true)
 *
 *   cert.add_extension \
 *     extension_factory.create_extension(
 *       'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
 *
 *   cert.add_extension \
 *     extension_factory.create_extension('subjectKeyIdentifier', 'hash')
 *
 * The list of supported extensions (and in some cases their possible values)
 * can be derived from the "objects.h" file in the OpenSSL source code.
 *
 * === Signing a Certificate
 *
 * To sign a certificate set the issuer and use OpenSSL::X509::Certificate#sign
 * with a digest algorithm.  This creates a self-signed cert because we're using
 * the same name and key to sign the certificate as was used to create the
 * certificate.
 *
 *   cert.issuer = name
 *   cert.sign key, OpenSSL::Digest::SHA1.new
 *
 *   open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
 *
 * === Loading a Certificate
 *
 * Like a key, a cert can also be loaded from a file.
 *
 *   cert2 = OpenSSL::X509::Certificate.new File.read 'certificate.pem'
 *
 * === Verifying a Certificate
 *
 * Certificate#verify will return true when a certificate was signed with the
 * given public key.
 *
 *   raise 'certificate can not be verified' unless cert2.verify key
 *
 * == Certificate Authority
 *
 * A certificate authority (CA) is a trusted third party that allows you to
 * verify the ownership of unknown certificates.  The CA issues key signatures
 * that indicate it trusts the user of that key.  A user encountering the key
 * can verify the signature by using the CA's public key.
 *
 * === CA Key
 *
 * CA keys are valuable, so we encrypt and save it to disk and make sure it is
 * not readable by other users.
 *
 *   ca_key = OpenSSL::PKey::RSA.new 2048
 *
 *   cipher = OpenSSL::Cipher::Cipher.new 'AES-128-CBC'
 *
 *   open 'ca_key.pem', 'w', 0400 do |io|
 *     io.write ca_key.export(cipher, pass_phrase)
 *   end
 *
 * === CA Certificate
 *
 * A CA certificate is created the same way we created a certificate above, but
 * with different extensions.
 *
 *   ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
 *
 *   ca_cert = OpenSSL::X509::Certificate.new
 *   ca_cert.serial = 0
 *   ca_cert.version = 2
 *   ca_cert.not_before = Time.now
 *   ca_cert.not_after = Time.now + 86400
 *
 *   ca_cert.public_key = ca_key.public_key
 *   ca_cert.subject = ca_name
 *   ca_cert.issuer = ca_name
 *
 *   extension_factory = OpenSSL::X509::ExtensionFactory.new
 *   extension_factory.subject_certificate = ca_cert
 *   extension_factory.issuer_certificate = ca_cert
 *
 *   ca_cert.add_extension \
 *     extension_factory.create_extension('subjectKeyIdentifier', 'hash')
 *
 * This extension indicates the CA's key may be used as a CA.
 *
 *   ca_cert.add_extension \
 *     extension_factory.create_extension('basicConstraints', 'CA:TRUE', true)
 *
 * This extension indicates the CA's key may be used to verify signatures on
 * both certificates and certificate revocations.
 *
 *   ca_cert.add_extension \
 *     extension_factory.create_extension(
 *       'keyUsage', 'cRLSign,keyCertSign', true)
 *
 * Root CA certificates are self-signed.
 *
 *   ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
 *
 * The CA certificate is saved to disk so it may be distributed to all the
 * users of the keys this CA will sign.
 *
 *   open 'ca_cert.pem', 'w' do |io|
 *     io.write ca_cert.to_pem
 *   end
 *
 * === Certificate Signing Request
 *
 * The CA signs keys through a Certificate Signing Request (CSR).  The CSR
 * contains the information necessary to identify the key.
 *
 *   csr = OpenSSL::X509::Request.new
 *   csr.version = 0
 *   csr.subject = name
 *   csr.public_key = key.public_key
 *   csr.sign key, OpenSSL::Digest::SHA1.new
 *
 * A CSR is saved to disk and sent to the CA for signing.
 *
 *   open 'csr.pem', 'w' do |io|
 *     io.write csr.to_pem
 *   end
 *
 * === Creating a Certificate from a CSR
 *
 * Upon receiving a CSR the CA will verify it before signing it.  A minimal
 * verification would be to check the CSR's signature.
 *
 *   csr = OpenSSL::X509::Request.new File.read 'csr.pem'
 *
 *   raise 'CSR can not be verified' unless csr.verify csr.public_key
 *
 * After verification a certificate is created, marked for various usages,
 * signed with the CA key and returned to the requester.
 *
 *   csr_cert = OpenSSL::X509::Certificate.new
 *   csr_cert.serial = 0
 *   csr_cert.version = 2
 *   csr_cert.not_before = Time.now
 *   csr_cert.not_after = Time.now + 600
 *
 *   csr_cert.subject = csr.subject
 *   csr_cert.public_key = csr.public_key
 *   csr_cert.issuer = ca_cert.subject
 *
 *   extension_factory = OpenSSL::X509::ExtensionFactory.new
 *   extension_factory.subject_certificate = csr_cert
 *   extension_factory.issuer_certificate = ca_cert
 *
 *   csr_cert.add_extension \
 *     extension_factory.create_extension('basicConstraints', 'CA:FALSE')
 *
 *   csr_cert.add_extension \
 *     extension_factory.create_extension(
 *       'keyUsage', 'keyEncipherment,dataEncipherment,digitalSignature')
 *
 *   csr_cert.add_extension \
 *     extension_factory.create_extension('subjectKeyIdentifier', 'hash')
 *
 *   csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
 *
 *   open 'csr_cert.pem', 'w' do |io|
 *     io.write csr_cert.to_pem
 *   end
 *
 * == SSL and TLS Connections
 *
 * Using our created key and certificate we can create an SSL or TLS connection.
 * An SSLContext is used to set up an SSL session.
 *
 *   context = OpenSSL::SSL::SSLContext.new
 *
 * === SSL Server
 *
 * An SSL server requires the certificate and private key to communicate
 * securely with its clients:
 *
 *   context.cert = cert
 *   context.key = key
 *
 * Then create an SSLServer with a TCP server socket and the context.  Use the
 * SSLServer like an ordinary TCP server.
 *
 *   require 'socket'
 *
 *   tcp_server = TCPServer.new 5000
 *   ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
 *
 *   loop do
 *     ssl_connection = ssl_server.accept
 *
 *     data = connection.gets
 *
 *     response = "I got #{data.dump}"
 *     puts response
 *
 *     connection.puts "I got #{data.dump}"
 *     connection.close
 *   end
 *
 * === SSL client
 *
 * An SSL client is created with a TCP socket and the context.
 * SSLSocket#connect must be called to initiate the SSL handshake and start
 * encryption.  A key and certificate are not required for the client socket.
 *
 *   require 'socket'
 *
 *   tcp_client = TCPSocket.new 'localhost', 5000
 *   ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
 *   ssl_client.connect
 *
 *   ssl_client.puts "hello server!"
 *   puts ssl_client.gets
 *
 * === Peer Verification
 *
 * An unverified SSL connection does not provide much security.  For enhanced
 * security the client or server can verify the certificate of its peer.
 *
 * The client can be modified to verify the server's certificate against the
 * certificate authority's certificate:
 *
 *   context.ca_file = 'ca_cert.pem'
 *   context.verify_mode = OpenSSL::SSL::VERIFY_PEER
 *
 *   require 'socket'
 *
 *   tcp_client = TCPSocket.new 'localhost', 5000
 *   ssl_client = OpenSSL::SSL::SSLSocket.new client_socket, context
 *   ssl_client.connect
 *
 *   ssl_client.puts "hello server!"
 *   puts ssl_client.gets
 *
 * If the server certificate is invalid or <tt>context.ca_file</tt> is not set
 * when verifying peers an OpenSSL::SSL::SSLError will be raised.
 *
 */
void
Init_openssl()
{
    /*
     * Init timezone info
     */
#if 0
    tzset();
#endif

    /*
     * Init all digests, ciphers
     */
    /* CRYPTO_malloc_init(); */
    /* ENGINE_load_builtin_engines(); */
    OpenSSL_add_ssl_algorithms();
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
    SSL_load_error_strings();

    /*
     * FIXME:
     * On unload do:
     */
#if 0
    CONF_modules_unload(1);
    destroy_ui_method();
    EVP_cleanup();
    ENGINE_cleanup();
    CRYPTO_cleanup_all_ex_data();
    ERR_remove_state(0);
    ERR_free_strings();
#endif

    /*
     * Init main module
     */
    mOSSL = rb_define_module("OpenSSL");
    rb_global_variable(&mOSSL);

    /*
     * OpenSSL ruby extension version
     */
    rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));

    /*
     * Version of OpenSSL the ruby OpenSSL extension was built with
     */
    rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));

    /*
     * Version number of OpenSSL the ruby OpenSSL extension was built with
     * (base 16)
     */
    rb_define_const(mOSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));

    /*
     * Boolean indicating whether OpenSSL is FIPS-enabled or not
     */
#ifdef HAVE_OPENSSL_FIPS
    rb_define_const(mOSSL, "OPENSSL_FIPS", Qtrue);
#else
    rb_define_const(mOSSL, "OPENSSL_FIPS", Qfalse);
#endif
    rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);

    /*
     * Generic error,
     * common for all classes under OpenSSL module
     */
    eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
    rb_global_variable(&eOSSLError);

    /*
     * Verify callback Proc index for ext-data
     */
    if ((ossl_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"ossl_verify_cb_idx", 0, 0, 0)) < 0)
        ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");

    /*
     * Init debug core
     */
    dOSSL = Qfalse;
    rb_global_variable(&dOSSL);

    rb_define_module_function(mOSSL, "debug", ossl_debug_get, 0);
    rb_define_module_function(mOSSL, "debug=", ossl_debug_set, 1);
    rb_define_module_function(mOSSL, "errors", ossl_get_errors, 0);

    /*
     * Get ID of to_der
     */
    ossl_s_to_der = rb_intern("to_der");

    Init_ossl_locks();

    /*
     * Init components
     */
    Init_ossl_bn();
    Init_ossl_cipher();
    Init_ossl_config();
    Init_ossl_digest();
    Init_ossl_hmac();
    Init_ossl_ns_spki();
    Init_ossl_pkcs12();
    Init_ossl_pkcs7();
    Init_ossl_pkcs5();
    Init_ossl_pkey();
    Init_ossl_rand();
    Init_ossl_ssl();
    Init_ossl_x509();
    Init_ossl_ocsp();
    Init_ossl_engine();
    Init_ossl_asn1();
}
Ejemplo n.º 28
0
// NOTE: we do not cleanup in reverse initialization order
// the threading subsystem is deleted before the modules are
// unloaded in case there are any module-specific thread
// cleanup functions to be run...
void qore_cleanup() {
   // first delete all user modules
   QMM.delUser();

#ifdef _Q_WINDOWS 
   // do windows socket cleanup
   WSACleanup();
#endif

#ifdef HAVE_SIGNAL_HANDLING
   // stop signal manager
   QSM.del();
#endif

   // purge thread resources before deleting modules
   {
      ExceptionSink xsink;
      purge_thread_resources(&xsink);
   }

   // delete all loadable modules
   QMM.cleanup();

   // delete thread-local data
   delete_thread_local_data();

   // now free memory (like ARGV, QORE_ARGV, ENV, etc)
   delete_global_variables();

   // delete pseudo-methods
   pseudo_classes_del();

   // delete static system namespace after modules
   delete staticSystemNamespace;
#ifdef DEBUG
   staticSystemNamespace = 0;
#endif

   // delete default type values
   delete_qore_types();

   // delete threading infrastructure
   delete_qore_threads();

   // only perform openssl cleanup if not performed externally
   if (!qore_check_option(QLO_DISABLE_OPENSSL_CLEANUP)) {
      // cleanup openssl library
      ERR_free_strings();

      ENGINE_cleanup();
      EVP_cleanup();

      CONF_modules_finish();
      CONF_modules_free();
      CONF_modules_unload(1);

      CRYPTO_cleanup_all_ex_data();

      CRYPTO_set_id_callback(0);
      CRYPTO_set_locking_callback(0);

      // delete openssl locks
      for (mutex_vec_t::iterator i = q_openssl_mutex_list.begin(), e = q_openssl_mutex_list.end(); i != e; ++i)
	 delete *i;
   }
   printd(5, "qore_cleanup() exiting cleanly\n");
}
Ejemplo n.º 29
0
int main(int argc, char **argv)
{
	EVP_PKEY *private_key, *public_key;
	EVP_PKEY_CTX *pkey_ctx;
	EVP_MD_CTX *md_ctx;

	const EVP_MD *digest_algo;

	char *private_key_name, *public_key_name;

	unsigned char sig[4096];
	size_t sig_len;

	unsigned char md[128];
	size_t md_len;
	unsigned digest_len;

	char *key_pass = NULL;
	const char *module_path, *efile;

	ENGINE *e;

	int ret;

	if (argc < 5) {
		fprintf(stderr, "usage: %s [PIN] [CONF] [private key URL] [public key URL] [module]\n", argv[0]);
		fprintf(stderr, "\n");
		exit(1);
	}

	key_pass = argv[1];
	efile = argv[2];
	private_key_name = argv[3];
	public_key_name = argv[4];
	module_path = argv[5];

	ret = CONF_modules_load_file(efile, "engines", 0);
	if (ret <= 0) {
		fprintf(stderr, "cannot load %s\n", efile);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	ENGINE_add_conf_module();
#if OPENSSL_VERSION_NUMBER>=0x10100000
	OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
		| OPENSSL_INIT_ADD_ALL_DIGESTS \
		| OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
	OpenSSL_add_all_algorithms();
	OpenSSL_add_all_digests();
	ERR_load_crypto_strings();
#endif
	ERR_clear_error();

	ENGINE_load_builtin_engines();
	e = ENGINE_by_id("pkcs11");
	if (e == NULL) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_ctrl_cmd_string(e, "VERBOSE", NULL, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", module_path, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_init(e)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (key_pass && !ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	private_key = ENGINE_load_private_key(e, private_key_name, NULL, NULL);
	if (private_key == NULL) {
		fprintf(stderr, "cannot load: %s\n", private_key_name);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	public_key = ENGINE_load_public_key(e, public_key_name, NULL, NULL);
	if (public_key == NULL) {
		fprintf(stderr, "cannot load: %s\n", public_key_name);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	digest_algo = EVP_get_digestbyname("sha256");

#define TEST_DATA "test data"

	md_ctx = EVP_MD_CTX_create();
	if (EVP_DigestInit(md_ctx, digest_algo) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_DigestUpdate(md_ctx, TEST_DATA, sizeof(TEST_DATA)) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	digest_len = sizeof(md);
	if (EVP_DigestFinal(md_ctx, md, &digest_len) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}
	md_len = digest_len;

	EVP_MD_CTX_destroy(md_ctx);

	/* Sign the hash */
	pkey_ctx = EVP_PKEY_CTX_new(private_key, e);

	if (pkey_ctx == NULL) {
		fprintf(stderr, "Could not create context\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_sign_init(pkey_ctx) <= 0) {
		fprintf(stderr, "Could not init signature\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
		fprintf(stderr, "Could not set padding\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) {
		fprintf(stderr, "Could not set message digest algorithm\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	sig_len = sizeof(sig);
	if (EVP_PKEY_sign(pkey_ctx, sig, &sig_len, md,
			EVP_MD_size(digest_algo)) <= 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	EVP_PKEY_CTX_free(pkey_ctx);

	printf("Signature created\n");

#if OPENSSL_VERSION_NUMBER >= 0x1000000fL

	pkey_ctx = EVP_PKEY_CTX_new(public_key, e);

	if (pkey_ctx == NULL) {
		fprintf(stderr, "Could not create context\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_verify_init(pkey_ctx) <= 0) {
		fprintf(stderr, "Could not init verify\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) <= 0) {
		fprintf(stderr, "Could not set padding\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (EVP_PKEY_CTX_set_signature_md(pkey_ctx, digest_algo) <= 0) {
		fprintf(stderr, "Could not set message digest algorithm\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

	ret = EVP_PKEY_verify(pkey_ctx, sig, sig_len, md, md_len);
	if (ret < 0) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	EVP_PKEY_CTX_free(pkey_ctx);

	if (ret == 1) {
		printf("Signature verified\n");
	}
	else {
		printf("Verification failed\n");
		display_openssl_errors(__LINE__);
		exit(1);
	}

#else /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */

	printf("Unable to verify signature with %s\n", OPENSSL_VERSION_TEXT);

#endif /* OPENSSL_VERSION_NUMBER >= 0x1000000fL */

	ENGINE_finish(e);
	CONF_modules_unload(1);
	return 0;
}
Ejemplo n.º 30
0
int main(int argc, char *argv[])
{
	ENGINE *engine;
	EVP_PKEY *pkey;
	X509 *cert;
	FILE *cert_fp;

	const char *module, *efile, *certfile, *privkey;

	int ret = 0;

	if (argc < 4){
		printf("Too few arguments\n");
		usage(argv);
		return 1;
	}

	certfile = argv[1];
	privkey = argv[2];
	module = argv[3];
	efile = argv[4];

	cert_fp = fopen(certfile, "rb");
	if (!cert_fp) {
		fprintf(stderr, "%s:%d Could not open file %s\n", __FILE__, __LINE__, certfile);
		ret = 1;
		goto end;
	}

	cert = PEM_read_X509(cert_fp, NULL, NULL, NULL);
	if (!cert) {
		fprintf(stderr, "%s:%d Could not read certificate file"
		        "(must be PEM format)\n", __FILE__, __LINE__);
	}

	if (cert_fp) {
		fclose(cert_fp);
	}

	ret = CONF_modules_load_file(efile, "engines", 0);
	if (ret <= 0) {
		fprintf(stderr, "%s:%d cannot load %s\n", __FILE__, __LINE__, efile);
		display_openssl_errors(__LINE__);
		exit(1);
	}

	ENGINE_add_conf_module();
#if OPENSSL_VERSION_NUMBER>=0x10100000
	OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
		| OPENSSL_INIT_ADD_ALL_DIGESTS \
		| OPENSSL_INIT_LOAD_CONFIG, NULL);
#else
	OpenSSL_add_all_algorithms();
	OpenSSL_add_all_digests();
	ERR_load_crypto_strings();
#endif
	ERR_clear_error();

	ENGINE_load_builtin_engines();

	engine = ENGINE_by_id("pkcs11");
	if (engine == NULL) {
		printf("%s:%d Could not get engine\n", __FILE__, __LINE__);
		display_openssl_errors(__LINE__);
		ret = 1;
		goto end;
	}

	if (!ENGINE_ctrl_cmd_string(engine, "VERBOSE", NULL, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_ctrl_cmd_string(engine, "MODULE_PATH", module, 0)) {
		display_openssl_errors(__LINE__);
		exit(1);
	}

	if (!ENGINE_init(engine)) {
		printf("Could not initialize engine\n");
		display_openssl_errors(__LINE__);
		ret = 1;
		goto end;
	}

	pkey = ENGINE_load_private_key(engine, privkey, 0, 0);

	if (pkey == NULL) {
		printf("%s:%d Could not load key\n", __FILE__, __LINE__);
		display_openssl_errors(__LINE__);
		ret = 1;
		goto end;
	}



	ret = X509_check_private_key(cert, pkey);
	if (!ret) {
		printf("%s:%d Could not check private key\n", __FILE__, __LINE__);
		display_openssl_errors(__LINE__);
		ret = 1;
		goto end;
	}

	printf("Key and certificate matched\n");
	ret = 0;

	CONF_modules_unload(1);
end:
	X509_free(cert);
	EVP_PKEY_free(pkey);
	
	ENGINE_finish(engine);

	return ret;
}