tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

crypto_util.c (4103B)


      1 /* Copyright (c) 2001, Matej Pfajfar.
      2 * Copyright (c) 2001-2004, Roger Dingledine.
      3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      5 /* See LICENSE for licensing information */
      6 
      7 /**
      8 * \file crypto_util.c
      9 *
     10 * \brief Common cryptographic utilities.
     11 **/
     12 
     13 #include "lib/crypt_ops/crypto_util.h"
     14 #include "lib/cc/compat_compiler.h"
     15 
     16 #include <string.h>
     17 
     18 #ifdef _WIN32
     19 #include <winsock2.h>
     20 #include <windows.h>
     21 #include <wincrypt.h>
     22 #endif /* defined(_WIN32) */
     23 
     24 #include <stdlib.h>
     25 
     26 #ifdef ENABLE_OPENSSL
     27 DISABLE_GCC_WARNING("-Wredundant-decls")
     28 #include <openssl/err.h>
     29 #include <openssl/crypto.h>
     30 ENABLE_GCC_WARNING("-Wredundant-decls")
     31 #endif /* defined(ENABLE_OPENSSL) */
     32 
     33 #include "lib/log/log.h"
     34 #include "lib/log/util_bug.h"
     35 
     36 /**
     37 * Destroy the <b>sz</b> bytes of data stored at <b>mem</b>, setting them to
     38 * the value <b>byte</b>.
     39 * If <b>mem</b> is NULL or <b>sz</b> is zero, nothing happens.
     40 *
     41 * This function is preferable to memset, since many compilers will happily
     42 * optimize out memset() when they can convince themselves that the data being
     43 * cleared will never be read.
     44 *
     45 * Right now, our convention is to use this function when we are wiping data
     46 * that's about to become inaccessible, such as stack buffers that are about
     47 * to go out of scope or structures that are about to get freed.  (In
     48 * practice, it appears that the compilers we're currently using will optimize
     49 * out the memset()s for stack-allocated buffers, but not those for
     50 * about-to-be-freed structures. That could change, though, so we're being
     51 * wary.)  If there are live reads for the data, then you can just use
     52 * memset().
     53 */
     54 void
     55 memwipe(void *mem, uint8_t byte, size_t sz)
     56 {
     57  if (sz == 0) {
     58    return;
     59  }
     60  /* If sz is nonzero, then mem must not be NULL. */
     61  tor_assert(mem != NULL);
     62 
     63  /* Data this large is likely to be an underflow. */
     64  tor_assert(sz < SIZE_T_CEILING);
     65 
     66  /* Because whole-program-optimization exists, we may not be able to just
     67   * have this function call "memset".  A smart compiler could inline it, then
     68   * eliminate dead memsets, and declare itself to be clever. */
     69 
     70 #if defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY)
     71  /* Here's what you do on windows. */
     72  SecureZeroMemory(mem,sz);
     73 #elif defined(HAVE_RTLSECUREZEROMEMORY)
     74  RtlSecureZeroMemory(mem,sz);
     75 #elif defined(HAVE_EXPLICIT_BZERO)
     76  /* The BSDs provide this. */
     77  explicit_bzero(mem, sz);
     78 #elif defined(HAVE_MEMSET_S)
     79  /* This is in the C99 standard. */
     80  memset_s(mem, sz, 0, sz);
     81 #elif defined(ENABLE_OPENSSL)
     82  /* This is a slow and ugly function from OpenSSL that fills 'mem' with junk
     83   * based on the pointer value, then uses that junk to update a global
     84   * variable.  It's an elaborate ruse to trick the compiler into not
     85   * optimizing out the "wipe this memory" code.  Read it if you like zany
     86   * programming tricks! In later versions of Tor, we should look for better
     87   * not-optimized-out memory wiping stuff...
     88   *
     89   * ...or maybe not.  In practice, there are pure-asm implementations of
     90   * OPENSSL_cleanse() on most platforms, which ought to do the job.
     91   **/
     92 
     93  OPENSSL_cleanse(mem, sz);
     94 #else
     95  memset(mem, 0, sz);
     96  asm volatile("" ::: "memory");
     97 #endif /* defined(SecureZeroMemory) || defined(HAVE_SECUREZEROMEMORY) || ... */
     98 
     99  /* Just in case some caller of memwipe() is relying on getting a buffer
    100   * filled with a particular value, fill the buffer.
    101   *
    102   * If this function gets inlined, this memset might get eliminated, but
    103   * that's okay: We only care about this particular memset in the case where
    104   * the caller should have been using memset(), and the memset() wouldn't get
    105   * eliminated.  In other words, this is here so that we won't break anything
    106   * if somebody accidentally calls memwipe() instead of memset().
    107   **/
    108  memset(mem, byte, sz);
    109 }
    110 
    111 /**
    112 * Securely all memory in <b>str</b>, then free it.
    113 *
    114 * As tor_free(), tolerates null pointers.
    115 **/
    116 void
    117 tor_str_wipe_and_free_(char *str)
    118 {
    119  if (!str)
    120    return;
    121  memwipe(str, 0, strlen(str));
    122  tor_free_(str);
    123 }