src/openvpn/crypto_openssl.c
6825182b
 /*
  *  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.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
  *  Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com>
6825182b
  *
  *  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.
6825182b
  */
 
 /**
  * @file Data Channel Cryptography OpenSSL-specific backend interface
  */
 
c110b289
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #elif defined(_MSC_VER)
 #include "config-msvc.h"
 #endif
 
6825182b
 #include "syshead.h"
 
c7ca9133
 #if defined(ENABLE_CRYPTO_OPENSSL)
31ea2ee4
 
6825182b
 #include "basic.h"
 #include "buffer.h"
 #include "integer.h"
d344820f
 #include "crypto.h"
6825182b
 #include "crypto_backend.h"
c481ef00
 #include "openssl_compat.h"
c3e1809f
 
6825182b
 #include <openssl/des.h>
c3e1809f
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/objects.h>
6ede22c4
 #include <openssl/rand.h>
c3e1809f
 #include <openssl/ssl.h>
6825182b
 
 /*
23ee3563
  * Check for key size creepage.
  */
 
 #if MAX_CIPHER_KEY_LENGTH < EVP_MAX_KEY_LENGTH
 #warning Some OpenSSL EVP ciphers now support key lengths greater than MAX_CIPHER_KEY_LENGTH -- consider increasing MAX_CIPHER_KEY_LENGTH
 #endif
 
 #if MAX_HMAC_KEY_LENGTH < EVP_MAX_MD_SIZE
 #warning Some OpenSSL HMAC message digests now support key lengths greater than MAX_HMAC_KEY_LENGTH -- consider increasing MAX_HMAC_KEY_LENGTH
 #endif
 
9b33b5a4
 #if HAVE_OPENSSL_ENGINE
b01cb9ef
 #include <openssl/engine.h>
 
 static bool engine_initialized = false; /* GLOBAL */
 
 static ENGINE *engine_persist = NULL;   /* GLOBAL */
 
 /* Try to load an engine in a shareable library */
 static ENGINE *
81d882d5
 try_load_engine(const char *engine)
b01cb9ef
 {
81d882d5
     ENGINE *e = ENGINE_by_id("dynamic");
     if (e)
b01cb9ef
     {
81d882d5
         if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
             || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
         {
             ENGINE_free(e);
             e = NULL;
         }
b01cb9ef
     }
81d882d5
     return e;
b01cb9ef
 }
 
 static ENGINE *
81d882d5
 setup_engine(const char *engine)
b01cb9ef
 {
81d882d5
     ENGINE *e = NULL;
b01cb9ef
 
81d882d5
     ENGINE_load_builtin_engines();
b01cb9ef
 
81d882d5
     if (engine)
b01cb9ef
     {
81d882d5
         if (strcmp(engine, "auto") == 0)
         {
             msg(M_INFO, "Initializing OpenSSL auto engine support");
             ENGINE_register_all_complete();
             return NULL;
         }
         if ((e = ENGINE_by_id(engine)) == NULL
             && (e = try_load_engine(engine)) == NULL)
         {
             crypto_msg(M_FATAL, "OpenSSL error: cannot load engine '%s'",
                        engine);
         }
 
         if (!ENGINE_set_default(e, ENGINE_METHOD_ALL))
         {
             crypto_msg(M_FATAL,
                        "OpenSSL error: ENGINE_set_default failed on engine '%s'",
                        engine);
         }
 
         msg(M_INFO, "Initializing OpenSSL support for engine '%s'",
             ENGINE_get_id(e));
b01cb9ef
     }
81d882d5
     return e;
b01cb9ef
 }
 
9b33b5a4
 #endif /* HAVE_OPENSSL_ENGINE */
b01cb9ef
 
 void
81d882d5
 crypto_init_lib_engine(const char *engine_name)
b01cb9ef
 {
9b33b5a4
 #if HAVE_OPENSSL_ENGINE
81d882d5
     if (!engine_initialized)
b01cb9ef
     {
81d882d5
         ASSERT(engine_name);
         ASSERT(!engine_persist);
         engine_persist = setup_engine(engine_name);
         engine_initialized = true;
b01cb9ef
     }
81d882d5
 #else  /* if HAVE_OPENSSL_ENGINE */
     msg(M_WARN, "Note: OpenSSL hardware crypto engine functionality is not available");
7151f3f7
 #endif
b01cb9ef
 }
 
 /*
  *
  * Functions related to the core crypto library
  *
  */
 
 void
81d882d5
 crypto_init_lib(void)
b01cb9ef
 {
81d882d5
     /*
      * If you build the OpenSSL library and OpenVPN with
      * CRYPTO_MDEBUG, you will get a listing of OpenSSL
      * memory leaks on program termination.
      */
39b54baa
 
b01cb9ef
 #ifdef CRYPTO_MDEBUG
81d882d5
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
b01cb9ef
 #endif
 }
 
 void
81d882d5
 crypto_uninit_lib(void)
b01cb9ef
 {
 #ifdef CRYPTO_MDEBUG
81d882d5
     FILE *fp = fopen("sdlog", "w");
     ASSERT(fp);
     CRYPTO_mem_leaks_fp(fp);
     fclose(fp);
b01cb9ef
 #endif
 
9b33b5a4
 #if HAVE_OPENSSL_ENGINE
81d882d5
     if (engine_initialized)
b01cb9ef
     {
81d882d5
         ENGINE_cleanup();
         engine_persist = NULL;
         engine_initialized = false;
b01cb9ef
     }
 #endif
 }
7151f3f7
 
 void
81d882d5
 crypto_clear_error(void)
330715f0
 {
81d882d5
     ERR_clear_error();
330715f0
 }
 
e795d6ba
 void
4cd4899e
 crypto_print_openssl_errors(const unsigned int flags)
 {
81d882d5
     size_t err = 0;
e795d6ba
 
81d882d5
     while ((err = ERR_get_error()))
c3e1809f
     {
81d882d5
         /* Be more clear about frequently occurring "no shared cipher" error */
6ddc43d1
         if (ERR_GET_REASON(err) == SSL_R_NO_SHARED_CIPHER)
81d882d5
         {
             msg(D_CRYPT_ERRORS, "TLS error: The server has no TLS ciphersuites "
                 "in common with the client. Your --tls-cipher setting might be "
                 "too restrictive.");
         }
d3194688
         else if (ERR_GET_REASON(err) == SSL_R_UNSUPPORTED_PROTOCOL)
         {
             msg(D_CRYPT_ERRORS, "TLS error: Unsupported protocol. This typically "
                  "indicates that client and server have no common TLS version enabled. "
                  "This can be caused by mismatched tls-version-min and tls-version-max "
                  "options on client and server. "
                  "If your OpenVPN client is between v2.3.6 and v2.3.2 try adding "
                  "tls-version-min 1.0 to the client configuration to use TLS 1.0+ "
                  "instead of TLS 1.0 only");
         }
81d882d5
         msg(flags, "OpenSSL: %s", ERR_error_string(err, NULL));
c3e1809f
     }
e795d6ba
 }
 
 
b01cb9ef
 /*
  *
  * OpenSSL memory debugging.  If dmalloc debugging is enabled, tell
  * OpenSSL to use our private malloc/realloc/free functions so that
  * we can dispatch them to dmalloc.
  *
  */
 
 #ifdef DMALLOC
 static void *
81d882d5
 crypto_malloc(size_t size, const char *file, int line)
b01cb9ef
 {
81d882d5
     return dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0);
b01cb9ef
 }
 
 static void *
81d882d5
 crypto_realloc(void *ptr, size_t size, const char *file, int line)
b01cb9ef
 {
81d882d5
     return dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0);
b01cb9ef
 }
 
 static void
81d882d5
 crypto_free(void *ptr)
b01cb9ef
 {
81d882d5
     dmalloc_free(__FILE__, __LINE__, ptr, DMALLOC_FUNC_FREE);
b01cb9ef
 }
 
 void
81d882d5
 crypto_init_dmalloc(void)
b01cb9ef
 {
81d882d5
     CRYPTO_set_mem_ex_functions(crypto_malloc,
                                 crypto_realloc,
                                 crypto_free);
b01cb9ef
 }
 #endif /* DMALLOC */
 
44dc5d30
 const cipher_name_pair cipher_name_translation_table[] = {
     { "AES-128-GCM", "id-aes128-GCM" },
     { "AES-192-GCM", "id-aes192-GCM" },
     { "AES-256-GCM", "id-aes256-GCM" },
6d0d0af9
     { "CHACHA20-POLY1305", "ChaCha20-Poly1305" },
44dc5d30
 };
 const size_t cipher_name_translation_table_count =
81d882d5
     sizeof(cipher_name_translation_table) / sizeof(*cipher_name_translation_table);
f499b921
 
 
c94b3ff0
 static int
 cipher_name_cmp(const void *a, const void *b)
 {
81d882d5
     const EVP_CIPHER *const *cipher_a = a;
     const EVP_CIPHER *const *cipher_b = b;
c94b3ff0
 
81d882d5
     const char *cipher_name_a =
         translate_cipher_name_to_openvpn(EVP_CIPHER_name(*cipher_a));
     const char *cipher_name_b =
         translate_cipher_name_to_openvpn(EVP_CIPHER_name(*cipher_b));
c94b3ff0
 
81d882d5
     return strcmp(cipher_name_a, cipher_name_b);
c94b3ff0
 }
 
330715f0
 void
e2a0cad4
 show_available_ciphers(void)
7151f3f7
 {
81d882d5
     int nid;
     size_t i;
7151f3f7
 
81d882d5
     /* If we ever exceed this, we must be more selective */
db1b4d96
     const EVP_CIPHER *cipher_list[1000];
81d882d5
     size_t num_ciphers = 0;
7151f3f7
 #ifndef ENABLE_SMALL
81d882d5
     printf("The following ciphers and cipher modes are available for use\n"
            "with " PACKAGE_NAME ".  Each cipher shown below may be use as a\n"
            "parameter to the --cipher option.  The default key size is\n"
            "shown as well as whether or not it can be changed with the\n"
            "--keysize directive.  Using a CBC or GCM mode is recommended.\n"
            "In static key mode only CBC mode is allowed.\n\n");
7151f3f7
 #endif
 
81d882d5
     for (nid = 0; nid < 10000; ++nid)
7151f3f7
     {
81d882d5
         const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
         if (cipher && (cipher_kt_mode_cbc(cipher)
c353af2f
 #ifdef ENABLE_OFB_CFB_MODE
81d882d5
                        || cipher_kt_mode_ofb_cfb(cipher)
7151f3f7
 #endif
66407e11
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
                        || cipher_kt_mode_aead(cipher)
66407e11
 #endif
81d882d5
                        ))
         {
             cipher_list[num_ciphers++] = cipher;
         }
db1b4d96
         if (num_ciphers == (sizeof(cipher_list)/sizeof(*cipher_list)))
81d882d5
         {
             msg(M_WARN, "WARNING: Too many ciphers, not showing all");
             break;
         }
7151f3f7
     }
c94b3ff0
 
81d882d5
     qsort(cipher_list, num_ciphers, sizeof(*cipher_list), cipher_name_cmp);
c94b3ff0
 
81d882d5
     for (i = 0; i < num_ciphers; i++) {
6d0d0af9
         if (!cipher_kt_insecure(cipher_list[i]))
81d882d5
         {
             print_cipher(cipher_list[i]);
         }
     }
c94b3ff0
 
81d882d5
     printf("\nThe following ciphers have a block size of less than 128 bits, \n"
            "and are therefore deprecated.  Do not use unless you have to.\n\n");
     for (i = 0; i < num_ciphers; i++) {
6d0d0af9
         if (cipher_kt_insecure(cipher_list[i]))
81d882d5
         {
             print_cipher(cipher_list[i]);
         }
     }
     printf("\n");
7151f3f7
 }
 
 void
e2a0cad4
 show_available_digests(void)
7151f3f7
 {
81d882d5
     int nid;
7151f3f7
 
 #ifndef ENABLE_SMALL
81d882d5
     printf("The following message digests are available for use with\n"
            PACKAGE_NAME ".  A message digest is used in conjunction with\n"
            "the HMAC function, to authenticate received packets.\n"
            "You can specify a message digest as parameter to\n"
            "the --auth option.\n\n");
7151f3f7
 #endif
 
81d882d5
     for (nid = 0; nid < 10000; ++nid)
7151f3f7
     {
81d882d5
         const EVP_MD *digest = EVP_get_digestbynid(nid);
         if (digest)
         {
             printf("%s %d bit digest size\n",
                    OBJ_nid2sn(nid), EVP_MD_size(digest) * 8);
         }
7151f3f7
     }
81d882d5
     printf("\n");
7151f3f7
 }
 
 void
e2a0cad4
 show_available_engines(void)
7151f3f7
 {
9b33b5a4
 #if HAVE_OPENSSL_ENGINE /* Only defined for OpenSSL */
81d882d5
     ENGINE *e;
7151f3f7
 
81d882d5
     printf("OpenSSL Crypto Engines\n\n");
7151f3f7
 
81d882d5
     ENGINE_load_builtin_engines();
7151f3f7
 
81d882d5
     e = ENGINE_get_first();
     while (e)
7151f3f7
     {
81d882d5
         printf("%s [%s]\n",
                ENGINE_get_name(e),
                ENGINE_get_id(e));
         e = ENGINE_get_next(e);
7151f3f7
     }
81d882d5
     ENGINE_cleanup();
 #else  /* if HAVE_OPENSSL_ENGINE */
     printf("Sorry, OpenSSL hardware crypto engine functionality is not available.\n");
7151f3f7
 #endif
 }
 
a5d35a01
 
 bool
 crypto_pem_encode(const char *name, struct buffer *dst,
                   const struct buffer *src, struct gc_arena *gc)
 {
     bool ret = false;
     BIO *bio = BIO_new(BIO_s_mem());
     if (!bio || !PEM_write_bio(bio, name, "", BPTR(src), BLEN(src)))
     {
         ret = false;
         goto cleanup;
     }
 
     BUF_MEM *bptr;
     BIO_get_mem_ptr(bio, &bptr);
 
     *dst = alloc_buf_gc(bptr->length, gc);
     ASSERT(buf_write(dst, bptr->data, bptr->length));
 
     ret = true;
 cleanup:
     if (!BIO_free(bio))
     {
         ret = false;;
     }
 
     return ret;
 }
 
 bool
 crypto_pem_decode(const char *name, struct buffer *dst,
                   const struct buffer *src)
 {
     bool ret = false;
 
     BIO *bio = BIO_new_mem_buf((char *)BPTR(src), BLEN(src));
     if (!bio)
     {
         crypto_msg(M_FATAL, "Cannot open memory BIO for PEM decode");
     }
 
     char *name_read = NULL;
     char *header_read = NULL;
     uint8_t *data_read = NULL;
     long data_read_len = 0;
     if (!PEM_read_bio(bio, &name_read, &header_read, &data_read,
                       &data_read_len))
     {
         dmsg(D_CRYPT_ERRORS, "%s: PEM decode failed", __func__);
         goto cleanup;
     }
 
     if (strcmp(name, name_read))
     {
         dmsg(D_CRYPT_ERRORS,
              "%s: unexpected PEM name (got '%s', expected '%s')",
              __func__, name_read, name);
         goto cleanup;
     }
 
     uint8_t *dst_data = buf_write_alloc(dst, data_read_len);
     if (!dst_data)
     {
         dmsg(D_CRYPT_ERRORS, "%s: dst too small (%i, needs %li)", __func__,
              BCAP(dst), data_read_len);
         goto cleanup;
     }
     memcpy(dst_data, data_read, data_read_len);
 
     ret = true;
 cleanup:
     OPENSSL_free(name_read);
     OPENSSL_free(header_read);
     OPENSSL_free(data_read);
     if (!BIO_free(bio))
     {
         ret = false;;
     }
 
     return ret;
 }
 
7151f3f7
 /*
  *
6825182b
  * Random number functions, used in cases where we want
  * reasonably strong cryptographic random number generation
  * without depleting our entropy pool.  Used for random
  * IV values and a number of other miscellaneous tasks.
  *
  */
 
81d882d5
 int
 rand_bytes(uint8_t *output, int len)
6825182b
 {
81d882d5
     if (unlikely(1 != RAND_bytes(output, len)))
756602e7
     {
81d882d5
         crypto_msg(D_CRYPT_ERRORS, "RAND_bytes() failed");
         return 0;
756602e7
     }
81d882d5
     return 1;
6825182b
 }
 
183c3d19
 /*
  *
  * Key functions, allow manipulation of keys.
  *
  */
 
 
 int
81d882d5
 key_des_num_cblocks(const EVP_CIPHER *kt)
183c3d19
 {
81d882d5
     int ret = 0;
     const char *name = OBJ_nid2sn(EVP_CIPHER_nid(kt));
     if (name)
183c3d19
     {
81d882d5
         if (!strncmp(name, "DES-", 4))
         {
             ret = EVP_CIPHER_key_length(kt) / sizeof(DES_cblock);
         }
         else if (!strncmp(name, "DESX-", 5))
         {
             ret = 1;
         }
183c3d19
     }
81d882d5
     dmsg(D_CRYPTO_DEBUG, "CRYPTO INFO: n_DES_cblocks=%d", ret);
     return ret;
183c3d19
 }
 
 bool
81d882d5
 key_des_check(uint8_t *key, int key_len, int ndc)
183c3d19
 {
81d882d5
     int i;
     struct buffer b;
183c3d19
 
81d882d5
     buf_set_read(&b, key, key_len);
183c3d19
 
81d882d5
     for (i = 0; i < ndc; ++i)
183c3d19
     {
81d882d5
         DES_cblock *dc = (DES_cblock *) buf_read_alloc(&b, sizeof(DES_cblock));
         if (!dc)
         {
             crypto_msg(D_CRYPT_ERRORS,
                        "CRYPTO INFO: check_key_DES: insufficient key material");
             goto err;
         }
         if (DES_is_weak_key(dc))
         {
             crypto_msg(D_CRYPT_ERRORS,
                        "CRYPTO INFO: check_key_DES: weak key detected");
             goto err;
         }
         if (!DES_check_key_parity(dc))
         {
             crypto_msg(D_CRYPT_ERRORS,
                        "CRYPTO INFO: check_key_DES: bad parity detected");
             goto err;
         }
183c3d19
     }
81d882d5
     return true;
183c3d19
 
81d882d5
 err:
     ERR_clear_error();
     return false;
183c3d19
 }
 
 void
81d882d5
 key_des_fixup(uint8_t *key, int key_len, int ndc)
183c3d19
 {
81d882d5
     int i;
     struct buffer b;
183c3d19
 
81d882d5
     buf_set_read(&b, key, key_len);
     for (i = 0; i < ndc; ++i)
183c3d19
     {
81d882d5
         DES_cblock *dc = (DES_cblock *) buf_read_alloc(&b, sizeof(DES_cblock));
         if (!dc)
         {
             msg(D_CRYPT_ERRORS, "CRYPTO INFO: fixup_key_DES: insufficient key material");
             ERR_clear_error();
             return;
         }
         DES_set_odd_parity(dc);
183c3d19
     }
 }
4a5a6033
 
 
670f9dd9
 /*
  *
  * Generic cipher key type functions
  *
  */
 
 
 const EVP_CIPHER *
81d882d5
 cipher_kt_get(const char *ciphername)
670f9dd9
 {
81d882d5
     const EVP_CIPHER *cipher = NULL;
670f9dd9
 
81d882d5
     ASSERT(ciphername);
670f9dd9
 
81d882d5
     cipher = EVP_get_cipherbyname(ciphername);
670f9dd9
 
81d882d5
     if (NULL == cipher)
dc4fa3c4
     {
81d882d5
         crypto_msg(D_LOW, "Cipher algorithm '%s' not found", ciphername);
         return NULL;
dc4fa3c4
     }
 
670f9dd9
 
81d882d5
     if (EVP_CIPHER_key_length(cipher) > MAX_CIPHER_KEY_LENGTH)
dc4fa3c4
     {
81d882d5
         msg(D_LOW, "Cipher algorithm '%s' uses a default key size (%d bytes) "
             "which is larger than " PACKAGE_NAME "'s current maximum key size "
             "(%d bytes)", ciphername, EVP_CIPHER_key_length(cipher),
             MAX_CIPHER_KEY_LENGTH);
         return NULL;
dc4fa3c4
     }
670f9dd9
 
81d882d5
     return cipher;
670f9dd9
 }
 
 const char *
81d882d5
 cipher_kt_name(const EVP_CIPHER *cipher_kt)
670f9dd9
 {
81d882d5
     if (NULL == cipher_kt)
     {
         return "[null-cipher]";
     }
     return EVP_CIPHER_name(cipher_kt);
670f9dd9
 }
 
 int
81d882d5
 cipher_kt_key_size(const EVP_CIPHER *cipher_kt)
670f9dd9
 {
81d882d5
     return EVP_CIPHER_key_length(cipher_kt);
670f9dd9
 }
 
 int
81d882d5
 cipher_kt_iv_size(const EVP_CIPHER *cipher_kt)
670f9dd9
 {
81d882d5
     return EVP_CIPHER_iv_length(cipher_kt);
670f9dd9
 }
 
 int
4cd4899e
 cipher_kt_block_size(const EVP_CIPHER *cipher)
 {
     /*
      * OpenSSL reports OFB/CFB/GCM cipher block sizes as '1 byte'.  To work
81d882d5
      * around that, try to replace the mode with 'CBC' and return the block size
      * reported for that cipher, if possible.  If that doesn't work, just return
      * the value reported by OpenSSL.
      */
     char *name = NULL;
     char *mode_str = NULL;
     const char *orig_name = NULL;
     const EVP_CIPHER *cbc_cipher = NULL;
 
     int block_size = EVP_CIPHER_block_size(cipher);
 
     orig_name = cipher_kt_name(cipher);
     if (!orig_name)
     {
         goto cleanup;
     }
 
     name = string_alloc(translate_cipher_name_to_openvpn(orig_name), NULL);
     mode_str = strrchr(name, '-');
     if (!mode_str || strlen(mode_str) < 4)
     {
         goto cleanup;
     }
 
     strcpy(mode_str, "-CBC");
 
     cbc_cipher = EVP_get_cipherbyname(translate_cipher_name_from_openvpn(name));
     if (cbc_cipher)
     {
         block_size = EVP_CIPHER_block_size(cbc_cipher);
     }
c94b3ff0
 
 cleanup:
81d882d5
     free(name);
     return block_size;
670f9dd9
 }
 
6449a149
 int
81d882d5
 cipher_kt_tag_size(const EVP_CIPHER *cipher_kt)
66407e11
 {
81d882d5
     if (cipher_kt_mode_aead(cipher_kt))
     {
         return OPENVPN_AEAD_TAG_LENGTH;
     }
     else
     {
         return 0;
     }
66407e11
 }
 
6d0d0af9
 bool
 cipher_kt_insecure(const EVP_CIPHER *cipher)
 {
     return !(cipher_kt_block_size(cipher) >= 128 / 8
 #ifdef NID_chacha20_poly1305
              || EVP_CIPHER_nid(cipher) == NID_chacha20_poly1305
 #endif
             );
 }
 
66407e11
 int
81d882d5
 cipher_kt_mode(const EVP_CIPHER *cipher_kt)
670f9dd9
 {
81d882d5
     ASSERT(NULL != cipher_kt);
     return EVP_CIPHER_mode(cipher_kt);
670f9dd9
 }
 
a4b27b64
 bool
 cipher_kt_mode_cbc(const cipher_kt_t *cipher)
 {
81d882d5
     return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC
a4b27b64
 #ifdef EVP_CIPH_FLAG_AEAD_CIPHER
81d882d5
            /* Exclude AEAD cipher modes, they require a different API */
            && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
a4b27b64
 #endif
     ;
 }
 
 bool
 cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher)
 {
81d882d5
     return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB
                       || cipher_kt_mode(cipher) == OPENVPN_MODE_CFB)
a4b27b64
 #ifdef EVP_CIPH_FLAG_AEAD_CIPHER
81d882d5
            /* Exclude AEAD cipher modes, they require a different API */
            && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
a4b27b64
 #endif
     ;
 }
 
66407e11
 bool
 cipher_kt_mode_aead(const cipher_kt_t *cipher)
 {
 #ifdef HAVE_AEAD_CIPHER_MODES
6d0d0af9
     if (cipher)
     {
         switch (EVP_CIPHER_nid(cipher))
         {
         case NID_aes_128_gcm:
         case NID_aes_192_gcm:
         case NID_aes_256_gcm:
 #ifdef NID_chacha20_poly1305
         case NID_chacha20_poly1305:
 #endif
             return true;
         }
     }
66407e11
 #endif
6d0d0af9
 
     return false;
66407e11
 }
 
485c5f76
 /*
  *
  * Generic cipher context functions
  *
  */
 
6cbd48a3
 cipher_ctx_t *
 cipher_ctx_new(void)
 {
     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
     check_malloc_return(ctx);
     return ctx;
 }
 
 void
 cipher_ctx_free(EVP_CIPHER_CTX *ctx)
 {
     EVP_CIPHER_CTX_free(ctx);
 }
485c5f76
 
 void
5e6e4b7d
 cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
81d882d5
                 const EVP_CIPHER *kt, int enc)
485c5f76
 {
81d882d5
     ASSERT(NULL != kt && NULL != ctx);
485c5f76
 
81d882d5
     EVP_CIPHER_CTX_init(ctx);
     if (!EVP_CipherInit(ctx, kt, NULL, NULL, enc))
     {
         crypto_msg(M_FATAL, "EVP cipher init #1");
     }
485c5f76
 #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH
81d882d5
     if (!EVP_CIPHER_CTX_set_key_length(ctx, key_len))
     {
         crypto_msg(M_FATAL, "EVP set key size");
     }
485c5f76
 #endif
8d00afae
     if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, enc))
81d882d5
     {
         crypto_msg(M_FATAL, "EVP cipher init #2");
     }
485c5f76
 
81d882d5
     /* make sure we used a big enough key */
     ASSERT(EVP_CIPHER_CTX_key_length(ctx) <= key_len);
485c5f76
 }
 
 void
81d882d5
 cipher_ctx_cleanup(EVP_CIPHER_CTX *ctx)
485c5f76
 {
81d882d5
     EVP_CIPHER_CTX_cleanup(ctx);
485c5f76
 }
 
 int
81d882d5
 cipher_ctx_iv_length(const EVP_CIPHER_CTX *ctx)
485c5f76
 {
81d882d5
     return EVP_CIPHER_CTX_iv_length(ctx);
485c5f76
 }
 
81d882d5
 int
 cipher_ctx_get_tag(EVP_CIPHER_CTX *ctx, uint8_t *tag_buf, int tag_size)
66407e11
 {
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag_buf);
66407e11
 #else
81d882d5
     ASSERT(0);
66407e11
 #endif
 }
 
485c5f76
 int
 cipher_ctx_block_size(const EVP_CIPHER_CTX *ctx)
 {
81d882d5
     return EVP_CIPHER_CTX_block_size(ctx);
485c5f76
 }
 
 int
81d882d5
 cipher_ctx_mode(const EVP_CIPHER_CTX *ctx)
485c5f76
 {
81d882d5
     return EVP_CIPHER_CTX_mode(ctx);
485c5f76
 }
 
a4b27b64
 const cipher_kt_t *
81d882d5
 cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)
a4b27b64
 {
81d882d5
     return ctx ? EVP_CIPHER_CTX_cipher(ctx) : NULL;
a4b27b64
 }
 
 
485c5f76
 int
5e6e4b7d
 cipher_ctx_reset(EVP_CIPHER_CTX *ctx, const uint8_t *iv_buf)
485c5f76
 {
8d00afae
     return EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv_buf, -1);
485c5f76
 }
 
 int
81d882d5
 cipher_ctx_update_ad(EVP_CIPHER_CTX *ctx, const uint8_t *src, int src_len)
66407e11
 {
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     int len;
     if (!EVP_CipherUpdate(ctx, NULL, &len, src, src_len))
     {
         crypto_msg(M_FATAL, "%s: EVP_CipherUpdate() failed", __func__);
     }
     return 1;
 #else  /* ifdef HAVE_AEAD_CIPHER_MODES */
     ASSERT(0);
66407e11
 #endif
 }
 
 int
81d882d5
 cipher_ctx_update(EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len,
                   uint8_t *src, int src_len)
485c5f76
 {
81d882d5
     if (!EVP_CipherUpdate(ctx, dst, dst_len, src, src_len))
     {
         crypto_msg(M_FATAL, "%s: EVP_CipherUpdate() failed", __func__);
     }
     return 1;
485c5f76
 }
 
 int
81d882d5
 cipher_ctx_final(EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len)
485c5f76
 {
81d882d5
     return EVP_CipherFinal(ctx, dst, dst_len);
485c5f76
 }
 
66407e11
 int
81d882d5
 cipher_ctx_final_check_tag(EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len,
                            uint8_t *tag, size_t tag_len)
66407e11
 {
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     ASSERT(tag_len < SIZE_MAX);
     if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag_len, tag))
     {
         return 0;
     }
66407e11
 
81d882d5
     return cipher_ctx_final(ctx, dst, dst_len);
 #else  /* ifdef HAVE_AEAD_CIPHER_MODES */
     ASSERT(0);
66407e11
 #endif
 }
485c5f76
 
4a5a6033
 void
81d882d5
 cipher_des_encrypt_ecb(const unsigned char key[DES_KEY_LENGTH],
                        unsigned char *src,
                        unsigned char *dst)
4a5a6033
 {
899e9e4c
     DES_key_schedule sched;
4a5a6033
 
81d882d5
     DES_set_key_unchecked((DES_cblock *)key, &sched);
6e8b90ec
     DES_ecb_encrypt((DES_cblock *)src, (DES_cblock *)dst, &sched, DES_ENCRYPT);
4a5a6033
 }
902f674e
 
 /*
  *
  * Generic message digest information functions
  *
  */
 
 
 const EVP_MD *
81d882d5
 md_kt_get(const char *digest)
 {
     const EVP_MD *md = NULL;
     ASSERT(digest);
     md = EVP_get_digestbyname(digest);
     if (!md)
     {
         crypto_msg(M_FATAL, "Message hash algorithm '%s' not found", digest);
     }
     if (EVP_MD_size(md) > MAX_HMAC_KEY_LENGTH)
98ea2ec5
     {
81d882d5
         crypto_msg(M_FATAL, "Message hash algorithm '%s' uses a default hash "
                    "size (%d bytes) which is larger than " PACKAGE_NAME "'s current "
                    "maximum hash size (%d bytes)",
                    digest, EVP_MD_size(md), MAX_HMAC_KEY_LENGTH);
98ea2ec5
     }
81d882d5
     return md;
902f674e
 }
 
 const char *
81d882d5
 md_kt_name(const EVP_MD *kt)
902f674e
 {
81d882d5
     if (NULL == kt)
     {
         return "[null-digest]";
     }
     return EVP_MD_name(kt);
902f674e
 }
 
 int
81d882d5
 md_kt_size(const EVP_MD *kt)
902f674e
 {
81d882d5
     return EVP_MD_size(kt);
902f674e
 }
d5f44617
 
 
 /*
  *
  * Generic message digest functions
  *
  */
 
 int
81d882d5
 md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst)
d5f44617
 {
81d882d5
     unsigned int in_md_len = 0;
d5f44617
 
81d882d5
     return EVP_Digest(src, src_len, dst, &in_md_len, kt, NULL);
d5f44617
 }
 
c481ef00
 EVP_MD_CTX *
 md_ctx_new(void)
 {
     EVP_MD_CTX *ctx = EVP_MD_CTX_new();
     check_malloc_return(ctx);
     return ctx;
 }
 
 void md_ctx_free(EVP_MD_CTX *ctx)
 {
     EVP_MD_CTX_free(ctx);
 }
 
d5f44617
 void
81d882d5
 md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt)
d5f44617
 {
81d882d5
     ASSERT(NULL != ctx && NULL != kt);
d5f44617
 
81d882d5
     EVP_MD_CTX_init(ctx);
     EVP_DigestInit(ctx, kt);
d5f44617
 }
 
 void
 md_ctx_cleanup(EVP_MD_CTX *ctx)
 {
c481ef00
     EVP_MD_CTX_reset(ctx);
d5f44617
 }
 
 int
81d882d5
 md_ctx_size(const EVP_MD_CTX *ctx)
d5f44617
 {
81d882d5
     return EVP_MD_CTX_size(ctx);
d5f44617
 }
 
 void
81d882d5
 md_ctx_update(EVP_MD_CTX *ctx, const uint8_t *src, int src_len)
d5f44617
 {
81d882d5
     EVP_DigestUpdate(ctx, src, src_len);
d5f44617
 }
 
 void
81d882d5
 md_ctx_final(EVP_MD_CTX *ctx, uint8_t *dst)
d5f44617
 {
81d882d5
     unsigned int in_md_len = 0;
d5f44617
 
81d882d5
     EVP_DigestFinal(ctx, dst, &in_md_len);
d5f44617
 }
e8c950f1
 
 
 /*
  *
  * Generic HMAC functions
  *
  */
 
aba98e90
 HMAC_CTX *
 hmac_ctx_new(void)
 {
     HMAC_CTX *ctx = HMAC_CTX_new();
     check_malloc_return(ctx);
     return ctx;
 }
 
 void
 hmac_ctx_free(HMAC_CTX *ctx)
 {
     HMAC_CTX_free(ctx);
 }
e8c950f1
 
 void
81d882d5
 hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len,
               const EVP_MD *kt)
e8c950f1
 {
81d882d5
     ASSERT(NULL != kt && NULL != ctx);
e8c950f1
 
64b8a4ae
     HMAC_CTX_reset(ctx);
81d882d5
     HMAC_Init_ex(ctx, key, key_len, kt, NULL);
e8c950f1
 
81d882d5
     /* make sure we used a big enough key */
     ASSERT(HMAC_size(ctx) <= key_len);
e8c950f1
 }
 
 void
 hmac_ctx_cleanup(HMAC_CTX *ctx)
 {
aba98e90
     HMAC_CTX_reset(ctx);
e8c950f1
 }
 
 int
81d882d5
 hmac_ctx_size(const HMAC_CTX *ctx)
e8c950f1
 {
81d882d5
     return HMAC_size(ctx);
e8c950f1
 }
 
 void
81d882d5
 hmac_ctx_reset(HMAC_CTX *ctx)
e8c950f1
 {
81d882d5
     HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
e8c950f1
 }
 
 void
81d882d5
 hmac_ctx_update(HMAC_CTX *ctx, const uint8_t *src, int src_len)
e8c950f1
 {
81d882d5
     HMAC_Update(ctx, src, src_len);
e8c950f1
 }
 
 void
81d882d5
 hmac_ctx_final(HMAC_CTX *ctx, uint8_t *dst)
e8c950f1
 {
81d882d5
     unsigned int in_hmac_len = 0;
e8c950f1
 
81d882d5
     HMAC_Final(ctx, dst, &in_hmac_len);
e8c950f1
 }
31ea2ee4
 
c7ca9133
 #endif /* ENABLE_CRYPTO_OPENSSL */