]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
OpenSSL: don't use direct access to the internal of EVP_MD_CTX
authorEmmanuel Deloget <logout@free.fr>
Mon, 12 Jun 2017 13:43:27 +0000 (15:43 +0200)
committerGert Doering <gert@greenie.muc.de>
Sun, 18 Jun 2017 12:52:37 +0000 (14:52 +0200)
OpenSSL 1.1 does not allow us to directly access the internal of
any data type, including EVP_MD_CTX. We have to use the defined
functions to do so.

Compatibility with OpenSSL 1.0 is kept by defining the corresponding
functions when they are not found in the library.

Signed-off-by: Emmanuel Deloget <logout@free.fr>
Acked-by: Steffan Karger <steffan.karger@fox-it.com>
Message-Id: <20170612134330.20971-6-logout@free.fr>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg14793.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
configure.ac
src/openvpn/crypto_backend.h
src/openvpn/crypto_mbedtls.c
src/openvpn/crypto_openssl.c
src/openvpn/httpdigest.c
src/openvpn/misc.c
src/openvpn/openssl_compat.h
src/openvpn/openvpn.h
src/openvpn/push.c

index 523487809ae1d59be2654dd5889f2fac9020b2b5..f971e54a057efc6e4bad177930e8acd23ca8c428 100644 (file)
@@ -919,6 +919,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then
 
        AC_CHECK_FUNCS(
                [ \
+                       EVP_MD_CTX_new \
+                       EVP_MD_CTX_free \
+                       EVP_MD_CTX_reset \
                        SSL_CTX_get_default_passwd_cb \
                        SSL_CTX_get_default_passwd_cb_userdata \
                        X509_get0_pubkey \
index e2d2c96f138c3c6055e6cb9ad47bcc2bc2f4d9d7..f1da04326375c7141fc7f35c3181edf66aa8b05e 100644 (file)
@@ -506,6 +506,20 @@ int md_kt_size(const md_kt_t *kt);
  */
 int md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst);
 
+/*
+ * Allocate a new message digest context
+ *
+ * @return              a new zeroed MD context
+ */
+md_ctx_t *md_ctx_new(void);
+
+/*
+ * Free an existing, non-null message digest context
+ *
+ * @param ctx           Message digest context
+ */
+void md_ctx_free(md_ctx_t *ctx);
+
 /*
  * Initialises the given message digest context.
  *
index e6388dd5bda6ee17de0455250a3fb17f0592f008..03cc13082298fd0aa4a0ca039b0334aeaf90193e 100644 (file)
@@ -765,6 +765,18 @@ md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst)
     return 0 == mbedtls_md(kt, src, src_len, dst);
 }
 
+mbedtls_md_context_t *
+md_ctx_new(void)
+{
+    mbedtls_md_context_t *ctx;
+    ALLOC_OBJ_CLEAR(ctx, mbedtls_md_context_t);
+    return ctx;
+}
+
+void md_ctx_free(mbedtls_md_context_t *ctx)
+{
+    free(ctx);
+}
 
 void
 md_ctx_init(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *kt)
index ee20902f072b0649a7981241aa99f99d90dba43c..3a5a26f8558cabdb034b0a2d324c92f4016e45f7 100644 (file)
@@ -41,6 +41,7 @@
 #include "integer.h"
 #include "crypto.h"
 #include "crypto_backend.h"
+#include "openssl_compat.h"
 
 #include <openssl/des.h>
 #include <openssl/err.h>
@@ -843,13 +844,24 @@ md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst)
     return EVP_Digest(src, src_len, dst, &in_md_len, kt, NULL);
 }
 
+EVP_MD_CTX *
+md_ctx_new(void)
+{
+    EVP_MD_CTX *ctx = EVP_MD_CTX_new();
+    check_malloc_return(ctx);
+    return ctx;
+}
+
+void md_ctx_free(EVP_MD_CTX *ctx)
+{
+    EVP_MD_CTX_free(ctx);
+}
+
 void
 md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt)
 {
     ASSERT(NULL != ctx && NULL != kt);
 
-    CLEAR(*ctx);
-
     EVP_MD_CTX_init(ctx);
     EVP_DigestInit(ctx, kt);
 }
@@ -857,7 +869,7 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt)
 void
 md_ctx_cleanup(EVP_MD_CTX *ctx)
 {
-    EVP_MD_CTX_cleanup(ctx);
+    EVP_MD_CTX_reset(ctx);
 }
 
 int
index e578c85d4d4cb4b016318014e72aa28b89176de7..c553f939c0120236a7591b7913e240c8cc4c81ec 100644 (file)
@@ -80,27 +80,28 @@ DigestCalcHA1(
     )
 {
     HASH HA1;
-    md_ctx_t md5_ctx;
+    md_ctx_t *md5_ctx = md_ctx_new();
     const md_kt_t *md5_kt = md_kt_get("MD5");
 
-    md_ctx_init(&md5_ctx, md5_kt);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
-    md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
-    md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
-    md_ctx_final(&md5_ctx, HA1);
+    md_ctx_init(md5_ctx, md5_kt);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
+    md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
+    md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
+    md_ctx_final(md5_ctx, HA1);
     if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)
     {
-        md_ctx_init(&md5_ctx, md5_kt);
-        md_ctx_update(&md5_ctx, HA1, HASHLEN);
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-        md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-        md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
-        md_ctx_final(&md5_ctx, HA1);
+        md_ctx_init(md5_ctx, md5_kt);
+        md_ctx_update(md5_ctx, HA1, HASHLEN);
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
+        md_ctx_final(md5_ctx, HA1);
     }
-    md_ctx_cleanup(&md5_ctx);
+    md_ctx_cleanup(md5_ctx);
+    md_ctx_free(md5_ctx);
     CvtHex(HA1, SessionKey);
 }
 
@@ -122,40 +123,41 @@ DigestCalcResponse(
     HASH RespHash;
     HASHHEX HA2Hex;
 
-    md_ctx_t md5_ctx;
+    md_ctx_t *md5_ctx = md_ctx_new();
     const md_kt_t *md5_kt = md_kt_get("MD5");
 
     /* calculate H(A2) */
-    md_ctx_init(&md5_ctx, md5_kt);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
-    md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
+    md_ctx_init(md5_ctx, md5_kt);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
+    md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
     if (strcasecmp(pszQop, "auth-int") == 0)
     {
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-        md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN);
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, HEntity, HASHHEXLEN);
     }
-    md_ctx_final(&md5_ctx, HA2);
+    md_ctx_final(md5_ctx, HA2);
     CvtHex(HA2, HA2Hex);
 
     /* calculate response */
-    md_ctx_init(&md5_ctx, md5_kt);
-    md_ctx_update(&md5_ctx, HA1, HASHHEXLEN);
-    md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-    md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
-    md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
+    md_ctx_init(md5_ctx, md5_kt);
+    md_ctx_update(md5_ctx, HA1, HASHHEXLEN);
+    md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+    md_ctx_update(md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
+    md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
     if (*pszQop)
     {
-        md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-        md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
-        md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
-        md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
+        md_ctx_update(md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
+        md_ctx_update(md5_ctx, (const uint8_t *) ":", 1);
     }
-    md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN);
-    md_ctx_final(&md5_ctx, RespHash);
-    md_ctx_cleanup(&md5_ctx);
+    md_ctx_update(md5_ctx, HA2Hex, HASHHEXLEN);
+    md_ctx_final(md5_ctx, RespHash);
+    md_ctx_cleanup(md5_ctx);
+    md_ctx_free(md5_ctx);
     CvtHex(RespHash, Response);
 }
 
index d286c197f8d0d5b1397d1fa6fd2a2ca809e27d92..df108b08d9e89e9cf80dc7233e30de979bd720b4 100644 (file)
@@ -1387,7 +1387,7 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)
     static const uint8_t hashprefix[] = "AUTO_USERID_DIGEST";
 
     const md_kt_t *md5_kt = md_kt_get("MD5");
-    md_ctx_t ctx;
+    md_ctx_t *ctx;
 
     CLEAR(*up);
     buf_set_write(&buf, (uint8_t *)up->username, USER_PASS_LEN);
@@ -1395,11 +1395,13 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)
     if (get_default_gateway_mac_addr(macaddr))
     {
         dmsg(D_AUTO_USERID, "GUPAU: macaddr=%s", format_hex_ex(macaddr, sizeof(macaddr), 0, 1, ":", &gc));
-        md_ctx_init(&ctx, md5_kt);
-        md_ctx_update(&ctx, hashprefix, sizeof(hashprefix) - 1);
-        md_ctx_update(&ctx, macaddr, sizeof(macaddr));
-        md_ctx_final(&ctx, digest);
-        md_ctx_cleanup(&ctx)
+        ctx = md_ctx_new();
+        md_ctx_init(ctx, md5_kt);
+        md_ctx_update(ctx, hashprefix, sizeof(hashprefix) - 1);
+        md_ctx_update(ctx, macaddr, sizeof(macaddr));
+        md_ctx_final(ctx, digest);
+        md_ctx_cleanup(ctx);
+        md_ctx_free(ctx);
         buf_printf(&buf, "%s", format_hex_ex(digest, sizeof(digest), 0, 256, " ", &gc));
     }
     else
index eeacb525dedd5893bf85a82de8cb4c60915949f2..3d8fad106de04a4f32efe6dd4ab363df12b7e7f7 100644 (file)
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 
+#if !defined(HAVE_EVP_MD_CTX_RESET)
+/**
+ * Reset a message digest context
+ *
+ * @param ctx                 The message digest context
+ * @return                    1 on success, 0 on error
+ */
+static inline int
+EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
+{
+    EVP_MD_CTX_cleanup(ctx);
+    return 1;
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_FREE)
+/**
+ * Free an existing message digest context
+ *
+ * @param ctx                 The message digest context
+ */
+static inline void
+EVP_MD_CTX_free(EVP_MD_CTX *ctx)
+{
+    free(ctx);
+}
+#endif
+
+#if !defined(HAVE_EVP_MD_CTX_NEW)
+/**
+ * Allocate a new message digest object
+ *
+ * @return                    A zero'ed message digest object
+ */
+static inline EVP_MD_CTX *
+EVP_MD_CTX_new(void)
+{
+    EVP_MD_CTX *ctx = NULL;
+    ALLOC_OBJ_CLEAR(ctx, EVP_MD_CTX);
+    return ctx;
+}
+#endif
+
 #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA)
 /**
  * Fetch the default password callback user data from the SSL context
index c01e8a2c224c6c89a463663915b9f9d6a723b0a6..9262e68ba0da72019a237250471c07aa50705029 100644 (file)
@@ -472,7 +472,7 @@ struct context_2
 
     /* hash of pulled options, so we can compare when options change */
     bool pulled_options_digest_init_done;
-    md_ctx_t pulled_options_state;
+    md_ctx_t *pulled_options_state;
     struct sha256_digest pulled_options_digest;
 
     struct event_timeout scheduled_exit;
index 441d303e4cda0886c98989733220c301d6195fc1..5947a31f8feff8f03d88a0e7efbc1513bbbc3f4b 100644 (file)
@@ -723,7 +723,8 @@ process_incoming_push_msg(struct context *c,
             struct buffer buf_orig = buf;
             if (!c->c2.pulled_options_digest_init_done)
             {
-                md_ctx_init(&c->c2.pulled_options_state, md_kt_get("SHA256"));
+                c->c2.pulled_options_state = md_ctx_new();
+                md_ctx_init(c->c2.pulled_options_state, md_kt_get("SHA256"));
                 c->c2.pulled_options_digest_init_done = true;
             }
             if (!c->c2.did_pre_pull_restore)
@@ -737,14 +738,16 @@ process_incoming_push_msg(struct context *c,
                                    option_types_found,
                                    c->c2.es))
             {
-                push_update_digest(&c->c2.pulled_options_state, &buf_orig,
+                push_update_digest(c->c2.pulled_options_state, &buf_orig,
                                    &c->options);
                 switch (c->options.push_continuation)
                 {
                     case 0:
                     case 1:
-                        md_ctx_final(&c->c2.pulled_options_state, c->c2.pulled_options_digest.digest);
-                        md_ctx_cleanup(&c->c2.pulled_options_state);
+                        md_ctx_final(c->c2.pulled_options_state, c->c2.pulled_options_digest.digest);
+                        md_ctx_cleanup(c->c2.pulled_options_state);
+                        md_ctx_free(c->c2.pulled_options_state);
+                        c->c2.pulled_options_state = NULL;
                         c->c2.pulled_options_digest_init_done = false;
                         ret = PUSH_MSG_REPLY;
                         break;