diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb
index d773536..7dfc87c 100644
--- a/ext/openssl/deprecation.rb
+++ b/ext/openssl/deprecation.rb
@@ -16,7 +16,11 @@ def self.deprecated_warning_flag
   end
 
   def self.check_func(func, header)
-    have_func(func, header, deprecated_warning_flag) and
-      have_header(header, nil, deprecated_warning_flag)
+    have_func(func, header, deprecated_warning_flag)
+  end
+
+  def self.check_func_or_macro(func, header)
+    check_func(func, header) or
+      have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}")
   end
 end
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index 60e3553..c2bf9d6 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -19,12 +19,15 @@
 
 Logging::message "=== OpenSSL for Ruby configurator ===\n"
 
+# Add -Werror=deprecated-declarations to $warnflags if available
+OpenSSL.deprecated_warning_flag
+
 ##
 # Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used
 # To turn it on, use: --with-debug or --enable-debug
 #
 if with_config("debug") or enable_config("debug")
-  $defs.push("-DOSSL_DEBUG") unless $defs.include? "-DOSSL_DEBUG"
+  $defs.push("-DOSSL_DEBUG")
 end
 
 Logging::message "=== Checking for system dependent stuff... ===\n"
@@ -39,7 +42,6 @@
 end
 
 result = pkg_config("openssl") && have_header("openssl/ssl.h")
-
 unless result
   result = have_header("openssl/ssl.h")
   result &&= %w[crypto libeay32].any? {|lib| have_library(lib, "OpenSSL_add_all_digests")}
@@ -51,37 +53,34 @@
   end
 end
 
-unless checking_for("OpenSSL version is 0.9.8 or later") {
-    try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h") }
+result = checking_for("OpenSSL version is 0.9.8 or later") {
+  try_static_assert("OPENSSL_VERSION_NUMBER >= 0x00908000L", "openssl/opensslv.h")
+}
+unless result
   raise "OpenSSL 0.9.8 or later is required."
 end
+
 unless OpenSSL.check_func("SSL_library_init()", "openssl/ssl.h")
   raise "Ignore OpenSSL broken by Apple.\nPlease use another openssl. (e.g. using `configure --with-openssl-dir=/path/to/openssl')"
 end
 
 Logging::message "=== Checking for OpenSSL features... ===\n"
-def have_func_like(name, header)
-  have_func(name, [header]) ||
-    have_macro(name, [header]) && $defs.push("-DHAVE_#{name.upcase}")
-end
-
 # compile options
 have_func("SSLv2_method")
 have_func("SSLv3_method")
 have_func("TLSv1_1_method")
 have_func("TLSv1_2_method")
 have_func("RAND_egd")
-# ENGINE_load_xx is deprecated in OpenSSL 1.1.0 and become a macro
 engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil
              cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni}
 engines.each { |name|
-  have_func_like("ENGINE_load_#{name}", "openssl/engine.h")
+  OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h")
 }
 
 # added in 0.9.8X
 have_func("EVP_CIPHER_CTX_new")
 have_func("EVP_CIPHER_CTX_free")
-have_func_like("SSL_CTX_clear_options", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_CTX_clear_options", "openssl/ssl.h")
 
 # added in 1.0.0
 have_func("EVP_CIPHER_CTX_copy")
@@ -91,7 +90,7 @@ def have_func_like(name, header)
 have_func("X509_NAME_hash_old")
 have_func("X509_STORE_CTX_get0_current_crl")
 have_func("X509_STORE_set_verify_cb")
-have_func_like("SSL_set_tlsext_host_name", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_set_tlsext_host_name", "openssl/ssl.h")
 have_struct_member("CRYPTO_THREADID", "ptr", "openssl/crypto.h")
 
 # added in 1.0.1
@@ -105,9 +104,9 @@ def have_func_like(name, header)
 have_func("X509_STORE_CTX_get0_store")
 have_func("SSL_is_server");
 have_func("SSL_CTX_set_alpn_select_cb")
-have_func_like("SSL_CTX_set1_curves_list", "openssl/ssl.h")
-have_func_like("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
-have_func_like("SSL_get_server_tmp_key", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h")
 
 # added in 1.1.0
 have_func("CRYPTO_lock") || $defs.push("-DHAVE_OPENSSL_110_THREADING_API")
@@ -120,8 +119,9 @@ def have_func_like(name, header)
 have_func("HMAC_CTX_new")
 have_func("HMAC_CTX_free")
 have_func("HMAC_CTX_reset")
-have_func("RAND_pseudo_bytes", ["openssl/rand.h"], "-Werror=deprecated-declarations") # deprecated
+OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated
 have_func("X509_STORE_get_ex_data")
+have_func("X509_STORE_set_ex_data")
 have_func("X509_CRL_get0_signature")
 have_func("X509_REQ_get0_signature")
 have_func("X509_REVOKED_get0_serialNumber")
@@ -135,12 +135,11 @@ def have_func_like(name, header)
 have_func("X509_CRL_up_ref")
 have_func("X509_STORE_up_ref")
 have_func("SSL_CTX_get_ciphers")
-have_func("SSL_CTX_get_security_level")
-have_func_like("SSL_CTX_set_min_proto_version", "openssl/ssl.h")
-have_func_like("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
 have_func("SSL_SESSION_up_ref")
 have_func("EVP_PKEY_up_ref")
-have_func("ENGINE_cleanup") # removed
+have_func("SSL_CTX_get_security_level")
+OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h")
+OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
 
 Logging::message "=== Checking done. ===\n"
 
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
index f213888..3318880 100644
--- a/ext/openssl/openssl_missing.c
+++ b/ext/openssl/openssl_missing.c
@@ -18,7 +18,7 @@
 
 #include "openssl_missing.h"
 
-/*** added in 0.9.8X ***/
+/* added in 0.9.8X */
 #if !defined(HAVE_EVP_CIPHER_CTX_NEW)
 EVP_CIPHER_CTX *
 EVP_CIPHER_CTX_new(void)
@@ -40,7 +40,7 @@ EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
 }
 #endif
 
-/*** added in 1.0.0 ***/
+/* added in 1.0.0 */
 #if !defined(HAVE_EVP_CIPHER_CTX_COPY)
 /*
  * this function does not exist in OpenSSL yet... or ever?.
@@ -68,6 +68,9 @@ EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
 int
 HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
 {
+    if (!out || !in)
+	return 0;
+
     memcpy(out, in, sizeof(HMAC_CTX));
 
     EVP_MD_CTX_copy(&out->md_ctx, &in->md_ctx);
@@ -76,11 +79,9 @@ HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in)
 
     return 1;
 }
-#endif
-
-/*** added in 1.0.1 ***/
+#endif /* HAVE_HMAC_CTX_COPY */
 
-/*** added in 1.0.2 ***/
+/* added in 1.0.2 */
 #if !defined(HAVE_CRYPTO_MEMCMP)
 int
 CRYPTO_memcmp(const volatile void * volatile in_a,
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 7d73618..2cb03ec 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -10,11 +10,7 @@
 #if !defined(_OSSL_OPENSSL_MISSING_H_)
 #define _OSSL_OPENSSL_MISSING_H_
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-/*** added in 0.9.8X ***/
+/* added in 0.9.8X */
 #if !defined(HAVE_EVP_CIPHER_CTX_NEW)
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
 #endif
@@ -28,7 +24,7 @@ void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
 	(ctx)->options &= ~(op); while (0)
 #endif
 
-/*** added in 1.0.0 ***/
+/* added in 1.0.0 */
 #if !defined(HAVE_EVP_PKEY_BASE_ID)
 #  define EVP_PKEY_base_id(pkey) EVP_PKEY_type((pkey)->type)
 #endif
@@ -49,8 +45,7 @@ int HMAC_CTX_copy(HMAC_CTX *out, HMAC_CTX *in);
 #  define X509_STORE_set_verify_cb X509_STORE_set_verify_cb_func
 #endif
 
-/*** added in 1.0.1 ***/
-/*** added in 1.0.2 ***/
+/* added in 1.0.2 */
 #if !defined(HAVE_CRYPTO_MEMCMP)
 int CRYPTO_memcmp(const volatile void * volatile in_a, const volatile void * volatile in_b, size_t len);
 #endif
@@ -74,7 +69,7 @@ int EC_curve_nist2nid(const char *str);
 #  define SSL_is_server(s) ((s)->server)
 #endif
 
-/*** added in 1.1.0 ***/
+/* added in 1.1.0 */
 #if !defined(HAVE_BN_GENCB_NEW)
 #  define BN_GENCB_new() ((BN_GENCB *)OPENSSL_malloc(sizeof(BN_GENCB)))
 #endif
@@ -108,12 +103,15 @@ int HMAC_CTX_reset(HMAC_CTX *ctx);
 #endif
 
 #if !defined(HAVE_X509_STORE_GET_EX_DATA)
-#  define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
-	CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef)
 #  define X509_STORE_get_ex_data(x, idx) \
 	CRYPTO_get_ex_data(&(x)->ex_data, idx)
+#endif
+
+#if !defined(HAVE_X509_STORE_SET_EX_DATA)
 #  define X509_STORE_set_ex_data(x, idx, data) \
 	CRYPTO_set_ex_data(&(x)->ex_data, idx, data)
+#  define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
+	CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, l, p, newf, dupf, freef)
 #endif
 
 #if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
@@ -264,8 +262,4 @@ static inline EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { return pkey->pkey.e
 #endif
 #endif
 
-#if defined(__cplusplus)
-}
-#endif
-
 #endif /* _OSSL_OPENSSL_MISSING_H_ */
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 8c5802a..cebbc2a 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -12,10 +12,6 @@
 
 #include RUBY_EXTCONF_H
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
 #if 0
   mOSSL = rb_define_module("OpenSSL");
   mX509 = rb_define_module_under(mOSSL, "X509");
@@ -57,7 +53,9 @@ extern "C" {
 #include <openssl/rand.h>
 #include <openssl/conf.h>
 #include <openssl/conf_api.h>
-#include <openssl/ocsp.h>
+#if !defined(OPENSSL_NO_OCSP)
+#  include <openssl/ocsp.h>
+#endif
 #if !defined(_WIN32)
 #  include <openssl/crypto.h>
 #endif
@@ -223,8 +221,4 @@ void ossl_debug(const char *, ...);
 
 void Init_openssl(void);
 
-#if defined(__cplusplus)
-}
-#endif
-
 #endif /* _OSSL_H_ */
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 2553b30..2f48843 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -160,16 +160,14 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
  * It is only necessary to run cleanup when engines are loaded via
  * OpenSSL::Engine.load. However, running cleanup before exit is recommended.
  *
- * If you are using OpenSSL 1.1.0 or newer, this method is no-op.
+ * Note that this method is no-op if using OpenSSL 1.1.0 or newer.
  *
  * See also, https://www.openssl.org/docs/crypto/engine.html
  */
 static VALUE
 ossl_engine_s_cleanup(VALUE self)
 {
-#if defined(HAVE_ENGINE_CLEANUP)
     ENGINE_cleanup();
-#endif
     return Qnil;
 }
 
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index 7dde73a..ae15d93 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -10,6 +10,8 @@
  */
 #include "ossl.h"
 
+#if !defined(OPENSSL_NO_OCSP)
+
 #define NewOCSPReq(klass) \
     TypedData_Wrap_Struct((klass), &ossl_ocsp_request_type, 0)
 #define SetOCSPReq(obj, req) do { \
@@ -1249,3 +1251,10 @@ Init_ossl_ocsp(void)
     /* The responder ID is based on the public key. */
     rb_define_const(mOCSP, "V_RESPID_KEY", INT2NUM(V_OCSP_RESPID_KEY));
 }
+
+#else
+void
+Init_ossl_ocsp(void)
+{
+}
+#endif
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index f50a3e3..d4865f5 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -84,20 +84,20 @@ static VALUE sym_exception, sym_wait_readable, sym_wait_writable;
  */
 static const struct {
     const char *name;
-    const SSL_METHOD *(*func)(void);
+    SSL_METHOD *(*func)(void); /* FIXME: constify when dropping 0.9.8 */
     int version;
 } ossl_ssl_method_tab[] = {
 #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
 /* OpenSSL 1.1.0; version specific method is deprecated */
 #define OSSL_SSL_METHOD_ENTRY(name, version) \
-    { #name,          TLS_method, version }, \
-    { #name"_server", TLS_server_method, version }, \
-    { #name"_client", TLS_client_method, version }
+    { #name,          (SSL_METHOD *(*)(void))TLS_method, version }, \
+    { #name"_server", (SSL_METHOD *(*)(void))TLS_server_method, version }, \
+    { #name"_client", (SSL_METHOD *(*)(void))TLS_client_method, version }
 #else
 #define OSSL_SSL_METHOD_ENTRY(name, version) \
-    { #name,          name##_method, version }, \
-    { #name"_server", name##_server_method, version }, \
-    { #name"_client", name##_client_method, version }
+    { #name,          (SSL_METHOD *(*)(void))name##_method, version }, \
+    { #name"_server", (SSL_METHOD *(*)(void))name##_server_method, version }, \
+    { #name"_client", (SSL_METHOD *(*)(void))name##_client_method, version }
 #endif
 #if defined(HAVE_SSLV2_METHOD)
     OSSL_SSL_METHOD_ENTRY(SSLv2, SSL2_VERSION),
@@ -184,7 +184,7 @@ ossl_sslctx_set_ssl_version(VALUE self, VALUE ssl_method)
     s = StringValueCStr(m);
     for (i = 0; i < numberof(ossl_ssl_method_tab); i++) {
         if (strcmp(ossl_ssl_method_tab[i].name, s) == 0) {
-            SSL_METHOD *method = (SSL_METHOD *)ossl_ssl_method_tab[i].func();
+            SSL_METHOD *method = ossl_ssl_method_tab[i].func();
 #if defined(HAVE_SSL_CTX_SET_MIN_PROTO_VERSION)
 	    int version = ossl_ssl_method_tab[i].version;
 #endif
@@ -1019,8 +1019,11 @@ ossl_sslctx_get_security_level(VALUE self)
  *    ctx.security_level = 0
  *    ctx.security_level = 5
  *
- * Sets the security level for this context. This is new in OpenSSL 1.1.0 and
- * no-op if using older OpenSSL.
+ * Sets the security level for this context. This is new in OpenSSL 1.1.0.
+ * If using older OpenSSL, setting a value other than 0 raises
+ * NotImplementedError.
+ *
+ * See the manpage of SSL_CTX_set_security_level(3) for details.
  */
 static VALUE
 ossl_sslctx_set_security_level(VALUE self, VALUE v)
@@ -1035,6 +1038,10 @@ ossl_sslctx_set_security_level(VALUE self, VALUE v)
 
 #if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
     SSL_CTX_set_security_level(ctx, NUM2INT(v));
+#else
+    if (NUM2INT(v) != 0)
+	ossl_raise(rb_eNotImpError, "setting security level != 0 is not "
+		   "supported in this version of OpenSSL");
 #endif
 
     return v;
