@@ -1,13 +1,13 @@
-This version of OpenVPN has mbed TLS support. To enable follow the following
-instructions:
+This version of OpenVPN has mbed TLS support. To enable, follow the
+instructions below:
-To Build and Install,
+To build and install,
./configure --with-crypto-library=mbedtls
make
make install
-This version depends on mbed TLS 2.0 (and requires at least 2.0.0).
+This version requires mbed TLS version >= 2.0.0 or >= 3.2.1.
*************************************************************************
@@ -16,7 +16,8 @@
As of mbed TLS 2.17, it can be licensed *only* under the Apache v2.0 license.
That license is incompatible with OpenVPN's GPLv2.
-If you wish to distribute OpenVPN linked with mbed TLS, there are two options:
+We are currently in the process of resolving this problem, but for now, if you
+wish to distribute OpenVPN linked with mbed TLS, there are two options:
* Ensure that your case falls under the system library exception in GPLv2, or
@@ -24,9 +25,6 @@
that may be licensed under GPLv2. Unfortunately, this version is
unsupported and won't receive any more updates.
-If nothing changes about the license situation, mbed TLS support may be
-deprecated in a future release of OpenVPN.
-
*************************************************************************
Due to limitations in the mbed TLS library, the following features are missing
@@ -42,3 +40,8 @@
* X.509 subject line has a different format than the OpenSSL subject line
* X.509 certificate export does not work
* X.509 certificate tracking
+
+*************************************************************************
+
+Mbed TLS 3 has implemented (parts of) the TLS 1.3 protocol, but we have disabled
+support in OpenVPN because the TLS-Exporter function is not yet implemented.
@@ -387,7 +387,10 @@
#undef HAVE_VSNPRINTF
/* we always assume a recent mbed TLS version */
-#define HAVE_CTR_DRBG_UPDATE_RET 1
+#define HAVE_MBEDTLS_PSA_CRYPTO_H 1
+#define HAVE_MBEDTLS_SSL_TLS_PRF 1
+#define HAVE_MBEDTLS_SSL_SET_EXPORT_KEYS_CB 1
+#define HAVE_MBEDTLS_CTR_DRBG_UPDATE_RET 1
/* Path to ifconfig tool */
#define IFCONFIG_PATH "@IFCONFIG_PATH@"
@@ -1019,13 +1019,19 @@
#include <mbedtls/version.h>
]],
[[
-#if MBEDTLS_VERSION_NUMBER < 0x02000000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
+#if MBEDTLS_VERSION_NUMBER < 0x02000000 || (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03020100)
#error invalid version
#endif
]]
)],
[AC_MSG_RESULT([ok])],
- [AC_MSG_ERROR([mbed TLS 2.y.z required])]
+ [AC_MSG_ERROR([mbed TLS version >= 2.0.0 or >= 3.2.1 required])]
+ )
+
+ AC_CHECK_HEADER(
+ psa/crypto.h,
+ [AC_DEFINE([HAVE_MBEDTLS_PSA_CRYPTO_H], [1], [yes])],
+ [AC_DEFINE([HAVE_MBEDTLS_PSA_CRYPTO_H], [0], [no])]
)
AC_CHECK_FUNCS(
@@ -1037,16 +1043,32 @@
[AC_MSG_ERROR([mbed TLS check for AEAD support failed])]
)
+ AC_CHECK_FUNC(
+ [mbedtls_ssl_tls_prf],
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_TLS_PRF], [1], [yes])],
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_TLS_PRF], [0], [no])]
+ )
+
have_export_keying_material="yes"
AC_CHECK_FUNC(
[mbedtls_ssl_conf_export_keys_ext_cb],
- ,
- [have_export_keying_material="no"]
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_CONF_EXPORT_KEYS_EXT_CB], [1], [yes])],
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_CONF_EXPORT_KEYS_EXT_CB], [0], [no])]
)
+ if test "x$ac_cv_func_mbedtls_ssl_conf_export_keys_ext_cb" != xyes; then
+ AC_CHECK_FUNC(
+ [mbedtls_ssl_set_export_keys_cb],
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_SET_EXPORT_KEYS_CB], [1], [yes])],
+ [AC_DEFINE([HAVE_MBEDTLS_SSL_SET_EXPORT_KEYS_CB], [0], [no])]
+ )
+ if test "x$ac_cv_func_mbedtls_ssl_set_export_keys_cb" != xyes; then
+ have_export_keying_material="no"
+ fi
+ fi
AC_CHECK_FUNC(
[mbedtls_ctr_drbg_update_ret],
- AC_DEFINE([HAVE_CTR_DRBG_UPDATE_RET], [1],
+ AC_DEFINE([HAVE_MBEDTLS_CTR_DRBG_UPDATE_RET], [1],
[Use mbedtls_ctr_drbg_update_ret from mbed TLS]),
)
@@ -82,6 +82,7 @@
ovpn_dco_win.h \
platform.c platform.h \
console.c console.h console_builtin.c console_systemd.c \
+ mbedtls_compat.h \
mroute.c mroute.h \
mss.c mss.h \
mstats.c mstats.h \
@@ -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>
@@ -170,10 +171,11 @@
while (*ciphers != 0)
{
const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(*ciphers);
- if (info && !cipher_kt_insecure(info->name)
- && (cipher_kt_mode_aead(info->name) || cipher_kt_mode_cbc(info->name)))
+ const char *name = mbedtls_cipher_info_get_name(info);
+ if (info && name && !cipher_kt_insecure(name)
+ && (cipher_kt_mode_aead(name) || cipher_kt_mode_cbc(name)))
{
- print_cipher(info->name);
+ print_cipher(name);
}
ciphers++;
}
@@ -184,10 +186,11 @@
while (*ciphers != 0)
{
const mbedtls_cipher_info_t *info = mbedtls_cipher_info_from_type(*ciphers);
- if (info && cipher_kt_insecure(info->name)
- && (cipher_kt_mode_aead(info->name) || cipher_kt_mode_cbc(info->name)))
+ const char *name = mbedtls_cipher_info_get_name(info);
+ if (info && name && cipher_kt_insecure(name)
+ && (cipher_kt_mode_aead(name) || cipher_kt_mode_cbc(name)))
{
- print_cipher(info->name);
+ print_cipher(name);
}
ciphers++;
}
@@ -295,7 +298,9 @@
mbedtls_pem_context ctx = { 0 };
bool ret = mbed_ok(mbedtls_pem_read_buffer(&ctx, header, footer, BPTR(&input),
NULL, 0, &use_len));
- if (ret && !buf_write(dst, ctx.buf, ctx.buflen))
+ size_t buf_size = 0;
+ const unsigned char *buf = mbedtls_pem_get_buffer(&ctx, &buf_size);
+ if (ret && !buf_write(dst, buf, buf_size))
{
ret = false;
msg(M_WARN, "PEM decode error: destination buffer too small");
@@ -416,11 +421,12 @@
return false;
}
- if (cipher->key_bitlen/8 > MAX_CIPHER_KEY_LENGTH)
+ const size_t key_bytelen = mbedtls_cipher_info_get_key_bitlen(cipher)/8;
+ if (key_bytelen > MAX_CIPHER_KEY_LENGTH)
{
- msg(D_LOW, "Cipher algorithm '%s' uses a default key size (%d bytes) "
+ msg(D_LOW, "Cipher algorithm '%s' uses a default key size (%zu bytes) "
"which is larger than " PACKAGE_NAME "'s current maximum key size "
- "(%d bytes)", ciphername, cipher->key_bitlen/8, MAX_CIPHER_KEY_LENGTH);
+ "(%d bytes)", ciphername, key_bytelen, MAX_CIPHER_KEY_LENGTH);
*reason = "disabled due to key size too large";
return false;
}
@@ -438,7 +444,7 @@
return "[null-cipher]";
}
- return translate_cipher_name_to_openvpn(cipher_kt->name);
+ return translate_cipher_name_to_openvpn(mbedtls_cipher_info_get_name(cipher_kt));
}
int
@@ -451,7 +457,7 @@
return 0;
}
- return cipher_kt->key_bitlen/8;
+ return (int)mbedtls_cipher_info_get_key_bitlen(cipher_kt)/8;
}
int
@@ -463,7 +469,7 @@
{
return 0;
}
- return cipher_kt->iv_size;
+ return (int)mbedtls_cipher_info_get_iv_size(cipher_kt);
}
int
@@ -474,7 +480,7 @@
{
return 0;
}
- return cipher_kt->block_size;
+ return (int)mbedtls_cipher_info_get_block_size(cipher_kt);
}
int
@@ -498,16 +504,16 @@
return !(cipher_kt_block_size(ciphername) >= 128 / 8
#ifdef MBEDTLS_CHACHAPOLY_C
- || cipher_kt->type == MBEDTLS_CIPHER_CHACHA20_POLY1305
+ || mbedtls_cipher_info_get_type(cipher_kt) == MBEDTLS_CIPHER_CHACHA20_POLY1305
#endif
);
}
-static int
+static mbedtls_cipher_mode_t
cipher_kt_mode(const mbedtls_cipher_info_t *cipher_kt)
{
ASSERT(NULL != cipher_kt);
- return cipher_kt->mode;
+ return mbedtls_cipher_info_get_mode(cipher_kt);
}
bool
@@ -566,22 +572,29 @@
CLEAR(*ctx);
const mbedtls_cipher_info_t *kt = cipher_get(ciphername);
- int key_len = kt->key_bitlen/8;
-
ASSERT(kt);
+ size_t key_bitlen = mbedtls_cipher_info_get_key_bitlen(kt);
if (!mbed_ok(mbedtls_cipher_setup(ctx, kt)))
{
msg(M_FATAL, "mbed TLS cipher context init #1");
}
- if (!mbed_ok(mbedtls_cipher_setkey(ctx, key, key_len*8, operation)))
+ if (!mbed_ok(mbedtls_cipher_setkey(ctx, key, (int)key_bitlen, operation)))
{
msg(M_FATAL, "mbed TLS cipher set key");
}
+ if (mbedtls_cipher_info_get_mode(kt) == MBEDTLS_MODE_CBC)
+ {
+ if (!mbed_ok(mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7)))
+ {
+ msg(M_FATAL, "mbed TLS cipher set padding mode");
+ }
+ }
+
/* make sure we used a big enough key */
- ASSERT(ctx->key_bitlen <= key_len*8);
+ ASSERT(mbedtls_cipher_get_key_bitlen(ctx) <= key_bitlen);
}
int
@@ -609,7 +622,7 @@
int
cipher_ctx_block_size(const mbedtls_cipher_context_t *ctx)
{
- return mbedtls_cipher_get_block_size(ctx);
+ return (int)mbedtls_cipher_get_block_size(ctx);
}
int
@@ -617,7 +630,7 @@
{
ASSERT(NULL != ctx);
- return cipher_kt_mode(ctx->cipher_info);
+ return mbedtls_cipher_get_cipher_mode(ctx);
}
bool
@@ -652,7 +665,7 @@
return 0;
}
- if (!mbed_ok(mbedtls_cipher_set_iv(ctx, iv_buf, ctx->cipher_info->iv_size)))
+ if (!mbed_ok(mbedtls_cipher_set_iv(ctx, iv_buf, (size_t)mbedtls_cipher_get_iv_size(ctx))))
{
return 0;
}
@@ -714,7 +727,7 @@
{
size_t olen = 0;
- if (MBEDTLS_DECRYPT != ctx->operation)
+ if (MBEDTLS_DECRYPT != mbedtls_cipher_get_operation(ctx))
{
return 0;
}
@@ -866,7 +879,7 @@
{
return 0;
}
- return mbedtls_md_get_size(ctx->md_info);
+ return (int)mbedtls_md_get_size(mbedtls_md_info_from_ctx(ctx));
}
void
@@ -936,7 +949,7 @@
{
return 0;
}
- return mbedtls_md_get_size(ctx->md_info);
+ return mbedtls_md_get_size(mbedtls_md_info_from_ctx(ctx));
}
void
@@ -976,8 +989,9 @@
return diff;
}
-/* mbedtls-2.18.0 or newer */
-#ifdef HAVE_MBEDTLS_SSL_TLS_PRF
+/* mbedtls-2.18.0 or newer implements tls_prf, but prf_tls1 is removed
+ * from recent versions, so we use our own implementation if necessary. */
+#if HAVE_MBEDTLS_SSL_TLS_PRF && defined(MBEDTLS_SSL_TLS_PRF_TLS1)
bool
ssl_tls1_PRF(const uint8_t *seed, int seed_len, const uint8_t *secret,
int secret_len, uint8_t *output, int output_len)
@@ -986,7 +1000,7 @@
secret_len, "", seed, seed_len, output,
output_len));
}
-#else /* ifdef HAVE_MBEDTLS_SSL_TLS_PRF */
+#else /* HAVE_MBEDTLS_SSL_TLS_PRF && defined(MBEDTLS_SSL_TLS_PRF_TLS1) */
/*
* Generate the hash required by for the \c tls1_PRF function.
*
@@ -1115,5 +1129,5 @@
gc_free(&gc);
return true;
}
-#endif /* ifdef HAVE_MBEDTLS_SSL_TLS_PRF */
+#endif /* HAVE_MBEDTLS_SSL_TLS_PRF && defined(MBEDTLS_SSL_TLS_PRF_TLS1) */
#endif /* ENABLE_CRYPTO_MBEDTLS */
new file mode 100644
@@ -0,0 +1,189 @@
+/*
+ * 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 "syshead.h"
+
+#include "errlevel.h"
+
+#include <mbedtls/cipher.h>
+#include <mbedtls/ctr_drbg.h>
+#include <mbedtls/dhm.h>
+#include <mbedtls/md.h>
+#include <mbedtls/pem.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/ssl.h>
+#include <mbedtls/version.h>
+#include <mbedtls/x509_crt.h>
+
+#if HAVE_MBEDTLS_PSA_CRYPTO_H
+ #include <psa/crypto.h>
+#endif
+
+static inline void
+mbedtls_compat_psa_crypto_init(void)
+{
+#if HAVE_MBEDTLS_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 /* HAVE_MBEDTLS_PSA_CRYPTO_H && defined(MBEDTLS_PSA_CRYPTO_C) */
+}
+
+/*
+ * In older versions of mbedtls, mbedtls_ctr_drbg_update() did not return an
+ * error code, and it was deprecated in favor of mbedtls_ctr_drbg_update_ret()
+ * which does.
+ *
+ * In mbedtls 3, this function was removed and mbedtls_ctr_drbg_update() returns
+ * an error code.
+ */
+static inline int
+mbedtls_compat_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx,
+ const unsigned char *additional,
+ size_t add_len)
+{
+#if HAVE_MBEDTLS_CTR_DRBG_UPDATE_RET
+ return mbedtls_ctr_drbg_update_ret(ctx, additional, add_len);
+#elif MBEDTLS_VERSION_NUMBER < 0x03020100
+ mbedtls_ctr_drbg_update(ctx, additional, add_len);
+ return 0;
+#else
+ return mbedtls_ctr_drbg_update(ctx, additional, add_len);
+#endif /* HAVE_MBEDTLS_CTR_DRBG_UPDATE_RET */
+}
+
+static inline int
+mbedtls_compat_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
+ return mbedtls_pk_check_pair(pub, prv);
+#else
+ return mbedtls_pk_check_pair(pub, prv, f_rng, p_rng);
+#endif /* MBEDTLS_VERSION_NUMBER < 0x03020100 */
+}
+
+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 size_t
+mbedtls_cipher_info_get_block_size(const mbedtls_cipher_info_t *cipher)
+{
+ return (size_t)cipher->block_size;
+}
+
+static inline size_t
+mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *cipher)
+{
+ return (size_t)cipher->iv_size;
+}
+
+static inline size_t
+mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *cipher)
+{
+ return (size_t)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_ */
@@ -653,8 +653,10 @@
"--verify-x509-name name: Accept connections only from a host with X509 subject\n"
" DN name. The remote host must also pass all other tests\n"
" of verification.\n"
+#ifndef ENABLE_CRYPTO_MBEDTLS
"--ns-cert-type t: (DEPRECATED) Require that peer certificate was signed with \n"
" an explicit nsCertType designation t = 'client' | 'server'.\n"
+#endif
"--x509-track x : Save peer X509 attribute x in environment for use by\n"
" plugins and management interface.\n"
#ifdef HAVE_EXPORT_KEYING_MATERIAL
@@ -9051,6 +9053,10 @@
}
else if (streq(p[0], "ns-cert-type") && p[1] && !p[2])
{
+#ifdef ENABLE_CRYPTO_MBEDTLS
+ msg(msglevel, "--ns-cert-type is not available with mbedtls.");
+ goto err;
+#else
VERIFY_PERMISSION(OPT_P_GENERAL);
if (streq(p[1], "server"))
{
@@ -9065,6 +9071,7 @@
msg(msglevel, "--ns-cert-type must be 'client' or 'server'");
goto err;
}
+#endif /* ENABLE_CRYPTO_MBEDTLS */
}
else if (streq(p[0], "remote-cert-ku"))
{
@@ -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"
@@ -58,25 +59,6 @@
#include <mbedtls/oid.h>
#include <mbedtls/pem.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.
- * For older versions, we call mbedtls_ctr_drbg_update and return 0 (success).
- *
- * Note: this change was backported to other mbedTLS branches, therefore we
- * rely on function detection at configure time.
- */
-#ifndef HAVE_CTR_DRBG_UPDATE_RET
-static int
-mbedtls_ctr_drbg_update_ret(mbedtls_ctr_drbg_context *ctx,
- const unsigned char *additional,
- size_t add_len)
-{
- mbedtls_ctr_drbg_update(ctx, additional, add_len);
- return 0;
-}
-#endif
-
static const mbedtls_x509_crt_profile openvpn_x509_crt_profile_legacy =
{
/* Hashes from SHA-1 and above */
@@ -108,6 +90,7 @@
void
tls_init_lib(void)
{
+ mbedtls_compat_psa_crypto_init();
}
void
@@ -190,6 +173,16 @@
}
#ifdef HAVE_EXPORT_KEYING_MATERIAL
+
+#if HAVE_MBEDTLS_SSL_CONF_EXPORT_KEYS_EXT_CB
+/*
+ * Key export callback for older versions of mbed TLS, to be used with
+ * mbedtls_ssl_conf_export_keys_ext_cb(). It is called with the master
+ * secret, client random and server random, and the type of PRF function
+ * to use.
+ *
+ * Mbed TLS stores this callback in the mbedtls_ssl_config struct and it
+ * is used in the mbedtls_ssl_contexts set up from that config. */
int
mbedtls_ssl_export_keys_cb(void *p_expkey, const unsigned char *ms,
const unsigned char *kb, size_t maclen,
@@ -210,8 +203,55 @@
memcpy(cache->master_secret, ms, sizeof(cache->master_secret));
cache->tls_prf_type = tls_prf_type;
- return true;
+ return 0;
}
+#elif HAVE_MBEDTLS_SSL_SET_EXPORT_KEYS_CB
+/*
+ * Key export callback for newer versions of mbed TLS, to be used with
+ * mbedtls_ssl_set_export_keys_cb(). When used with TLS 1.2, the callback
+ * is called with the TLS 1.2 master secret, client random, server random
+ * and the type of PRF to use. With TLS 1.3, it is called with several
+ * different keys (indicated by type), but unfortunately not the exporter
+ * master secret.
+ *
+ * Unlike in older versions, the callback is not stored in the
+ * mbedtls_ssl_config. It is placed in the mbedtls_ssl_context after it
+ * has been set up. */
+void
+mbedtls_ssl_export_keys_cb(void *p_expkey,
+ mbedtls_ssl_key_export_type type,
+ const unsigned char *secret,
+ size_t secret_len,
+ const unsigned char client_random[32],
+ const unsigned char server_random[32],
+ mbedtls_tls_prf_types tls_prf_type)
+{
+ /* Since we can't get the TLS 1.3 exporter master secret, we ignore all key
+ * types except MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET. */
+ if (type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET)
+ {
+ return;
+ }
+
+ struct tls_session *session = p_expkey;
+ struct key_state_ssl *ks_ssl = &session->key[KS_PRIMARY].ks_ssl;
+ struct tls_key_cache *cache = &ks_ssl->tls_key_cache;
+
+ /* The TLS 1.2 master secret has a fixed size, so if secret_len has
+ * a different value, something is wrong with mbed TLS. */
+ if (secret_len != sizeof(cache->master_secret))
+ {
+ msg(M_FATAL,
+ "ERROR: Incorrect TLS 1.2 master secret length: Got %zu, expected %zu",
+ secret_len, sizeof(cache->master_secret));
+ }
+
+ memcpy(cache->client_server_random, client_random, 32);
+ memcpy(cache->client_server_random + 32, server_random, 32);
+ memcpy(cache->master_secret, secret, sizeof(cache->master_secret));
+ cache->tls_prf_type = tls_prf_type;
+}
+#endif /* HAVE_MBEDTLS_SSL_CONF_EXPORT_KEYS_EXT_CB */
bool
key_state_export_keying_material(struct tls_session *session,
@@ -430,7 +470,7 @@
}
msg(D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with " counter_format " bit key",
- (counter_type) 8 * mbedtls_mpi_size(&ctx->dhm_ctx->P));
+ (counter_type) mbedtls_dhm_get_bitlen(ctx->dhm_ctx));
}
void
@@ -504,29 +544,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);
+ 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));
+ 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);
+ 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);
+ status = mbedtls_compat_pk_parse_keyfile(ctx->priv_key,
+ priv_key_file, passbuf,
+ mbedtls_ctr_drbg_random,
+ rand_ctx_get());
}
}
if (!mbed_ok(status))
@@ -542,7 +593,10 @@
return 1;
}
- if (!mbed_ok(mbedtls_pk_check_pair(&ctx->crt_chain->pk, ctx->priv_key)))
+ if (!mbed_ok(mbedtls_compat_pk_check_pair(&ctx->crt_chain->pk,
+ ctx->priv_key,
+ mbedtls_ctr_drbg_random,
+ rand_ctx_get())))
{
msg(M_WARN, "Private key does not match the certificate");
return 1;
@@ -558,7 +612,6 @@
* @param ctx_voidptr Management external key context.
* @param f_rng (Unused)
* @param p_rng (Unused)
- * @param mode RSA mode (should be RSA_PRIVATE).
* @param md_alg Message digest ('hash') algorithm type.
* @param hashlen Length of hash (overridden by length specified by md_alg
* if md_alg != MBEDTLS_MD_NONE).
@@ -572,7 +625,10 @@
*/
static inline int
external_pkcs1_sign( void *ctx_voidptr,
- int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int mode,
+ 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 )
{
@@ -587,10 +643,12 @@
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
+#if MBEDTLS_VERSION_NUMBER < 0x03020100
if (MBEDTLS_RSA_PRIVATE != mode)
{
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
+#endif
/*
* Support a wide range of hashes. TLSv1.1 and before only need SIG_RSA_RAW,
@@ -967,7 +1025,7 @@
if (0 != memcmp(old_sha256_hash, sha256_hash, sizeof(sha256_hash)))
{
- if (!mbed_ok(mbedtls_ctr_drbg_update_ret(cd_ctx, sha256_hash, 32)))
+ if (!mbed_ok(mbedtls_compat_ctr_drbg_update(cd_ctx, sha256_hash, 32)))
{
msg(M_WARN, "WARNING: failed to personalise random, could not update CTR_DRBG");
}
@@ -979,13 +1037,15 @@
int
tls_version_max(void)
{
-#if defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_3)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
return TLS_VER_1_2;
-#elif defined(MBEDTLS_SSL_MAJOR_VERSION_3) && defined(MBEDTLS_SSL_MINOR_VERSION_2)
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_1)
return TLS_VER_1_1;
-#else
+#elif defined(MBEDTLS_SSL_PROTO_TLS1)
return TLS_VER_1_0;
-#endif
+#else /* defined(MBEDTLS_SSL_PROTO_TLS1_2) */
+ #error "mbedtls is compiled without support for TLS 1.0, 1.1 and 1.2."
+#endif /* defined(MBEDTLS_SSL_PROTO_TLS1_2) */
}
/**
@@ -1006,23 +1066,29 @@
switch (tls_ver)
{
+#if defined(MBEDTLS_SSL_PROTO_TLS1)
case TLS_VER_1_0:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_1;
break;
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_1)
case TLS_VER_1_1:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_2;
break;
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
case TLS_VER_1_2:
*major = MBEDTLS_SSL_MAJOR_VERSION_3;
*minor = MBEDTLS_SSL_MINOR_VERSION_3;
break;
+#endif
default:
- msg(M_FATAL, "%s: invalid TLS version %d", __func__, tls_ver);
+ msg(M_FATAL, "%s: invalid or unsupported TLS version %d", __func__, tls_ver);
break;
}
}
@@ -1149,17 +1215,17 @@
/* 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;
- /* default to TLS 1.0 */
+ /* default to TLS 1.2 */
int major = MBEDTLS_SSL_MAJOR_VERSION_3;
- int minor = MBEDTLS_SSL_MINOR_VERSION_1;
+ 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);
@@ -1167,20 +1233,28 @@
/* 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;
- if (tls_version_max > TLS_VER_UNSPEC)
+ int major = 0;
+ int minor = 0;
+
+ if (configured_tls_version_max > TLS_VER_UNSPEC)
{
- int major, minor;
- tls_version_to_major_minor(tls_version_max, &major, &minor);
- mbedtls_ssl_conf_max_version(ks_ssl->ssl_config, 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);
}
-#ifdef HAVE_EXPORT_KEYING_MATERIAL
- /* Initialize keying material exporter */
+#if HAVE_MBEDTLS_SSL_CONF_EXPORT_KEYS_EXT_CB
+ /* Initialize keying material exporter, old style. */
mbedtls_ssl_conf_export_keys_ext_cb(ks_ssl->ssl_config,
mbedtls_ssl_export_keys_cb, session);
#endif
@@ -1188,7 +1262,12 @@
/* Initialise SSL context */
ALLOC_OBJ_CLEAR(ks_ssl->ctx, mbedtls_ssl_context);
mbedtls_ssl_init(ks_ssl->ctx);
- mbedtls_ssl_setup(ks_ssl->ctx, ks_ssl->ssl_config);
+ mbed_ok(mbedtls_ssl_setup(ks_ssl->ctx, ks_ssl->ssl_config));
+
+#if HAVE_MBEDTLS_SSL_SET_EXPORT_KEYS_CB
+ /* Initialize keying material exporter, new style. */
+ mbedtls_ssl_set_export_keys_cb(ks_ssl->ctx, mbedtls_ssl_export_keys_cb, session);
+#endif
/* Initialise BIOs */
ALLOC_OBJ_CLEAR(ks_ssl->bio_ctx, bio_ctx);
@@ -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>
@@ -432,6 +433,8 @@
}
}
+/* Dummy function because Netscape certificate types are not supported in OpenVPN with mbedtls.
+ * Returns SUCCESS if usage is NS_CERT_CHECK_NONE, FAILURE otherwise. */
result_t
x509_verify_ns_cert_type(mbedtls_x509_crt *cert, const int usage)
{
@@ -439,18 +442,6 @@
{
return SUCCESS;
}
- if (usage == NS_CERT_CHECK_CLIENT)
- {
- return ((cert->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE)
- && (cert->ns_cert_type & MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT)) ?
- SUCCESS : FAILURE;
- }
- if (usage == NS_CERT_CHECK_SERVER)
- {
- return ((cert->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE)
- && (cert->ns_cert_type & MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER)) ?
- SUCCESS : FAILURE;
- }
return FAILURE;
}
@@ -461,7 +452,7 @@
{
msg(D_HANDSHAKE, "Validating certificate key usage");
- if (!(cert->ext_types & MBEDTLS_X509_EXT_KEY_USAGE))
+ if (!mbedtls_x509_crt_has_ext_type(cert, MBEDTLS_X509_EXT_KEY_USAGE))
{
msg(D_TLS_ERRORS,
"ERROR: Certificate does not have key usage extension");
@@ -486,9 +477,7 @@
if (fFound != SUCCESS)
{
- msg(D_TLS_ERRORS,
- "ERROR: Certificate has key usage %04x, expected one of:",
- cert->key_usage);
+ msg(D_TLS_ERRORS, "ERROR: Certificate has invalid key usage, expected one of:");
for (size_t i = 0; i < expected_len && expected_ku[i]; i++)
{
msg(D_TLS_ERRORS, " * %04x", expected_ku[i]);
@@ -503,7 +492,7 @@
{
result_t fFound = FAILURE;
- if (!(cert->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE))
+ if (!mbedtls_x509_crt_has_ext_type(cert, MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE))
{
msg(D_HANDSHAKE, "Certificate does not have extended key usage extension");
}
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/+/404?usp=email to review the following change. Change subject: Backport mbed TLS 3 support to OpenVPN 2.6 ...................................................................... Backport mbed TLS 3 support to OpenVPN 2.6 Based on commits - ace7a4f1c271550bb8ad276663e045ab97a46f16 - f53f06316dbb804128fc5cbee1d8edb274ce81df - efad93d049c318a3bd9ea5956c6ac8237b8d6d70 - b5faf1b2e90fd44c5137a2b8f3da98c7ae482fc1 Change-Id: Icb4ae73741dc84ef0ff7ef72721cc12b999f4d03 Signed-off-by: Max Fillinger <maximilian.fillinger@foxcrypto.com> --- M README.mbedtls M config.h.cmake.in M configure.ac M src/openvpn/Makefile.am M src/openvpn/crypto_mbedtls.c A src/openvpn/mbedtls_compat.h M src/openvpn/options.c M src/openvpn/ssl_mbedtls.c M src/openvpn/ssl_verify_mbedtls.c 9 files changed, 422 insertions(+), 115 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/04/404/1