Exemple #1
0
DH *ssl_dh_GetTmpParam(int nKeyLen)
{
    DH *dh;

    if (nKeyLen == 512)
        dh = get_dh512();
    else if (nKeyLen == 1024)
        dh = get_dh1024();
    else
        dh = get_dh1024();
    return dh;
}
Exemple #2
0
VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
    VALUE obj;
    SSL_CTX* ctx;
    SSL* ssl;

    ms_conn* conn = engine_alloc(self, &obj);

    ID sym_key = rb_intern("key");
    VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0);

    ID sym_cert = rb_intern("cert");
    VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);

    ID sym_ca = rb_intern("ca");
    VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);

    ID sym_verify_mode = rb_intern("verify_mode");
    VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);

    ctx = SSL_CTX_new(SSLv23_server_method());
    conn->ctx = ctx;

    SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert));
    SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);

    if (!NIL_P(ca)) {
        SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
    }

    SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION);
    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);

    SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH");

    DH *dh = get_dh1024();
    SSL_CTX_set_tmp_dh(ctx, dh);

#ifndef OPENSSL_NO_ECDH
    EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
    if (ecdh) {
        SSL_CTX_set_tmp_ecdh(ctx, ecdh);
        EC_KEY_free(ecdh);
    }
#endif

    ssl = SSL_new(ctx);
    conn->ssl = ssl;
    SSL_set_app_data(ssl, NULL);

    if (NIL_P(verify_mode)) {
        /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
    } else {
        SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
    }

    SSL_set_bio(ssl, conn->read, conn->write);

    SSL_set_accept_state(ssl);
    return obj;
}
Exemple #3
0
int
ssl_setup(SSL_CTX **ctxp, struct pki *pki)
{
	DH	*dh;
	SSL_CTX	*ctx;

	ctx = ssl_ctx_create(pki->pki_name, pki->pki_cert, pki->pki_cert_len);

	if (!SSL_CTX_set_session_id_context(ctx,
		(const unsigned char *)pki->pki_name,
		strlen(pki->pki_name) + 1))
		goto err;

	if (pki->pki_dhparams_len == 0)
		dh = get_dh1024();
	else
		dh = get_dh_from_memory(pki->pki_dhparams,
		    pki->pki_dhparams_len);
	ssl_set_ephemeral_key_exchange(ctx, dh);
	DH_free(dh);

	ssl_set_ecdh_curve(ctx, SSL_ECDH_CURVE);

	*ctxp = ctx;
	return 1;

err:
	SSL_CTX_free(ctx);
	ssl_error("ssl_setup");
	return 0;
}
/*
 * This function generates my Diffie Hellmann parameter
 */
DH* dh_genkey(){
	DH *dh = get_dh1024();
	if(DH_generate_key(dh)!=1){
		DH_free(dh);
		return NULL;
	}
	return dh;
}
Exemple #5
0
/* From OpenSSL's documentation:
 *
 * If "strong" primes were used to generate the DH parameters, it is
 * not strictly necessary to generate a new key for each handshake
 * but it does improve forward secrecy.
 *
 * -- gilles@
 */
DH *
get_dh(void)
{
#if defined(USE_DH1024)
	return get_dh1024();
#else
	return get_dh2048();
#endif
}
Exemple #6
0
int initssl(void)
{
    DH *dh_tmp = NULL;

    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();
    ircdssl_ctx = SSL_CTX_new(SSLv23_server_method());
    if (!ircdssl_ctx) {
	ERR_print_errors_fp(stderr);
	return 0;
    }

    /* Kill SSLv2 support */
    SSL_CTX_set_options(ircdssl_ctx, SSL_OP_NO_SSLv2);

    if (SSL_CTX_use_certificate_file(ircdssl_ctx,
		IRCDSSL_CPATH, SSL_FILETYPE_PEM) <= 0) {
	ERR_print_errors_fp(stderr);
	SSL_CTX_free(ircdssl_ctx);
	return 0;
    }
    if (SSL_CTX_use_PrivateKey_file(ircdssl_ctx,
		IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0) {
	ERR_print_errors_fp(stderr);
	SSL_CTX_free(ircdssl_ctx);
	return 0;
    }
    if (!SSL_CTX_check_private_key(ircdssl_ctx)) {
	fprintf(stderr, "Server certificate does not match Server key");
	SSL_CTX_free(ircdssl_ctx);
	return 0;
    }
    if (!SSL_CTX_set_cipher_list(ircdssl_ctx, IRCD_CIPHER_LIST))
    {
	ERR_print_errors_fp(stderr);
	SSL_CTX_free(ircdssl_ctx);
	return 0;
    }
    if ((dh_tmp = get_dh1024()) == NULL)
    {
	ERR_print_errors_fp(stderr);
	SSL_CTX_free(ircdssl_ctx);
	return 0;
    }
    if (!SSL_CTX_set_tmp_dh(ircdssl_ctx, dh_tmp))
    {
	ERR_print_errors_fp(stderr);
	SSL_CTX_free(ircdssl_ctx);
	DH_free(dh_tmp);
	return 0;
    }
    DH_free(dh_tmp);

    return 1;
}
Exemple #7
0
static void init_dhparams( void )
{
    if ( (dh512==NULL)
         && ((dh512=load_dhparam("dh512.pem")) ==NULL) ) {
        dh512 = get_dh512();
    }

    if ( (dh1024==NULL)
         && ((dh1024=load_dhparam("dh1024.pem")) ==NULL) ) {
        dh1024 = get_dh1024();
    }
}
extern "C" DH*
tmp_dh_callback (SSL *s, int is_export, int keylength)
{
  ACE_UNUSED_ARG(s);
  ACE_UNUSED_ARG(is_export);

  switch (keylength) {
  case 1024:
    if (dh1024 == 0)
    {
      dh1024 = get_dh1024();
    }
    return dh1024;
  default:
    /* Generating a key on the fly is very costly, so use what is there */
    ACE_ERROR ((LM_ERROR,
      ACE_TEXT ("tmp_dh_callback, unsupported key length, %d\n"),
      keylength));
  }
  return(0);
}
Exemple #9
0
int MaOpenSslConfig::start()
{
	const SSL_METHOD	*meth;
	char		        *hostName;

	if (keyFile == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing key file");
		return MPR_ERR_CANT_INITIALIZE;
	}
	if (certFile == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Cant start SSL: missing certificate file");
		return MPR_ERR_CANT_INITIALIZE;
	}

	//
	//	Depending on the order in the configuration file, we may get called 
	//	by sslModule::start() before OpenSslModule::start has run. So we 
	//	must initialize here.
	//
	openSslModule->start();
	
	hostName = host->getName();
	
	if (protocols == MPR_HTTP_PROTO_SSLV2) {
		meth = SSLv2_server_method();
	} else {
		meth = SSLv23_server_method();
	}
	context = SSL_CTX_new(meth);
	mprAssert(context);
	if (context == 0) {
		mprError(MPR_L, MPR_LOG, "OpenSSL: Unable to create SSL context"); 
		return MPR_ERR_CANT_CREATE;
	}

    SSL_CTX_set_app_data(context, (void*) this);
	SSL_CTX_set_quiet_shutdown(context, 1);
	SSL_CTX_sess_set_cache_size(context, 512);

	//
	//	Configure the certificate for this host
	//
	if (configureCertificates(context, keyFile, certFile) != 0) {
		SSL_CTX_free(context);
		context = 0;
		return MPR_ERR_CANT_INITIALIZE;
	}

	mprLog(4, "SSL: %s: Using ciphers %s\n", hostName, ciphers);
	SSL_CTX_set_cipher_list(context, ciphers);

	//
	//	Configure the client verification certificate locations
	//
	if (verifyClient) {
		if (caFile == 0 && caPath == 0) {
			mprError(MPR_L, MPR_LOG, 
				"OpenSSL: Must define CA certificates if using client verification");
			SSL_CTX_free(context);
			context = 0;
			return MPR_ERR_BAD_STATE;
		}
		if (caFile || caPath) {
			if ((!SSL_CTX_load_verify_locations(context, caFile, caPath)) ||
					(!SSL_CTX_set_default_verify_paths(context))) {
				mprError(MPR_L, MPR_LOG, 
					"OpenSSL: Unable to set certificate locations"); 
				SSL_CTX_free(context);
				context = 0;
				return MPR_ERR_CANT_ACCESS;
			}
			if (caFile) {
				STACK_OF(X509_NAME) *certNames;
				certNames = SSL_load_client_CA_file(caFile);
				if (certNames == 0) {
				} else {
					//
					//	Define the list of CA certificates to send to the client
					//	before they send their client certificate for validation
					//
					SSL_CTX_set_client_CA_list(context, certNames);
				}
			}
		}
		mprLog(4, "SSL: %s: is verifying client connections\n", hostName);
		if (caFile) {
			mprLog(4, "SSL: %s: Using certificates from %s\n", hostName, 
				caFile);
		} else if (caPath) {
			mprLog(4, "SSL: %s: Using certificates from directory %s\n", 
				hostName, caPath);
		}
		SSL_CTX_set_verify(context, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyX509Certificate);
		SSL_CTX_set_verify_depth(context, verifyDepth);

	} else {
		SSL_CTX_set_verify(context, SSL_VERIFY_NONE, verifyX509Certificate);
	}

	//
	//	Define callbacks
	//
	SSL_CTX_set_tmp_rsa_callback(context, rsaCallback);
	SSL_CTX_set_tmp_dh_callback(context, dhCallback);

	//
	//	Enable all buggy client work-arounds 
	//
	SSL_CTX_set_options(context, SSL_OP_ALL);

#ifdef SSL_OP_NO_TICKET
    SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
    SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif
    SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);

	//
	//	Select the required protocols
	//
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
	if (!(protocols & MPR_HTTP_PROTO_SSLV3)) {
		SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
		mprLog(4, "SSL: %s: Disabling SSLv3\n", hostName);
	}
	if (!(protocols & MPR_HTTP_PROTO_TLSV1)) {
		SSL_CTX_set_options(context, SSL_OP_NO_TLSv1);
		mprLog(4, "SSL: %s: Disabling TLSv1\n", hostName);
	}

	//
	//	Ensure we generate a new private key for each connection
	//
    SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE);

	//
	//	Pre-generate some keys that are slow to compute
	//
	rsaKey512 = RSA_generate_key(512, RSA_F4, 0, 0);
	rsaKey1024 = RSA_generate_key(1024, RSA_F4, 0, 0);

	dhKey512 = get_dh512();
	dhKey1024 = get_dh1024();

	return 0;
}
Exemple #10
0
/** Initialize the SSL context.
 * \return pointer to SSL context object.
 */
SSL_CTX *
ssl_init(char *private_key_file, char *ca_file, int req_client_cert)
{
  const SSL_METHOD *meth;       /* If this const gives you a warning, you're
                                   using an old version of OpenSSL. Walker, this means you! */
  /* uint8_t context[128]; */
  DH *dh;
  unsigned int reps = 1;

  if (!bio_err) {
    if (!SSL_library_init())
      return NULL;
    SSL_load_error_strings();
    /* Error write context */
    bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
  }

  lock_file(stderr);
  fputs("Seeding OpenSSL random number pool.\n", stderr);
  unlock_file(stderr);
  while (!RAND_status()) {
    /* At this point, a system with /dev/urandom or a EGD file in the usual
       places will have enough entropy. Otherwise, be lazy and use random numbers
       until it's satisfied. */
    uint32_t gibberish[4];
    int n;

    /* sfmt_fill_array32 requires a much larger array. */
    for (n = 0; n < 4; n++)
      gibberish[n] = sfmt_genrand_uint32(&rand_state);

    RAND_seed(gibberish, sizeof gibberish);

    reps += 1;
  }

  lock_file(stderr);
  fprintf(stderr, "Seeded after %u %s.\n", reps, reps > 1 ? "cycles" : "cycle");
  unlock_file(stderr);

  /* Set up SIGPIPE handler here? */

  /* Create context */
  meth = SSLv23_server_method();
  ctx = SSL_CTX_new(meth);

  /* Load keys/certs */
  if (private_key_file && *private_key_file) {
    if (!SSL_CTX_use_certificate_chain_file(ctx, private_key_file)) {
      ssl_errordump
        ("Unable to load server certificate - only anonymous ciphers supported.");
    }
    if (!SSL_CTX_use_PrivateKey_file(ctx, private_key_file, SSL_FILETYPE_PEM)) {
      ssl_errordump
        ("Unable to load private key - only anonymous ciphers supported.");
    }
  }

  /* Load trusted CAs */
  if (ca_file && *ca_file) {
    if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) {
      ssl_errordump("Unable to load CA certificates");
    } else {
      if (req_client_cert)
        SSL_CTX_set_verify(ctx,
                           SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                           client_verify_callback);
      else
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, client_verify_callback);
#if (OPENSSL_VERSION_NUMBER < 0x0090600fL)
      SSL_CTX_set_verify_depth(ctx, 1);
#endif
    }
  }

  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE | SSL_OP_ALL);
  SSL_CTX_set_mode(ctx,
                   SSL_MODE_ENABLE_PARTIAL_WRITE |
                   SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

  /* Set up DH callback */
  dh = get_dh1024();
  SSL_CTX_set_tmp_dh(ctx, dh);
  /* The above function makes a private copy of this */
  DH_free(dh);

  /* Set the cipher list to the usual default list, except that
   * we'll allow anonymous diffie-hellman, too.
   */
  SSL_CTX_set_cipher_list(ctx, "ALL:ADH:RC4+RSA:+SSLv2:@STRENGTH");

  /* Set up session cache if we can */
  /*
     strncpy((char *) context, MUDNAME, 128);
     SSL_CTX_set_session_id_context(ctx, context, strlen(context));
   */

  return ctx;
}
Exemple #11
0
int rehash_ssl(void)
{
    DH *dh_tmp = NULL;

    if(ircdssl_ctx)
    {
	SSL_CTX_free(ircdssl_ctx);
    }

    if(!(ircdssl_ctx = SSL_CTX_new(SSLv23_server_method())))
    {
	disable_ssl(1);
	return 0;
    }

    /* Kill SSLv2 support */
    SSL_CTX_set_options(ircdssl_ctx, SSL_OP_NO_SSLv2);

    if (SSL_CTX_use_certificate_file(ircdssl_ctx,
		IRCDSSL_CPATH, SSL_FILETYPE_PEM) <= 0)
    {
	disable_ssl(1);

	return 0;
    }

    if (SSL_CTX_use_PrivateKey_file(ircdssl_ctx,
		IRCDSSL_KPATH, SSL_FILETYPE_PEM) <= 0)
    {
	disable_ssl(1);

	return 0;
    }

    if (!SSL_CTX_check_private_key(ircdssl_ctx)) 
    {
	sendto_realops("SSL ERROR: Server certificate does not match server key");
	disable_ssl(0);

	return 0;
    }

    if (!SSL_CTX_set_cipher_list(ircdssl_ctx, IRCD_CIPHER_LIST))
    {
	disable_ssl(1);
	return 0;
    }

    if ((dh_tmp = get_dh1024()) == NULL)
    {
	disable_ssl(1);
	return 0;
    }

    if (!SSL_CTX_set_tmp_dh(ircdssl_ctx, dh_tmp))
    {
	disable_ssl(1);
	DH_free(dh_tmp);
	return 0;
    }
    DH_free(dh_tmp);

    return 1;
}
Exemple #12
0
int main(int argc, char *argv[])
	{
	char *CApath=NULL,*CAfile=NULL;
	int badop=0;
	int bio_pair=0;
	int force=0;
	int tls1=0,ssl2=0,ssl3=0,ret=1;
	int client_auth=0;
	int server_auth=0,i;
	int app_verify=0;
	char *server_cert=TEST_SERVER_CERT;
	char *server_key=NULL;
	char *client_cert=TEST_CLIENT_CERT;
	char *client_key=NULL;
	SSL_CTX *s_ctx=NULL;
	SSL_CTX *c_ctx=NULL;
	SSL_METHOD *meth=NULL;
	SSL *c_ssl,*s_ssl;
	int number=1,reuse=0;
	long bytes=1L;
#ifndef OPENSSL_NO_DH
	DH *dh;
	int dhe1024 = 0, dhe1024dsa = 0;
#endif
	int no_dhe = 0;
	int print_time = 0;
	clock_t s_time = 0, c_time = 0;
	int comp = 0;
	COMP_METHOD *cm = NULL;

	verbose = 0;
	debug = 0;
	cipher = 0;

	bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);	

	CRYPTO_set_locking_callback(lock_dbg_cb);

	/* enable memory leak checking unless explicitly disabled */
	if (!((getenv("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))))
		{
		CRYPTO_malloc_debug_init();
		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
		}
	else
		{
		/* OPENSSL_DEBUG_MEMORY=off */
		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
		}
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

	RAND_seed(rnd_seed, sizeof rnd_seed);

	bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);

	argc--;
	argv++;

	while (argc >= 1)
		{
		if	(strcmp(*argv,"-server_auth") == 0)
			server_auth=1;
		else if	(strcmp(*argv,"-client_auth") == 0)
			client_auth=1;
		else if	(strcmp(*argv,"-v") == 0)
			verbose=1;
		else if	(strcmp(*argv,"-d") == 0)
			debug=1;
		else if	(strcmp(*argv,"-reuse") == 0)
			reuse=1;
		else if	(strcmp(*argv,"-dhe1024") == 0)
			{
#ifndef OPENSSL_NO_DH
			dhe1024=1;
#else
			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
#endif
			}
		else if	(strcmp(*argv,"-dhe1024dsa") == 0)
			{
#ifndef OPENSSL_NO_DH
			dhe1024dsa=1;
#else
			fprintf(stderr,"ignoring -dhe1024, since I'm compiled without DH\n");
#endif
			}
		else if	(strcmp(*argv,"-no_dhe") == 0)
			no_dhe=1;
		else if	(strcmp(*argv,"-ssl2") == 0)
			ssl2=1;
		else if	(strcmp(*argv,"-tls1") == 0)
			tls1=1;
		else if	(strcmp(*argv,"-ssl3") == 0)
			ssl3=1;
		else if	(strncmp(*argv,"-num",4) == 0)
			{
			if (--argc < 1) goto bad;
			number= atoi(*(++argv));
			if (number == 0) number=1;
			}
		else if	(strcmp(*argv,"-bytes") == 0)
			{
			if (--argc < 1) goto bad;
			bytes= atol(*(++argv));
			if (bytes == 0L) bytes=1L;
			i=strlen(argv[0]);
			if (argv[0][i-1] == 'k') bytes*=1024L;
			if (argv[0][i-1] == 'm') bytes*=1024L*1024L;
			}
		else if	(strcmp(*argv,"-cert") == 0)
			{
			if (--argc < 1) goto bad;
			server_cert= *(++argv);
			}
		else if	(strcmp(*argv,"-s_cert") == 0)
			{
			if (--argc < 1) goto bad;
			server_cert= *(++argv);
			}
		else if	(strcmp(*argv,"-key") == 0)
			{
			if (--argc < 1) goto bad;
			server_key= *(++argv);
			}
		else if	(strcmp(*argv,"-s_key") == 0)
			{
			if (--argc < 1) goto bad;
			server_key= *(++argv);
			}
		else if	(strcmp(*argv,"-c_cert") == 0)
			{
			if (--argc < 1) goto bad;
			client_cert= *(++argv);
			}
		else if	(strcmp(*argv,"-c_key") == 0)
			{
			if (--argc < 1) goto bad;
			client_key= *(++argv);
			}
		else if	(strcmp(*argv,"-cipher") == 0)
			{
			if (--argc < 1) goto bad;
			cipher= *(++argv);
			}
		else if	(strcmp(*argv,"-CApath") == 0)
			{
			if (--argc < 1) goto bad;
			CApath= *(++argv);
			}
		else if	(strcmp(*argv,"-CAfile") == 0)
			{
			if (--argc < 1) goto bad;
			CAfile= *(++argv);
			}
		else if	(strcmp(*argv,"-bio_pair") == 0)
			{
			bio_pair = 1;
			}
		else if	(strcmp(*argv,"-f") == 0)
			{
			force = 1;
			}
		else if	(strcmp(*argv,"-time") == 0)
			{
			print_time = 1;
			}
		else if	(strcmp(*argv,"-zlib") == 0)
			{
			comp = COMP_ZLIB;
			}
		else if	(strcmp(*argv,"-rle") == 0)
			{
			comp = COMP_RLE;
			}
		else if	(strcmp(*argv,"-app_verify") == 0)
			{
			app_verify = 1;
			}
		else
			{
			fprintf(stderr,"unknown option %s\n",*argv);
			badop=1;
			break;
			}
		argc--;
		argv++;
		}
	if (badop)
		{
bad:
		sv_usage();
		goto end;
		}

	if (!ssl2 && !ssl3 && !tls1 && number > 1 && !reuse && !force)
		{
		fprintf(stderr, "This case cannot work.  Use -f to perform "
			"the test anyway (and\n-d to see what happens), "
			"or add one of -ssl2, -ssl3, -tls1, -reuse\n"
			"to avoid protocol mismatch.\n");
		EXIT(1);
		}

	if (print_time)
		{
		if (!bio_pair)
			{
			fprintf(stderr, "Using BIO pair (-bio_pair)\n");
			bio_pair = 1;
			}
		if (number < 50 && !force)
			fprintf(stderr, "Warning: For accurate timings, use more connections (e.g. -num 1000)\n");
		}

/*	if (cipher == NULL) cipher=getenv("SSL_CIPHER"); */

	SSL_library_init();
	SSL_load_error_strings();

	if (comp == COMP_ZLIB) cm = COMP_zlib();
	if (comp == COMP_RLE) cm = COMP_rle();
	if (cm != NULL)
		{
		if (cm->type != NID_undef)
			SSL_COMP_add_compression_method(comp, cm);
		else
			{
			fprintf(stderr,
				"Warning: %s compression not supported\n",
				(comp == COMP_RLE ? "rle" :
					(comp == COMP_ZLIB ? "zlib" :
						"unknown")));
			ERR_print_errors_fp(stderr);
			}
		}

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
	if (ssl2)
		meth=SSLv2_method();
	else 
	if (tls1)
		meth=TLSv1_method();
	else
	if (ssl3)
		meth=SSLv3_method();
	else
		meth=SSLv23_method();
#else
#ifdef OPENSSL_NO_SSL2
	meth=SSLv3_method();
#else
	meth=SSLv2_method();
#endif
#endif

	c_ctx=SSL_CTX_new(meth);
	s_ctx=SSL_CTX_new(meth);
	if ((c_ctx == NULL) || (s_ctx == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if (cipher != NULL)
		{
		SSL_CTX_set_cipher_list(c_ctx,cipher);
		SSL_CTX_set_cipher_list(s_ctx,cipher);
		}

#ifndef OPENSSL_NO_DH
	if (!no_dhe)
		{
		if (dhe1024dsa)
			{
			/* use SSL_OP_SINGLE_DH_USE to avoid small subgroup attacks */
			SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
			dh=get_dh1024dsa();
			}
		else if (dhe1024)
			dh=get_dh1024();
		else
			dh=get_dh512();
		SSL_CTX_set_tmp_dh(s_ctx,dh);
		DH_free(dh);
		}
#else
	(void)no_dhe;
#endif

#ifndef OPENSSL_NO_RSA
	SSL_CTX_set_tmp_rsa_callback(s_ctx,tmp_rsa_cb);
#endif

	if (!SSL_CTX_use_certificate_file(s_ctx,server_cert,SSL_FILETYPE_PEM))
		{
		ERR_print_errors(bio_err);
		}
	else if (!SSL_CTX_use_PrivateKey_file(s_ctx,
		(server_key?server_key:server_cert), SSL_FILETYPE_PEM))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if (client_auth)
		{
		SSL_CTX_use_certificate_file(c_ctx,client_cert,
			SSL_FILETYPE_PEM);
		SSL_CTX_use_PrivateKey_file(c_ctx,
			(client_key?client_key:client_cert),
			SSL_FILETYPE_PEM);
		}

	if (	(!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
		(!SSL_CTX_set_default_verify_paths(s_ctx)) ||
		(!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
		(!SSL_CTX_set_default_verify_paths(c_ctx)))
		{
		/* fprintf(stderr,"SSL_load_verify_locations\n"); */
		ERR_print_errors(bio_err);
		/* goto end; */
		}

	if (client_auth)
		{
		BIO_printf(bio_err,"client authentication\n");
		SSL_CTX_set_verify(s_ctx,
			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
			verify_callback);
		if (app_verify) 
			{
			SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg);
			}
		}
	if (server_auth)
		{
		BIO_printf(bio_err,"server authentication\n");
		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
			verify_callback);
		if (app_verify) 
			{
			SSL_CTX_set_cert_verify_callback(s_ctx, app_verify_callback, app_verify_arg);
			}
		}
	
	{
		int session_id_context = 0;
		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);
	}

	c_ssl=SSL_new(c_ctx);
	s_ssl=SSL_new(s_ctx);

#ifndef OPENSSL_NO_KRB5
	if (c_ssl  &&  c_ssl->kssl_ctx)
                {
                char	localhost[MAXHOSTNAMELEN+2];

		if (gethostname(localhost, sizeof localhost-1) == 0)
                        {
			localhost[sizeof localhost-1]='\0';
			if(strlen(localhost) == sizeof localhost-1)
				{
				BIO_printf(bio_err,"localhost name too long\n");
				goto end;
				}
			kssl_ctx_setstring(c_ssl->kssl_ctx, KSSL_SERVER,
                                localhost);
			}
		}
#endif    /* OPENSSL_NO_KRB5  */

	for (i=0; i<number; i++)
		{
		if (!reuse) SSL_set_session(c_ssl,NULL);
		if (bio_pair)
			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time);
		else
			ret=doit(s_ssl,c_ssl,bytes);
		}

	if (!verbose)
		{
		print_details(c_ssl, "");
		}
	if ((number > 1) || (bytes > 1L))
		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes);
	if (print_time)
		{
#ifdef CLOCKS_PER_SEC
		/* "To determine the time in seconds, the value returned
		 * by the clock function should be divided by the value
		 * of the macro CLOCKS_PER_SEC."
		 *                                       -- ISO/IEC 9899 */
		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"
			"Approximate total client time: %6.2f s\n",
			(double)s_time/CLOCKS_PER_SEC,
			(double)c_time/CLOCKS_PER_SEC);
#else
		/* "`CLOCKS_PER_SEC' undeclared (first use this function)"
		 *                            -- cc on NeXTstep/OpenStep */
		BIO_printf(bio_stdout,
			"Approximate total server time: %6.2f units\n"
			"Approximate total client time: %6.2f units\n",
			(double)s_time,
			(double)c_time);
#endif
		}

	SSL_free(s_ssl);
	SSL_free(c_ssl);

end:
	if (s_ctx != NULL) SSL_CTX_free(s_ctx);
	if (c_ctx != NULL) SSL_CTX_free(c_ctx);

	if (bio_stdout != NULL) BIO_free(bio_stdout);

#ifndef OPENSSL_NO_RSA
	free_tmp_rsa();
#endif
#ifndef OPENSSL_NO_ENGINE
	ENGINE_cleanup();
#endif
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_state(0);
	EVP_cleanup();
	CRYPTO_mem_leaks(bio_err);
	if (bio_err != NULL) BIO_free(bio_err);
	EXIT(ret);
	}