Пример #1
0
/** setup SSL context */
static SSL_CTX*
setup_ctx(char* key, char* cert)
{
	SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
	if(!ctx) print_exit("out of memory");
	(void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
	(void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
	if(!SSL_CTX_use_certificate_chain_file(ctx, cert))
		print_exit("cannot read cert");
	if(!SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM))
		print_exit("cannot read key");
	if(!SSL_CTX_check_private_key(ctx))
		print_exit("private key is not correct");
#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
	if (!SSL_CTX_set_ecdh_auto(ctx,1))
		if(verb>=1) printf("failed to set_ecdh_auto, not enabling ECDHE\n");
#elif defined(USE_ECDSA)
	if(1) {
		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
		if (!ecdh) {
			if(verb>=1) printf("could not find p256, not enabling ECDHE\n");
		} else {
			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
				if(verb>=1) printf("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE\n");
			}
			EC_KEY_free(ecdh);
		}
	}
#endif
	if(!SSL_CTX_load_verify_locations(ctx, cert, NULL))
		print_exit("cannot load cert verify locations");
	return ctx;
}
Пример #2
0
int
ssl_setup(SSL_CTX **ctxp, struct pki *pki,
    int (*sni_cb)(SSL *,int *,void *), const char *ciphers)
{
	SSL_CTX	*ctx;
	uint8_t sid[SSL_MAX_SID_CTX_LENGTH];

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

	/*
	 * Set session ID context to a random value.  We don't support
	 * persistent caching of sessions so it is OK to set a temporary
	 * session ID context that is valid during run time.
	 */
	arc4random_buf(sid, sizeof(sid));
	if (!SSL_CTX_set_session_id_context(ctx, sid, sizeof(sid)))
		goto err;

	if (sni_cb)
		SSL_CTX_set_tlsext_servername_callback(ctx, sni_cb);

	SSL_CTX_set_dh_auto(ctx, pki->pki_dhe);

	SSL_CTX_set_ecdh_auto(ctx, 1);

	*ctxp = ctx;
	return 1;

err:
	SSL_CTX_free(ctx);
	ssl_error("ssl_setup");
	return 0;
}
Пример #3
0
void
listen_sslctx_setup_2(void* ctxt)
{
#ifdef HAVE_SSL
	SSL_CTX* ctx = (SSL_CTX*)ctxt;
	(void)ctx;
#if HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
	if(!SSL_CTX_set_ecdh_auto(ctx,1)) {
		log_crypto_err("Error in SSL_CTX_ecdh_auto, not enabling ECDHE");
	}
#elif defined(USE_ECDSA)
	if(1) {
		EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
		if (!ecdh) {
			log_crypto_err("could not find p256, not enabling ECDHE");
		} else {
			if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) {
				log_crypto_err("Error in SSL_CTX_set_tmp_ecdh, not enabling ECDHE");
			}
			EC_KEY_free (ecdh);
		}
	}
#endif
#else
	(void)ctxt;
#endif /* HAVE_SSL */
}
Пример #4
0
/* ECDH temporary parameters */
static int cmd_ECDHParameters(SSL_CONF_CTX *cctx, const char *value)
	{
	int onoff = -1, rv = 1;
	if (!(cctx->flags & SSL_CONF_FLAG_SERVER))
		return -2;
	if (cctx->flags & SSL_CONF_FLAG_FILE)
		{
		if (*value == '+')
			{
			onoff = 1;
			value++;
			}
		if (*value == '-')
			{
			onoff = 0;
			value++;
			}
		if (!strcasecmp(value, "automatic"))
			{
			if (onoff == -1)
				onoff = 1;
			}
		else if (onoff != -1)
			return 0;
		}
	else if (cctx->flags & SSL_CONF_FLAG_CMDLINE)
		{
		if (!strcmp(value, "auto"))
			onoff = 1;
		}

	if (onoff != -1)
		{
		if (cctx->ctx)
			rv = SSL_CTX_set_ecdh_auto(cctx->ctx, onoff);
		else if (cctx->ssl)
			rv = SSL_set_ecdh_auto(cctx->ssl, onoff);
		}
	else
		{
		EC_KEY *ecdh;
		int nid;
		nid = EC_curve_nist2nid(value);
		if (nid == NID_undef)
			nid = OBJ_sn2nid(value);
		if (nid == 0)
			return 0;
		ecdh = EC_KEY_new_by_curve_name(nid);
		if (!ecdh)
			return 0;
		if (cctx->ctx)
			rv = SSL_CTX_set_tmp_ecdh(cctx->ctx, ecdh);
		else if (cctx->ssl)
			rv = SSL_set_tmp_ecdh(cctx->ssl, ecdh);
		EC_KEY_free(ecdh);
		}

	return rv > 0;
	}
Пример #5
0
int
tls_configure_server(struct tls *ctx)
{
	EC_KEY *ecdh_key;
	unsigned char sid[SSL_MAX_SSL_SESSION_ID_LENGTH];

	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
		tls_set_error(ctx, "ssl context failure");
		goto err;
	}

	if (tls_configure_ssl(ctx) != 0)
		goto err;
	if (tls_configure_keypair(ctx) != 0)
		goto err;

	if (ctx->config->dheparams == -1)
		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1);
	else if (ctx->config->dheparams == 1024)
		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 2);

	if (ctx->config->ecdhecurve == -1) {
		SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
	} else if (ctx->config->ecdhecurve != NID_undef) {
		if ((ecdh_key = EC_KEY_new_by_curve_name(
		    ctx->config->ecdhecurve)) == NULL) {
			tls_set_error(ctx, "failed to set ECDHE curve");
			goto err;
		}
		SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
		SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ecdh_key);
		EC_KEY_free(ecdh_key);
	}

	/*
	 * Set session ID context to a random value.  We don't support
	 * persistent caching of sessions so it is OK to set a temporary
	 * session ID context that is valid during run time.
	 */
	arc4random_buf(sid, sizeof(sid));
	if (!SSL_CTX_set_session_id_context(ctx->ssl_ctx, sid, sizeof(sid))) {
		tls_set_error(ctx, "failed to set session id context");
		goto err;
	}

	return (0);

err:
	return (-1);
}
Пример #6
0
/*
Openssl supports setting ecdh curves by default from version 1.1.0.
For lower versions, this is the recommended approach.
Returns 1 on success, 0 on failure.
*/
static long TrySetECDHNamedCurve(SSL_CTX* ctx)
{
	long result = 0;
#ifdef SSL_CTX_set_ecdh_auto
	result = SSL_CTX_set_ecdh_auto(ctx, 1);
#else
	EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
	if (ecdh != nullptr)
	{
		result = SSL_CTX_set_tmp_ecdh(ctx, ecdh);
		EC_KEY_free(ecdh);
	}
#endif

	return result;
}
Пример #7
0
static int set_curve(lua_State *L)
{
  long ret;
  SSL_CTX *ctx = lsec_checkcontext(L, 1);
  const char *str = luaL_checkstring(L, 2);

  SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);

#if defined(SSL_CTRL_SET_ECDH_AUTO) || defined(SSL_CTRL_SET_CURVES_LIST) || defined(SSL_CTX_set1_curves_list)
  if (SSL_CTX_set1_curves_list(ctx, str) != 1) {
    lua_pushboolean(L, 0);
    lua_pushfstring(L, "unknown elliptic curve in \"%s\"", str);
    return 2;
  }

#ifdef SSL_CTRL_SET_ECDH_AUTO
  SSL_CTX_set_ecdh_auto(ctx, 1);
#endif

  lua_pushboolean(L, 1);
  return 1;

#else /* !defined(SSL_CTRL_SET_CURVES_LIST) */
  EC_KEY *key = lsec_find_ec_key(L, str);

  if (!key) {
    lua_pushboolean(L, 0);
    lua_pushfstring(L, "elliptic curve %s not supported", str);
    return 2;
  }

  ret = SSL_CTX_set_tmp_ecdh(ctx, key);
  /* SSL_CTX_set_tmp_ecdh takes its own reference */
  EC_KEY_free(key);

  if (!ret) {
    lua_pushboolean(L, 0);
    lua_pushfstring(L, "error setting elliptic curve (%s)",
      ERR_reason_error_string(ERR_get_error()));
    return 2;
  }
  lua_pushboolean(L, 1);
  return 1;
#endif /* defined(SSL_CTRL_SET_CURVES_LIST) */
}
Пример #8
0
void ILibWrapper_WebRTC_InitializeCrypto(ILibWrapper_WebRTC_ConnectionFactoryStruct *factory)
{
	int l = 32;

	// Init SSL
	util_openssl_init();

	// Init Certs
	util_mkCert(NULL, &(factory->selfcert), 2048, 10000, "localhost", CERTIFICATE_ROOT, NULL);
	util_keyhash(factory->selfcert, factory->g_selfid);
	util_mkCert(&(factory->selfcert), &(factory->selftlscert), 2048, 10000, "localhost", CERTIFICATE_TLS_SERVER, NULL);
	util_mkCert(&(factory->selfcert), &(factory->selftlsclientcert), 2048, 10000, "localhost", CERTIFICATE_TLS_CLIENT, NULL);

	// Init DTLS
	factory->ctx = SSL_CTX_new(DTLS_method());
	SSL_CTX_set_ecdh_auto(factory->ctx, 1);

	SSL_CTX_use_certificate(factory->ctx, factory->selftlscert.x509);
	SSL_CTX_use_PrivateKey(factory->ctx, factory->selftlscert.pkey);		
	X509_digest(factory->selftlscert.x509, EVP_get_digestbyname("sha256"), (unsigned char*)factory->tlsServerCertThumbprint, (unsigned int*)&l);
}
Пример #9
0
void initialize_openssl(const config_t *config, global_data_t *global_data)
{
	SSL_library_init();
	SSL_load_error_strings();
	openssl_global_data.num_lock = CRYPTO_num_locks();
	openssl_global_data.lock = calloc(openssl_global_data.num_lock,
	                                  sizeof(*openssl_global_data.lock));
	CHECK_ERROR(pthread_mutexattr_init, &openssl_global_data.lock_attr);
	CHECK_ERROR(pthread_mutexattr_settype,
	            &openssl_global_data.lock_attr,
	            PTHREAD_MUTEX_ADAPTIVE_NP);

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

	CRYPTO_set_locking_callback(locking_function);
	CRYPTO_set_dynlock_create_callback(dyn_create_function);
	CRYPTO_set_dynlock_destroy_callback(dyn_destroy_function);
	CRYPTO_set_dynlock_lock_callback(dyn_lock_function);
	global_data->ssl_ctx = SSL_CTX_new(TLSv1_2_server_method());
#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
	SSL_CTX_set_ecdh_auto(global_data->ssl_ctx, 1);
	h2o_ssl_register_alpn_protocols(global_data->ssl_ctx, h2o_http2_alpn_protocols);
#endif
	SSL_CTX_set_cipher_list(global_data->ssl_ctx, "DEFAULT:!3DES:!RC4");
	CHECK_OPENSSL_ERROR(SSL_CTX_use_certificate_file,
	                    global_data->ssl_ctx,
	                    config->cert,
	                    SSL_FILETYPE_PEM);
	CHECK_OPENSSL_ERROR(SSL_CTX_use_PrivateKey_file,
	                    global_data->ssl_ctx,
	                    config->key,
	                    SSL_FILETYPE_PEM);
}
Пример #10
0
int
tls_configure_server(struct tls *ctx)
{
	EC_KEY *ecdh_key;
	unsigned char sid[SSL_MAX_SSL_SESSION_ID_LENGTH];

	if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
		tls_set_errorx(ctx, "ssl context failure");
		goto err;
	}

	if (tls_configure_ssl(ctx) != 0)
		goto err;
	if (tls_configure_keypair(ctx, ctx->ssl_ctx, ctx->config->keypair, 1) != 0)
		goto err;
	if (ctx->config->verify_client != 0) {
		int verify = SSL_VERIFY_PEER;
		if (ctx->config->verify_client == 1)
			verify |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		if (tls_configure_ssl_verify(ctx, verify) == -1)
			goto err;
	}

	if (ctx->config->dheparams == -1)
		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 1);
	else if (ctx->config->dheparams == 1024)
		SSL_CTX_set_dh_auto(ctx->ssl_ctx, 2);

	if (ctx->config->ecdhecurve == -1) {
		SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
	} else if (ctx->config->ecdhecurve != NID_undef) {
		if ((ecdh_key = EC_KEY_new_by_curve_name(
		    ctx->config->ecdhecurve)) == NULL) {
			tls_set_errorx(ctx, "failed to set ECDHE curve");
			goto err;
		}
		SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
		SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ecdh_key);
		EC_KEY_free(ecdh_key);
	}

	if (ctx->config->ciphers_server == 1)
		SSL_CTX_set_options(ctx->ssl_ctx,
		    SSL_OP_CIPHER_SERVER_PREFERENCE);

	if (SSL_CTX_set_tlsext_status_cb(ctx->ssl_ctx, tls_ocsp_stapling_callback) != 1) {
		tls_set_errorx(ctx, "ssl OCSP stapling setup failure");
		goto err;
	}

	/*
	 * Set session ID context to a random value.  We don't support
	 * persistent caching of sessions so it is OK to set a temporary
	 * session ID context that is valid during run time.
	 */
	if (!RAND_bytes(sid, sizeof(sid))) {
		tls_set_errorx(ctx, "failed to generate session id");
		goto err;
	}
	if (!SSL_CTX_set_session_id_context(ctx->ssl_ctx, sid, sizeof(sid))) {
		tls_set_errorx(ctx, "failed to set session id context");
		goto err;
	}

	return (0);

 err:
	return (-1);
}
Пример #11
0
eventer_ssl_ctx_t *
eventer_ssl_ctx_new(eventer_ssl_orientation_t type,
                    const char *layer,
                    const char *certificate, const char *key,
                    const char *ca, const char *ciphers) {
  char ssl_ctx_key[SSL_CTX_KEYLEN];
  eventer_ssl_ctx_t *ctx;
  const char *layer_str;
  char *ctx_layer, *opts;
  char *opts_fallback = DEFAULT_OPTS_STRING;
  time_t now;
  ctx = calloc(1, sizeof(*ctx));
  if(!ctx) return NULL;

  layer_str = layer ? layer : DEFAULT_LAYER_STRING;
  ctx_layer = alloca(strlen(layer_str)+1);
  memcpy(ctx_layer, layer_str, strlen(layer_str)+1);
  opts = strchr(ctx_layer,':');
  if(opts) *opts++ = '\0';
  else {
    opts = alloca(strlen(opts_fallback)+1);
    memcpy(opts, opts_fallback, strlen(opts_fallback)+1);
  }

  now = time(NULL);
  ssl_ctx_key_write(ssl_ctx_key, sizeof(ssl_ctx_key),
                    type, layer, certificate, key, ca, ciphers);
  ctx->ssl_ctx_cn = ssl_ctx_cache_get(ssl_ctx_key);
  if(ctx->ssl_ctx_cn) {
    if(now - ctx->ssl_ctx_cn->creation_time > ssl_ctx_cache_expiry ||
       (now - ctx->ssl_ctx_cn->last_stat_time > ssl_ctx_cache_finfo_expiry &&
           (validate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate) ||
            validate_finfo(&ctx->ssl_ctx_cn->key_finfo, key) ||
            validate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca) || 
            (ctx->ssl_ctx_cn->last_stat_time = now) == 0))) { /* assignment */
      ssl_ctx_cache_remove(ssl_ctx_key);
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = NULL;
    }
  }

  if(!ctx->ssl_ctx_cn) {
    char *part = NULL, *brkt = NULL;
    long ctx_options = 0;
    ssl_ctx_cache_node *existing_ctx_cn;
    ctx->ssl_ctx_cn = calloc(1, sizeof(*ctx->ssl_ctx_cn));
    ctx->ssl_ctx_cn->key = strdup(ssl_ctx_key);
    ctx->ssl_ctx_cn->refcnt = 1;
    ctx->ssl_ctx_cn->creation_time = now;
    ctx->ssl_ctx_cn->last_stat_time = now;
    populate_finfo(&ctx->ssl_ctx_cn->cert_finfo, certificate);
    populate_finfo(&ctx->ssl_ctx_cn->key_finfo, key);
    populate_finfo(&ctx->ssl_ctx_cn->ca_finfo, ca);
    ctx->ssl_ctx = NULL;
    if(0)
      ;
#if defined(SSL_TXT_SSLV3) && defined(HAVE_SSLV3_SERVER) && defined(HAVE_SSLV3_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV3))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv3_server_method() : SSLv3_client_method());
#endif
#if defined(SSL_TXT_SSLV2) && defined(HAVE_SSLV2_SERVER) && defined(HAVE_SSLV2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_SSLV2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv2_server_method() : SSLv2_client_method());
#endif
#if defined(SSL_TXT_TLSV1) && defined(HAVE_TLSV1_SERVER) && defined(HAVE_TLSV1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_server_method() : TLSv1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_1) && defined(HAVE_TLSV1_1_SERVER) && defined(HAVE_TLSV1_1_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_1))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_1_server_method() : TLSv1_1_client_method());
#endif
#if defined(SSL_TXT_TLSV1_2) && defined(HAVE_TLSV1_2_SERVER) && defined(HAVE_TLSV1_2_CLIENT)
    else if(layer && !strcasecmp(layer, SSL_TXT_TLSV1_2))
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 TLSv1_2_server_method() : TLSv1_2_client_method());
#endif
    if(ctx->ssl_ctx == NULL)
      ctx->ssl_ctx = SSL_CTX_new(type == SSL_SERVER ?
                                 SSLv23_server_method() : SSLv23_client_method());
    if(!ctx->ssl_ctx) goto bail;

    for(part = strtok_r(opts, ",", &brkt);
        part;
        part = strtok_r(NULL, ",", &brkt)) {
      char *optname = part;
      int neg = 0;
      if(*optname == '!') neg = 1, optname++;

#define SETBITOPT(name, neg, opt) \
  if(!strcasecmp(optname, name)) { \
    if(neg) ctx_options &= ~(opt); \
    else    ctx_options |= (opt); \
  }

      SETBITOPT("all", neg, SSL_OP_ALL)
#ifdef SSL_TXT_SSLV2
      else SETBITOPT(SSL_TXT_SSLV2, !neg, SSL_OP_NO_SSLv2)
#endif
#ifdef SSL_TXT_SSLV3
      else SETBITOPT(SSL_TXT_SSLV3, !neg, SSL_OP_NO_SSLv3)
#endif
#ifdef SSL_TXT_TLSV1
      else SETBITOPT(SSL_TXT_TLSV1, !neg, SSL_OP_NO_TLSv1)
#endif
#ifdef SSL_TXT_TLSV1_1
      else SETBITOPT(SSL_TXT_TLSV1_1, !neg, SSL_OP_NO_TLSv1_1)
#endif
#ifdef SSL_TXT_TLSV1_2
      else SETBITOPT(SSL_TXT_TLSV1_2, !neg, SSL_OP_NO_TLSv1_2)
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
      else SETBITOPT("cipher_server_preference", neg, SSL_OP_CIPHER_SERVER_PREFERENCE)
#endif
      else {
        mtevL(mtev_error, "SSL layer part '%s' not understood.\n", optname);
      }
    }

    if (type == SSL_SERVER)
      SSL_CTX_set_session_id_context(ctx->ssl_ctx,
              (unsigned char *)EVENTER_SSL_DATANAME,
              sizeof(EVENTER_SSL_DATANAME)-1);
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
    ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#endif
#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
    ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG;
#endif
#ifdef SSL_OP_NO_COMPRESSION
    ctx_options |= SSL_OP_NO_COMPRESSION;
#endif
#ifdef SSL_OP_NO_TICKET
    ctx_options |= SSL_OP_NO_TICKET;
#endif
#ifdef SSL_OP_SINGLE_DH_USE
    ctx_options |= SSL_OP_SINGLE_DH_USE;
#endif
#ifdef SSL_OP_SINGLE_ECDH_USE
    ctx_options |= SSL_OP_SINGLE_ECDH_USE;
#endif
    SSL_CTX_set_options(ctx->ssl_ctx, ctx_options);
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(ctx->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
    if(certificate &&
       SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, certificate) != 1)
      goto bail;
    if(key &&
       SSL_CTX_use_RSAPrivateKey_file(ctx->ssl_ctx,key,
                                      SSL_FILETYPE_PEM) != 1)
      goto bail;
    if(ca) {
      STACK_OF(X509_NAME) *cert_stack;
      if(!SSL_CTX_load_verify_locations(ctx->ssl_ctx,ca,NULL) ||
         (cert_stack = SSL_load_client_CA_file(ca)) == NULL)
        goto bail;
      SSL_CTX_set_client_CA_list(ctx->ssl_ctx, cert_stack);
    }
    SSL_CTX_set_cipher_list(ctx->ssl_ctx, ciphers ? ciphers : "DEFAULT");
    SSL_CTX_set_verify(ctx->ssl_ctx, SSL_VERIFY_PEER, verify_cb);
#ifndef OPENSSL_NO_EC
#if defined(SSL_CTX_set_ecdh_auto)
    SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
#elif defined(NID_X9_62_prime256v1)
    EC_KEY *ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
    SSL_CTX_set_tmp_ecdh(ctx->ssl_ctx, ec_key);
    EC_KEY_free(ec_key);
#endif
#endif
    existing_ctx_cn = ssl_ctx_cache_set(ctx->ssl_ctx_cn);
    if(existing_ctx_cn != ctx->ssl_ctx_cn) {
      ssl_ctx_cache_node_free(ctx->ssl_ctx_cn);
      ctx->ssl_ctx_cn = existing_ctx_cn;
    }
  }
Пример #12
0
boost::asio::ssl::context ssl_options_t::create_context() const
{
  boost::asio::ssl::context ssl_context{boost::asio::ssl::context::tlsv12};
  if (!bool(*this))
    return ssl_context;

  // only allow tls v1.2 and up
  ssl_context.set_options(boost::asio::ssl::context::default_workarounds);
  ssl_context.set_options(boost::asio::ssl::context::no_sslv2);
  ssl_context.set_options(boost::asio::ssl::context::no_sslv3);
  ssl_context.set_options(boost::asio::ssl::context::no_tlsv1);
  ssl_context.set_options(boost::asio::ssl::context::no_tlsv1_1);

  // only allow a select handful of tls v1.3 and v1.2 ciphers to be used
  SSL_CTX_set_cipher_list(ssl_context.native_handle(), "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256");

  // set options on the SSL context for added security
  SSL_CTX *ctx = ssl_context.native_handle();
  CHECK_AND_ASSERT_THROW_MES(ctx, "Failed to get SSL context");
  SSL_CTX_clear_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT); // SSL_CTX_SET_OPTIONS(3)
  SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); // https://stackoverflow.com/questions/22378442
#ifdef SSL_OP_NO_TICKET
  SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); // https://stackoverflow.com/questions/22378442
#endif
#ifdef SSL_OP_NO_RENEGOTIATION
  SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION);
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
  SSL_CTX_set_options(ctx, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#endif
#ifdef SSL_OP_NO_COMPRESSION
  SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
  SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif
  SSL_CTX_set_ecdh_auto(ctx, 1);

  switch (verification)
  {
    case ssl_verification_t::system_ca:
      ssl_context.set_default_verify_paths();
      break;
    case ssl_verification_t::user_certificates:
      ssl_context.set_verify_depth(0);
      /* fallthrough */
    case ssl_verification_t::user_ca:
      if (!ca_path.empty())
      {
        const boost::system::error_code err = load_ca_file(ssl_context, ca_path);
        if (err)
          throw boost::system::system_error{err, "Failed to load user CA file at " + ca_path};
      }
      break;
    default:
      break;
  }

  CHECK_AND_ASSERT_THROW_MES(auth.private_key_path.empty() == auth.certificate_path.empty(), "private key and certificate must be either both given or both empty");
  if (auth.private_key_path.empty())
  {
    EVP_PKEY *pkey;
    X509 *cert;
    bool ok = false;

#ifdef USE_EXTRA_EC_CERT
    CHECK_AND_ASSERT_THROW_MES(create_ec_ssl_certificate(pkey, cert, NID_secp256k1), "Failed to create certificate");
    CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate");
    if (!SSL_CTX_use_PrivateKey(ctx, pkey))
      MERROR("Failed to use generated EC private key for " << NID_secp256k1);
    else
      ok = true;
    X509_free(cert);
    EVP_PKEY_free(pkey);
#endif

    CHECK_AND_ASSERT_THROW_MES(create_rsa_ssl_certificate(pkey, cert), "Failed to create certificate");
    CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate");
    if (!SSL_CTX_use_PrivateKey(ctx, pkey))
      MERROR("Failed to use generated RSA private key for RSA");
    else
      ok = true;
    X509_free(cert);
    EVP_PKEY_free(pkey);

    CHECK_AND_ASSERT_THROW_MES(ok, "Failed to use any generated certificate");
  }
  else
    auth.use_ssl_certificate(ssl_context);

  return ssl_context;
}
Пример #13
0
    SSL_CTX *
tls_server_setup( int authlevel, const char *caFile,
	const char *caDir, const char *cert, const char *privatekey,
	const char *ciphers )
{
    SSL_CTX		*ssl_ctx;
    int                 ssl_mode = 0;
    static unsigned char dh4096_p[ ] = {
	0x91, 0x6B, 0xA1, 0x6D, 0xC7, 0xE7, 0x1C, 0x21, 0x69, 0xCE, 0x7C, 0x3D,
	0x72, 0x28, 0x01, 0x56, 0xAE, 0x71, 0xFE, 0xEF, 0x29, 0x4B, 0xDC, 0xD1,
	0x23, 0x37, 0x9E, 0xA5, 0x80, 0x45, 0xEF, 0x51, 0x7A, 0x65, 0x77, 0x41,
	0x90, 0x5D, 0xEA, 0xAB, 0x52, 0x39, 0xF0, 0xE1, 0xA9, 0x77, 0xA1, 0xCD,
	0x14, 0xB1, 0x8B, 0x07, 0x4F, 0xC5, 0x44, 0xD9, 0x2F, 0x7A, 0x74, 0xFD,
	0xBB, 0xEA, 0x6C, 0x4A, 0x22, 0xD0, 0x78, 0xCA, 0xCF, 0x51, 0x04, 0x0E,
	0x88, 0x44, 0x65, 0x41, 0xD9, 0x10, 0x6A, 0x11, 0x66, 0x21, 0x0E, 0xE7,
	0x9B, 0x39, 0x36, 0xF6, 0x59, 0x15, 0x83, 0xFB, 0x57, 0x51, 0x02, 0xE2,
	0x95, 0xBE, 0x85, 0xDA, 0x78, 0x40, 0xC1, 0x9A, 0x0A, 0xE6, 0x43, 0x95,
	0xD8, 0x7A, 0x30, 0x50, 0x15, 0x9F, 0x37, 0x5E, 0xAA, 0x27, 0x50, 0xA4,
	0x15, 0x1C, 0x6E, 0xFE, 0x3B, 0xA5, 0xD9, 0xF6, 0x0F, 0xE3, 0xA5, 0xFF,
	0xE7, 0xDA, 0xD9, 0x68, 0x64, 0x40, 0xF3, 0x54, 0x32, 0x84, 0xF3, 0x12,
	0xC4, 0xD3, 0x77, 0x25, 0x00, 0x60, 0x0D, 0x95, 0xEA, 0x16, 0xE0, 0x51,
	0x91, 0x8F, 0xF4, 0x40, 0x1B, 0x8A, 0x2D, 0x84, 0x0E, 0xAC, 0x53, 0x58,
	0x08, 0x4E, 0x52, 0xC8, 0xE4, 0x6E, 0xA1, 0xCB, 0xA6, 0xF8, 0x3B, 0xE0,
	0x1F, 0x35, 0xA6, 0x37, 0x6A, 0x62, 0x61, 0xDE, 0x6D, 0x5A, 0x70, 0x70,
	0x71, 0xC9, 0x24, 0x41, 0x70, 0x7C, 0xCD, 0x3F, 0xD9, 0x38, 0xDB, 0x7B,
	0x26, 0xFA, 0xB5, 0x6B, 0xAC, 0xF0, 0x2D, 0x45, 0xD8, 0x55, 0x68, 0xCB,
	0x89, 0x04, 0x1F, 0xA0, 0xAD, 0x6F, 0xCB, 0x05, 0x04, 0xB3, 0x26, 0xF4,
	0x53, 0x02, 0x9E, 0xB8, 0x76, 0x8D, 0xC6, 0xE8, 0x12, 0x24, 0x38, 0x4E,
	0x46, 0x27, 0x30, 0xAE, 0x55, 0x1A, 0xD0, 0xDB, 0xCE, 0x4C, 0x35, 0xFA,
	0x7D, 0x9D, 0x40, 0x3E, 0x66, 0x7A, 0xBA, 0xEA, 0x78, 0x6C, 0x6E, 0x47,
	0x81, 0xBD, 0xB0, 0x57, 0x5D, 0x1C, 0x94, 0xCC, 0x4F, 0x08, 0xF3, 0x5E,
	0xB1, 0x6E, 0x0B, 0xD5, 0x55, 0x45, 0x3F, 0x8B, 0xFD, 0x01, 0x4E, 0x01,
	0x21, 0x34, 0x20, 0xA8, 0x49, 0xB0, 0x75, 0x40, 0xB4, 0x55, 0x17, 0x3A,
	0x55, 0x1E, 0xBA, 0xF2, 0x31, 0x1D, 0x89, 0x81, 0x7A, 0xB3, 0x87, 0xC9,
	0xFB, 0xBB, 0x8A, 0x26, 0x66, 0x99, 0x19, 0x7E, 0x3C, 0xB1, 0x6A, 0x9A,
	0x4A, 0xDC, 0xE9, 0x3C, 0xF0, 0x7C, 0x29, 0xC9, 0xA1, 0xE1, 0x78, 0x3A,
	0x73, 0x8F, 0xEF, 0x2B, 0x33, 0xDF, 0x0C, 0x53, 0xCE, 0x98, 0x91, 0x7C,
	0xE3, 0xC9, 0xE2, 0x26, 0xD8, 0x2F, 0x1A, 0x69, 0xCA, 0xB8, 0x64, 0x3B,
	0x43, 0x38, 0xBB, 0xFA, 0x89, 0x59, 0xE0, 0x3C, 0xDA, 0xED, 0x93, 0x65,
	0x8B, 0x12, 0xED, 0xDB, 0x6F, 0x8F, 0xC5, 0xFE, 0x9C, 0xEB, 0x88, 0xD2,
	0xAB, 0x89, 0xAF, 0xAF, 0x60, 0xFF, 0xFC, 0x40, 0x69, 0x3C, 0xD0, 0x22,
	0x02, 0xB8, 0x2C, 0x1D, 0x9A, 0x26, 0x19, 0x33, 0xCB, 0x5A, 0x9D, 0x91,
	0xDD, 0x05, 0x39, 0x68, 0xBA, 0x15, 0x2B, 0x14, 0xFD, 0x5D, 0xB8, 0x87,
	0x90, 0xAF, 0xAA, 0x5F, 0x54, 0xC7, 0x43, 0x04, 0xF4, 0xE1, 0x49, 0x91,
	0x42, 0x27, 0x23, 0xCC, 0x5A, 0xFC, 0xF1, 0xA6, 0x2A, 0x39, 0x19, 0xC1,
	0x31, 0xBF, 0xE5, 0x89, 0x8C, 0x48, 0xA7, 0xCE, 0x0E, 0x67, 0x18, 0xA1,
	0x07, 0x8E, 0xBD, 0xFE, 0x2A, 0x9F, 0xF0, 0xA3, 0x19, 0xAA, 0xBC, 0xD7,
	0x6D, 0x43, 0x1C, 0x3D, 0x31, 0xBA, 0x9B, 0xD4, 0xF7, 0xDF, 0x2C, 0x7F,
	0x37, 0x7B, 0xD9, 0x7B, 0xDE, 0x62, 0x5C, 0xDE, 0x21, 0x38, 0x4D, 0xB7,
	0x4A, 0x45, 0x04, 0x7D, 0x76, 0x4A, 0x93, 0xFE, 0x8E, 0x49, 0x04, 0xD0,
	0xAD, 0x99, 0xCD, 0xF0, 0x86, 0x24, 0x5E, 0x73, };
    static unsigned char    dh4096_g[ ] = { 0x02, };
    DH			*dh = NULL;

    /* OpenSSL 1.1.0 added auto-init */
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
    SSL_load_error_strings();
    SSL_library_init();
#endif /* OpenSSL < 1.1.0 */

    if (( ssl_ctx = SSL_CTX_new( SSLv23_server_method())) == NULL ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_new: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	return( NULL );
    }

    if (( dh = DH_new( )) == NULL ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup DH_new: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
    if ( DH_set0_pqg( dh,
	    BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL ),
	    NULL,
	    BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL )) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup DH_set0_pqg: %s",
		ERR_error_string( ERR_get_error(), NULL ));
    }
#else
    dh->p = BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL );
    dh->g = BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL );
    if (( dh->p == NULL ) || ( dh->g == NULL )) {
	syslog( LOG_ERR, "Liberror: tls_server_setup BN_bin2bn: %s",
		ERR_error_string( ERR_get_error(), NULL ));
        goto error;
    }
#endif /* OpenSSL 1.1.0 */

    if ( SSL_CTX_set_tmp_dh( ssl_ctx, dh ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_set_tmp_dh: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

    /* Disable SSLv2 and SSLv3, prefer server cipher ordering */
    SSL_CTX_set_options( ssl_ctx,
	    SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
	    SSL_OP_CIPHER_SERVER_PREFERENCE );

    if ( ciphers == NULL ) {
	SSL_CTX_set_cipher_list( ssl_ctx,
		"EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:"
		"RSA+AES256:DH+CHACHA20:DH+AES128:DH+AES256:!MD5" );
    } else {
	SSL_CTX_set_cipher_list( ssl_ctx, ciphers );
    }

    if ( SSL_CTX_use_PrivateKey_file( ssl_ctx, privatekey,
	    SSL_FILETYPE_PEM ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_use_PrivateKey_file: %s: %s",
		privatekey, ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }
    if ( SSL_CTX_use_certificate_chain_file( ssl_ctx, cert ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_use_certificate_chain_file: %s: %s",
		cert, ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }
    /* Verify that private key matches cert */
    if ( SSL_CTX_check_private_key( ssl_ctx ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_check_private_key: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

    /* Load CA */
    if ( caFile != NULL ) {
	if ( SSL_CTX_load_verify_locations( ssl_ctx, caFile, NULL ) != 1 ) {
	    syslog( LOG_ERR, "Liberror: tls_server_setup "
		    "SSL_CTX_load_verify_locations: %s: %s",
		    caFile, ERR_error_string( ERR_get_error(), NULL ));
	    goto error;
	}
    }
    if ( caDir != NULL ) {
	if ( SSL_CTX_load_verify_locations( ssl_ctx, NULL, caDir ) != 1 ) {
	    syslog( LOG_ERR, "Liberror: tls_server_setup "
		    "SSL_CTX_load_verify_locations: %s: %s",
		    caDir, ERR_error_string( ERR_get_error(), NULL ));
	    goto error;
	}
    }

    /* Set level of security expecations */
    if ( authlevel <= 1 ) {
	ssl_mode = SSL_VERIFY_NONE;
    } else {
	/* authlevel == 2 */
	ssl_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    }
    SSL_CTX_set_verify( ssl_ctx, ssl_mode, NULL );

#ifndef OPENSSL_NO_ECDH
    /* Do not reuse the same ECDH key pair */
    SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE);

#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER))
    /* OpenSSL >= 1.1.0 automatically enables automatic handling of parameter
     * selection and makes SSL_CTX_set_ecdh_auto a noop, so we don't want
     * to do anything.
     */
#elif OPENSSL_VERSION_NUMBER >= 0x10002000L
    /* OpenSSL >= 1.0.2 automatically handles parameter selection */
    SSL_CTX_set_ecdh_auto(ssl_ctx, 1);

#elif OPENSSL_VERSION_NUMBER >= 0x10000000L
    /* Manually select the curve. This selection is compliant with RFC 6460
     * when AES-256 cipher suites are in use, but noncompliant when AES-128
     * cipher suites are used. Oh, well. */
    EC_KEY *ecdh;
    if (( ecdh = EC_KEY_new_by_curve_name( NID_secp384r1 )) != NULL ) {
	SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
	EC_KEY_free(ecdh);
    } else {
	syslog( LOG_ERR, "Liberror: tls_server_setup EC_KEY_new failed: %s",
		ERR_error_string( ERR_get_error(), NULL ));
    }
#endif /* openssl 1.0 - 1.0.1 */
#endif /* OPENSSL_NO_ECDH */

    return( ssl_ctx );

    error:
    SSL_CTX_free( ssl_ctx );
    if ( dh != NULL ) {
	DH_free( dh );
    }
    return( NULL );
}
Пример #14
0
	void DtlsTransport::CreateSSL_CTX()
	{
		MS_TRACE();

		std::string ssl_srtp_profiles;
		EC_KEY* ecdh = nullptr;
		int ret;

		/* Set the global DTLS context. */

		// - Both DTLS 1.0 and 1.2 (requires OpenSSL >= 1.1.0).
		#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
			DtlsTransport::sslCtx = SSL_CTX_new(DTLS_method());
		// - Just DTLS 1.0 (requires OpenSSL >= 1.0.1).
		#elif (OPENSSL_VERSION_NUMBER >= 0x10001000L)
			DtlsTransport::sslCtx = SSL_CTX_new(DTLSv1_method());
		#else
			#error "too old OpenSSL version"
		#endif

		if (!DtlsTransport::sslCtx)
		{
			LOG_OPENSSL_ERROR("SSL_CTX_new() failed");
			goto error;
		}

		ret = SSL_CTX_use_certificate(DtlsTransport::sslCtx, DtlsTransport::certificate);
		if (ret == 0)
		{
			LOG_OPENSSL_ERROR("SSL_CTX_use_certificate() failed");
			goto error;
		}

		ret = SSL_CTX_use_PrivateKey(DtlsTransport::sslCtx, DtlsTransport::privateKey);
		if (ret == 0)
		{
			LOG_OPENSSL_ERROR("SSL_CTX_use_PrivateKey() failed");
			goto error;
		}

		ret = SSL_CTX_check_private_key(DtlsTransport::sslCtx);
		if (ret == 0)
		{
			LOG_OPENSSL_ERROR("SSL_CTX_check_private_key() failed");
			goto error;
		}

		// Set options.
		SSL_CTX_set_options(DtlsTransport::sslCtx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_TICKET | SSL_OP_SINGLE_ECDH_USE);

		// Don't use sessions cache.
		SSL_CTX_set_session_cache_mode(DtlsTransport::sslCtx, SSL_SESS_CACHE_OFF);

		// Read always as much into the buffer as possible.
		// NOTE: This is the default for DTLS, but a bug in non latest OpenSSL
		// versions makes this call required.
		SSL_CTX_set_read_ahead(DtlsTransport::sslCtx, 1);

		SSL_CTX_set_verify_depth(DtlsTransport::sslCtx, 4);

		// Require certificate from peer.
		SSL_CTX_set_verify(DtlsTransport::sslCtx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, on_ssl_certificate_verify);

		// Set SSL info callback.
		SSL_CTX_set_info_callback(DtlsTransport::sslCtx, on_ssl_info);

		// Set ciphers.
		ret = SSL_CTX_set_cipher_list(DtlsTransport::sslCtx, "ALL:!ADH:!LOW:!EXP:!MD5:!aNULL:!eNULL:@STRENGTH");
		if (ret == 0)
		{
			LOG_OPENSSL_ERROR("SSL_CTX_set_cipher_list() failed");
			goto error;
		}

		// Enable ECDH ciphers.
		// DOC: http://en.wikibooks.org/wiki/OpenSSL/Diffie-Hellman_parameters
		// NOTE: https://code.google.com/p/chromium/issues/detail?id=406458
		// For OpenSSL >= 1.0.2:
		#if (OPENSSL_VERSION_NUMBER >= 0x10002000L)
			SSL_CTX_set_ecdh_auto(DtlsTransport::sslCtx, 1);
		#else
			ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
			if (!ecdh)
			{
				LOG_OPENSSL_ERROR("EC_KEY_new_by_curve_name() failed");
				goto error;
			}
			if (SSL_CTX_set_tmp_ecdh(DtlsTransport::sslCtx, ecdh) != 1)
			{
				LOG_OPENSSL_ERROR("SSL_CTX_set_tmp_ecdh() failed");
				goto error;
			}
			EC_KEY_free(ecdh);
			ecdh = nullptr;
		#endif

		// Set the "use_srtp" DTLS extension.
		for (auto it = DtlsTransport::srtpProfiles.begin(); it != DtlsTransport::srtpProfiles.end(); ++it)
		{
			if (it != DtlsTransport::srtpProfiles.begin())
				ssl_srtp_profiles += ":";

			SrtpProfileMapEntry* profile_entry = &(*it);
			ssl_srtp_profiles += profile_entry->name;
		}
		MS_DEBUG("setting SRTP profiles for DTLS: %s", ssl_srtp_profiles.c_str());
		// NOTE: This function returns 0 on success.
		ret = SSL_CTX_set_tlsext_use_srtp(DtlsTransport::sslCtx, ssl_srtp_profiles.c_str());
		if (ret != 0)
		{
			MS_ERROR("SSL_CTX_set_tlsext_use_srtp() failed when entering '%s'", ssl_srtp_profiles.c_str());
			LOG_OPENSSL_ERROR("SSL_CTX_set_tlsext_use_srtp() failed");
			goto error;
		}

		return;

	error:
		if (DtlsTransport::sslCtx)
		{
			SSL_CTX_free(DtlsTransport::sslCtx);
			DtlsTransport::sslCtx = nullptr;
		}

		if (ecdh)
			EC_KEY_free(ecdh);

		MS_THROW_ERROR("SSL context creation failed");
	}
Пример #15
0
/*
    Open the SSL module
 */
PUBLIC int sslOpen()
{
    RandBuf     randBuf;
    X509_STORE  *store;
    uchar       resume[16];
    char        *ciphers;

    trace(7, "Initializing SSL");

    randBuf.now = time(0);
    randBuf.pid = getpid();
    RAND_seed((void*) &randBuf, sizeof(randBuf));
#if ME_UNIX_LIKE
    trace(6, "OpenSsl: Before calling RAND_load_file");
    RAND_load_file("/dev/urandom", 256);
    trace(6, "OpenSsl: After calling RAND_load_file");
#endif

    CRYPTO_malloc_init();
#if !ME_WIN_LIKE
    OpenSSL_add_all_algorithms();
#endif
    SSL_library_init();
    SSL_load_error_strings();
    SSLeay_add_ssl_algorithms();

    if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) {
        error("Unable to create SSL context");
        return -1;
    }

    /*
          Set the server certificate and key files
     */
    if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) {
        sslClose();
        return -1;
    }
    if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) {
        sslClose();
        return -1;
    }

    if (ME_GOAHEAD_SSL_VERIFY_PEER) {
        SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate);
        SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH);
    } else {
        SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate);
    }
    /*
          Set the client certificate verification locations
     */
    if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) {
        if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) ||
                (!SSL_CTX_set_default_verify_paths(sslctx))) {
            error("Unable to read cert verification locations");
            sslClose();
            return -1;
        }
        /*
            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(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY));
    }
    if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) {
        store = SSL_CTX_get_cert_store(sslctx);
        if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) {
            error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE);
            sslClose();
            return -1;
        }
    }

    /*
        Configure DH parameters
     */
    dhKey = getDhKey();
    SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback);

    /*
        Configure cipher suite
     */
    if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) {
        ciphers = ME_GOAHEAD_SSL_CIPHERS;
    } else {
        ciphers = OPENSSL_DEFAULT_CIPHERS;
    }
    ciphers = mapCipherNames(ciphers);
    trace(5, "Using OpenSSL ciphers: %s", ciphers);
    if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) {
        error("Unable to set cipher list \"%s\"", ciphers);
        sslClose();
        wfree(ciphers);
        return -1;
    }
    wfree(ciphers);

    /*
        Define default OpenSSL options
     */
    SSL_CTX_set_options(sslctx, SSL_OP_ALL);

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

    /*
        Define a session reuse context
     */
    RAND_bytes(resume, sizeof(resume));
    SSL_CTX_set_session_id_context(sslctx, resume, sizeof(resume));

    /*
        Elliptic Curve initialization
     */
#if SSL_OP_SINGLE_ECDH_USE
#ifdef SSL_CTX_set_ecdh_auto
    SSL_CTX_set_ecdh_auto(sslctx, 1);
#else
    {
        EC_KEY  *ecdh;
        cchar   *name;
        int      nid;

        name = ME_GOAHEAD_SSL_CURVE;
        if ((nid = OBJ_sn2nid(name)) == 0) {
            error("Unknown curve name \"%s\"", name);
            sslClose();
            return -1;
        }
        if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
            error("Unable to create curve \"%s\"", name);
            sslClose();
            return -1;
        }
        SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE);
        SSL_CTX_set_tmp_ecdh(sslctx, ecdh);
        EC_KEY_free(ecdh);
    }
#endif
#endif

    SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    SSL_CTX_set_options(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif

    /*
        Select the required protocols
        Disable both SSLv2 and SSLv3 by default - they are insecure
     */
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2);
    SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3);

#if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1);
#endif
#if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1);
#endif
#if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2
    SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2);
#endif


#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
#if defined(ME_GOAHEAD_SSL_TICKET)
    if (ME_GOAHEAD_SSL_TICKET) {
        SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
    } else {
        SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET);
    }
#else
    SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET);
#endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /*
        CRIME attack targets compression
     */
    SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION);
#endif

#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
    /*
        Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
        Defaults to true.
     */
#if defined(ME_GOAHEAD_SSL_EMPTY_FRAGMENTS)
    if (ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) {
        /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
        SSL_CTX_clear_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    } else {
        SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    }
#else
    SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
#endif
#endif

#if defined(ME_GOAHEAD_SSL_CACHE)
    /*
        Set the number of sessions supported. Default in OpenSSL is 20K.
     */
    SSL_CTX_sess_set_cache_size(sslctx, ME_GOAHEAD_SSL_CACHE);
#else
    SSL_CTX_sess_set_cache_size(sslctx, 256);
#endif

    return 0;
}
Пример #16
0
int main(int argc, char **argv)
{
  char buf[BUFFER_SIZE];

  SSL_CTX *ctx;
  const SSL_METHOD *method;
  BIO *abio, *cbio;

  if (argc < 2) {
    fprintf(stderr, "Usage: %s [port]\n", argv[0]);
    exit(EXIT_FAILURE);
  }

  // init openssl lib.
  SSL_library_init(); // call OpenSSL_add_ssl_algorithms();
  ERR_load_BIO_strings();
  SSL_load_error_strings();

  // setup tls context.
  method = TLSv1_2_server_method(); // SSLv23_server_method();
  ctx = SSL_CTX_new(method);
  if (!ctx) {
    perror("Unable to create SSL context");
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  /* Set the key and cert */
  if (SSL_CTX_use_certificate_file(ctx, CERT_FILE_PATH, SSL_FILETYPE_PEM) <= 0) {
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  if (SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE_PATH, SSL_FILETYPE_PEM) <= 0 ) {
    ERR_print_errors_fp(stderr);
    exit(EXIT_FAILURE);
  }
  SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384");
  SSL_CTX_set_ecdh_auto(ctx, 1);

  // create BIO(high level API); for accept
  abio = BIO_new_accept(argv[1]);
  if(BIO_do_accept(abio) <= 0) {
    // first BIO_do_accept() is as to init BIO.
    fprintf(stderr, "Error setting up accept\n");
    ERR_print_errors_fp(stderr);
    exit(0);
  }
  // configuration for I/O operation over ssl/tls.
  BIO_set_accept_bios(abio, BIO_new_ssl(ctx, 0));

  // listen loop
  printf("Server is listening on %d\n", atoi(argv[1]));
  while (1) {
    if(BIO_do_accept(abio) <= 0) {
      fprintf(stderr, "Error accepting connection\n");
      ERR_print_errors_fp(stderr);
      exit(0);
    }
    fprintf(stderr, "Connection 1 established\n");
    /* Retrieve BIO for connection */
    cbio = BIO_pop(abio);
    while (1) {
      int len, err;
      len = BIO_read(cbio, buf, BUFFER_SIZE);
      if (!len) break;
      if (len < 0) {
        fprintf(stderr, "error SSL_read");
        break;
      }
      err = BIO_write(cbio, buf, len);
      if (err < 0) {
        fprintf(stderr, "error SSL_write");
        break;
      }
    }
    BIO_free(cbio);
  }
}
Пример #17
0
/* static */ void
BSecureSocket::Private::_CreateContext()
{
	// We want SSL to report errors in human readable format.
	SSL_load_error_strings();

	// "SSLv23" means "any SSL or TLS version". We disable SSL v2 and v3 below
	// to keep only TLS 1.0 and above.
	sContext = SSL_CTX_new(SSLv23_method());

#if TRACE_SSL
	// For debugging purposes: get all SSL messages to the standard error.
	SSL_CTX_set_info_callback(sContext, apps_ssl_info_callback);
#endif

	// Disable legacy protocols. They have known vulnerabilities.
	SSL_CTX_set_options(sContext, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	// Disable SSL/TLS compression to prevent the CRIME attack.
	SSL_CTX_set_options(sContext, SSL_OP_NO_COMPRESSION);

	// Don't bother us with ERROR_WANT_READ.
	SSL_CTX_set_mode(sContext, SSL_MODE_AUTO_RETRY);

	// Setup cipher suites.
	// Only accept reasonably secure ones ("HIGH") and disable some known
	// broken stuff (https://wiki.openssl.org/index.php/SSL/TLS_Client)
	SSL_CTX_set_cipher_list(sContext, "HIGH:!aNULL:!PSK:!SRP:!MD5:!RC4");

	SSL_CTX_set_ecdh_auto(sContext, 1);

	// Setup certificate verification
	BPath certificateStore;
	find_directory(B_SYSTEM_DATA_DIRECTORY, &certificateStore);
	certificateStore.Append("ssl/CARootCertificates.pem");
	// TODO we may want to add a non-packaged certificate directory?
	// (would make it possible to store user-added certificate exceptions
	// there)
	SSL_CTX_load_verify_locations(sContext, certificateStore.Path(), NULL);
	SSL_CTX_set_verify(sContext, SSL_VERIFY_PEER, VerifyCallback);

	// OpenSSL 1.0.2 and later: use the alternate "trusted first" algorithm to
	// validate certificate chains. This makes the validation stop as soon as a
	// recognized certificate is found in the chain, instead of validating the
	// whole chain, then seeing if the root certificate is known.
#ifdef X509_V_FLAG_TRUSTED_FIRST
	X509_VERIFY_PARAM* verifyParam = X509_VERIFY_PARAM_new();
	X509_VERIFY_PARAM_set_flags(verifyParam, X509_V_FLAG_TRUSTED_FIRST);
	SSL_CTX_set1_param(sContext, verifyParam);

	// TODO we need to free this after freeing the SSL context (which we
	// currently never do)
	// X509_VERIFY_PARAM_free(verifyParam);
#endif

	// Get an unique index number for storing application data in SSL
	// structs. We will store a pointer to the BSecureSocket class there.
	sDataIndex = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);

#ifdef TRACE_SESSION_KEY
	FILE *keylog = NULL;
	const char *logpath = getenv("SSLKEYLOGFILE");
	if (logpath)
		keylog = fopen(logpath, "w+");
	if (keylog) {
		fprintf(keylog, "# Key Log File generated by Haiku Network Kit\n");
		sKeyLogBIO = BIO_new_fp(keylog, BIO_NOCLOSE);
	}
#endif
}
Пример #18
0
void enclave_main()
{
    SSL_METHOD *method;
    SSL_CTX *ctx;
    BIO *bio_cert;
    BIO *bio_pkey;
    X509 *cert = NULL;
    EVP_PKEY *pkey = NULL;
    int port = 5566;
    int srvr_fd;
    int clnt_fd;
    struct sockaddr_in addr;

    // Initialize ssl
    SSL_library_init();

    // Initialize ctx
    OpenSSL_add_all_algorithms();
    method = TLSv1_2_server_method();
    ctx = SSL_CTX_new(method);

    // Load certificate
    bio_cert = BIO_new(BIO_s_mem());
    BIO_puts(bio_cert, cert_s);

    cert = PEM_read_bio_X509(bio_cert, NULL, 0, NULL);

    if (cert == NULL) {
        sgx_debug("cert is NULL");
    } else {
        sgx_debug("cert is not NULL");
    }

    bio_pkey = BIO_new(BIO_s_mem());
    BIO_puts(bio_pkey, pkey_s);

    pkey = PEM_read_bio_PrivateKey(bio_pkey, NULL, 0, NULL);

    if (pkey == NULL) {
        sgx_debug("key is NULL\n");
    } else {
        sgx_debug("key is not NULL\n");
    }

    if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
    	sgx_debug("SSL_CTX_use_certificate failed\n");
        //sgx_exit(NULL);
    } else {
        sgx_debug("SSL_CTX_use_certificate succeeded\n");
    }

    if (SSL_CTX_use_PrivateKey(ctx, pkey) <= 0) {
    	sgx_debug("SSL_CTX_use_PrivateKey failed\n");
        //sgx_exit(NULL);
    } else {
    	sgx_debug("SSL_CTX_use_PrivateKey succeeded\n");
    }

    SSL_CTX_set_ecdh_auto(ctx, 1);
    SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);

    srvr_fd = sgx_socket(PF_INET, SOCK_STREAM, 0);

    if (srvr_fd == -1) {
        sgx_exit(NULL);
    }

    sgx_memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = sgx_htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (sgx_bind(srvr_fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
        sgx_exit(NULL);
    }

    if (sgx_listen(srvr_fd, 10) != 0) {
        sgx_exit(NULL);
    }

    while (1) {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL *ssl;
        int sd;
        int bytes;
        char buf[256];
        const char* echo="<html><body><pre>%s</pre></body></html>\n\n";

        clnt_fd = sgx_accept(srvr_fd, (struct sockaddr *)&addr, &len);
        if (clnt_fd < 0) {
            sgx_puts("ERROR on accept\n");
            continue;
        }

        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, clnt_fd);
        if (SSL_accept(ssl) == -1)
            sgx_puts("SSL accept failed\n");
        else {
            sgx_puts("SSL accept succeeded\n");

            bytes = SSL_read(ssl, buf, sizeof(buf));
            if (bytes > 0) {
                buf[bytes] = 0;
                sgx_puts(buf);
                char msg[] = "Successfully connected\n";
                SSL_write(ssl, msg, sgx_strlen(msg));
            }
        }

        sd = SSL_get_fd(ssl);
        //SSL_free(ssl);
        sgx_close(sd);
        //sgx_close(clnt_fd);
    }

    sgx_close(srvr_fd);

    sgx_exit(NULL);
}
Пример #19
0
int
mowgli_vio_openssl_default_listen(mowgli_vio_t *vio, int backlog)
{
	return_val_if_fail(vio, -255);

	mowgli_ssl_connection_t *connection = vio->privdata;
	const int fd = mowgli_vio_getfd(vio);

	vio->error.op = MOWGLI_VIO_ERR_OP_LISTEN;

#ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API
	connection->ssl_context = SSL_CTX_new(SSLv23_server_method());
#else
	connection->ssl_context = SSL_CTX_new(TLS_server_method());
#endif

	if (connection->ssl_context == NULL)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

#ifndef MOWGLI_HAVE_OPENSSL_TLS_METHOD_API
#  ifdef SSL_OP_NO_SSLv2
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv2);
#  endif
#  ifdef SSL_OP_NO_SSLv3
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_NO_SSLv3);
#  endif
#endif

	connection->ssl_handle = SSL_new(connection->ssl_context);

	if (connection->ssl_handle == NULL)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	SSL_set_accept_state(connection->ssl_handle);
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_DH_USE);

#ifdef OPENSSL_EC_AVAILABLE
#  ifdef MOWGLI_HAVE_OPENSSL_ECDH_AUTO
	SSL_CTX_set_ecdh_auto(connection->ssl_context, 1);
#  else

	EC_KEY *ec_key_p256 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);

	if (ec_key_p256 != NULL)
	{
		SSL_CTX_set_tmp_ecdh(connection->ssl_context, ec_key_p256);
		EC_KEY_free(ec_key_p256);
		ec_key_p256 = NULL;
	}

#  endif
#  ifdef SSL_OP_SINGLE_ECDH_USE
	SSL_CTX_set_options(connection->ssl_context, SSL_OP_SINGLE_ECDH_USE);
#  endif
#endif

	if (connection->settings.password_func)
	{
		SSL_CTX_set_default_passwd_cb(connection->ssl_context, connection->settings.password_func);
		SSL_CTX_set_default_passwd_cb_userdata(connection->ssl_context, vio->userdata);
	}

	if (SSL_CTX_use_certificate_file(connection->ssl_context, connection->settings.cert_path, SSL_FILETYPE_PEM) != 1)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	if (SSL_CTX_use_PrivateKey_file(connection->ssl_context, connection->settings.privatekey_path, SSL_FILETYPE_PEM) != 1)
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	if (listen(fd, backlog) != 0)
		return mowgli_vio_err_errcode(vio, strerror, errno);

	if (!SSL_set_fd(connection->ssl_handle, fd))
		return mowgli_vio_err_sslerrcode(vio, ERR_get_error());

	mowgli_vio_setflag(vio, MOWGLI_VIO_FLAGS_ISSERVER, true);
	vio->error.op = MOWGLI_VIO_ERR_OP_NONE;

	return 0;
}
Пример #20
0
int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) {
    return SSL_CTX_set_ecdh_auto(ctx, onoff);
}
Пример #21
0
int LLVMFuzzerInitialize(int* argc, char*** argv)
{
    rand_predictable = 1;

    SSL_library_init();
    OpenSSL_add_ssl_algorithms();
    ERR_load_crypto_strings();

    if (RAND_reset_for_fuzzing)
        RAND_reset_for_fuzzing();

    ctx = SSL_CTX_new(SSLv23_method());
    const uint8_t* bufp = kRSAPrivateKeyDER;
    RSA* privkey = d2i_RSAPrivateKey(NULL, &bufp, sizeof(kRSAPrivateKeyDER));
    assert(privkey != NULL);
    EVP_PKEY* pkey = EVP_PKEY_new();
    EVP_PKEY_assign_RSA(pkey, privkey);
    int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
    assert(ret == 1);
    EVP_PKEY_free(pkey);

    bufp = kCertificateDER;
    X509* cert = d2i_X509(NULL, &bufp, sizeof(kCertificateDER));
    assert(cert != NULL);
    ret = SSL_CTX_use_certificate(ctx, cert);
    assert(ret == 1);
    X509_free(cert);
    ret = SSL_CTX_set_cipher_list(ctx, "ALL:eNULL:aNULL:DSS");
    assert(ret == 1);

    X509_STORE* store = X509_STORE_new();
    assert(store != NULL);

    bufp = kRSACACertDER;
    cert = d2i_X509(NULL, &bufp, sizeof(kRSACACertDER));
    assert(cert != NULL);
    ret = SSL_CTX_add_client_CA(ctx, cert);
    assert(ret == 1);
    ret = X509_STORE_add_cert(store, cert);
    assert(ret == 1);
    X509_free(cert);

    bufp = kECCACertDER;
    cert = d2i_X509(NULL, &bufp, sizeof(kECCACertDER));
    assert(cert != NULL);
    ret = SSL_CTX_add_client_CA(ctx, cert);
    assert(ret == 1);
    ret = X509_STORE_add_cert(store, cert);
    assert(ret == 1);
    X509_free(cert);

    bufp = kDSACertDER;
    cert = d2i_X509(NULL, &bufp, sizeof(kDSACertDER));
    ret = SSL_CTX_add_client_CA(ctx, cert);
    assert(ret == 1);
    ret = X509_STORE_add_cert(store, cert);
    assert(ret == 1);
    X509_free(cert);

    SSL_CTX_set_cert_store(ctx, store);
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, NULL);
    SSL_CTX_set_verify_depth(ctx, 10);

#if !defined(LIBRESSL_VERSION_NUMBER)
    SSL_CTX_set_psk_server_callback(ctx, psk_callback);
    ret = SSL_CTX_use_psk_identity_hint(ctx, "ABCDEFUZZ");
    assert(ret == 1);
#endif /* !defined(LIBRESSL_VERSION_NUMBER) */

#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION)
    ret = SSL_CTX_set_srp_username_callback(ctx, srp_callback);
    assert(ret == 1);
    ret = SSL_CTX_set_srp_cb_arg(ctx, NULL);
    assert(ret == 1);
#endif /* !defined(LIBRESSL_VERSION_NUMBER) && !defined(BORINGSSL_API_VERSION) */

    SSL_CTX_set_alpn_select_cb(ctx, alpn_callback, NULL);
    SSL_CTX_set_next_protos_advertised_cb(ctx, npn_callback, NULL);
    SSL_CTX_set_ecdh_auto(ctx, 1);

    return 1;
}
Пример #22
0
int
rb_setup_ssl_server(const char *certfile, const char *keyfile, const char *dhfile, const char *cipher_list)
{
	const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!aNULL";

	#ifdef LRB_HAVE_TLS_SET_CURVES
	const char librb_curves[] = "P-521:P-384:P-256";
	#endif

	if(certfile == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No certificate file");
		return 0;
	}

	if(keyfile == NULL)
		keyfile = certfile;

	if(cipher_list == NULL)
		cipher_list = librb_ciphers;

	if (ssl_server_ctx)
		SSL_CTX_free(ssl_server_ctx);

	if (ssl_client_ctx)
		SSL_CTX_free(ssl_client_ctx);

	#ifdef LRB_HAVE_TLS_METHOD_API
	ssl_server_ctx = SSL_CTX_new(TLS_server_method());
	ssl_client_ctx = SSL_CTX_new(TLS_client_method());
	#else
	ssl_server_ctx = SSL_CTX_new(SSLv23_server_method());
	ssl_client_ctx = SSL_CTX_new(SSLv23_client_method());
	#endif

	if(ssl_server_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s",
			   get_ssl_error(ERR_get_error()));
		return 0;
	}

	if(ssl_client_ctx == NULL)
	{
		rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s",
			   get_ssl_error(ERR_get_error()));
		return 0;
	}

	#ifndef LRB_HAVE_TLS_METHOD_API
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
	#endif

	#ifdef SSL_OP_SINGLE_DH_USE
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_DH_USE);
	#endif

	#ifdef SSL_OP_SINGLE_ECDH_USE
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_SINGLE_ECDH_USE);
	#endif

	#ifdef SSL_OP_NO_TICKET
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_NO_TICKET);
	SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET);
	#endif

	#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
	SSL_CTX_set_options(ssl_server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
	#endif

	SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb);
	SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF);

	#ifdef LRB_HAVE_TLS_SET_CURVES
	SSL_CTX_set1_curves_list(ssl_server_ctx, librb_curves);
	#endif

	#ifdef LRB_HAVE_TLS_ECDH_AUTO
	SSL_CTX_set_ecdh_auto(ssl_server_ctx, 1);
	#endif

	/*
	 * Set manual ECDHE curve on OpenSSL 1.0.0 & 1.0.1, but make sure it's actually available
	 */
	#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && (OPENSSL_VERSION_NUMBER < 0x10002000L) && !defined(OPENSSL_NO_ECDH)
	EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1);
	if (key) {
		SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key);
		EC_KEY_free(key);
	}
	#endif

	SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list);
	SSL_CTX_set_cipher_list(ssl_client_ctx, cipher_list);

	if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, certfile) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, certfile))
	{
		rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", certfile,
			   get_ssl_error(ERR_get_error()));
		return 0;
	}

	if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM))
	{
		rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
			   get_ssl_error(ERR_get_error()));
		return 0;
	}

	if(dhfile != NULL)
	{
		/* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
		FILE *fp = fopen(dhfile, "r");
		DH *dh = NULL;

		if(fp == NULL)
		{
			rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
			           dhfile, strerror(errno));
		}
		else if(PEM_read_DHparams(fp, &dh, NULL, NULL) == NULL)
		{
			rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
			           dhfile, get_ssl_error(ERR_get_error()));
			fclose(fp);
		}
		else
		{
			SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
			DH_free(dh);
			fclose(fp);
		}
	}

	return 1;
}
Пример #23
0
/*
    Create and initialize an SSL configuration for a route. This configuration is used by all requests for
    a given route. An application can have different SSL configurations for different routes. There is also
    a default SSL configuration that is used when a route does not define a configuration and one for clients.
 */
static int configOss(MprSsl *ssl, int flags, char **errorMsg)
{
    OpenConfig      *cfg;
    X509_STORE      *store;
    SSL_CTX         *ctx;
    cchar           *key;
    uchar           resume[16];
    int             verifyMode;

    assert(ssl);
    if (ssl->config && !ssl->changed) {
        return 0;
    }
    if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) {
        return MPR_ERR_MEMORY;
    }
    cfg = ssl->config;

    if ((ctx = SSL_CTX_new(SSLv23_method())) == 0) {
        mprLog("error openssl", 0, "Unable to create SSL context");
        return MPR_ERR_CANT_INITIALIZE;
    }
    SSL_CTX_set_app_data(ctx, (void*) ssl);

    if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) {
        *errorMsg = sfmt("Cannot verify peer due to undefined CA certificates");
        SSL_CTX_free(ctx);
        return MPR_ERR_CANT_INITIALIZE;
    }

    /*
        Configure the certificates
     */
    if (ssl->certFile) {
        if (setCertFile(ctx, ssl->certFile) < 0) {
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile;
        if (key) {
            if (setKeyFile(ctx, key) < 0) {
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            if (!SSL_CTX_check_private_key(ctx)) {
                mprLog("error openssl", 0, "Check of private key file failed: %s", key);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
        }
    }
    if (ssl->ciphers) {
        ssl->ciphers = mapCipherNames(ssl->ciphers);
    }
    if (!ssl->ciphers && (flags & MPR_SOCKET_SERVER)) {
        ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS);
    }
    if (ssl->ciphers) {
        mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers);
        if (SSL_CTX_set_cipher_list(ctx, ssl->ciphers) != 1) {
            *errorMsg = sfmt("Unable to set cipher list \"%s\"", ssl->ciphers);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
    }
    verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE;
    if (verifyMode != SSL_VERIFY_NONE) {
        if (!(ssl->caFile || ssl->caPath)) {
            *errorMsg = sclone("No defined certificate authority file");
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if ((!SSL_CTX_load_verify_locations(ctx, (char*) ssl->caFile, (char*) ssl->caPath)) ||
                (!SSL_CTX_set_default_verify_paths(ctx))) {
            *errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if (ssl->caFile) {
            STACK_OF(X509_NAME) *certNames;
            certNames = SSL_load_client_CA_file(ssl->caFile);
            if (certNames) {
                /*
                    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(ctx, certNames);
            }
        }
        store = SSL_CTX_get_cert_store(ctx);
        if (ssl->revoke && !X509_STORE_load_locations(store, ssl->revoke, 0)) {
            mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revoke);
            SSL_CTX_free(ctx);
            return MPR_ERR_CANT_INITIALIZE;
        }
        if (flags & MPR_SOCKET_SERVER) {
            SSL_CTX_set_verify_depth(ctx, ssl->verifyDepth);
        }
    }

    /*
        Define callbacks
     */
    SSL_CTX_set_verify(ctx, verifyMode, verifyPeerCertificate);
    if (flags & MPR_SOCKET_SERVER) {
        SSL_CTX_set_tlsext_servername_callback(ctx, sniHostname);
    }

    /*
        Configure DH parameters
     */
    SSL_CTX_set_tmp_dh_callback(ctx, dhcallback);
    cfg->dhKey = getDhKey();

    /*
        Define default OpenSSL options
        Ensure we generate a new private key for each connection
        Disable SSLv2 and SSLv3 by default -- they are insecure.
     */
    cfg->setFlags = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
#ifdef SSL_OP_NO_TLSv1
    if (!(ssl->protocols & MPR_PROTO_TLSV1)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1;
    }
#endif
#ifdef SSL_OP_NO_TLSv1_1
    if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1_1;
    }
#endif
#ifdef SSL_OP_NO_TLSv1_2
    if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) {
        cfg->setFlags |= SSL_OP_NO_TLSv1_2;
    }
#endif
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    cfg->setFlags |= SSL_OP_MSIE_SSLV2_RSA_PADDING;
#endif
#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
    #if defined(ME_MPR_SSL_TICKET)
        if (ME_MPR_SSL_TICKET) {
            cfg->clearFlags |= SSL_OP_NO_TICKET;
        } else {
            cfg->setFlags |= SSL_OP_NO_TICKET;
        }
    #else
        cfg->clearFlags |= SSL_OP_NO_TICKET;
    #endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /*
        CRIME attack targets compression
     */
    cfg->clearFlags |= SSL_OP_NO_COMPRESSION;
#endif

#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
    /*
        Force a new session on renegotiation. Default to true.
        This is required when using SNI and changing context during the SSL hello
     */
    #if defined(ME_MPR_SSL_RENEGOTIATE)
        if (ME_MPR_SSL_RENEGOTIATE) {
            cfg->clearFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
        } else {
            cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
        }
    #else
        cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
    #endif
#endif

#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
    /*
        Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
        Defaults to true.
     */
    #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS)
        if (ME_MPR_SSL_EMPTY_FRAGMENTS) {
            /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
            cfg->clearFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
        } else {
            cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
        }
    #else
        cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
    #endif
#endif

    /*
        Define a session reuse context
     */
    RAND_bytes(resume, sizeof(resume));
    SSL_CTX_set_session_id_context(ctx, resume, sizeof(resume));

    /*
        Elliptic Curve initialization
     */
#if SSL_OP_SINGLE_ECDH_USE
    #ifdef SSL_CTX_set_ecdh_auto
        /* This is supported in OpenSSL 1.0.2 */
        SSL_CTX_set_ecdh_auto(ctx, 1);
    #else
        {
            EC_KEY  *ecdh;
            cchar   *name;
            int      nid;

            name = ME_MPR_SSL_CURVE;
            if ((nid = OBJ_sn2nid(name)) == 0) {
                *errorMsg = sfmt("Unknown curve name \"%s\"", name);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
                *errorMsg = sfmt("Unable to create curve \"%s\"", name);
                SSL_CTX_free(ctx);
                return MPR_ERR_CANT_INITIALIZE;
            }
            SSL_CTX_set_tmp_ecdh(ctx, ecdh);
            EC_KEY_free(ecdh);
        }
    #endif
#endif

    SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif

#if defined(ME_MPR_SSL_CACHE)
    /*
        Set the number of sessions supported. Default in OpenSSL is 20K.
     */
    SSL_CTX_sess_set_cache_size(ctx, ME_MPR_SSL_CACHE);
#else
    SSL_CTX_sess_set_cache_size(ctx, 1024);
#endif

    SSL_CTX_set_options(ctx, cfg->setFlags);
    SSL_CTX_clear_options(ctx, cfg->clearFlags);

    cfg->ctx = ctx;
    ssl->changed = 0;
    ssl->config = cfg;
    return 0;
}
Пример #24
0
int dill_tls_attach_server_mem(int s, const char *cert, const char *pkey,
      struct dill_tls_storage *mem, int64_t deadline) {
    int err;
    if(dill_slow(!mem)) {err = EINVAL; goto error1;}
    /* Check whether underlying socket is a bytestream. */
    void *q = dill_hquery(s, dill_bsock_type);
    if(dill_slow(!q && errno == ENOTSUP)) {err = EPROTO; goto error1;}
    if(dill_slow(!q)) {err = errno; goto error1;}
    /* Create OpenSSL connection context. */
    dill_tls_init();
    const SSL_METHOD *method = SSLv23_server_method();
    if(dill_slow(!method)) {err = EFAULT; goto error1;}
    SSL_CTX *ctx = SSL_CTX_new(method);
    if(dill_slow(!ctx)) {err = EFAULT; goto error1;}
    int rc = SSL_CTX_set_ecdh_auto(ctx, 1);
    if(dill_slow(rc != 1)) {err = EFAULT; goto error2;}
    rc = SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM);
    if(dill_slow(rc <= 0)) {err = EFAULT; goto error2;}
    rc = SSL_CTX_use_PrivateKey_file(ctx, pkey, SSL_FILETYPE_PEM);
    if(dill_slow(rc <= 0 )) {err = EFAULT; goto error2;}
    /* Create OpenSSL connection object. */
    SSL *ssl = SSL_new(ctx);
    if(dill_slow(!ssl)) {err = EFAULT; goto error2;}
	  SSL_set_accept_state(ssl);
    /* Create a BIO and attach it to the connection. */
    BIO *bio = dill_tls_new_cbio(mem);
    if(dill_slow(!bio)) {err = errno; goto error3;}
	  SSL_set_bio(ssl, bio, bio);
    /* Take ownership of the underlying socket. */
    s = dill_hown(s);
    if(dill_slow(s < 0)) {err = errno; goto error1;}
    /* Create the object. */
    struct dill_tls_sock *self = (struct dill_tls_sock*)mem;
    self->hvfs.query = dill_tls_hquery;
    self->hvfs.close = dill_tls_hclose;
    self->bvfs.bsendl = dill_tls_bsendl;
    self->bvfs.brecvl = dill_tls_brecvl;
    self->ctx = ctx;
    self->ssl = ssl;
    self->u = s;
    self->deadline = -1;
    self->indone = 0;
    self->outdone = 0;
    self->inerr = 0;
    self->outerr = 0;
    self->mem = 1;
    /* Initial handshaking. */
    while(1) {
        ERR_clear_error();
        rc = SSL_accept(ssl);
        if(dill_tls_followup(self, rc)) break;
        if(dill_slow(errno != 0)) {err = errno; goto error4;}
    }
    /* Create the handle. */
    int h = dill_hmake(&self->hvfs);
    if(dill_slow(h < 0)) {int err = errno; goto error4;}
    return h;
error4:
    BIO_vfree(bio);
error3:
    SSL_free(ssl);
error2:
    SSL_CTX_free(ctx);
error1:
    if(s >= 0) dill_hclose(s);
    errno = err;
    return -1;
}
Пример #25
0
void
tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name
    )
{
#ifndef OPENSSL_NO_EC
  int nid = NID_undef;
  EC_KEY *ecdh = NULL;
  const char *sname = NULL;

  /* Generate a new ECDH key for each SSL session (for non-ephemeral ECDH) */
  SSL_CTX_set_options(ctx->ctx, SSL_OP_SINGLE_ECDH_USE);
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
  /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter loading */
  if (NULL == curve_name) {
    SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
    return;
  }
#endif
  /* For older OpenSSL, we'll have to do the parameter loading on our own */
  if (curve_name != NULL)
    {
      /* Use user supplied curve if given */
      msg (D_TLS_DEBUG, "Using user specified ECDH curve (%s)", curve_name);
      nid = OBJ_sn2nid(curve_name);
    }
  else
    {
      /* Extract curve from key */
      EC_KEY *eckey = NULL;
      const EC_GROUP *ecgrp = NULL;
      EVP_PKEY *pkey = NULL;

      /* Little hack to get private key ref from SSL_CTX, yay OpenSSL... */
      SSL ssl;
      ssl.cert = ctx->ctx->cert;
      pkey = SSL_get_privatekey(&ssl);

      msg (D_TLS_DEBUG, "Extracting ECDH curve from private key");

      if (pkey != NULL && (eckey = EVP_PKEY_get1_EC_KEY(pkey)) != NULL &&
          (ecgrp = EC_KEY_get0_group(eckey)) != NULL)
        nid = EC_GROUP_get_curve_name(ecgrp);
    }

  /* Translate NID back to name , just for kicks */
  sname = OBJ_nid2sn(nid);
  if (sname == NULL) sname = "(Unknown)";

  /* Create new EC key and set as ECDH key */
  if (NID_undef == nid || NULL == (ecdh = EC_KEY_new_by_curve_name(nid)))
    {
      /* Creating key failed, fall back on sane default */
      ecdh = EC_KEY_new_by_curve_name(NID_secp384r1);
      const char *source = (NULL == curve_name) ?
          "extract curve from certificate" : "use supplied curve";
      msg (D_TLS_DEBUG_LOW,
          "Failed to %s (%s), using secp384r1 instead.", source, sname);
      sname = OBJ_nid2sn(NID_secp384r1);
    }

  if (!SSL_CTX_set_tmp_ecdh(ctx->ctx, ecdh))
    msg (M_SSLERR, "SSL_CTX_set_tmp_ecdh: cannot add curve");

  msg (D_TLS_DEBUG_LOW, "ECDH curve %s added", sname);

  EC_KEY_free(ecdh);
#else
  msg (M_DEBUG, "Your OpenSSL library was built without elliptic curve support."
		" Skipping ECDH parameter loading.");
#endif /* OPENSSL_NO_EC */
}
Пример #26
0
/*
    Create and initialize an SSL configuration for a route. This configuration is used by all requests for
    a given route. An application can have different SSL configurations for different routes. There is also 
    a default SSL configuration that is used when a route does not define a configuration and one for clients.
 */
static OpenConfig *createOpenSslConfig(MprSocket *sp)
{
    MprSsl          *ssl;
    OpenConfig      *cfg;
    X509_STORE      *store;
    SSL_CTX         *context;
    cchar           *key;
    uchar           resume[16];
    int             verifyMode;

    ssl = sp->ssl;
    assert(ssl);

    if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) {
        return 0;
    }
    cfg = ssl->config;

    if ((context = SSL_CTX_new(SSLv23_method())) == 0) {
        mprLog("error openssl", 0, "Unable to create SSL context"); 
        return 0;
    }
    SSL_CTX_set_app_data(context, (void*) ssl);

    if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) {
        sp->errorMsg = sfmt("Cannot verify peer due to undefined CA certificates");
        SSL_CTX_free(context);
        return 0;
    }

    /*
        Configure the certificates
     */
    if (ssl->certFile) {
        if (SSL_CTX_use_certificate_chain_file(context, ssl->certFile) <= 0) {
            if (SSL_CTX_use_certificate_file(context, ssl->certFile, SSL_FILETYPE_ASN1) <= 0) {
                mprLog("error openssl", 0, "Cannot open certificate file: %s", ssl->certFile);
                SSL_CTX_free(context);
                return 0;
            }
        }
        key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile;
        if (key) {
            if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0) {
                /* attempt ASN1 for self-signed format */
                if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_ASN1) <= 0) {
                    mprLog("error openssl", 0, "Cannot open private key file: %s", key);
                    SSL_CTX_free(context);
                    return 0;
                }
            }
            if (!SSL_CTX_check_private_key(context)) {
                mprLog("error openssl", 0, "Check of private key file failed: %s", key);
                SSL_CTX_free(context);
                return 0;
            }
        }
    }
    if (ssl->ciphers) {
        ssl->ciphers = mapCipherNames(ssl->ciphers);
    }
    if (!ssl->ciphers && (sp->flags & MPR_SOCKET_SERVER)) {
        ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS);
    }
    if (ssl->ciphers) {
        mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers);
        if (SSL_CTX_set_cipher_list(context, ssl->ciphers) != 1) {
            sp->errorMsg = sfmt("Unable to set cipher list \"%s\". %s", ssl->ciphers, getOssError(sp)); 
            SSL_CTX_free(context);
            return 0;
        }
    }
    verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE;
    if (verifyMode != SSL_VERIFY_NONE) {
        if (!(ssl->caFile || ssl->caPath)) {
            sp->errorMsg = sclone("No defined certificate authority file");
            SSL_CTX_free(context);
            return 0;
        }
        if ((!SSL_CTX_load_verify_locations(context, (char*) ssl->caFile, (char*) ssl->caPath)) ||
                (!SSL_CTX_set_default_verify_paths(context))) {
            sp->errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); 
            SSL_CTX_free(context);
            return 0;
        }
        if (ssl->caFile) {
            STACK_OF(X509_NAME) *certNames;
            certNames = SSL_load_client_CA_file(ssl->caFile);
            if (certNames) {
                /*
                    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);
            }
        }
        store = SSL_CTX_get_cert_store(context);
        if (ssl->revokeList && !X509_STORE_load_locations(store, ssl->revokeList, 0)) {
            mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revokeList);
            SSL_CTX_free(context);
            return 0;
        }
        if (sp->flags & MPR_SOCKET_SERVER) {
            SSL_CTX_set_verify_depth(context, ssl->verifyDepth);
        }
    }

    /*
        Define callbacks
     */
    SSL_CTX_set_verify(context, verifyMode, verifyPeerCertificate);

    /*
        Configure DH parameters
     */
    SSL_CTX_set_tmp_dh_callback(context, dhcallback);
    cfg->dhKey = getDhKey();

    /*
        Define default OpenSSL options
     */
    SSL_CTX_set_options(context, SSL_OP_ALL);

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

    /*
        Define a session reuse context
     */
    RAND_bytes(resume, sizeof(resume));
    SSL_CTX_set_session_id_context(context, resume, sizeof(resume));

    /*
        Elliptic Curve initialization
     */
#if SSL_OP_SINGLE_ECDH_USE
    #ifdef SSL_CTX_set_ecdh_auto
        SSL_CTX_set_ecdh_auto(context, 1);
    #else
        {
            EC_KEY  *ecdh;
            cchar   *name;
            int      nid;

            name = ME_MPR_SSL_CURVE;
            if ((nid = OBJ_sn2nid(name)) == 0) {
                sp->errorMsg = sfmt("Unknown curve name \"%s\"", name);
                SSL_CTX_free(context);
                return 0;
            }
            if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) {
                sp->errorMsg = sfmt("Unable to create curve \"%s\"", name);
                SSL_CTX_free(context);
                return 0;
            }
            SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE);
            SSL_CTX_set_tmp_ecdh(context, ecdh);
            EC_KEY_free(ecdh);
        }
    #endif
#endif

    SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
#ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING
    SSL_CTX_set_options(context, SSL_OP_MSIE_SSLV2_RSA_PADDING);
#endif
#ifdef SSL_MODE_RELEASE_BUFFERS
    SSL_CTX_set_mode(context, SSL_MODE_RELEASE_BUFFERS);
#endif
#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
    SSL_CTX_set_mode(context, SSL_OP_CIPHER_SERVER_PREFERENCE);
#endif
    /*
        Select the required protocols
        Disable SSLv2 and SSLv3 by default -- they are insecure.
     */
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv2);
    SSL_CTX_set_options(context, SSL_OP_NO_SSLv3);
#ifdef SSL_OP_NO_TLSv1
    if (!(ssl->protocols & MPR_PROTO_TLSV1)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1);
    }
#endif
#ifdef SSL_OP_NO_TLSv1_1
    if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_1);
    }
#endif
#ifdef SSL_OP_NO_TLSv1_2
    if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) {
        SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_2);
    }
#endif

    /*
        Options set via main.me mpr.ssl.*
     */
#if defined(SSL_OP_NO_TICKET)
    /*
        Ticket based session reuse is enabled by default
     */
    #if defined(ME_MPR_SSL_TICKET)
        if (ME_MPR_SSL_TICKET) {
            SSL_CTX_clear_options(context, SSL_OP_NO_TICKET);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_TICKET);
        }
    #else
        SSL_CTX_clear_options(context, SSL_OP_NO_TICKET);
    #endif
#endif

#if defined(SSL_OP_NO_COMPRESSION)
    /* 
        Use of compression is not secure. Disabled by default.
     */
    #if defined(ME_MPR_SSL_COMPRESSION)
        if (ME_MPR_SSL_COMPRESSION) {
            SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION);
        }
    #else
        /*
            CRIME attack targets compression
         */
        SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION);
    #endif
#endif

#if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)
    /*
        Force a new session on renegotiation. Default to true.
     */
    #if defined(ME_MPR_SSL_RENEGOTIATE)
        if (ME_MPR_SSL_RENEGOTIATE) {
            SSL_CTX_clear_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
        } else {
            SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
        }
    #else
        SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
    #endif
#endif

#if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
    /*
        Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers.
        Defaults to true.
     */
    #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS)
        if (ME_MPR_SSL_EMPTY_FRAGMENTS) {
            /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */
            SSL_CTX_clear_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
        } else {
            SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
        }
    #else
        SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    #endif
#endif

#if defined(ME_MPR_SSL_CACHE)
    /*
        Set the number of sessions supported. Default in OpenSSL is 20K.
     */
    SSL_CTX_sess_set_cache_size(context, ME_MPR_SSL_CACHE);
#else
    SSL_CTX_sess_set_cache_size(context, 1024);
#endif

    cfg->context = context;
    return cfg;
}