src/openvpn/ssl_openssl.c
9a160b79
 /*
  *  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.
  *
b25c6d7e
  *  Copyright (C) 2002-2024 OpenVPN Inc <sales@openvpn.net>
ccee09d1
  *  Copyright (C) 2010-2021 Fox Crypto B.V. <openvpn@foxcrypto.com>
9a160b79
  *
  *  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.
  *
caa54ac3
  *  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.
9a160b79
  */
 
 /**
  * @file Control Channel OpenSSL Backend
  */
 
c110b289
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
9a160b79
 #include "syshead.h"
31ea2ee4
 
c7ca9133
 #if defined(ENABLE_CRYPTO_OPENSSL)
31ea2ee4
 
9a160b79
 #include "errlevel.h"
 #include "buffer.h"
 #include "misc.h"
 #include "manage.h"
 #include "memdbg.h"
 #include "ssl_backend.h"
 #include "ssl_common.h"
be960aad
 #include "base64.h"
6554ac9f
 #include "openssl_compat.h"
4b85c488
 #include "xkey_common.h"
9a160b79
 
9009aa46
 #ifdef ENABLE_CRYPTOAPI
 #include "cryptoapi.h"
 #endif
 
9a160b79
 #include "ssl_verify_openssl.h"
3094d8fb
 #include "ssl_util.h"
9a160b79
 
19874982
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
 #include <openssl/dh.h>
 #include <openssl/dsa.h>
9a160b79
 #include <openssl/err.h>
 #include <openssl/pkcs12.h>
19874982
 #include <openssl/rsa.h>
9a160b79
 #include <openssl/x509.h>
7aeabadd
 #include <openssl/ssl.h>
609e8131
 #ifndef OPENSSL_NO_EC
 #include <openssl/ec.h>
af5de933
 #endif
 
 #if defined(_MSC_VER) && !defined(_M_ARM64)
 #include <openssl/applink.c>
609e8131
 #endif
95993a1d
 
6121001e
 OSSL_LIB_CTX *tls_libctx; /* Global */
4b85c488
 
 static void unload_xkey_provider(void);
 
95993a1d
 /*
  * Allocate space in SSL objects in which to store a struct tls_session
  * pointer back to parent.
  *
  */
 
 int mydata_index; /* GLOBAL */
 
 void
e2a0cad4
 tls_init_lib(void)
95993a1d
 {
2c0ebe0f
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
81d882d5
     SSL_library_init();
39b54baa
 #ifndef ENABLE_SMALL
81d882d5
     SSL_load_error_strings();
39b54baa
 #endif
81d882d5
     OpenSSL_add_all_algorithms();
8a01147f
 #endif
81d882d5
     mydata_index = SSL_get_ex_new_index(0, "struct session *", NULL, NULL, NULL);
     ASSERT(mydata_index >= 0);
95993a1d
 }
 
 void
e2a0cad4
 tls_free_lib(void)
95993a1d
 {
2c0ebe0f
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
81d882d5
     EVP_cleanup();
39b54baa
 #ifndef ENABLE_SMALL
81d882d5
     ERR_free_strings();
39b54baa
 #endif
8a01147f
 #endif
95993a1d
 }
 
 void
62451786
 tls_ctx_server_new(struct tls_root_ctx *ctx)
 {
81d882d5
     ASSERT(NULL != ctx);
62451786
 
4b85c488
     ctx->ctx = SSL_CTX_new_ex(tls_libctx, NULL, SSLv23_server_method());
62451786
 
81d882d5
     if (ctx->ctx == NULL)
     {
         crypto_msg(M_FATAL, "SSL_CTX_new SSLv23_server_method");
     }
75aa88af
     if (ERR_peek_error() != 0)
     {
         crypto_msg(M_WARN, "Warning: TLS server context initialisation "
                    "has warnings.");
     }
62451786
 }
 
 void
 tls_ctx_client_new(struct tls_root_ctx *ctx)
 {
81d882d5
     ASSERT(NULL != ctx);
62451786
 
4b85c488
     ctx->ctx = SSL_CTX_new_ex(tls_libctx, NULL, SSLv23_client_method());
62451786
 
81d882d5
     if (ctx->ctx == NULL)
     {
         crypto_msg(M_FATAL, "SSL_CTX_new SSLv23_client_method");
     }
75aa88af
     if (ERR_peek_error() != 0)
     {
         crypto_msg(M_WARN, "Warning: TLS client context initialisation "
                    "has warnings.");
     }
62451786
 }
 
 void
 tls_ctx_free(struct tls_root_ctx *ctx)
 {
81d882d5
     ASSERT(NULL != ctx);
cb70cf51
     SSL_CTX_free(ctx->ctx);
81d882d5
     ctx->ctx = NULL;
4b85c488
     unload_xkey_provider(); /* in case it is loaded */
62451786
 }
 
81d882d5
 bool
 tls_ctx_initialised(struct tls_root_ctx *ctx)
62451786
 {
81d882d5
     ASSERT(NULL != ctx);
     return NULL != ctx->ctx;
62451786
 }
 
f0734e49
 bool
10abd656
 key_state_export_keying_material(struct tls_session *session,
abe49856
                                  const char *label, size_t label_size,
f0734e49
                                  void *ekm, size_t ekm_size)
10abd656
 
685e486e
 {
abe49856
     SSL *ssl = session->key[KS_PRIMARY].ks_ssl.ssl;
10abd656
 
     if (SSL_export_keying_material(ssl, ekm, ekm_size, label,
                                    label_size, NULL, 0, 0) == 1)
     {
f0734e49
         return true;
10abd656
     }
     else
685e486e
     {
10abd656
         secure_memzero(ekm, ekm_size);
f0734e49
         return false;
685e486e
     }
 }
 
b5563f11
 /*
  * Print debugging information on SSL/TLS session negotiation.
  */
 
 #ifndef INFO_CALLBACK_SSL_CONST
 #define INFO_CALLBACK_SSL_CONST const
 #endif
 static void
81d882d5
 info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)
b5563f11
 {
81d882d5
     if (where & SSL_CB_LOOP)
b5563f11
     {
81d882d5
         dmsg(D_HANDSHAKE_VERBOSE, "SSL state (%s): %s",
              where & SSL_ST_CONNECT ? "connect" :
              where &SSL_ST_ACCEPT ? "accept" :
              "undefined", SSL_state_string_long(s));
b5563f11
     }
81d882d5
     else if (where & SSL_CB_ALERT)
b5563f11
     {
a1cb1b47
         dmsg(D_TLS_DEBUG_LOW, "%s %s SSL alert: %s",
              where & SSL_CB_READ ? "Received" : "Sent",
81d882d5
              SSL_alert_type_string_long(ret),
              SSL_alert_desc_string_long(ret));
b5563f11
     }
 }
 
4b67f984
 /*
  * Return maximum TLS version supported by local OpenSSL library.
  * Assume that presence of SSL_OP_NO_TLSvX macro indicates that
  * TLSvX is supported.
  */
 int
 tls_version_max(void)
 {
8ca9eda1
 #if defined(TLS1_3_VERSION)
6328aef9
     /* If this is defined we can safely assume TLS 1.3 support */
8ca9eda1
     return TLS_VER_1_3;
6328aef9
 #elif OPENSSL_VERSION_NUMBER >= 0x10100000L
     /*
      * If TLS_VER_1_3 is not defined, we were compiled against a version that
      * did not support TLS 1.3.
      *
      * However, the library we are *linked* against might be OpenSSL 1.1.1
      * and therefore supports TLS 1.3. This needs to be checked at runtime
      * since we can be compiled against 1.1.0 and then the library can be
8be444df
      * upgraded to 1.1.1.
      * We only need to check this for OpenSSL versions that can be
      * upgraded to 1.1.1 without recompile (>= 1.1.0)
6328aef9
      */
     if (OpenSSL_version_num() >= 0x1010100fL)
     {
         return TLS_VER_1_3;
     }
     else
     {
         return TLS_VER_1_2;
     }
8ca9eda1
 #elif defined(TLS1_2_VERSION) || defined(SSL_OP_NO_TLSv1_2)
81d882d5
     return TLS_VER_1_2;
0e8a30c0
 #elif defined(TLS1_1_VERSION) || defined(SSL_OP_NO_TLSv1_1)
81d882d5
     return TLS_VER_1_1;
f57431cd
 #else  /* if defined(TLS1_3_VERSION) */
81d882d5
     return TLS_VER_1_0;
4b67f984
 #endif
 }
 
0e8a30c0
 /** Convert internal version number to openssl version number */
 static int
 openssl_tls_version(int ver)
 {
     if (ver == TLS_VER_1_0)
     {
         return TLS1_VERSION;
     }
     else if (ver == TLS_VER_1_1)
     {
         return TLS1_1_VERSION;
     }
     else if (ver == TLS_VER_1_2)
     {
         return TLS1_2_VERSION;
     }
8ca9eda1
     else if (ver == TLS_VER_1_3)
     {
6328aef9
         /*
          * Supporting the library upgraded to TLS1.3 without recompile
          * is enough to support here with a simple constant that the same
          * as in the TLS 1.3, so spec it is very unlikely that OpenSSL
          * will change this constant
          */
 #ifndef TLS1_3_VERSION
         /*
          * We do not want to define TLS_VER_1_3 if not defined
          * since other parts of the code use the existance of this macro
          * as proxy for TLS 1.3 support
          */
         return 0x0304;
 #else
8ca9eda1
         return TLS1_3_VERSION;
 #endif
6328aef9
     }
0e8a30c0
     return 0;
 }
 
 static bool
 tls_ctx_set_tls_versions(struct tls_root_ctx *ctx, unsigned int ssl_flags)
 {
     int tls_ver_min = openssl_tls_version(
         (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) & SSLF_TLS_VERSION_MIN_MASK);
     int tls_ver_max = openssl_tls_version(
         (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) & SSLF_TLS_VERSION_MAX_MASK);
 
     if (!tls_ver_min)
     {
         /* Enforce at least TLS 1.0 */
         int cur_min = SSL_CTX_get_min_proto_version(ctx->ctx);
         tls_ver_min = cur_min < TLS1_VERSION ? TLS1_VERSION : cur_min;
     }
 
     if (!SSL_CTX_set_min_proto_version(ctx->ctx, tls_ver_min))
     {
         msg(D_TLS_ERRORS, "%s: failed to set minimum TLS version", __func__);
         return false;
     }
 
     if (tls_ver_max && !SSL_CTX_set_max_proto_version(ctx->ctx, tls_ver_max))
     {
         msg(D_TLS_ERRORS, "%s: failed to set maximum TLS version", __func__);
         return false;
     }
 
     return true;
 }
 
 bool
81d882d5
 tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)
b5563f11
 {
81d882d5
     ASSERT(NULL != ctx);
b8cdb213
 
0e8a30c0
     /* process SSL options */
     long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET;
5fd8e94d
 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
0e8a30c0
     sslopt |= SSL_OP_CIPHER_SERVER_PREFERENCE;
5fd8e94d
 #endif
0e8a30c0
     sslopt |= SSL_OP_NO_COMPRESSION;
9e702a5d
     /* Disable TLS renegotiations. OpenVPN's renegotiation creates new SSL
      * session and does not depend on this feature. And TLS renegotiations have
      * been problematic in the past */
 #ifdef SSL_OP_NO_RENEGOTIATION
     sslopt |= SSL_OP_NO_RENEGOTIATION;
 #endif
0e8a30c0
 
     SSL_CTX_set_options(ctx->ctx, sslopt);
 
     if (!tls_ctx_set_tls_versions(ctx, ssl_flags))
     {
         return false;
81d882d5
     }
4b67f984
 
a6c573d2
 #ifdef SSL_MODE_RELEASE_BUFFERS
81d882d5
     SSL_CTX_set_mode(ctx->ctx, SSL_MODE_RELEASE_BUFFERS);
a6c573d2
 #endif
81d882d5
     SSL_CTX_set_session_cache_mode(ctx->ctx, SSL_SESS_CACHE_OFF);
     SSL_CTX_set_default_passwd_cb(ctx->ctx, pem_password_callback);
b5563f11
 
81d882d5
     /* Require peer certificate verification */
e05aca45
     int verify_flags = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
81d882d5
     if (ssl_flags & SSLF_CLIENT_CERT_NOT_REQUIRED)
b5563f11
     {
e05aca45
         verify_flags = 0;
b5563f11
     }
81d882d5
     else if (ssl_flags & SSLF_CLIENT_CERT_OPTIONAL)
f107c620
     {
e05aca45
         verify_flags = SSL_VERIFY_PEER;
f107c620
     }
e05aca45
     SSL_CTX_set_verify(ctx->ctx, verify_flags, verify_callback);
b5563f11
 
81d882d5
     SSL_CTX_set_info_callback(ctx->ctx, info_callback);
0e8a30c0
 
     return true;
b5563f11
 }
 
397c0a35
 void
e51d9a73
 convert_tls_list_to_openssl(char *openssl_ciphers, size_t len, const char *ciphers)
2e74a9d0
 {
81d882d5
     /* Parse supplied cipher list and pass on to OpenSSL */
     size_t begin_of_cipher, end_of_cipher;
 
     const char *current_cipher;
     size_t current_cipher_len;
3b23b18d
 
81d882d5
     const tls_cipher_name_pair *cipher_pair;
3b23b18d
 
81d882d5
     size_t openssl_ciphers_len = 0;
     openssl_ciphers[0] = '\0';
3b23b18d
 
81d882d5
     /* Translate IANA cipher suite names to OpenSSL names */
     begin_of_cipher = end_of_cipher = 0;
4cd4899e
     for (; begin_of_cipher < strlen(ciphers); begin_of_cipher = end_of_cipher)
     {
81d882d5
         end_of_cipher += strcspn(&ciphers[begin_of_cipher], ":");
         cipher_pair = tls_get_cipher_name_pair(&ciphers[begin_of_cipher], end_of_cipher - begin_of_cipher);
 
         if (NULL == cipher_pair)
         {
             /* No translation found, use original */
             current_cipher = &ciphers[begin_of_cipher];
             current_cipher_len = end_of_cipher - begin_of_cipher;
 
             /* Issue warning on missing translation */
             /* %.*s format specifier expects length of type int, so guarantee */
             /* that length is small enough and cast to int. */
             msg(D_LOW, "No valid translation found for TLS cipher '%.*s'",
                 constrain_int(current_cipher_len, 0, 256), current_cipher);
         }
         else
         {
             /* Use OpenSSL name */
             current_cipher = cipher_pair->openssl_name;
             current_cipher_len = strlen(current_cipher);
2e74a9d0
 
81d882d5
             if (end_of_cipher - begin_of_cipher == current_cipher_len
                 && 0 != memcmp(&ciphers[begin_of_cipher], cipher_pair->iana_name,
                                end_of_cipher - begin_of_cipher))
             {
                 /* Non-IANA name used, show warning */
                 msg(M_WARN, "Deprecated TLS cipher name '%s', please use IANA name '%s'", cipher_pair->openssl_name, cipher_pair->iana_name);
             }
         }
3b23b18d
 
81d882d5
         /* Make sure new cipher name fits in cipher string */
e6bf7e03
         if ((SIZE_MAX - openssl_ciphers_len) < current_cipher_len
3b9d4d2a
             || (len - 1) < (openssl_ciphers_len + current_cipher_len))
3b23b18d
         {
81d882d5
             msg(M_FATAL,
                 "Failed to set restricted TLS cipher list, too long (>%d).",
3b9d4d2a
                 (int)(len - 1));
3b23b18d
         }
81d882d5
 
         /* Concatenate cipher name to OpenSSL cipher string */
         memcpy(&openssl_ciphers[openssl_ciphers_len], current_cipher, current_cipher_len);
         openssl_ciphers_len += current_cipher_len;
         openssl_ciphers[openssl_ciphers_len] = ':';
         openssl_ciphers_len++;
 
         end_of_cipher++;
     }
 
     if (openssl_ciphers_len > 0)
     {
         openssl_ciphers[openssl_ciphers_len-1] = '\0';
     }
3b9d4d2a
 }
ea4ee313
 
3b9d4d2a
 void
 tls_ctx_restrict_ciphers(struct tls_root_ctx *ctx, const char *ciphers)
 {
     if (ciphers == NULL)
     {
         /* Use sane default TLS cipher list */
         if (!SSL_CTX_set_cipher_list(ctx->ctx,
                                      /* Use openssl's default list as a basis */
                                      "DEFAULT"
                                      /* Disable export ciphers and openssl's 'low' and 'medium' ciphers */
                                      ":!EXP:!LOW:!MEDIUM"
                                      /* Disable static (EC)DH keys (no forward secrecy) */
                                      ":!kDH:!kECDH"
                                      /* Disable DSA private keys */
                                      ":!DSS"
                                      /* Disable unsupported TLS modes */
                                      ":!PSK:!SRP:!kRSA"))
         {
             crypto_msg(M_FATAL, "Failed to set default TLS cipher list.");
         }
         return;
     }
 
     char openssl_ciphers[4096];
     convert_tls_list_to_openssl(openssl_ciphers, sizeof(openssl_ciphers), ciphers);
 
     ASSERT(NULL != ctx);
81d882d5
 
     /* Set OpenSSL cipher list */
     if (!SSL_CTX_set_cipher_list(ctx->ctx, openssl_ciphers))
     {
         crypto_msg(M_FATAL, "Failed to set restricted TLS cipher list: %s", openssl_ciphers);
     }
2e74a9d0
 }
 
 void
7aeabadd
 convert_tls13_list_to_openssl(char *openssl_ciphers, size_t len,
                               const char *ciphers)
ea4ee313
 {
     /*
      * OpenSSL (and official IANA) cipher names have _ in them. We
      * historically used names with - in them. Silently convert names
      * with - to names with _ to support both
      */
     if (strlen(ciphers) >= (len - 1))
     {
         msg(M_FATAL,
             "Failed to set restricted TLS 1.3 cipher list, too long (>%d).",
             (int) (len - 1));
     }
 
     strncpy(openssl_ciphers, ciphers, len);
 
     for (size_t i = 0; i < strlen(openssl_ciphers); i++)
     {
         if (openssl_ciphers[i] == '-')
         {
             openssl_ciphers[i] = '_';
         }
     }
 }
 
 void
 tls_ctx_restrict_ciphers_tls13(struct tls_root_ctx *ctx, const char *ciphers)
 {
     if (ciphers == NULL)
     {
         /* default cipher list of OpenSSL 1.1.1 is sane, do not set own
          * default as we do with tls-cipher */
         return;
     }
 
a4750860
 #if !defined(TLS1_3_VERSION)
f57431cd
     crypto_msg(M_WARN, "Not compiled with OpenSSL 1.1.1 or higher. "
                "Ignoring TLS 1.3 only tls-ciphersuites '%s' setting.",
                ciphers);
ea4ee313
 #else
     ASSERT(NULL != ctx);
 
     char openssl_ciphers[4096];
     convert_tls13_list_to_openssl(openssl_ciphers, sizeof(openssl_ciphers),
                                   ciphers);
 
     if (!SSL_CTX_set_ciphersuites(ctx->ctx, openssl_ciphers))
     {
         crypto_msg(M_FATAL, "Failed to set restricted TLS 1.3 cipher list: %s",
                    openssl_ciphers);
     }
 #endif
 }
 
 void
aba75874
 tls_ctx_set_cert_profile(struct tls_root_ctx *ctx, const char *profile)
 {
b66701e5
 #if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
aba75874
     /* OpenSSL does not have certificate profiles, but a complex set of
      * callbacks that we could try to implement to achieve something similar.
      * For now, use OpenSSL's security levels to achieve similar (but not equal)
      * behaviour. */
     if (!profile || 0 == strcmp(profile, "legacy"))
     {
         SSL_CTX_set_security_level(ctx->ctx, 1);
     }
23efeb7a
     else if (0 == strcmp(profile, "insecure"))
     {
         SSL_CTX_set_security_level(ctx->ctx, 0);
     }
aba75874
     else if (0 == strcmp(profile, "preferred"))
     {
         SSL_CTX_set_security_level(ctx->ctx, 2);
     }
     else if (0 == strcmp(profile, "suiteb"))
     {
         SSL_CTX_set_security_level(ctx->ctx, 3);
         SSL_CTX_set_cipher_list(ctx->ctx, "SUITEB128");
     }
     else
     {
         msg(M_FATAL, "ERROR: Invalid cert profile: %s", profile);
     }
b66701e5
 #else  /* if OPENSSL_VERSION_NUMBER > 0x10100000L */
aba75874
     if (profile)
     {
b66701e5
         msg(M_WARN, "WARNING: OpenSSL 1.0.2 and LibreSSL do not support "
             "--tls-cert-profile, ignoring user-set profile: '%s'", profile);
aba75874
     }
b66701e5
 #endif /* if OPENSSL_VERSION_NUMBER > 0x10100000L */
aba75874
 }
 
 void
8353ae80
 tls_ctx_set_tls_groups(struct tls_root_ctx *ctx, const char *groups)
 {
     ASSERT(ctx);
711a4044
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
8353ae80
     struct gc_arena gc = gc_new();
     /* This method could be as easy as
      *  SSL_CTX_set1_groups_list(ctx->ctx, groups)
711a4044
      * but OpenSSL (< 3.0) does not like the name secp256r1 for prime256v1
8353ae80
      * This is one of the important curves.
      * To support the same name for OpenSSL and mbedTLS, we do
      * this dance.
711a4044
      * Also note that the code is wrong in the presence of OpenSSL3 providers.
8353ae80
      */
 
     int groups_count = get_num_elements(groups, ':');
 
     int *glist;
     /* Allocate an array for them */
     ALLOC_ARRAY_CLEAR_GC(glist, int, groups_count, &gc);
 
     /* Parse allowed ciphers, getting IDs */
     int glistlen = 0;
     char *tmp_groups = string_alloc(groups, &gc);
 
     const char *token;
     while ((token = strsep(&tmp_groups, ":")))
     {
         if (streq(token, "secp256r1"))
         {
             token = "prime256v1";
         }
         int nid = OBJ_sn2nid(token);
 
         if (nid == 0)
         {
             msg(M_WARN, "Warning unknown curve/group specified: %s", token);
         }
         else
         {
             glist[glistlen] = nid;
             glistlen++;
         }
     }
 
     if (!SSL_CTX_set1_groups(ctx->ctx, glist, glistlen))
     {
         crypto_msg(M_FATAL, "Failed to set allowed TLS group list: %s",
                    groups);
     }
     gc_free(&gc);
abe49856
 #else  /* if OPENSSL_VERSION_NUMBER < 0x30000000L */
711a4044
     if (!SSL_CTX_set1_groups_list(ctx->ctx, groups))
     {
         crypto_msg(M_FATAL, "Failed to set allowed TLS group list: %s",
                    groups);
     }
abe49856
 #endif /* if OPENSSL_VERSION_NUMBER < 0x30000000L */
8353ae80
 }
 
 void
81d882d5
 tls_ctx_check_cert_time(const struct tls_root_ctx *ctx)
091edd8e
 {
81d882d5
     int ret;
     const X509 *cert;
0e591a2f
 
81d882d5
     ASSERT(ctx);
868d9d01
 
81d882d5
     cert = SSL_CTX_get0_certificate(ctx->ctx);
091edd8e
 
81d882d5
     if (cert == NULL)
868d9d01
     {
ec7d0e8e
         return; /* Nothing to check if there is no certificate */
868d9d01
     }
 
8a01147f
     ret = X509_cmp_time(X509_get0_notBefore(cert), NULL);
81d882d5
     if (ret == 0)
091edd8e
     {
81d882d5
         msg(D_TLS_DEBUG_MED, "Failed to read certificate notBefore field.");
091edd8e
     }
81d882d5
     if (ret > 0)
091edd8e
     {
81d882d5
         msg(M_WARN, "WARNING: Your certificate is not yet valid!");
091edd8e
     }
 
8a01147f
     ret = X509_cmp_time(X509_get0_notAfter(cert), NULL);
81d882d5
     if (ret == 0)
091edd8e
     {
81d882d5
         msg(D_TLS_DEBUG_MED, "Failed to read certificate notAfter field.");
091edd8e
     }
81d882d5
     if (ret < 0)
091edd8e
     {
81d882d5
         msg(M_WARN, "WARNING: Your certificate has expired!");
091edd8e
     }
 }
 
 void
81d882d5
 tls_ctx_load_dh_params(struct tls_root_ctx *ctx, const char *dh_file,
cb2e9218
                        bool dh_file_inline)
ac3e8d62
 {
81d882d5
     BIO *bio;
ac3e8d62
 
81d882d5
     ASSERT(NULL != ctx);
ac3e8d62
 
cb2e9218
     if (dh_file_inline)
ac3e8d62
     {
cb2e9218
         if (!(bio = BIO_new_mem_buf((char *)dh_file, -1)))
81d882d5
         {
             crypto_msg(M_FATAL, "Cannot open memory BIO for inline DH parameters");
         }
ac3e8d62
     }
81d882d5
     else
ac3e8d62
     {
81d882d5
         /* Get Diffie Hellman Parameters */
         if (!(bio = BIO_new_file(dh_file, "r")))
         {
             crypto_msg(M_FATAL, "Cannot open %s for DH parameters", dh_file);
         }
ac3e8d62
     }
 
658c72e6
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
     EVP_PKEY *dh = PEM_read_bio_Parameters(bio, NULL);
     BIO_free(bio);
 
     if (!dh)
     {
         crypto_msg(M_FATAL, "Cannot load DH parameters from %s",
                    print_key_filename(dh_file, dh_file_inline));
     }
     if (!SSL_CTX_set0_tmp_dh_pkey(ctx->ctx, dh))
     {
f1dd638c
         crypto_msg(M_FATAL, "SSL_CTX_set0_tmp_dh_pkey");
658c72e6
     }
 
     msg(D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key",
         8 * EVP_PKEY_get_size(dh));
abe49856
 #else  /* if OPENSSL_VERSION_NUMBER >= 0x30000000L */
658c72e6
     DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
81d882d5
     BIO_free(bio);
ac3e8d62
 
81d882d5
     if (!dh)
     {
cb2e9218
         crypto_msg(M_FATAL, "Cannot load DH parameters from %s",
                    print_key_filename(dh_file, dh_file_inline));
81d882d5
     }
     if (!SSL_CTX_set_tmp_dh(ctx->ctx, dh))
     {
         crypto_msg(M_FATAL, "SSL_CTX_set_tmp_dh");
     }
ac3e8d62
 
81d882d5
     msg(D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key",
         8 * DH_size(dh));
ac3e8d62
 
81d882d5
     DH_free(dh);
abe49856
 #endif /* if OPENSSL_VERSION_NUMBER >= 0x30000000L */
ac3e8d62
 }
 
609e8131
 void
39eb3125
 tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name)
609e8131
 {
39eb3125
 #if OPENSSL_VERSION_NUMBER >= 0x30000000L
     if (curve_name != NULL)
     {
         msg(M_WARN, "WARNING: OpenSSL 3.0+ builds do not support specifying an "
abe49856
             "ECDH curve with --ecdh-curve, using default curves. Use "
             "--tls-groups to specify groups.");
39eb3125
     }
 #elif !defined(OPENSSL_NO_EC)
81d882d5
     int nid = NID_undef;
     EC_KEY *ecdh = NULL;
     const char *sname = NULL;
609e8131
 
81d882d5
     /* Generate a new ECDH key for each SSL session (for non-ephemeral ECDH) */
     SSL_CTX_set_options(ctx->ctx, SSL_OP_SINGLE_ECDH_USE);
5b004f99
 
81d882d5
     if (curve_name != NULL)
609e8131
     {
81d882d5
         /* Use user supplied curve if given */
         msg(D_TLS_DEBUG, "Using user specified ECDH curve (%s)", curve_name);
         nid = OBJ_sn2nid(curve_name);
609e8131
     }
81d882d5
     else
609e8131
     {
2c0ebe0f
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
8a01147f
 
5b004f99
         /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter
          * loading */
         SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
d8ac887c
 
         /* OpenSSL 1.1.0 and newer have always ecdh auto loading enabled,
          * so do nothing */
8a01147f
 #endif
d8ac887c
         return;
609e8131
     }
 
81d882d5
     /* Translate NID back to name , just for kicks */
     sname = OBJ_nid2sn(nid);
     if (sname == NULL)
     {
         sname = "(Unknown)";
     }
609e8131
 
81d882d5
     /* Create new EC key and set as ECDH key */
     if (NID_undef == nid || NULL == (ecdh = EC_KEY_new_by_curve_name(nid)))
609e8131
     {
81d882d5
         /* 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);
609e8131
     }
 
81d882d5
     if (!SSL_CTX_set_tmp_ecdh(ctx->ctx, ecdh))
     {
         crypto_msg(M_FATAL, "SSL_CTX_set_tmp_ecdh: cannot add curve");
     }
609e8131
 
81d882d5
     msg(D_TLS_DEBUG_LOW, "ECDH curve %s added", sname);
609e8131
 
81d882d5
     EC_KEY_free(ecdh);
 #else  /* ifndef OPENSSL_NO_EC */
68441882
     msg(D_LOW, "Your OpenSSL library was built without elliptic curve support."
81d882d5
         " Skipping ECDH parameter loading.");
609e8131
 #endif /* OPENSSL_NO_EC */
 }
 
289a8bb8
 int
 tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file,
cb2e9218
                     bool pkcs12_file_inline, bool load_ca_file)
289a8bb8
 {
81d882d5
     FILE *fp;
     EVP_PKEY *pkey;
     X509 *cert;
     STACK_OF(X509) *ca = NULL;
     PKCS12 *p12;
     int i;
     char password[256];
 
     ASSERT(NULL != ctx);
 
cb2e9218
     if (pkcs12_file_inline)
81d882d5
     {
         BIO *b64 = BIO_new(BIO_f_base64());
cb2e9218
         BIO *bio = BIO_new_mem_buf((void *) pkcs12_file,
                                    (int) strlen(pkcs12_file));
81d882d5
         ASSERT(b64 && bio);
         BIO_push(b64, bio);
         p12 = d2i_PKCS12_bio(b64, NULL);
         if (!p12)
         {
             crypto_msg(M_FATAL, "Error reading inline PKCS#12 file");
         }
         BIO_free(b64);
         BIO_free(bio);
     }
     else
     {
         /* Load the PKCS #12 file */
         if (!(fp = platform_fopen(pkcs12_file, "rb")))
         {
             crypto_msg(M_FATAL, "Error opening file %s", pkcs12_file);
         }
         p12 = d2i_PKCS12_fp(fp, NULL);
         fclose(fp);
         if (!p12)
         {
             crypto_msg(M_FATAL, "Error reading PKCS#12 file %s", pkcs12_file);
         }
     }
 
     /* Parse the PKCS #12 file */
     if (!PKCS12_parse(p12, "", &pkey, &cert, &ca))
     {
         pem_password_callback(password, sizeof(password) - 1, 0, NULL);
         /* Reparse the PKCS #12 file with password */
         ca = NULL;
         if (!PKCS12_parse(p12, password, &pkey, &cert, &ca))
         {
6ac4e63c
             crypto_msg(M_WARN, "Decoding PKCS12 failed. Probably wrong password "
abe49856
                        "or unsupported/legacy encryption");
289a8bb8
 #ifdef ENABLE_MANAGEMENT
81d882d5
             if (management && (ERR_GET_REASON(ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE))
             {
                 management_auth_failure(management, UP_TYPE_PRIVATE_KEY, NULL);
             }
289a8bb8
 #endif
81d882d5
             PKCS12_free(p12);
             return 1;
         }
     }
     PKCS12_free(p12);
 
     /* Load Certificate */
     if (!SSL_CTX_use_certificate(ctx->ctx, cert))
     {
2671dcb6
         crypto_print_openssl_errors(M_WARN);
81d882d5
         crypto_msg(M_FATAL, "Cannot use certificate");
     }
 
     /* Load Private Key */
     if (!SSL_CTX_use_PrivateKey(ctx->ctx, pkey))
     {
         crypto_msg(M_FATAL, "Cannot use private key");
     }
 
     /* Check Private Key */
     if (!SSL_CTX_check_private_key(ctx->ctx))
     {
         crypto_msg(M_FATAL, "Private key does not match the certificate");
     }
 
     /* Set Certificate Verification chain */
     if (load_ca_file)
     {
         /* Add CAs from PKCS12 to the cert store and mark them as trusted.
          * They're also used to fill in the chain of intermediate certs as
          * necessary.
          */
         if (ca && sk_X509_num(ca))
         {
             for (i = 0; i < sk_X509_num(ca); i++)
             {
6554ac9f
                 X509_STORE *cert_store = SSL_CTX_get_cert_store(ctx->ctx);
e51d9a73
                 if (!X509_STORE_add_cert(cert_store, sk_X509_value(ca, i)))
81d882d5
                 {
e51d9a73
                     crypto_msg(M_FATAL, "Cannot add certificate to certificate chain (X509_STORE_add_cert)");
81d882d5
                 }
                 if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i)))
                 {
e51d9a73
                     crypto_msg(M_FATAL, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)");
81d882d5
                 }
             }
         }
     }
     else
     {
         /* If trusted CA certs were loaded from a PEM file, and we ignore the
          * ones in PKCS12, do load PKCS12-provided certs to the client extra
          * certs chain just in case they include intermediate CAs needed to
          * prove my identity to the other end. This does not make them trusted.
          */
         if (ca && sk_X509_num(ca))
         {
             for (i = 0; i < sk_X509_num(ca); i++)
             {
e51d9a73
                 if (!SSL_CTX_add_extra_chain_cert(ctx->ctx, sk_X509_value(ca, i)))
81d882d5
                 {
                     crypto_msg(M_FATAL, "Cannot add extra certificate to chain (SSL_CTX_add_extra_chain_cert)");
                 }
             }
         }
     }
     return 0;
289a8bb8
 }
 
93c22ecc
 #ifdef ENABLE_CRYPTOAPI
d494c315
 void
 tls_ctx_load_cryptoapi(struct tls_root_ctx *ctx, const char *cryptoapi_cert)
 {
81d882d5
     ASSERT(NULL != ctx);
d494c315
 
81d882d5
     /* Load Certificate and Private Key */
     if (!SSL_CTX_use_CryptoAPI_certificate(ctx->ctx, cryptoapi_cert))
     {
         crypto_msg(M_FATAL, "Cannot load certificate \"%s\" from Microsoft Certificate Store", cryptoapi_cert);
     }
d494c315
 }
445b192a
 #endif /* ENABLE_CRYPTOAPI */
d494c315
 
71bbbd76
 static void
3608d890
 tls_ctx_add_extra_certs(struct tls_root_ctx *ctx, BIO *bio, bool optional)
f4047d74
 {
81d882d5
     X509 *cert;
3608d890
     while (true)
f4047d74
     {
81d882d5
         cert = NULL;
3608d890
         if (!PEM_read_bio_X509(bio, &cert, NULL, NULL))
81d882d5
         {
3608d890
             /*  a PEM_R_NO_START_LINE "Error" indicates that no certificate
              *  is found in the buffer.  If loading more certificates is
              *  optional, break without raising an error
              */
             if (optional
                 && ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
             {
                 /* remove that error from error stack */
                 (void)ERR_get_error();
                 break;
             }
 
             /* Otherwise, bail out with error */
81d882d5
             crypto_msg(M_FATAL, "Error reading extra certificate");
         }
3608d890
         /* takes ownership of cert like a set1 method */
81d882d5
         if (SSL_CTX_add_extra_chain_cert(ctx->ctx, cert) != 1)
         {
             crypto_msg(M_FATAL, "Error adding extra certificate");
         }
3608d890
         /* We loaded at least one certificate, so loading more is optional */
         optional = true;
f4047d74
     }
 }
 
98bfeeb4
 void
 tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file,
cb2e9218
                        bool cert_file_inline)
f4047d74
 {
81d882d5
     BIO *in = NULL;
     X509 *x = NULL;
     int ret = 0;
71bbbd76
 
81d882d5
     ASSERT(NULL != ctx);
f4047d74
 
cb2e9218
     if (cert_file_inline)
81d882d5
     {
cb2e9218
         in = BIO_new_mem_buf((char *) cert_file, -1);
81d882d5
     }
     else
     {
         in = BIO_new_file(cert_file, "r");
     }
71bbbd76
 
81d882d5
     if (in == NULL)
71bbbd76
     {
81d882d5
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_SYS_LIB);
         goto end;
71bbbd76
     }
 
6554ac9f
     x = PEM_read_bio_X509(in, NULL,
                           SSL_CTX_get_default_passwd_cb(ctx->ctx),
                           SSL_CTX_get_default_passwd_cb_userdata(ctx->ctx));
81d882d5
     if (x == NULL)
f4047d74
     {
81d882d5
         SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_PEM_LIB);
         goto end;
71bbbd76
     }
 
81d882d5
     ret = SSL_CTX_use_certificate(ctx->ctx, x);
     if (ret)
     {
3608d890
         tls_ctx_add_extra_certs(ctx, in, true);
81d882d5
     }
71bbbd76
 
 end:
81d882d5
     if (!ret)
71bbbd76
     {
2671dcb6
         crypto_print_openssl_errors(M_WARN);
cb2e9218
         if (cert_file_inline)
81d882d5
         {
             crypto_msg(M_FATAL, "Cannot load inline certificate file");
         }
         else
         {
             crypto_msg(M_FATAL, "Cannot load certificate file %s", cert_file);
         }
f4047d74
     }
f67efa94
     else
     {
         crypto_print_openssl_errors(M_DEBUG);
     }
71bbbd76
 
cb70cf51
     BIO_free(in);
     X509_free(x);
f4047d74
 }
 
d67c3147
 int
81d882d5
 tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file,
cb2e9218
                        bool priv_key_file_inline)
d67c3147
 {
81d882d5
     SSL_CTX *ssl_ctx = NULL;
     BIO *in = NULL;
     EVP_PKEY *pkey = NULL;
     int ret = 1;
d67c3147
 
81d882d5
     ASSERT(NULL != ctx);
be960aad
 
81d882d5
     ssl_ctx = ctx->ctx;
71bbbd76
 
cb2e9218
     if (priv_key_file_inline)
81d882d5
     {
cb2e9218
         in = BIO_new_mem_buf((char *) priv_key_file, -1);
81d882d5
     }
     else
     {
         in = BIO_new_file(priv_key_file, "r");
     }
71bbbd76
 
81d882d5
     if (!in)
     {
         goto end;
     }
71bbbd76
 
81d882d5
     pkey = PEM_read_bio_PrivateKey(in, NULL,
6554ac9f
                                    SSL_CTX_get_default_passwd_cb(ctx->ctx),
                                    SSL_CTX_get_default_passwd_cb_userdata(ctx->ctx));
8155f8aa
 
f67efa94
     if (!pkey || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey))
d67c3147
     {
 #ifdef ENABLE_MANAGEMENT
81d882d5
         if (management && (ERR_GET_REASON(ERR_peek_error()) == EVP_R_BAD_DECRYPT))
         {
             management_auth_failure(management, UP_TYPE_PRIVATE_KEY, NULL);
         }
d67c3147
 #endif
cb2e9218
         crypto_msg(M_WARN, "Cannot load private key file %s",
                    print_key_filename(priv_key_file, priv_key_file_inline));
81d882d5
         goto end;
d67c3147
     }
 
81d882d5
     /* Check Private Key */
     if (!SSL_CTX_check_private_key(ssl_ctx))
     {
         crypto_msg(M_FATAL, "Private key does not match the certificate");
     }
     ret = 0;
d67c3147
 
71bbbd76
 end:
cb70cf51
     EVP_PKEY_free(pkey);
     BIO_free(in);
81d882d5
     return ret;
d67c3147
 }
 
160504a2
 void
ce91c187
 backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file,
cb2e9218
                            bool crl_inline)
160504a2
 {
81d882d5
     BIO *in = NULL;
160504a2
 
81d882d5
     X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
     if (!store)
     {
         crypto_msg(M_FATAL, "Cannot get certificate store");
     }
160504a2
 
81d882d5
     /* Always start with a cleared CRL list, for that we
      * we need to manually find the CRL object from the stack
      * and remove it */
f05665df
     STACK_OF(X509_OBJECT) *objs = X509_STORE_get0_objects(store);
     for (int i = 0; i < sk_X509_OBJECT_num(objs); i++)
160504a2
     {
f05665df
         X509_OBJECT *obj = sk_X509_OBJECT_value(objs, i);
81d882d5
         ASSERT(obj);
47191f49
         if (X509_OBJECT_get_type(obj) == X509_LU_CRL)
81d882d5
         {
f05665df
             sk_X509_OBJECT_delete(objs, i);
47191f49
             X509_OBJECT_free(obj);
81d882d5
         }
160504a2
     }
 
81d882d5
     X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
160504a2
 
cb2e9218
     if (crl_inline)
81d882d5
     {
cb2e9218
         in = BIO_new_mem_buf((char *) crl_file, -1);
81d882d5
     }
     else
     {
         in = BIO_new_file(crl_file, "r");
     }
160504a2
 
81d882d5
     if (in == NULL)
160504a2
     {
cb2e9218
         msg(M_WARN, "CRL: cannot read: %s",
             print_key_filename(crl_file, crl_inline));
81d882d5
         goto end;
160504a2
     }
 
05229fb5
     int num_crls_loaded = 0;
     while (true)
160504a2
     {
05229fb5
         X509_CRL *crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
         if (crl == NULL)
         {
             /*
              * PEM_R_NO_START_LINE can be considered equivalent to EOF.
              */
             bool eof = ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE;
             /* but warn if no CRLs have been loaded */
             if (num_crls_loaded > 0 && eof)
             {
                 /* remove that error from error stack */
                 (void)ERR_get_error();
                 break;
             }
160504a2
 
cb2e9218
             crypto_msg(M_WARN, "CRL: cannot read CRL from file %s",
                        print_key_filename(crl_file, crl_inline));
05229fb5
             break;
         }
160504a2
 
05229fb5
         if (!X509_STORE_add_crl(store, crl))
         {
             X509_CRL_free(crl);
cb2e9218
             crypto_msg(M_WARN, "CRL: cannot add %s to store",
                        print_key_filename(crl_file, crl_inline));
05229fb5
             break;
         }
         X509_CRL_free(crl);
         num_crls_loaded++;
     }
     msg(M_INFO, "CRL: loaded %d CRLs from file %s", num_crls_loaded, crl_file);
160504a2
 end:
81d882d5
     BIO_free(in);
160504a2
 }
 
 
199df03b
 #if defined(ENABLE_MANAGEMENT) && !defined(HAVE_XKEY_PROVIDER)
5f4eb537
 
 /* encrypt */
 static int
 rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 {
81d882d5
     ASSERT(0);
     return -1;
5f4eb537
 }
 
 /* verify arbitrary data */
 static int
 rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 {
81d882d5
     ASSERT(0);
     return -1;
5f4eb537
 }
 
 /* decrypt */
 static int
 rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
 {
81d882d5
     ASSERT(0);
     return -1;
5f4eb537
 }
 
 /* called at RSA_free */
 static int
f7780af6
 openvpn_extkey_rsa_finish(RSA *rsa)
5f4eb537
 {
98bfeeb4
     /* meth was allocated in tls_ctx_use_management_external_key() ; since
f7780af6
      * this function is called when the parent RSA object is destroyed,
      * it is no longer used after this point so kill it. */
     const RSA_METHOD *meth = RSA_get_method(rsa);
     RSA_meth_free((RSA_METHOD *)meth);
81d882d5
     return 1;
5f4eb537
 }
 
8be444df
 /*
  * Convert OpenSSL's constant to the strings used in the management
  * interface query
  */
 const char *
9cf7b492
 get_rsa_padding_name(const int padding)
8be444df
 {
     switch (padding)
     {
         case RSA_PKCS1_PADDING:
             return "RSA_PKCS1_PADDING";
 
         case RSA_NO_PADDING:
             return "RSA_NO_PADDING";
 
         default:
             return "UNKNOWN";
     }
 }
 
 /**
  * Pass the input hash in 'dgst' to management and get the signature back.
  *
9cf7b492
  * @param dgst          hash to be signed
  * @param dgstlen       len of data in dgst
  * @param sig           On successful return signature is in sig.
  * @param siglen        length of buffer sig
  * @param algorithm     padding/hashing algorithm for the signature
  *
  * @return              signature length or -1 on error.
7eca140c
  */
5f4eb537
 static int
7eca140c
 get_sig_from_man(const unsigned char *dgst, unsigned int dgstlen,
8be444df
                  unsigned char *sig, unsigned int siglen,
                  const char *algorithm)
5f4eb537
 {
81d882d5
     char *in_b64 = NULL;
     char *out_b64 = NULL;
7eca140c
     int len = -1;
5f4eb537
 
8be444df
     int bencret = openvpn_base64_encode(dgst, dgstlen, &in_b64);
 
     if (management && bencret > 0)
81d882d5
     {
8be444df
         out_b64 = management_query_pk_sig(management, in_b64, algorithm);
 
81d882d5
     }
7eca140c
     if (out_b64)
81d882d5
     {
7eca140c
         len = openvpn_base64_decode(out_b64, sig, siglen);
81d882d5
     }
c3b2d487
 
7eca140c
     free(in_b64);
     free(out_b64);
     return len;
 }
68793f40
 
7eca140c
 /* sign arbitrary data */
 static int
8be444df
 rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,
              int padding)
7eca140c
 {
     unsigned int len = RSA_size(rsa);
     int ret = -1;
5f4eb537
 
8be444df
     if (padding != RSA_PKCS1_PADDING && padding != RSA_NO_PADDING)
81d882d5
     {
7eca140c
         RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
         return -1;
81d882d5
     }
7eca140c
 
9cf7b492
     ret = get_sig_from_man(from, flen, to, len, get_rsa_padding_name(padding));
7eca140c
 
f57431cd
     return (ret == len) ? ret : -1;
81d882d5
 }
5f4eb537
 
d59a1c2f
 static int
 tls_ctx_use_external_rsa_key(struct tls_root_ctx *ctx, EVP_PKEY *pkey)
81d882d5
 {
     RSA *rsa = NULL;
     RSA_METHOD *rsa_meth;
 
     ASSERT(NULL != ctx);
 
6fc292d2
     const RSA *pub_rsa = EVP_PKEY_get0_RSA(pkey);
d59a1c2f
     ASSERT(NULL != pub_rsa);
81d882d5
 
     /* allocate custom RSA method object */
09776c5b
     rsa_meth = RSA_meth_new("OpenVPN external private key RSA Method",
                             RSA_METHOD_FLAG_NO_CHECK);
     check_malloc_return(rsa_meth);
     RSA_meth_set_pub_enc(rsa_meth, rsa_pub_enc);
     RSA_meth_set_pub_dec(rsa_meth, rsa_pub_dec);
     RSA_meth_set_priv_enc(rsa_meth, rsa_priv_enc);
     RSA_meth_set_priv_dec(rsa_meth, rsa_priv_dec);
     RSA_meth_set_init(rsa_meth, NULL);
f7780af6
     RSA_meth_set_finish(rsa_meth, openvpn_extkey_rsa_finish);
09776c5b
     RSA_meth_set0_app_data(rsa_meth, NULL);
81d882d5
 
     /* allocate RSA object */
     rsa = RSA_new();
     if (rsa == NULL)
     {
         SSLerr(SSL_F_SSL_USE_PRIVATEKEY, ERR_R_MALLOC_FAILURE);
         goto err;
     }
5f4eb537
 
81d882d5
     /* initialize RSA object */
f7780af6
     const BIGNUM *n = NULL;
     const BIGNUM *e = NULL;
     RSA_get0_key(pub_rsa, &n, &e, NULL);
     RSA_set0_key(rsa, BN_dup(n), BN_dup(e), NULL);
     RSA_set_flags(rsa, RSA_flags(rsa) | RSA_FLAG_EXT_PKEY);
81d882d5
     if (!RSA_set_method(rsa, rsa_meth))
     {
d59a1c2f
         RSA_meth_free(rsa_meth);
81d882d5
         goto err;
     }
d59a1c2f
     /* from this point rsa_meth will get freed with rsa */
5f4eb537
 
81d882d5
     /* bind our custom RSA object to ssl_ctx */
     if (!SSL_CTX_use_RSAPrivateKey(ctx->ctx, rsa))
     {
         goto err;
     }
5f4eb537
 
81d882d5
     RSA_free(rsa); /* doesn't necessarily free, just decrements refcount */
     return 1;
 
 err:
     if (rsa)
     {
         RSA_free(rsa);
     }
cb70cf51
     else if (rsa_meth)
5f4eb537
     {
cb70cf51
         RSA_meth_free(rsa_meth);
5f4eb537
     }
d59a1c2f
     return 0;
 }
 
2c0ebe0f
 #if OPENSSL_VERSION_NUMBER > 0x10100000L && !defined(OPENSSL_NO_EC)
7eca140c
 
 /* called when EC_KEY is destroyed */
 static void
 openvpn_extkey_ec_finish(EC_KEY *ec)
 {
     /* release the method structure */
     const EC_KEY_METHOD *ec_meth = EC_KEY_get_method(ec);
     EC_KEY_METHOD_free((EC_KEY_METHOD *) ec_meth);
 }
 
 /* EC_KEY_METHOD callback: sign().
  * Sign the hash using EC key and return DER encoded signature in sig,
  * its length in siglen. Return value is 1 on success, 0 on error.
  */
 static int
 ecdsa_sign(int type, const unsigned char *dgst, int dgstlen, unsigned char *sig,
            unsigned int *siglen, const BIGNUM *kinv, const BIGNUM *r, EC_KEY *ec)
 {
     int capacity = ECDSA_size(ec);
8be444df
     /*
      * ECDSA does not seem to have proper constants for paddings since
      * there are only signatures without padding at the moment, use
      * a generic ECDSA for the moment
      */
     int len = get_sig_from_man(dgst, dgstlen, sig, capacity, "ECDSA");
7eca140c
 
     if (len > 0)
     {
         *siglen = len;
         return 1;
     }
     return 0;
 }
 
 /* EC_KEY_METHOD callback: sign_setup(). We do no precomputations */
 static int
 ecdsa_sign_setup(EC_KEY *ec, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 {
     return 1;
 }
 
 /* EC_KEY_METHOD callback: sign_sig().
  * Sign the hash and return the result as a newly allocated ECDS_SIG
  * struct or NULL on error.
  */
 static ECDSA_SIG *
 ecdsa_sign_sig(const unsigned char *dgst, int dgstlen, const BIGNUM *in_kinv,
                const BIGNUM *in_r, EC_KEY *ec)
 {
     ECDSA_SIG *ecsig = NULL;
     unsigned int len = ECDSA_size(ec);
     struct gc_arena gc = gc_new();
 
     unsigned char *buf = gc_malloc(len, false, &gc);
     if (ecdsa_sign(0, dgst, dgstlen, buf, &len, NULL, NULL, ec) != 1)
     {
         goto out;
     }
     /* const char ** should be avoided: not up to us, so we cast our way through */
     ecsig = d2i_ECDSA_SIG(NULL, (const unsigned char **)&buf, len);
 
 out:
     gc_free(&gc);
     return ecsig;
 }
 
 static int
 tls_ctx_use_external_ec_key(struct tls_root_ctx *ctx, EVP_PKEY *pkey)
 {
     EC_KEY *ec = NULL;
     EVP_PKEY *privkey = NULL;
     EC_KEY_METHOD *ec_method;
 
     ASSERT(ctx);
 
     ec_method = EC_KEY_METHOD_new(EC_KEY_OpenSSL());
     if (!ec_method)
     {
         goto err;
     }
 
     /* Among init methods, we only need the finish method */
     EC_KEY_METHOD_set_init(ec_method, NULL, openvpn_extkey_ec_finish, NULL, NULL, NULL, NULL);
     EC_KEY_METHOD_set_sign(ec_method, ecdsa_sign, ecdsa_sign_setup, ecdsa_sign_sig);
 
     ec = EC_KEY_dup(EVP_PKEY_get0_EC_KEY(pkey));
     if (!ec)
     {
         EC_KEY_METHOD_free(ec_method);
         goto err;
     }
     if (!EC_KEY_set_method(ec, ec_method))
     {
         EC_KEY_METHOD_free(ec_method);
         goto err;
     }
     /* from this point ec_method will get freed when ec is freed */
 
     privkey = EVP_PKEY_new();
     if (!EVP_PKEY_assign_EC_KEY(privkey, ec))
     {
         goto err;
     }
     /* from this point ec will get freed when privkey is freed */
 
     if (!SSL_CTX_use_PrivateKey(ctx->ctx, privkey))
     {
         ec = NULL; /* avoid double freeing it below */
         goto err;
     }
 
     EVP_PKEY_free(privkey); /* this will down ref privkey and ec */
     return 1;
 
 err:
     /* Reach here only when ec and privkey can be independenly freed */
cb70cf51
     EVP_PKEY_free(privkey);
     EC_KEY_free(ec);
7eca140c
     return 0;
 }
a4750860
 #endif /* OPENSSL_VERSION_NUMBER > 1.1.0 dev && !defined(OPENSSL_NO_EC) */
199df03b
 #endif /* ENABLE_MANAGEMENT && !HAVE_XKEY_PROVIDER */
7eca140c
 
199df03b
 #ifdef ENABLE_MANAGEMENT
d59a1c2f
 int
98bfeeb4
 tls_ctx_use_management_external_key(struct tls_root_ctx *ctx)
d59a1c2f
 {
98bfeeb4
     int ret = 1;
d59a1c2f
 
     ASSERT(NULL != ctx);
 
98bfeeb4
     X509 *cert = SSL_CTX_get0_certificate(ctx->ctx);
d59a1c2f
 
     ASSERT(NULL != cert);
 
     /* get the public key */
     EVP_PKEY *pkey = X509_get0_pubkey(cert);
     ASSERT(pkey); /* NULL before SSL_CTX_use_certificate() is called */
 
c279986b
 #ifdef HAVE_XKEY_PROVIDER
     EVP_PKEY *privkey = xkey_load_management_key(tls_libctx, pkey);
     if (!privkey
         || !SSL_CTX_use_PrivateKey(ctx->ctx, privkey))
     {
0f7cd474
         EVP_PKEY_free(privkey);
c279986b
         goto cleanup;
     }
     EVP_PKEY_free(privkey);
abe49856
 #else  /* ifdef HAVE_XKEY_PROVIDER */
6c111be9
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
7eca140c
     if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA)
6c111be9
 #else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
     if (EVP_PKEY_is_a(pkey, "RSA"))
 #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
d59a1c2f
     {
         if (!tls_ctx_use_external_rsa_key(ctx, pkey))
         {
98bfeeb4
             goto cleanup;
d59a1c2f
         }
     }
2c0ebe0f
 #if (OPENSSL_VERSION_NUMBER > 0x10100000L) && !defined(OPENSSL_NO_EC)
6c111be9
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
7eca140c
     else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC)
6c111be9
 #else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
     else if (EVP_PKEY_is_a(pkey, "EC"))
 #endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
7eca140c
     {
         if (!tls_ctx_use_external_ec_key(ctx, pkey))
         {
98bfeeb4
             goto cleanup;
7eca140c
         }
     }
     else
     {
         crypto_msg(M_WARN, "management-external-key requires an RSA or EC certificate");
98bfeeb4
         goto cleanup;
7eca140c
     }
a4750860
 #else  /* OPENSSL_VERSION_NUMBER > 1.1.0 dev && !defined(OPENSSL_NO_EC) */
d59a1c2f
     else
     {
7eca140c
         crypto_msg(M_WARN, "management-external-key requires an RSA certificate");
98bfeeb4
         goto cleanup;
d59a1c2f
     }
a4750860
 #endif /* OPENSSL_VERSION_NUMBER > 1.1.0 dev && !defined(OPENSSL_NO_EC) */
d59a1c2f
 
c279986b
 #endif /* HAVE_XKEY_PROVIDER */
 
98bfeeb4
     ret = 0;
 cleanup:
     if (ret)
     {
         crypto_msg(M_FATAL, "Cannot enable SSL external private key capability");
     }
     return ret;
5f4eb537
 }
 
66b9409b
 #endif /* ifdef ENABLE_MANAGEMENT */
5f4eb537
 
244da317
 static int
81d882d5
 sk_x509_name_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
244da317
 {
81d882d5
     return X509_NAME_cmp(*a, *b);
244da317
 }
 
 void
81d882d5
 tls_ctx_load_ca(struct tls_root_ctx *ctx, const char *ca_file,
cb2e9218
                 bool ca_file_inline, const char *ca_path, bool tls_server)
244da317
 {
81d882d5
     STACK_OF(X509_INFO) *info_stack = NULL;
     STACK_OF(X509_NAME) *cert_names = NULL;
     X509_LOOKUP *lookup = NULL;
     X509_STORE *store = NULL;
     X509_NAME *xn = NULL;
     BIO *in = NULL;
     int i, added = 0, prev = 0;
 
     ASSERT(NULL != ctx);
 
     store = SSL_CTX_get_cert_store(ctx->ctx);
     if (!store)
     {
         crypto_msg(M_FATAL, "Cannot get certificate store");
     }
71bbbd76
 
81d882d5
     /* Try to add certificates and CRLs from ca_file */
     if (ca_file)
71bbbd76
     {
cb2e9218
         if (ca_file_inline)
81d882d5
         {
cb2e9218
             in = BIO_new_mem_buf((char *)ca_file, -1);
81d882d5
         }
         else
         {
             in = BIO_new_file(ca_file, "r");
         }
244da317
 
81d882d5
         if (in)
         {
             info_stack = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
         }
71bbbd76
 
81d882d5
         if (info_stack)
71bbbd76
         {
81d882d5
             for (i = 0; i < sk_X509_INFO_num(info_stack); i++)
71bbbd76
             {
81d882d5
                 X509_INFO *info = sk_X509_INFO_value(info_stack, i);
                 if (info->crl)
9927cdbd
                 {
81d882d5
                     X509_STORE_add_crl(store, info->crl);
9927cdbd
                 }
 
81d882d5
                 if (tls_server && !info->x509)
71bbbd76
                 {
81d882d5
                     crypto_msg(M_FATAL, "X509 name was missing in TLS mode");
                 }
71bbbd76
 
81d882d5
                 if (info->x509)
                 {
                     X509_STORE_add_cert(store, info->x509);
                     added++;
71bbbd76
 
81d882d5
                     if (!tls_server)
71bbbd76
                     {
                         continue;
                     }
 
81d882d5
                     /* Use names of CAs as a client CA list */
                     if (cert_names == NULL)
                     {
                         cert_names = sk_X509_NAME_new(sk_x509_name_cmp);
                         if (!cert_names)
                         {
                             continue;
                         }
                     }
71bbbd76
 
81d882d5
                     xn = X509_get_subject_name(info->x509);
                     if (!xn)
71bbbd76
                     {
                         continue;
81d882d5
                     }
 
                     /* Don't add duplicate CA names */
                     if (sk_X509_NAME_find(cert_names, xn) == -1)
                     {
                         xn = X509_NAME_dup(xn);
                         if (!xn)
                         {
                             continue;
                         }
                         sk_X509_NAME_push(cert_names, xn);
71bbbd76
                     }
                 }
9927cdbd
 
81d882d5
                 if (tls_server)
                 {
                     int cnum = sk_X509_NAME_num(cert_names);
                     if (cnum != (prev + 1))
                     {
                         crypto_msg(M_WARN,
                                    "Cannot load CA certificate file %s (entry %d did not validate)",
cb2e9218
                                    print_key_filename(ca_file, ca_file_inline),
                                    added);
81d882d5
                     }
                     prev = cnum;
                 }
71bbbd76
             }
81d882d5
             sk_X509_INFO_pop_free(info_stack, X509_INFO_free);
71bbbd76
         }
 
81d882d5
         if (tls_server)
         {
             SSL_CTX_set_client_CA_list(ctx->ctx, cert_names);
         }
71bbbd76
 
81d882d5
         if (!added)
         {
             crypto_msg(M_FATAL,
                        "Cannot load CA certificate file %s (no entries were read)",
cb2e9218
                        print_key_filename(ca_file, ca_file_inline));
81d882d5
         }
9927cdbd
 
81d882d5
         if (tls_server)
         {
             int cnum = sk_X509_NAME_num(cert_names);
             if (cnum != added)
             {
                 crypto_msg(M_FATAL, "Cannot load CA certificate file %s (only %d "
                            "of %d entries were valid X509 names)",
cb2e9218
                            print_key_filename(ca_file, ca_file_inline), cnum,
                            added);
81d882d5
             }
         }
9927cdbd
 
cb70cf51
         BIO_free(in);
71bbbd76
     }
244da317
 
81d882d5
     /* Set a store for certs (CA & CRL) with a lookup on the "capath" hash directory */
     if (ca_path)
71bbbd76
     {
81d882d5
         lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
         if (lookup && X509_LOOKUP_add_dir(lookup, ca_path, X509_FILETYPE_PEM))
         {
             msg(M_WARN, "WARNING: experimental option --capath %s", ca_path);
         }
         else
         {
             crypto_msg(M_FATAL, "Cannot add lookup at --capath %s", ca_path);
         }
         X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
71bbbd76
     }
fceecbab
 }
 
 void
81d882d5
 tls_ctx_load_extra_certs(struct tls_root_ctx *ctx, const char *extra_certs_file,
cb2e9218
                          bool extra_certs_file_inline)
fceecbab
 {
81d882d5
     BIO *in;
cb2e9218
     if (extra_certs_file_inline)
81d882d5
     {
cb2e9218
         in = BIO_new_mem_buf((char *)extra_certs_file, -1);
81d882d5
     }
     else
     {
         in = BIO_new_file(extra_certs_file, "r");
     }
 
     if (in == NULL)
     {
cb2e9218
         crypto_msg(M_FATAL, "Cannot load extra-certs file: %s",
                    print_key_filename(extra_certs_file,
                                       extra_certs_file_inline));
 
81d882d5
     }
     else
     {
3608d890
         tls_ctx_add_extra_certs(ctx, in, false);
81d882d5
     }
 
     BIO_free(in);
244da317
 }
 
d7efe640
 /* **************************************
  *
  * Key-state specific functions
  *
  ***************************************/
 /*
  *
  * BIO functions
  *
  */
 
dea110e0
 #ifdef BIO_DEBUG
 
 #warning BIO_DEBUG defined
 
 static FILE *biofp;                            /* GLOBAL */
 static bool biofp_toggle;                      /* GLOBAL */
 static time_t biofp_last_open;                 /* GLOBAL */
 static const int biofp_reopen_interval = 600;  /* GLOBAL */
 
 static void
e2a0cad4
 close_biofp(void)
dea110e0
 {
81d882d5
     if (biofp)
dea110e0
     {
81d882d5
         ASSERT(!fclose(biofp));
         biofp = NULL;
dea110e0
     }
 }
 
 static void
e2a0cad4
 open_biofp(void)
dea110e0
 {
81d882d5
     const time_t current = time(NULL);
     const pid_t pid = getpid();
dea110e0
 
81d882d5
     if (biofp_last_open + biofp_reopen_interval < current)
     {
         close_biofp();
     }
     if (!biofp)
dea110e0
     {
81d882d5
         char fn[256];
130548fe
         snprintf(fn, sizeof(fn), "bio/%d-%d.log", pid, biofp_toggle);
81d882d5
         biofp = fopen(fn, "w");
         ASSERT(biofp);
         biofp_last_open = time(NULL);
         biofp_toggle ^= 1;
dea110e0
     }
 }
 
 static void
81d882d5
 bio_debug_data(const char *mode, BIO *bio, const uint8_t *buf, int len, const char *desc)
dea110e0
 {
81d882d5
     struct gc_arena gc = gc_new();
     if (len > 0)
dea110e0
     {
81d882d5
         open_biofp();
f57431cd
         fprintf(biofp, "BIO_%s %s time=%" PRIi64 " bio=" ptr_format " len=%d data=%s\n",
06ad53e0
                 mode, desc, (int64_t)time(NULL), (ptr_type)bio, len, format_hex(buf, len, 0, &gc));
81d882d5
         fflush(biofp);
dea110e0
     }
81d882d5
     gc_free(&gc);
dea110e0
 }
 
 static void
81d882d5
 bio_debug_oc(const char *mode, BIO *bio)
dea110e0
 {
81d882d5
     open_biofp();
f57431cd
     fprintf(biofp, "BIO %s time=%" PRIi64 " bio=" ptr_format "\n",
06ad53e0
             mode, (int64_t)time(NULL), (ptr_type)bio);
81d882d5
     fflush(biofp);
dea110e0
 }
 
81d882d5
 #endif /* ifdef BIO_DEBUG */
dea110e0
 
d7efe640
 /*
bf707bd2
  * Write to an OpenSSL BIO in non-blocking mode.
  */
 static int
81d882d5
 bio_write(BIO *bio, const uint8_t *data, int size, const char *desc)
bf707bd2
 {
81d882d5
     int i;
     int ret = 0;
     ASSERT(size >= 0);
     if (size)
     {
         /*
          * Free the L_TLS lock prior to calling BIO routines
          * so that foreground thread can still call
          * tls_pre_decrypt or tls_pre_encrypt,
          * allowing tunnel packet forwarding to continue.
          */
bf707bd2
 #ifdef BIO_DEBUG
81d882d5
         bio_debug_data("write", bio, data, size, desc);
bf707bd2
 #endif
81d882d5
         i = BIO_write(bio, data, size);
 
         if (i < 0)
         {
f2454ec6
             if (!BIO_should_retry(bio))
81d882d5
             {
                 crypto_msg(D_TLS_ERRORS, "TLS ERROR: BIO write %s error", desc);
                 ret = -1;
                 ERR_clear_error();
             }
         }
         else if (i != size)
         {
             crypto_msg(D_TLS_ERRORS, "TLS ERROR: BIO write %s incomplete %d/%d",
                        desc, i, size);
             ret = -1;
             ERR_clear_error();
         }
         else
         {                       /* successful write */
             dmsg(D_HANDSHAKE_VERBOSE, "BIO write %s %d bytes", desc, i);
             ret = 1;
         }
     }
     return ret;
bf707bd2
 }
 
 /*
  * Inline functions for reading from and writing
  * to BIOs.
  */
 
 static void
81d882d5
 bio_write_post(const int status, struct buffer *buf)
bf707bd2
 {
81d882d5
     if (status == 1) /* success status return from bio_write? */
bf707bd2
     {
81d882d5
         memset(BPTR(buf), 0, BLEN(buf));  /* erase data just written */
         buf->len = 0;
bf707bd2
     }
 }
 
 /*
dd5e1102
  * Read from an OpenSSL BIO in non-blocking mode.
  */
 static int
4e9e25a9
 bio_read(BIO *bio, struct buffer *buf, const char *desc)
dd5e1102
 {
81d882d5
     ASSERT(buf->len >= 0);
     if (buf->len)
dd5e1102
     {
f2454ec6
         /* we only want to write empty buffers, ignore read request
          * if the buffer is not empty */
         return 0;
dd5e1102
     }
f2454ec6
     int len = buf_forward_capacity(buf);
dd5e1102
 
f2454ec6
     /*
      * BIO_read brackets most of the serious RSA
      * key negotiation number crunching.
      */
     int i = BIO_read(bio, BPTR(buf), len);
dd5e1102
 
f2454ec6
     VALGRIND_MAKE_READABLE((void *) &i, sizeof(i));
dd5e1102
 
 #ifdef BIO_DEBUG
f2454ec6
     bio_debug_data("read", bio, BPTR(buf), i, desc);
dd5e1102
 #endif
f2454ec6
 
     int ret = 0;
     if (i < 0)
     {
         if (!BIO_should_retry(bio))
81d882d5
         {
f2454ec6
             crypto_msg(D_TLS_ERRORS, "TLS_ERROR: BIO read %s error", desc);
81d882d5
             buf->len = 0;
f2454ec6
             ret = -1;
             ERR_clear_error();
81d882d5
         }
f2454ec6
     }
     else if (!i)
     {
         buf->len = 0;
     }
     else
     {                       /* successful read */
         dmsg(D_HANDSHAKE_VERBOSE, "BIO read %s %d bytes", desc, i);
         buf->len = i;
         ret = 1;
         VALGRIND_MAKE_READABLE((void *) BPTR(buf), BLEN(buf));
81d882d5
     }
     return ret;
dd5e1102
 }
 
d7efe640
 void
b97e2c3c
 key_state_ssl_init(struct key_state_ssl *ks_ssl, const struct tls_root_ctx *ssl_ctx, bool is_server, struct tls_session *session)
d7efe640
 {
81d882d5
     ASSERT(NULL != ssl_ctx);
     ASSERT(ks_ssl);
     CLEAR(*ks_ssl);
d7efe640
 
81d882d5
     ks_ssl->ssl = SSL_new(ssl_ctx->ctx);
     if (!ks_ssl->ssl)
     {
         crypto_msg(M_FATAL, "SSL_new failed");
     }
d7efe640
 
81d882d5
     /* put session * in ssl object so we can access it
      * from verify callback*/
     SSL_set_ex_data(ks_ssl->ssl, mydata_index, session);
d7efe640
 
006d6a57
     ASSERT((ks_ssl->ssl_bio = BIO_new(BIO_f_ssl())));
     ASSERT((ks_ssl->ct_in = BIO_new(BIO_s_mem())));
     ASSERT((ks_ssl->ct_out = BIO_new(BIO_s_mem())));
d7efe640
 
 #ifdef BIO_DEBUG
81d882d5
     bio_debug_oc("open ssl_bio", ks_ssl->ssl_bio);
     bio_debug_oc("open ct_in", ks_ssl->ct_in);
     bio_debug_oc("open ct_out", ks_ssl->ct_out);
d7efe640
 #endif
 
81d882d5
     if (is_server)
     {
         SSL_set_accept_state(ks_ssl->ssl);
     }
     else
     {
         SSL_set_connect_state(ks_ssl->ssl);
     }
d7efe640
 
81d882d5
     SSL_set_bio(ks_ssl->ssl, ks_ssl->ct_in, ks_ssl->ct_out);
     BIO_set_ssl(ks_ssl->ssl_bio, ks_ssl->ssl, BIO_NOCLOSE);
d7efe640
 }
 
81d882d5
 void
 key_state_ssl_free(struct key_state_ssl *ks_ssl)
214fc873
 {
81d882d5
     if (ks_ssl->ssl)
     {
214fc873
 #ifdef BIO_DEBUG
81d882d5
         bio_debug_oc("close ssl_bio", ks_ssl->ssl_bio);
         bio_debug_oc("close ct_in", ks_ssl->ct_in);
         bio_debug_oc("close ct_out", ks_ssl->ct_out);
214fc873
 #endif
81d882d5
         BIO_free_all(ks_ssl->ssl_bio);
         SSL_free(ks_ssl->ssl);
     }
214fc873
 }
 
dd5e1102
 int
81d882d5
 key_state_write_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf)
bf707bd2
 {
81d882d5
     int ret = 0;
     perf_push(PERF_BIO_WRITE_PLAINTEXT);
bf707bd2
 
81d882d5
     ASSERT(NULL != ks_ssl);
bf707bd2
 
81d882d5
     ret = bio_write(ks_ssl->ssl_bio, BPTR(buf), BLEN(buf),
                     "tls_write_plaintext");
     bio_write_post(ret, buf);
bf707bd2
 
81d882d5
     perf_pop();
     return ret;
bf707bd2
 }
 
 int
81d882d5
 key_state_write_plaintext_const(struct key_state_ssl *ks_ssl, const uint8_t *data, int len)
bf707bd2
 {
81d882d5
     int ret = 0;
     perf_push(PERF_BIO_WRITE_PLAINTEXT);
bf707bd2
 
81d882d5
     ASSERT(NULL != ks_ssl);
bf707bd2
 
81d882d5
     ret = bio_write(ks_ssl->ssl_bio, data, len, "tls_write_plaintext_const");
bf707bd2
 
81d882d5
     perf_pop();
     return ret;
bf707bd2
 }
 
 int
4e9e25a9
 key_state_read_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf)
dd5e1102
 {
81d882d5
     int ret = 0;
     perf_push(PERF_BIO_READ_CIPHERTEXT);
dd5e1102
 
81d882d5
     ASSERT(NULL != ks_ssl);
dd5e1102
 
4e9e25a9
     ret = bio_read(ks_ssl->ct_out, buf, "tls_read_ciphertext");
dd5e1102
 
81d882d5
     perf_pop();
     return ret;
dd5e1102
 }
 
 int
81d882d5
 key_state_write_ciphertext(struct key_state_ssl *ks_ssl, struct buffer *buf)
bf707bd2
 {
81d882d5
     int ret = 0;
     perf_push(PERF_BIO_WRITE_CIPHERTEXT);
bf707bd2
 
81d882d5
     ASSERT(NULL != ks_ssl);
bf707bd2
 
81d882d5
     ret = bio_write(ks_ssl->ct_in, BPTR(buf), BLEN(buf), "tls_write_ciphertext");
     bio_write_post(ret, buf);
bf707bd2
 
81d882d5
     perf_pop();
     return ret;
bf707bd2
 }
 
 int
4e9e25a9
 key_state_read_plaintext(struct key_state_ssl *ks_ssl, struct buffer *buf)
dd5e1102
 {
81d882d5
     int ret = 0;
     perf_push(PERF_BIO_READ_PLAINTEXT);
dd5e1102
 
81d882d5
     ASSERT(NULL != ks_ssl);
dd5e1102
 
4e9e25a9
     ret = bio_read(ks_ssl->ssl_bio, buf, "tls_read_plaintext");
dd5e1102
 
81d882d5
     perf_pop();
     return ret;
dd5e1102
 }
 
ca570706
 static void
4e80aac4
 print_pkey_details(EVP_PKEY *pkey, char *buf, size_t buflen)
ca570706
 {
     const char *curve = "";
     const char *type = "(error getting type)";
 
     if (pkey == NULL)
     {
         buf[0] = 0;
         return;
     }
 
     int typeid = EVP_PKEY_id(pkey);
6c111be9
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
     bool is_ec = typeid == EVP_PKEY_EC;
 #else
     bool is_ec = EVP_PKEY_is_a(pkey, "EC");
 #endif
ca570706
 
 #ifndef OPENSSL_NO_EC
6889d9e2
     char groupname[64];
6c111be9
     if (is_ec)
ca570706
     {
4b3c1e76
         size_t len;
abe49856
         if (EVP_PKEY_get_group_name(pkey, groupname, sizeof(groupname), &len))
4b3c1e76
         {
abe49856
             curve = groupname;
4b3c1e76
         }
         else
ca570706
         {
             curve = "(error getting curve name)";
         }
     }
 #endif
6c111be9
     if (typeid != 0)
ca570706
     {
6c111be9
 #if OPENSSL_VERSION_NUMBER < 0x30000000L
ca570706
         type = OBJ_nid2sn(typeid);
 
         /* OpenSSL reports rsaEncryption, dsaEncryption and
         * id-ecPublicKey, map these values to nicer ones */
         if (typeid == EVP_PKEY_RSA)
         {
             type = "RSA";
         }
         else if (typeid == EVP_PKEY_DSA)
         {
             type = "DSA";
         }
         else if (typeid == EVP_PKEY_EC)
         {
             /* EC gets the curve appended after the type */
             type = "EC, curve ";
         }
         else if (type == NULL)
         {
             type = "unknown type";
         }
6c111be9
 #else /* OpenSSL >= 3 */
         type = EVP_PKEY_get0_type_name(pkey);
         if (type == NULL)
         {
             type = "(error getting public key type)";
         }
 #endif /* if OPENSSL_VERSION_NUMBER < 0x30000000L */
ca570706
     }
 
130548fe
     snprintf(buf, buflen, "%d bits %s%s",
              EVP_PKEY_bits(pkey), type, curve);
4e80aac4
 }
 
 /**
  * Print human readable information about the certificate into buf
  * @param cert      the certificate being used
  * @param buf       output buffer
  * @param buflen    output buffer length
  */
 static void
 print_cert_details(X509 *cert, char *buf, size_t buflen)
 {
     EVP_PKEY *pkey = X509_get_pubkey(cert);
6889d9e2
     char pkeybuf[64] = { 0 };
4e80aac4
     print_pkey_details(pkey, pkeybuf, sizeof(pkeybuf));
 
ca570706
     char sig[128] = { 0 };
     int signature_nid = X509_get_signature_nid(cert);
     if (signature_nid != 0)
     {
130548fe
         snprintf(sig, sizeof(sig), ", signature: %s",
                  OBJ_nid2sn(signature_nid));
ca570706
     }
 
130548fe
     snprintf(buf, buflen, ", peer certificate: %s%s",
              pkeybuf, sig);
4e80aac4
 
     EVP_PKEY_free(pkey);
 }
 
 static void
 print_server_tempkey(SSL *ssl, char *buf, size_t buflen)
 {
     EVP_PKEY *pkey = NULL;
     SSL_get_peer_tmp_key(ssl, &pkey);
     if (!pkey)
     {
         return;
     }
 
     char pkeybuf[128] = { 0 };
     print_pkey_details(pkey, pkeybuf, sizeof(pkeybuf));
 
130548fe
     snprintf(buf, buflen, ", peer temporary key: %s",
              pkeybuf);
ca570706
 
     EVP_PKEY_free(pkey);
 }
 
ff402c7c
 #if (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1010000fL) \
     || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3090000fL)
b431721e
 /**
  * Translate an OpenSSL NID into a more human readable name
  * @param nid
  * @return
  */
 static const char *
 get_sigtype(int nid)
 {
     /* Fix a few OpenSSL names to be better understandable */
     switch (nid)
     {
         case EVP_PKEY_RSA:
             /* will otherwise say rsaEncryption */
             return "RSA";
 
         case EVP_PKEY_DSA:
             /* dsaEncryption otherwise */
             return "DSA";
 
         case EVP_PKEY_EC:
             /* will say id-ecPublicKey */
             return "ECDSA";
 
         case -1:
             return "(error getting name)";
 
         default:
             return OBJ_nid2sn(nid);
     }
 }
 #endif /* ifndef LIBRESSL_VERSION_NUMBER */
 
 /**
  * Get the type of the signature that is used by the peer during the
  * TLS handshake
  */
 static void
 print_peer_signature(SSL *ssl, char *buf, size_t buflen)
 {
     int peer_sig_nid = NID_undef, peer_sig_type_nid = NID_undef;
     const char *peer_sig = "unknown";
     const char *peer_sig_type = "unknown type";
 
     /* Even though these methods use the deprecated NIDs instead of using
      * string as new OpenSSL APIs do, there seem to be no API that replaces
      * it yet */
 #if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER > 0x3050400fL
     if (SSL_get_peer_signature_nid(ssl, &peer_sig_nid)
         && peer_sig_nid != NID_undef)
     {
         peer_sig = OBJ_nid2sn(peer_sig_nid);
     }
 #endif
 
 #if (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x1010000fL) \
     || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3090000fL)
     /* LibreSSL 3.7.x and 3.8.x implement this function but do not export it
      * and fail linking with an unresolved symbol */
     if (SSL_get_peer_signature_type_nid(ssl, &peer_sig_type_nid)
         && peer_sig_type_nid != NID_undef)
     {
         peer_sig_type = get_sigtype(peer_sig_type_nid);
     }
 #endif
 
     if (peer_sig_nid == NID_undef && peer_sig_type_nid == NID_undef)
     {
         return;
     }
 
130548fe
     snprintf(buf, buflen, ", peer signing digest/type: %s %s",
              peer_sig, peer_sig_type);
b431721e
 }
 
 
 
963ad54e
 /* **************************************
  *
  * Information functions
  *
  * Print information for the end user.
  *
  ***************************************/
 void
81d882d5
 print_details(struct key_state_ssl *ks_ssl, const char *prefix)
963ad54e
 {
81d882d5
     const SSL_CIPHER *ciph;
     char s1[256];
     char s2[256];
4e80aac4
     char s3[256];
b431721e
     char s4[256];
81d882d5
 
b431721e
     s1[0] = s2[0] = s3[0] = s4[0] = 0;
81d882d5
     ciph = SSL_get_current_cipher(ks_ssl->ssl);
130548fe
     snprintf(s1, sizeof(s1), "%s %s, cipher %s %s",
              prefix,
              SSL_get_version(ks_ssl->ssl),
              SSL_CIPHER_get_version(ciph),
              SSL_CIPHER_get_name(ciph));
ca570706
     X509 *cert = SSL_get_peer_certificate(ks_ssl->ssl);
bb23eca8
 
ca570706
     if (cert)
     {
         print_cert_details(cert, s2, sizeof(s2));
81d882d5
         X509_free(cert);
     }
4e80aac4
     print_server_tempkey(ks_ssl->ssl, s3, sizeof(s3));
b431721e
     print_peer_signature(ks_ssl->ssl, s4, sizeof(s4));
4e80aac4
 
b431721e
     msg(D_HANDSHAKE, "%s%s%s%s", s1, s2, s3, s4);
963ad54e
 }
 
244da317
 void
7aeabadd
 show_available_tls_ciphers_list(const char *cipher_list,
                                 const char *tls_cert_profile,
2569902c
                                 bool tls13)
397c0a35
 {
81d882d5
     struct tls_root_ctx tls_ctx;
 
     tls_ctx.ctx = SSL_CTX_new(SSLv23_method());
     if (!tls_ctx.ctx)
     {
         crypto_msg(M_FATAL, "Cannot create SSL_CTX object");
     }
397c0a35
 
a4750860
 #if defined(TLS1_3_VERSION)
7aeabadd
     if (tls13)
81d882d5
     {
6328aef9
         SSL_CTX_set_min_proto_version(tls_ctx.ctx,
                                       openssl_tls_version(TLS_VER_1_3));
68011752
         tls_ctx_restrict_ciphers_tls13(&tls_ctx, cipher_list);
7aeabadd
     }
     else
 #endif
     {
         SSL_CTX_set_max_proto_version(tls_ctx.ctx, TLS1_2_VERSION);
68011752
         tls_ctx_restrict_ciphers(&tls_ctx, cipher_list);
81d882d5
     }
397c0a35
 
aba75874
     tls_ctx_set_cert_profile(&tls_ctx, tls_cert_profile);
cb03dca8
 
7aeabadd
     SSL *ssl = SSL_new(tls_ctx.ctx);
     if (!ssl)
     {
         crypto_msg(M_FATAL, "Cannot create SSL object");
     }
 
2c0ebe0f
 #if OPENSSL_VERSION_NUMBER < 0x1010000fL
7aeabadd
     STACK_OF(SSL_CIPHER) *sk = SSL_get_ciphers(ssl);
 #else
     STACK_OF(SSL_CIPHER) *sk = SSL_get1_supported_ciphers(ssl);
 #endif
f57431cd
     for (int i = 0; i < sk_SSL_CIPHER_num(sk); i++)
3b23b18d
     {
7aeabadd
         const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
 
         const char *cipher_name = SSL_CIPHER_get_name(c);
 
         const tls_cipher_name_pair *pair =
             tls_get_cipher_name_pair(cipher_name, strlen(cipher_name));
3b23b18d
 
7aeabadd
         if (tls13)
         {
f57431cd
             printf("%s\n", cipher_name);
7aeabadd
         }
         else if (NULL == pair)
81d882d5
         {
             /* No translation found, print warning */
68011752
             printf("%s (No IANA name known to OpenVPN, use OpenSSL name.)\n",
                    cipher_name);
81d882d5
         }
         else
         {
             printf("%s\n", pair->iana_name);
         }
3b23b18d
     }
7aeabadd
 #if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
     sk_SSL_CIPHER_free(sk);
 #endif
81d882d5
     SSL_free(ssl);
     SSL_CTX_free(tls_ctx.ctx);
397c0a35
 }
b64ffdcf
 
609e8131
 /*
  * Show the Elliptic curves that are available for us to use
  * in the OpenSSL library.
  */
 void
e2a0cad4
 show_available_curves(void)
609e8131
 {
a840d509
     printf("Consider using 'openssl ecparam -list_curves' as alternative to running\n"
            "this command.\n"
            "Note this output does only list curves/groups that OpenSSL considers as\n"
            "builtin EC curves. It does not list additional curves nor X448 or X25519\n");
609e8131
 #ifndef OPENSSL_NO_EC
81d882d5
     EC_builtin_curve *curves = NULL;
     size_t crv_len = 0;
     size_t n = 0;
 
     crv_len = EC_get_builtin_curves(NULL, 0);
     ALLOC_ARRAY(curves, EC_builtin_curve, crv_len);
     if (EC_get_builtin_curves(curves, crv_len))
     {
8353ae80
         printf("\nAvailable Elliptic curves/groups:\n");
81d882d5
         for (n = 0; n < crv_len; n++)
         {
             const char *sname;
             sname   = OBJ_nid2sn(curves[n].nid);
             if (sname == NULL)
             {
                 sname = "";
             }
 
             printf("%s\n", sname);
         }
     }
     else
     {
         crypto_msg(M_FATAL, "Cannot get list of builtin curves");
     }
     free(curves);
 #else  /* ifndef OPENSSL_NO_EC */
     msg(M_WARN, "Your OpenSSL library was built without elliptic curve support. "
         "No curves available.");
 #endif /* ifndef OPENSSL_NO_EC */
609e8131
 }
 
b64ffdcf
 void
81d882d5
 get_highest_preference_tls_cipher(char *buf, int size)
b64ffdcf
 {
81d882d5
     SSL_CTX *ctx;
     SSL *ssl;
     const char *cipher_name;
 
     ctx = SSL_CTX_new(SSLv23_method());
     if (!ctx)
     {
         crypto_msg(M_FATAL, "Cannot create SSL_CTX object");
     }
     ssl = SSL_new(ctx);
     if (!ssl)
     {
         crypto_msg(M_FATAL, "Cannot create SSL object");
     }
 
     cipher_name = SSL_get_cipher_list(ssl, 0);
     strncpynt(buf, cipher_name, size);
 
     SSL_free(ssl);
     SSL_CTX_free(ctx);
b64ffdcf
 }
31ea2ee4
 
5b17803e
 const char *
1ec984b1
 get_ssl_library_version(void)
 {
17a476fd
     return OpenSSL_version(OPENSSL_VERSION);
1ec984b1
 }
 
4b85c488
 
 /** Some helper routines for provider load/unload */
 #ifdef HAVE_XKEY_PROVIDER
 static int
 provider_load(OSSL_PROVIDER *prov, void *dest_libctx)
 {
     const char *name = OSSL_PROVIDER_get0_name(prov);
     OSSL_PROVIDER_load(dest_libctx, name);
     return 1;
 }
 
 static int
 provider_unload(OSSL_PROVIDER *prov, void *unused)
 {
     (void) unused;
     OSSL_PROVIDER_unload(prov);
     return 1;
 }
 #endif /* HAVE_XKEY_PROVIDER */
 
 /**
  * Setup ovpn.xey provider for signing with external keys.
  * It is loaded into a custom library context so as not to pollute
  * the default context. Alternatively we could override any
  * system-wide property query set on the default context. But we
  * want to avoid that.
  */
 void
 load_xkey_provider(void)
 {
 #ifdef HAVE_XKEY_PROVIDER
 
     /* Make a new library context for use in TLS context */
     if (!tls_libctx)
     {
         tls_libctx = OSSL_LIB_CTX_new();
         check_malloc_return(tls_libctx);
 
         /* Load all providers in default LIBCTX into this libctx.
          * OpenSSL has a child libctx functionality to automate this,
          * but currently that is usable only from within providers.
          * So we do something close to it manually here.
          */
         OSSL_PROVIDER_do_all(NULL, provider_load, tls_libctx);
     }
 
     if (!OSSL_PROVIDER_available(tls_libctx, "ovpn.xkey"))
     {
         OSSL_PROVIDER_add_builtin(tls_libctx, "ovpn.xkey", xkey_provider_init);
         if (!OSSL_PROVIDER_load(tls_libctx, "ovpn.xkey"))
         {
             msg(M_NONFATAL, "ERROR: failed loading external key provider: "
abe49856
                 "Signing with external keys will not work.");
4b85c488
         }
     }
 
     /* We only implement minimal functionality in ovpn.xkey, so we do not want
      * methods in xkey to be picked unless absolutely required (i.e, when the key
      * is external). Ensure this by setting a default propquery for the custom
      * libctx that unprefers, but does not forbid, ovpn.xkey. See also man page
      * of "property" in OpenSSL 3.0.
      */
     EVP_set_default_properties(tls_libctx, "?provider!=ovpn.xkey");
 
 #endif /* HAVE_XKEY_PROVIDER */
 }
 
 /**
  * Undo steps in load_xkey_provider
  */
 static void
 unload_xkey_provider(void)
 {
 #ifdef HAVE_XKEY_PROVIDER
     if (tls_libctx)
     {
         OSSL_PROVIDER_do_all(tls_libctx, provider_unload, NULL);
         OSSL_LIB_CTX_free(tls_libctx);
     }
 #endif /* HAVE_XKEY_PROVIDER */
     tls_libctx = NULL;
 }
 
c7ca9133
 #endif /* defined(ENABLE_CRYPTO_OPENSSL) */