/** 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; }
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; }
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 */ }
/* 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; }
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); }
/* 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; }
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) */ }
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); }
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); }
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); }
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; } }
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; }
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 ); }
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"); }
/* 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; }
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); } }
/* 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 }
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); }
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; }
int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { return SSL_CTX_set_ecdh_auto(ctx, onoff); }
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; }
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; }
/* 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; }
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; }
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 */ }
/* 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; }