"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/openssl_link.c" (7 Sep 2020, 10871 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "openssl_link.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  *
   11  * Portions Copyright (C) Network Associates, Inc.
   12  *
   13  * Permission to use, copy, modify, and/or distribute this software for any
   14  * purpose with or without fee is hereby granted, provided that the above
   15  * copyright notice and this permission notice appear in all copies.
   16  *
   17  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
   18  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
   19  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
   20  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   21  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   22  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
   23  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   24  */
   25 
   26 #ifdef OPENSSL
   27 
   28 #include <config.h>
   29 
   30 #include <isc/entropy.h>
   31 #include <isc/mem.h>
   32 #include <isc/mutex.h>
   33 #include <isc/mutexblock.h>
   34 #include <isc/string.h>
   35 #include <isc/thread.h>
   36 #include <isc/util.h>
   37 
   38 #include <dns/log.h>
   39 
   40 #include <dst/result.h>
   41 
   42 #include "dst_internal.h"
   43 #include "dst_openssl.h"
   44 
   45 #if !defined(OPENSSL_NO_ENGINE)
   46 #include <openssl/engine.h>
   47 #endif
   48 
   49 static RAND_METHOD *rm = NULL;
   50 
   51 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
   52 static isc_mutex_t *locks = NULL;
   53 static int nlocks;
   54 #endif
   55 
   56 #if !defined(OPENSSL_NO_ENGINE)
   57 static ENGINE *e = NULL;
   58 #endif
   59 
   60 static int
   61 entropy_get(unsigned char *buf, int num) {
   62     isc_result_t result;
   63     if (num < 0)
   64         return (-1);
   65     result = dst__entropy_getdata(buf, (unsigned int) num, false);
   66     return (result == ISC_R_SUCCESS ? 1 : -1);
   67 }
   68 
   69 static int
   70 entropy_status(void) {
   71     return (dst__entropy_status() > 32);
   72 }
   73 
   74 static int
   75 entropy_getpseudo(unsigned char *buf, int num) {
   76     isc_result_t result;
   77     if (num < 0)
   78         return (-1);
   79     result = dst__entropy_getdata(buf, (unsigned int) num, true);
   80     return (result == ISC_R_SUCCESS ? 1 : -1);
   81 }
   82 
   83 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
   84 static void
   85 entropy_add(const void *buf, int num, double entropy) {
   86     /*
   87      * Do nothing.  The only call to this provides no useful data anyway.
   88      */
   89     UNUSED(buf);
   90     UNUSED(num);
   91     UNUSED(entropy);
   92 }
   93 #else
   94 static int
   95 entropy_add(const void *buf, int num, double entropy) {
   96     /*
   97      * Do nothing.  The only call to this provides no useful data anyway.
   98      */
   99     UNUSED(buf);
  100     UNUSED(num);
  101     UNUSED(entropy);
  102     return (1);
  103 }
  104 #endif
  105 
  106 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  107 static void
  108 lock_callback(int mode, int type, const char *file, int line) {
  109     UNUSED(file);
  110     UNUSED(line);
  111     if ((mode & CRYPTO_LOCK) != 0)
  112         LOCK(&locks[type]);
  113     else
  114         UNLOCK(&locks[type]);
  115 }
  116 #endif
  117 
  118 #if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(LIBRESSL_VERSION_NUMBER)
  119 static unsigned long
  120 id_callback(void) {
  121     return ((unsigned long)isc_thread_self());
  122 }
  123 #endif
  124 
  125 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  126 
  127 #define FLARG
  128 #define FILELINE
  129 #if ISC_MEM_TRACKLINES
  130 #define FLARG_PASS      , __FILE__, __LINE__
  131 #else
  132 #define FLARG_PASS
  133 #endif
  134 
  135 #else
  136 
  137 #define FLARG           , const char *file, int line
  138 #define FILELINE    , __FILE__, __LINE__
  139 #if ISC_MEM_TRACKLINES
  140 #define FLARG_PASS      , file, line
  141 #else
  142 #define FLARG_PASS
  143 #endif
  144 
  145 #endif
  146 
  147 static void *
  148 mem_alloc(size_t size FLARG) {
  149 #ifdef OPENSSL_LEAKS
  150     void *ptr;
  151 
  152     INSIST(dst__memory_pool != NULL);
  153     ptr = isc__mem_allocate(dst__memory_pool, size FLARG_PASS);
  154     return (ptr);
  155 #else
  156     INSIST(dst__memory_pool != NULL);
  157     return (isc__mem_allocate(dst__memory_pool, size FLARG_PASS));
  158 #endif
  159 }
  160 
  161 static void
  162 mem_free(void *ptr FLARG) {
  163     if (ptr != NULL) {
  164         INSIST(dst__memory_pool != NULL);
  165 
  166         isc__mem_free(dst__memory_pool, ptr FLARG_PASS);
  167     }
  168 }
  169 
  170 static void *
  171 mem_realloc(void *ptr, size_t size FLARG) {
  172 #ifdef OPENSSL_LEAKS
  173     void *rptr;
  174 
  175     INSIST(dst__memory_pool != NULL);
  176     rptr = isc__mem_reallocate(dst__memory_pool, ptr, size FLARG_PASS);
  177     return (rptr);
  178 #else
  179     INSIST(dst__memory_pool != NULL);
  180     return (isc__mem_reallocate(dst__memory_pool, ptr, size FLARG_PASS));
  181 #endif
  182 }
  183 
  184 #if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L
  185 static void
  186 _set_thread_id(CRYPTO_THREADID *id)
  187 {
  188     CRYPTO_THREADID_set_numeric(id, (unsigned long)isc_thread_self());
  189 }
  190 #endif
  191 
  192 isc_result_t
  193 dst__openssl_init(const char *engine) {
  194     isc_result_t result;
  195 #if !defined(OPENSSL_NO_ENGINE)
  196     ENGINE *re;
  197 #else
  198     UNUSED(engine);
  199 #endif
  200 
  201 #ifdef  DNS_CRYPTO_LEAKS
  202     CRYPTO_malloc_debug_init();
  203     CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
  204     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
  205 #endif
  206     CRYPTO_set_mem_functions(mem_alloc, mem_realloc, mem_free);
  207 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  208     nlocks = CRYPTO_num_locks();
  209     locks = mem_alloc(sizeof(isc_mutex_t) * nlocks FILELINE);
  210     if (locks == NULL)
  211         return (ISC_R_NOMEMORY);
  212     result = isc_mutexblock_init(locks, nlocks);
  213     if (result != ISC_R_SUCCESS)
  214         goto cleanup_mutexalloc;
  215     CRYPTO_set_locking_callback(lock_callback);
  216 # if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L
  217     CRYPTO_THREADID_set_callback(_set_thread_id);
  218 # else
  219     CRYPTO_set_id_callback(id_callback);
  220 # endif
  221 
  222     ERR_load_crypto_strings();
  223 #endif
  224 
  225     rm = mem_alloc(sizeof(RAND_METHOD) FILELINE);
  226     if (rm == NULL) {
  227         result = ISC_R_NOMEMORY;
  228         goto cleanup_mutexinit;
  229     }
  230     rm->seed = NULL;
  231     rm->bytes = entropy_get;
  232     rm->cleanup = NULL;
  233     rm->add = entropy_add;
  234     rm->pseudorand = entropy_getpseudo;
  235     rm->status = entropy_status;
  236 
  237 #if !defined(OPENSSL_NO_ENGINE)
  238 #if !defined(CONF_MFLAGS_DEFAULT_SECTION)
  239     OPENSSL_config(NULL);
  240 #else
  241     /*
  242      * OPENSSL_config() can only be called a single time as of
  243      * 1.0.2e so do the steps individually.
  244      */
  245     OPENSSL_load_builtin_modules();
  246     ENGINE_load_builtin_engines();
  247     ERR_clear_error();
  248     CONF_modules_load_file(NULL, NULL,
  249                    CONF_MFLAGS_DEFAULT_SECTION |
  250                    CONF_MFLAGS_IGNORE_MISSING_FILE);
  251 #endif
  252 
  253     if (engine != NULL && *engine == '\0')
  254         engine = NULL;
  255 
  256     if (engine != NULL) {
  257         e = ENGINE_by_id(engine);
  258         if (e == NULL) {
  259             result = DST_R_NOENGINE;
  260             goto cleanup_rm;
  261         }
  262         /* This will init the engine. */
  263         if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
  264             result = DST_R_NOENGINE;
  265             goto cleanup_rm;
  266         }
  267     }
  268 
  269     re = ENGINE_get_default_RAND();
  270     if (re == NULL) {
  271         re = ENGINE_new();
  272         if (re == NULL) {
  273             result = ISC_R_NOMEMORY;
  274             goto cleanup_rm;
  275         }
  276         ENGINE_set_RAND(re, rm);
  277         ENGINE_set_default_RAND(re);
  278         ENGINE_free(re);
  279     } else
  280         ENGINE_finish(re);
  281 #else
  282     RAND_set_rand_method(rm);
  283 #endif /* !defined(OPENSSL_NO_ENGINE) */
  284     return (ISC_R_SUCCESS);
  285 
  286 #if !defined(OPENSSL_NO_ENGINE)
  287  cleanup_rm:
  288     if (e != NULL)
  289         ENGINE_free(e);
  290     e = NULL;
  291     mem_free(rm FILELINE);
  292     rm = NULL;
  293 #endif
  294  cleanup_mutexinit:
  295 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  296     CRYPTO_set_locking_callback(NULL);
  297     DESTROYMUTEXBLOCK(locks, nlocks);
  298  cleanup_mutexalloc:
  299     mem_free(locks FILELINE);
  300     locks = NULL;
  301 #endif
  302     return (result);
  303 }
  304 
  305 void
  306 dst__openssl_destroy(void) {
  307 #if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x10100000L)
  308     OPENSSL_cleanup();
  309     if (rm != NULL) {
  310         mem_free(rm FILELINE);
  311         rm = NULL;
  312     }
  313 #else
  314     /*
  315      * Sequence taken from apps_shutdown() in <apps/apps.h>.
  316      */
  317     if (rm != NULL) {
  318 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
  319         RAND_cleanup();
  320 #endif
  321         mem_free(rm FILELINE);
  322         rm = NULL;
  323     }
  324 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
  325     CONF_modules_free();
  326 #endif
  327     OBJ_cleanup();
  328     EVP_cleanup();
  329 #if !defined(OPENSSL_NO_ENGINE)
  330     if (e != NULL)
  331         ENGINE_free(e);
  332     e = NULL;
  333 #if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER >= 0x00907000L
  334     ENGINE_cleanup();
  335 #endif
  336 #endif
  337 #if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
  338     CRYPTO_cleanup_all_ex_data();
  339 #endif
  340     ERR_clear_error();
  341 #if OPENSSL_VERSION_NUMBER >= 0x10000000L && OPENSSL_VERSION_NUMBER < 0x10100000L
  342     ERR_remove_thread_state(NULL);
  343 #elif OPENSSL_VERSION_NUMBER < 0x10000000L || defined(LIBRESSL_VERSION_NUMBER)
  344     ERR_remove_state(0);
  345 #endif
  346     ERR_free_strings();
  347 
  348 #ifdef  DNS_CRYPTO_LEAKS
  349     CRYPTO_mem_leaks_fp(stderr);
  350 #endif
  351 
  352     if (locks != NULL) {
  353         CRYPTO_set_locking_callback(NULL);
  354         DESTROYMUTEXBLOCK(locks, nlocks);
  355         mem_free(locks FILELINE);
  356         locks = NULL;
  357     }
  358 #endif
  359 }
  360 
  361 static isc_result_t
  362 toresult(isc_result_t fallback) {
  363     isc_result_t result = fallback;
  364     unsigned long err = ERR_peek_error();
  365 #if defined(HAVE_OPENSSL_ECDSA) && \
  366     defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED)
  367     int lib = ERR_GET_LIB(err);
  368 #endif
  369     int reason = ERR_GET_REASON(err);
  370 
  371     switch (reason) {
  372     /*
  373      * ERR_* errors are globally unique; others
  374      * are unique per sublibrary
  375      */
  376     case ERR_R_MALLOC_FAILURE:
  377         result = ISC_R_NOMEMORY;
  378         break;
  379     default:
  380 #if defined(HAVE_OPENSSL_ECDSA) && \
  381     defined(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED)
  382         if (lib == ERR_R_ECDSA_LIB &&
  383             reason == ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED) {
  384             result = ISC_R_NOENTROPY;
  385             break;
  386         }
  387 #endif
  388         break;
  389     }
  390 
  391     return (result);
  392 }
  393 
  394 isc_result_t
  395 dst__openssl_toresult(isc_result_t fallback) {
  396     isc_result_t result;
  397 
  398     result = toresult(fallback);
  399 
  400     ERR_clear_error();
  401     return (result);
  402 }
  403 
  404 isc_result_t
  405 dst__openssl_toresult2(const char *funcname, isc_result_t fallback) {
  406     return (dst__openssl_toresult3(DNS_LOGCATEGORY_GENERAL,
  407                        funcname, fallback));
  408 }
  409 
  410 isc_result_t
  411 dst__openssl_toresult3(isc_logcategory_t *category,
  412                const char *funcname, isc_result_t fallback) {
  413     isc_result_t result;
  414     unsigned long err;
  415     const char *file, *data;
  416     int line, flags;
  417     char buf[256];
  418 
  419     result = toresult(fallback);
  420 
  421     isc_log_write(dns_lctx, category,
  422               DNS_LOGMODULE_CRYPTO, ISC_LOG_WARNING,
  423               "%s failed (%s)", funcname,
  424               isc_result_totext(result));
  425 
  426     if (result == ISC_R_NOMEMORY)
  427         goto done;
  428 
  429     for (;;) {
  430         err = ERR_get_error_line_data(&file, &line, &data, &flags);
  431         if (err == 0U)
  432             goto done;
  433         ERR_error_string_n(err, buf, sizeof(buf));
  434         isc_log_write(dns_lctx, category,
  435                   DNS_LOGMODULE_CRYPTO, ISC_LOG_INFO,
  436                   "%s:%s:%d:%s", buf, file, line,
  437                   ((flags & ERR_TXT_STRING) != 0) ? data : "");
  438     }
  439 
  440     done:
  441     ERR_clear_error();
  442     return (result);
  443 }
  444 
  445 #if !defined(OPENSSL_NO_ENGINE)
  446 ENGINE *
  447 dst__openssl_getengine(const char *engine) {
  448 
  449     if (engine == NULL)
  450         return (NULL);
  451     if (e == NULL)
  452         return (NULL);
  453     if (strcmp(engine, ENGINE_get_id(e)) == 0)
  454         return (e);
  455     return (NULL);
  456 }
  457 #endif
  458 
  459 #else /* OPENSSL */
  460 
  461 #include <isc/util.h>
  462 
  463 EMPTY_TRANSLATION_UNIT
  464 
  465 #endif /* OPENSSL */
  466 /*! \file */