diff options
Diffstat (limited to 'main/openvpn/src/openvpn/crypto_openssl.c')
m--------- | main/openvpn | 0 | ||||
-rw-r--r-- | main/openvpn/src/openvpn/crypto_openssl.c | 766 |
2 files changed, 0 insertions, 766 deletions
diff --git a/main/openvpn b/main/openvpn new file mode 160000 +Subproject 7aaf01766f9718375986600216607aeb6397200 diff --git a/main/openvpn/src/openvpn/crypto_openssl.c b/main/openvpn/src/openvpn/crypto_openssl.c deleted file mode 100644 index 2d81a6d8..00000000 --- a/main/openvpn/src/openvpn/crypto_openssl.c +++ /dev/null @@ -1,766 +0,0 @@ -/* - * OpenVPN -- An application to securely tunnel IP networks - * over a single TCP/UDP port, with support for SSL/TLS-based - * session authentication and key exchange, - * packet encryption, packet authentication, and - * packet compression. - * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/** - * @file Data Channel Cryptography OpenSSL-specific backend interface - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#elif defined(_MSC_VER) -#include "config-msvc.h" -#endif - -#include "syshead.h" - -#if defined(ENABLE_CRYPTO) && defined(ENABLE_CRYPTO_OPENSSL) - -#include "basic.h" -#include "buffer.h" -#include "integer.h" -#include "crypto.h" -#include "crypto_backend.h" - -#include <openssl/des.h> -#include <openssl/err.h> -#include <openssl/evp.h> -#include <openssl/objects.h> -#include <openssl/ssl.h> - -/* - * 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 - -#if HAVE_OPENSSL_ENGINE -#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 * -try_load_engine (const char *engine) -{ - ENGINE *e = ENGINE_by_id ("dynamic"); - if (e) - { - if (!ENGINE_ctrl_cmd_string (e, "SO_PATH", engine, 0) - || !ENGINE_ctrl_cmd_string (e, "LOAD", NULL, 0)) - { - ENGINE_free (e); - e = NULL; - } - } - return e; -} - -static ENGINE * -setup_engine (const char *engine) -{ - ENGINE *e = NULL; - - ENGINE_load_builtin_engines (); - - if (engine) - { - 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)); - } - return e; -} - -#endif /* HAVE_OPENSSL_ENGINE */ - -void -crypto_init_lib_engine (const char *engine_name) -{ -#if HAVE_OPENSSL_ENGINE - if (!engine_initialized) - { - ASSERT (engine_name); - ASSERT (!engine_persist); - engine_persist = setup_engine (engine_name); - engine_initialized = true; - } -#else - msg (M_WARN, "Note: OpenSSL hardware crypto engine functionality is not available"); -#endif -} - -/* - * - * Functions related to the core crypto library - * - */ - -void -crypto_init_lib (void) -{ - /* - * If you build the OpenSSL library and OpenVPN with - * CRYPTO_MDEBUG, you will get a listing of OpenSSL - * memory leaks on program termination. - */ - -#ifdef CRYPTO_MDEBUG - CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); -#endif -} - -void -crypto_uninit_lib (void) -{ -#ifdef CRYPTO_MDEBUG - FILE* fp = fopen ("sdlog", "w"); - ASSERT (fp); - CRYPTO_mem_leaks_fp (fp); - fclose (fp); -#endif - -#if HAVE_OPENSSL_ENGINE - if (engine_initialized) - { - ENGINE_cleanup (); - engine_persist = NULL; - engine_initialized = false; - } -#endif -} - -void -crypto_clear_error (void) -{ - ERR_clear_error (); -} - -void -crypto_print_openssl_errors(const unsigned int flags) { - size_t err = 0; - - while ((err = ERR_get_error ())) - { - /* Be more clear about frequently occurring "no shared cipher" error */ - if (err == ERR_PACK(ERR_LIB_SSL,SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_NO_SHARED_CIPHER)) - { - 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."); - } - - msg (flags, "OpenSSL: %s", ERR_error_string (err, NULL)); - } -} - - -/* - * - * 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 * -crypto_malloc (size_t size, const char *file, int line) -{ - return dmalloc_malloc(file, line, size, DMALLOC_FUNC_MALLOC, 0, 0); -} - -static void * -crypto_realloc (void *ptr, size_t size, const char *file, int line) -{ - return dmalloc_realloc(file, line, ptr, size, DMALLOC_FUNC_REALLOC, 0); -} - -static void -crypto_free (void *ptr) -{ - dmalloc_free (__FILE__, __LINE__, ptr, DMALLOC_FUNC_FREE); -} - -void -crypto_init_dmalloc (void) -{ - CRYPTO_set_mem_ex_functions (crypto_malloc, - crypto_realloc, - crypto_free); -} -#endif /* DMALLOC */ - -const char * -translate_cipher_name_from_openvpn (const char *cipher_name) { - // OpenSSL doesn't require any translation - return cipher_name; -} - -const char * -translate_cipher_name_to_openvpn (const char *cipher_name) { - // OpenSSL doesn't require any translation - return cipher_name; -} - -void -show_available_ciphers () -{ - int nid; - -#ifndef ENABLE_SMALL - printf ("The following ciphers and cipher modes are available\n" - "for use with " PACKAGE_NAME ". Each cipher shown below may be\n" - "used as a parameter to the --cipher option. The default\n" - "key size is shown as well as whether or not it can be\n" - "changed with the --keysize directive. Using a CBC mode\n" - "is recommended. In static key mode only CBC mode is allowed.\n\n"); -#endif - - for (nid = 0; nid < 10000; ++nid) /* is there a better way to get the size of the nid list? */ - { - const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid); - if (cipher) - { - if (cipher_kt_mode_cbc(cipher) -#ifdef ENABLE_OFB_CFB_MODE - || cipher_kt_mode_ofb_cfb(cipher) -#endif - ) - { - const char *var_key_size = - (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ? - "variable" : "fixed"; - const char *ssl_only = cipher_kt_mode_ofb_cfb(cipher) ? - " (TLS client/server mode)" : ""; - - printf ("%s %d bit default key (%s)%s\n", OBJ_nid2sn (nid), - EVP_CIPHER_key_length (cipher) * 8, var_key_size, - ssl_only); - } - } - } - printf ("\n"); -} - -void -show_available_digests () -{ - int nid; - -#ifndef ENABLE_SMALL - 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"); -#endif - - for (nid = 0; nid < 10000; ++nid) - { - 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); - } - } - printf ("\n"); -} - -void -show_available_engines () -{ -#if HAVE_OPENSSL_ENGINE /* Only defined for OpenSSL */ - ENGINE *e; - - printf ("OpenSSL Crypto Engines\n\n"); - - ENGINE_load_builtin_engines (); - - e = ENGINE_get_first (); - while (e) - { - printf ("%s [%s]\n", - ENGINE_get_name (e), - ENGINE_get_id (e)); - e = ENGINE_get_next (e); - } - ENGINE_cleanup (); -#else - printf ("Sorry, OpenSSL hardware crypto engine functionality is not available.\n"); -#endif -} - -/* - * - * 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. - * - */ - -int rand_bytes(uint8_t *output, int len) -{ - return RAND_bytes (output, len); -} - -/* - * - * Key functions, allow manipulation of keys. - * - */ - - -int -key_des_num_cblocks (const EVP_CIPHER *kt) -{ - int ret = 0; - const char *name = OBJ_nid2sn (EVP_CIPHER_nid (kt)); - if (name) - { - if (!strncmp (name, "DES-", 4)) - { - ret = EVP_CIPHER_key_length (kt) / sizeof (DES_cblock); - } - else if (!strncmp (name, "DESX-", 5)) - { - ret = 1; - } - } - dmsg (D_CRYPTO_DEBUG, "CRYPTO INFO: n_DES_cblocks=%d", ret); - return ret; -} - -bool -key_des_check (uint8_t *key, int key_len, int ndc) -{ - int i; - struct buffer b; - - buf_set_read (&b, key, key_len); - - for (i = 0; i < ndc; ++i) - { - 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; - } - } - return true; - - err: - ERR_clear_error (); - return false; -} - -void -key_des_fixup (uint8_t *key, int key_len, int ndc) -{ - int i; - struct buffer b; - - buf_set_read (&b, key, key_len); - for (i = 0; i < ndc; ++i) - { - 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); - } -} - - -/* - * - * Generic cipher key type functions - * - */ - - -const EVP_CIPHER * -cipher_kt_get (const char *ciphername) -{ - const EVP_CIPHER *cipher = NULL; - - ASSERT (ciphername); - - cipher = EVP_get_cipherbyname (ciphername); - - if (NULL == cipher) - crypto_msg (M_FATAL, "Cipher algorithm '%s' not found", ciphername); - - if (EVP_CIPHER_key_length (cipher) > MAX_CIPHER_KEY_LENGTH) - msg (M_FATAL, "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 cipher; -} - -const char * -cipher_kt_name (const EVP_CIPHER *cipher_kt) -{ - if (NULL == cipher_kt) - return "[null-cipher]"; - return EVP_CIPHER_name (cipher_kt); -} - -int -cipher_kt_key_size (const EVP_CIPHER *cipher_kt) -{ - return EVP_CIPHER_key_length (cipher_kt); -} - -int -cipher_kt_iv_size (const EVP_CIPHER *cipher_kt) -{ - return EVP_CIPHER_iv_length (cipher_kt); -} - -int -cipher_kt_block_size (const EVP_CIPHER *cipher_kt) -{ - return EVP_CIPHER_block_size (cipher_kt); -} - -int -cipher_kt_mode (const EVP_CIPHER *cipher_kt) -{ - ASSERT(NULL != cipher_kt); - return EVP_CIPHER_mode (cipher_kt); -} - -bool -cipher_kt_mode_cbc(const cipher_kt_t *cipher) -{ - return cipher && cipher_kt_mode(cipher) == OPENVPN_MODE_CBC -#ifdef EVP_CIPH_FLAG_AEAD_CIPHER - /* Exclude AEAD cipher modes, they require a different API */ - && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) -#endif - ; -} - -bool -cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher) -{ - return cipher && (cipher_kt_mode(cipher) == OPENVPN_MODE_OFB || - cipher_kt_mode(cipher) == OPENVPN_MODE_CFB) -#ifdef EVP_CIPH_FLAG_AEAD_CIPHER - /* Exclude AEAD cipher modes, they require a different API */ - && !(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) -#endif - ; -} - -/* - * - * Generic cipher context functions - * - */ - - -void -cipher_ctx_init (EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, - const EVP_CIPHER *kt, int enc) -{ - ASSERT(NULL != kt && NULL != ctx); - - CLEAR (*ctx); - - EVP_CIPHER_CTX_init (ctx); - if (!EVP_CipherInit (ctx, kt, NULL, NULL, enc)) - crypto_msg (M_FATAL, "EVP cipher init #1"); -#ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH - if (!EVP_CIPHER_CTX_set_key_length (ctx, key_len)) - crypto_msg (M_FATAL, "EVP set key size"); -#endif - if (!EVP_CipherInit (ctx, NULL, key, NULL, enc)) - crypto_msg (M_FATAL, "EVP cipher init #2"); - - /* make sure we used a big enough key */ - ASSERT (EVP_CIPHER_CTX_key_length (ctx) <= key_len); -} - -void -cipher_ctx_cleanup (EVP_CIPHER_CTX *ctx) -{ - EVP_CIPHER_CTX_cleanup (ctx); -} - -int -cipher_ctx_iv_length (const EVP_CIPHER_CTX *ctx) -{ - return EVP_CIPHER_CTX_iv_length (ctx); -} - -int -cipher_ctx_block_size(const EVP_CIPHER_CTX *ctx) -{ - return EVP_CIPHER_CTX_block_size (ctx); -} - -int -cipher_ctx_mode (const EVP_CIPHER_CTX *ctx) -{ - return EVP_CIPHER_CTX_mode (ctx); -} - -const cipher_kt_t * -cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx) -{ - return EVP_CIPHER_CTX_cipher(ctx); -} - - -int -cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf) -{ - return EVP_CipherInit (ctx, NULL, NULL, iv_buf, -1); -} - -int -cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len, - uint8_t *src, int src_len) -{ - if (!EVP_CipherUpdate (ctx, dst, dst_len, src, src_len)) - crypto_msg(M_FATAL, "%s: EVP_CipherUpdate() failed", __func__); - return 1; -} - -int -cipher_ctx_final (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len) -{ - return EVP_CipherFinal (ctx, dst, dst_len); -} - - -void -cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH], - unsigned char *src, - unsigned char *dst) -{ - DES_key_schedule sched; - - DES_set_key_unchecked((DES_cblock*)key, &sched); - DES_ecb_encrypt((DES_cblock *)src, (DES_cblock *)dst, &sched, DES_ENCRYPT); -} - -/* - * - * Generic message digest information functions - * - */ - - -const EVP_MD * -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) - { - 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); - } - return md; -} - -const char * -md_kt_name (const EVP_MD *kt) -{ - if (NULL == kt) - return "[null-digest]"; - return EVP_MD_name (kt); -} - -int -md_kt_size (const EVP_MD *kt) -{ - return EVP_MD_size(kt); -} - - -/* - * - * Generic message digest functions - * - */ - -int -md_full (const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst) -{ - unsigned int in_md_len = 0; - - return EVP_Digest(src, src_len, dst, &in_md_len, kt, NULL); -} - -void -md_ctx_init (EVP_MD_CTX *ctx, const EVP_MD *kt) -{ - ASSERT(NULL != ctx && NULL != kt); - - CLEAR (*ctx); - - EVP_MD_CTX_init (ctx); - EVP_DigestInit(ctx, kt); -} - -void -md_ctx_cleanup(EVP_MD_CTX *ctx) -{ - EVP_MD_CTX_cleanup(ctx); -} - -int -md_ctx_size (const EVP_MD_CTX *ctx) -{ - return EVP_MD_CTX_size(ctx); -} - -void -md_ctx_update (EVP_MD_CTX *ctx, const uint8_t *src, int src_len) -{ - EVP_DigestUpdate(ctx, src, src_len); -} - -void -md_ctx_final (EVP_MD_CTX *ctx, uint8_t *dst) -{ - unsigned int in_md_len = 0; - - EVP_DigestFinal(ctx, dst, &in_md_len); -} - - -/* - * - * Generic HMAC functions - * - */ - - -void -hmac_ctx_init (HMAC_CTX *ctx, const uint8_t *key, int key_len, - const EVP_MD *kt) -{ - ASSERT(NULL != kt && NULL != ctx); - - CLEAR(*ctx); - - HMAC_CTX_init (ctx); - HMAC_Init_ex (ctx, key, key_len, kt, NULL); - - /* make sure we used a big enough key */ - ASSERT (HMAC_size (ctx) <= key_len); -} - -void -hmac_ctx_cleanup(HMAC_CTX *ctx) -{ - HMAC_CTX_cleanup (ctx); -} - -int -hmac_ctx_size (const HMAC_CTX *ctx) -{ - return HMAC_size (ctx); -} - -void -hmac_ctx_reset (HMAC_CTX *ctx) -{ - HMAC_Init_ex (ctx, NULL, 0, NULL, NULL); -} - -void -hmac_ctx_update (HMAC_CTX *ctx, const uint8_t *src, int src_len) -{ - HMAC_Update (ctx, src, src_len); -} - -void -hmac_ctx_final (HMAC_CTX *ctx, uint8_t *dst) -{ - unsigned int in_hmac_len = 0; - - HMAC_Final (ctx, dst, &in_hmac_len); -} - -#endif /* ENABLE_CRYPTO && ENABLE_CRYPTO_OPENSSL */ |