[Openvpn-devel,M] Change in openvpn[master]: Add compatibility functions for mbedtls 2.X.Y

Message ID 6bd2af685d5f2fa8282de05ca43ebcdd81d798f5-HTML@gerrit.openvpn.net
State Superseded
Headers show
Series [Openvpn-devel,M] Change in openvpn[master]: Add compatibility functions for mbedtls 2.X.Y | expand

Commit Message

flichtenheld (Code Review) Oct. 17, 2023, 5:05 p.m. UTC
Attention is currently required from: flichtenheld, plaisthos.

Hello plaisthos, flichtenheld,

I'd like you to do a code review.
Please visit

    http://gerrit.openvpn.net/c/openvpn/+/371?usp=email

to review the following change.


Change subject: Add compatibility functions for mbedtls 2.X.Y
......................................................................

Add compatibility functions for mbedtls 2.X.Y

Change-Id: I143ca14c27c0c378b5e6b4184e80890d2c0e225e
Signed-off-by: Max Fillinger <max@max-fillinger.net>
---
M configure.ac
M src/openvpn/crypto_mbedtls.c
A src/openvpn/mbedtls_compat.h
M src/openvpn/ssl_mbedtls.c
M src/openvpn/ssl_verify_mbedtls.c
5 files changed, 211 insertions(+), 36 deletions(-)



  git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/71/371/1

Patch

diff --git a/configure.ac b/configure.ac
index 2072e8c..6658485 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1025,6 +1025,12 @@ 
 		[AC_MSG_ERROR([mbed TLS version >= 2.16.12 or >= 3.2.1 required])]
 	)
 
+    AC_CHECK_HEADER(
+        psa/crypto.h,
+        [AC_DEFINE([MBEDTLS_HAVE_PSA_CRYPTO_H], [1], [yes])],
+        [AC_DEFINE([MBEDTLS_HAVE_PSA_CRYPTO_H], [0], [no])]
+    )
+
 	AC_CHECK_FUNCS(
 		[ \
 			mbedtls_cipher_write_tag \
diff --git a/src/openvpn/crypto_mbedtls.c b/src/openvpn/crypto_mbedtls.c
index e85e4de..f244863 100644
--- a/src/openvpn/crypto_mbedtls.c
+++ b/src/openvpn/crypto_mbedtls.c
@@ -41,6 +41,7 @@ 
 #include "integer.h"
 #include "crypto_backend.h"
 #include "otime.h"
+#include "mbedtls_compat.h"
 #include "misc.h"
 
 #include <mbedtls/base64.h>
diff --git a/src/openvpn/mbedtls_compat.h b/src/openvpn/mbedtls_compat.h
new file mode 100644
index 0000000..eac647d
--- /dev/null
+++ b/src/openvpn/mbedtls_compat.h
@@ -0,0 +1,151 @@ 
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2023 Fox Crypto B.V. <openvpn@foxcrypto.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @file mbedtls compatibility stub
+ *
+ * This file provide compatibility stubs for the mbedtls libraries
+ * prior to version 3. This version made most fields in structs private
+ * and requires accessor functions to be used. For earlier versions, we
+ * implement the accessor functions here.
+ */
+
+#ifndef MBEDTLS_COMPAT_H_
+#define MBEDTLS_COMPAT_H_
+
+#include "errlevel.h"
+
+#include <mbedtls/cipher.h>
+#include <mbedtls/dhm.h>
+#include <mbedtls/md.h>
+#include <mbedtls/pem.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/version.h>
+#include <mbedtls/x509_crt.h>
+
+#if MBEDTLS_HAVE_PSA_CRYPTO_H
+    #include <psa/crypto.h>
+#endif
+
+static inline void
+mbedtls_compat_psa_crypto_init(void)
+{
+#if MBEDTLS_HAVE_PSA_CRYPTO_H && defined(MBEDTLS_PSA_CRYPTO_C)
+    if (psa_crypto_init() != PSA_SUCCESS)
+    {
+        msg(M_FATAL, "mbedtls: psa_crypto_init() failed");
+    }
+#else
+    return;
+#endif /* MBEDTLS_HAVE_PSA_CRYPTO_H && defined(MBEDTLS_PSA_CRYPTO_C) */
+}
+
+static inline int
+mbedtls_compat_pk_parse_key(mbedtls_pk_context *ctx,
+                            const unsigned char *key, size_t keylen,
+                            const unsigned char *pwd, size_t pwdlen,
+                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+    return mbedtls_pk_parse_key(ctx, key, keylen, pwd, pwdlen);
+#else
+    return mbedtls_pk_parse_key(ctx, key, keylen, pwd, pwdlen, f_rng, p_rng);
+#endif
+}
+
+static inline int
+mbedtls_compat_pk_parse_keyfile(mbedtls_pk_context *ctx,
+                                const char *path, const char *password,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+    return mbedtls_pk_parse_keyfile(ctx, path, password);
+#else
+    return mbedtls_pk_parse_keyfile(ctx, path, password, f_rng, p_rng);
+#endif
+}
+
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+static inline unsigned int
+mbedtls_cipher_info_get_block_size(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->block_size;
+}
+
+static inline unsigned int
+mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->iv_size;
+}
+
+static inline unsigned int
+mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->key_bitlen;
+}
+
+static inline mbedtls_cipher_mode_t
+mbedtls_cipher_info_get_mode(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->mode;
+}
+
+static inline const char *
+mbedtls_cipher_info_get_name(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->name;
+}
+
+static inline mbedtls_cipher_type_t
+mbedtls_cipher_info_get_type(const mbedtls_cipher_info_t *cipher)
+{
+    return cipher->type;
+}
+
+static inline size_t
+mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
+{
+    return 8 * ctx->len;
+}
+
+static inline const mbedtls_md_info_t *
+mbedtls_md_info_from_ctx(const mbedtls_md_context_t *ctx)
+{
+    return ctx->md_info;
+}
+
+static inline const unsigned char *
+mbedtls_pem_get_buffer(const mbedtls_pem_context *ctx, size_t *buf_size)
+{
+    *buf_size = ctx->buflen;
+    return ctx->buf;
+}
+
+static inline int
+mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx, int ext_type)
+{
+    return ctx->ext_types & ext_type;
+}
+#endif /* MBEDTLS_VERSION_NUMBER < 0x03020100 */
+
+#endif /* MBEDTLS_COMPAT_H_ */
diff --git a/src/openvpn/ssl_mbedtls.c b/src/openvpn/ssl_mbedtls.c
index a4ed722..cdb0ebe 100644
--- a/src/openvpn/ssl_mbedtls.c
+++ b/src/openvpn/ssl_mbedtls.c
@@ -41,6 +41,7 @@ 
 #include "buffer.h"
 #include "misc.h"
 #include "manage.h"
+#include "mbedtls_compat.h"
 #include "pkcs11_backend.h"
 #include "ssl_common.h"
 
@@ -54,8 +55,6 @@ 
 #include <mbedtls/oid.h>
 #include <mbedtls/pem.h>
 
-#include <psa/crypto.h>
-
 /**
  * Compatibility: mbedtls_ctr_drbg_update was deprecated in mbedtls 2.16 and
  * replaced with mbedtls_ctr_drbg_update_ret, which returns an error code.
@@ -106,7 +105,7 @@ 
 void
 tls_init_lib(void)
 {
-    (void)psa_crypto_init();
+    mbedtls_compat_psa_crypto_init();
 }
 
 void
@@ -503,40 +502,40 @@ 
 
     if (priv_key_inline)
     {
-        status = mbedtls_pk_parse_key(ctx->priv_key,
-                                      (const unsigned char *) priv_key_file,
-                                      strlen(priv_key_file) + 1, NULL, 0,
-                                      mbedtls_ctr_drbg_random,
-                                      rand_ctx_get());
+        status = mbedtls_compat_pk_parse_key(ctx->priv_key,
+                                             (const unsigned char *) priv_key_file,
+                                             strlen(priv_key_file) + 1, NULL, 0,
+                                             mbedtls_ctr_drbg_random,
+                                             rand_ctx_get());
 
         if (MBEDTLS_ERR_PK_PASSWORD_REQUIRED == status)
         {
             char passbuf[512] = {0};
             pem_password_callback(passbuf, 512, 0, NULL);
-            status = mbedtls_pk_parse_key(ctx->priv_key,
-                                          (const unsigned char *) priv_key_file,
-                                          strlen(priv_key_file) + 1,
-                                          (unsigned char *) passbuf,
-                                          strlen(passbuf),
-                                          mbedtls_ctr_drbg_random,
-                                          rand_ctx_get());
+            status = mbedtls_compat_pk_parse_key(ctx->priv_key,
+                                                 (const unsigned char *) priv_key_file,
+                                                 strlen(priv_key_file) + 1,
+                                                 (unsigned char *) passbuf,
+                                                 strlen(passbuf),
+                                                 mbedtls_ctr_drbg_random,
+                                                 rand_ctx_get());
         }
     }
     else
     {
-        status = mbedtls_pk_parse_keyfile(ctx->priv_key,
-                                          priv_key_file,
-                                          NULL,
-                                          mbedtls_ctr_drbg_random,
-                                          rand_ctx_get());
+        status = mbedtls_compat_pk_parse_keyfile(ctx->priv_key,
+                                                 priv_key_file,
+                                                 NULL,
+                                                 mbedtls_ctr_drbg_random,
+                                                 rand_ctx_get());
         if (MBEDTLS_ERR_PK_PASSWORD_REQUIRED == status)
         {
             char passbuf[512] = {0};
             pem_password_callback(passbuf, 512, 0, NULL);
-            status = mbedtls_pk_parse_keyfile(ctx->priv_key,
-                                              priv_key_file, passbuf,
-                                              mbedtls_ctr_drbg_random,
-                                              rand_ctx_get());
+            status = mbedtls_compat_pk_parse_keyfile(ctx->priv_key,
+                                                     priv_key_file, passbuf,
+                                                     mbedtls_ctr_drbg_random,
+                                                     rand_ctx_get());
         }
     }
     if (!mbed_ok(status))
@@ -553,9 +552,12 @@ 
     }
 
     if (!mbed_ok(mbedtls_pk_check_pair(&ctx->crt_chain->pk,
-                                       ctx->priv_key,
-                                       mbedtls_ctr_drbg_random,
-                                       rand_ctx_get())))
+                                       ctx->priv_key
+#if MBEDTLS_VERSION_NUMBER >= 0x03000000
+                                       , mbedtls_ctr_drbg_random,
+                                       rand_ctx_get()
+#endif
+                                       )))
     {
         msg(M_WARN, "Private key does not match the certificate");
         return 1;
@@ -585,6 +587,9 @@ 
 static inline int
 external_pkcs1_sign( void *ctx_voidptr,
                      int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+                     int mode,
+#endif
                      mbedtls_md_type_t md_alg, unsigned int hashlen, const unsigned char *hash,
                      unsigned char *sig )
 {
@@ -599,6 +604,13 @@ 
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+    if (MBEDTLS_RSA_PRIVATE != mode)
+    {
+        return MBEDTLS_RSA_BAD_INPUT_DATA;
+    }
+#endif
+
     /*
      * Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW,
      * but TLSv1.2 needs the full suite of hashes.
@@ -1173,7 +1185,7 @@ 
 
     /* Initialize minimum TLS version */
     {
-        const int tls_version_min =
+        const int configured_tls_version_min =
             (session->opt->ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT)
             &SSLF_TLS_VERSION_MIN_MASK;
 
@@ -1181,9 +1193,9 @@ 
         int major = MBEDTLS_SSL_MAJOR_VERSION_3;
         int minor = MBEDTLS_SSL_MINOR_VERSION_3;
 
-        if (tls_version_min > TLS_VER_UNSPEC)
+        if (configured_tls_version_min > TLS_VER_UNSPEC)
         {
-            tls_version_to_major_minor(tls_version_min, &major, &minor);
+            tls_version_to_major_minor(configured_tls_version_min, &major, &minor);
         }
 
         mbedtls_ssl_conf_min_version(ks_ssl->ssl_config, major, minor);
@@ -1191,17 +1203,21 @@ 
 
     /* Initialize maximum TLS version */
     {
-        const int tls_version_max =
+        const int configured_tls_version_max =
             (session->opt->ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT)
             &SSLF_TLS_VERSION_MAX_MASK;
 
-        /* default to TLS 1.3 */
-        int major = MBEDTLS_SSL_MAJOR_VERSION_3;
-        int minor = MBEDTLS_SSL_MINOR_VERSION_4;
+        int major = 0;
+        int minor = 0;
 
-        if (tls_version_max > TLS_VER_UNSPEC)
+        if (configured_tls_version_max > TLS_VER_UNSPEC)
         {
-            tls_version_to_major_minor(tls_version_max, &major, &minor);
+            tls_version_to_major_minor(configured_tls_version_max, &major, &minor);
+        }
+        else
+        {
+            /* Default to tls_version_max(). */
+            tls_version_to_major_minor(tls_version_max(), &major, &minor);
         }
 
         mbedtls_ssl_conf_max_version(ks_ssl->ssl_config, major, minor);
diff --git a/src/openvpn/ssl_verify_mbedtls.c b/src/openvpn/ssl_verify_mbedtls.c
index 33c3769..ce21324 100644
--- a/src/openvpn/ssl_verify_mbedtls.c
+++ b/src/openvpn/ssl_verify_mbedtls.c
@@ -35,6 +35,7 @@ 
 #if defined(ENABLE_CRYPTO_MBEDTLS)
 
 #include "crypto_mbedtls.h"
+#include "mbedtls_compat.h"
 #include "ssl_verify.h"
 #include <mbedtls/asn1.h>
 #include <mbedtls/error.h>