From b0623cc5725f11a23d1d756d61c2ec8bb1bddac2 Mon Sep 17 00:00:00 2001
From: Dmitriy Gerasimov <dm@cifercom.com>
Date: Fri, 12 Jan 2018 17:10:06 +0700
Subject: [PATCH] [*] Common math and memory operations moved to core library

---
 core/common/int-util.h | 249 +++++++++++++++++++++++++++++++++++++++++
 core/common/memwipe.c  | 106 ++++++++++++++++++
 core/common/memwipe.h  |  36 ++++++
 3 files changed, 391 insertions(+)
 create mode 100644 core/common/int-util.h
 create mode 100644 core/common/memwipe.c
 create mode 100644 core/common/memwipe.h

diff --git a/core/common/int-util.h b/core/common/int-util.h
new file mode 100644
index 0000000000..7cec571ad8
--- /dev/null
+++ b/core/common/int-util.h
@@ -0,0 +1,249 @@
+// Copyright (c) 2014-2017, The Monero Project
+// 
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+// 
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+//    conditions and the following disclaimer.
+// 
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+//    of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+// 
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+//    used to endorse or promote products derived from this software without specific
+//    prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+
+#if defined(__ANDROID__)
+#include <byteswap.h>
+#endif
+
+#if defined(__sun) && defined(__SVR4)
+#include <endian.h>
+#endif
+
+#if defined(_MSC_VER)
+#include <stdlib.h>
+
+static inline uint32_t rol32(uint32_t x, int r) {
+  static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers");
+  return _rotl(x, r);
+}
+
+static inline uint64_t rol64(uint64_t x, int r) {
+  return _rotl64(x, r);
+}
+
+#else
+
+static inline uint32_t rol32(uint32_t x, int r) {
+  return (x << (r & 31)) | (x >> (-r & 31));
+}
+
+static inline uint64_t rol64(uint64_t x, int r) {
+  return (x << (r & 63)) | (x >> (-r & 63));
+}
+
+#endif
+
+static inline uint64_t hi_dword(uint64_t val) {
+  return val >> 32;
+}
+
+static inline uint64_t lo_dword(uint64_t val) {
+  return val & 0xFFFFFFFF;
+}
+
+static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) {
+  // multiplier   = ab = a * 2^32 + b
+  // multiplicand = cd = c * 2^32 + d
+  // ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
+  uint64_t a = hi_dword(multiplier);
+  uint64_t b = lo_dword(multiplier);
+  uint64_t c = hi_dword(multiplicand);
+  uint64_t d = lo_dword(multiplicand);
+
+  uint64_t ac = a * c;
+  uint64_t ad = a * d;
+  uint64_t bc = b * c;
+  uint64_t bd = b * d;
+
+  uint64_t adbc = ad + bc;
+  uint64_t adbc_carry = adbc < ad ? 1 : 0;
+
+  // multiplier * multiplicand = product_hi * 2^64 + product_lo
+  uint64_t product_lo = bd + (adbc << 32);
+  uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
+  *product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
+  assert(ac <= *product_hi);
+
+  return product_lo;
+}
+
+static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t* remainder) {
+  dividend |= ((uint64_t)*remainder) << 32;
+  *remainder = dividend % divisor;
+  return dividend / divisor;
+}
+
+// Long division with 2^32 base
+static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t* quotient_hi, uint64_t* quotient_lo) {
+  uint64_t dividend_dwords[4];
+  uint32_t remainder = 0;
+
+  dividend_dwords[3] = hi_dword(dividend_hi);
+  dividend_dwords[2] = lo_dword(dividend_hi);
+  dividend_dwords[1] = hi_dword(dividend_lo);
+  dividend_dwords[0] = lo_dword(dividend_lo);
+
+  *quotient_hi  = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32;
+  *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder);
+  *quotient_lo  = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32;
+  *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder);
+
+  return remainder;
+}
+
+#define IDENT32(x) ((uint32_t) (x))
+#define IDENT64(x) ((uint64_t) (x))
+
+#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \
+  (((uint32_t) (x) & 0x0000ff00) <<  8) | \
+  (((uint32_t) (x) & 0x00ff0000) >>  8) | \
+  (((uint32_t) (x) & 0xff000000) >> 24))
+#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
+  (((uint64_t) (x) & 0x000000000000ff00) << 40) | \
+  (((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
+  (((uint64_t) (x) & 0x00000000ff000000) <<  8) | \
+  (((uint64_t) (x) & 0x000000ff00000000) >>  8) | \
+  (((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
+  (((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
+  (((uint64_t) (x) & 0xff00000000000000) >> 56))
+
+static inline uint32_t ident32(uint32_t x) { return x; }
+static inline uint64_t ident64(uint64_t x) { return x; }
+
+#ifndef __OpenBSD__
+#  if defined(__ANDROID__) && defined(__swap32) && !defined(swap32)
+#      define swap32 __swap32
+#  elif !defined(swap32)
+static inline uint32_t swap32(uint32_t x) {
+  x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
+  return (x << 16) | (x >> 16);
+}
+#  endif
+#  if defined(__ANDROID__) && defined(__swap64) && !defined(swap64)
+#      define swap64 __swap64
+#  elif !defined(swap64)
+static inline uint64_t swap64(uint64_t x) {
+  x = ((x & 0x00ff00ff00ff00ff) <<  8) | ((x & 0xff00ff00ff00ff00) >>  8);
+  x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16);
+  return (x << 32) | (x >> 32);
+}
+#  endif
+#endif /* __OpenBSD__ */
+
+#if defined(__GNUC__)
+#define UNUSED __attribute__((unused))
+#else
+#define UNUSED
+#endif
+static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) { }
+#undef UNUSED
+
+static inline void mem_inplace_swap32(void *mem, size_t n) {
+  size_t i;
+  for (i = 0; i < n; i++) {
+    ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]);
+  }
+}
+static inline void mem_inplace_swap64(void *mem, size_t n) {
+  size_t i;
+  for (i = 0; i < n; i++) {
+    ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]);
+  }
+}
+
+static inline void memcpy_ident32(void *dst, const void *src, size_t n) {
+  memcpy(dst, src, 4 * n);
+}
+static inline void memcpy_ident64(void *dst, const void *src, size_t n) {
+  memcpy(dst, src, 8 * n);
+}
+
+static inline void memcpy_swap32(void *dst, const void *src, size_t n) {
+  size_t i;
+  for (i = 0; i < n; i++) {
+    ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]);
+  }
+}
+static inline void memcpy_swap64(void *dst, const void *src, size_t n) {
+  size_t i;
+  for (i = 0; i < n; i++) {
+    ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]);
+  }
+}
+
+#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
+static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled");
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define SWAP32LE IDENT32
+#define SWAP32BE SWAP32
+#define swap32le ident32
+#define swap32be swap32
+#define mem_inplace_swap32le mem_inplace_ident
+#define mem_inplace_swap32be mem_inplace_swap32
+#define memcpy_swap32le memcpy_ident32
+#define memcpy_swap32be memcpy_swap32
+#define SWAP64LE IDENT64
+#define SWAP64BE SWAP64
+#define swap64le ident64
+#define swap64be swap64
+#define mem_inplace_swap64le mem_inplace_ident
+#define mem_inplace_swap64be mem_inplace_swap64
+#define memcpy_swap64le memcpy_ident64
+#define memcpy_swap64be memcpy_swap64
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define SWAP32BE IDENT32
+#define SWAP32LE SWAP32
+#define swap32be ident32
+#define swap32le swap32
+#define mem_inplace_swap32be mem_inplace_ident
+#define mem_inplace_swap32le mem_inplace_swap32
+#define memcpy_swap32be memcpy_ident32
+#define memcpy_swap32le memcpy_swap32
+#define SWAP64BE IDENT64
+#define SWAP64LE SWAP64
+#define swap64be ident64
+#define swap64le swap64
+#define mem_inplace_swap64be mem_inplace_ident
+#define mem_inplace_swap64le mem_inplace_swap64
+#define memcpy_swap64be memcpy_ident64
+#define memcpy_swap64le memcpy_swap64
+#endif
diff --git a/core/common/memwipe.c b/core/common/memwipe.c
new file mode 100644
index 0000000000..da7e9f3461
--- /dev/null
+++ b/core/common/memwipe.c
@@ -0,0 +1,106 @@
+// Copyright (c) 2017, The Monero Project
+// 
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+// 
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+//    conditions and the following disclaimer.
+// 
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+//    of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+// 
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+//    used to endorse or promote products derived from this software without specific
+//    prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file Copyright (c) 2009-2015 The Bitcoin Core developers
+
+#define __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_EXPLICIT_BZERO
+#include <strings.h>
+#endif
+#include "memwipe.h"
+
+#if defined(_MSC_VER)
+#define SCARECROW \
+    __asm;
+#else
+#define SCARECROW \
+    __asm__ __volatile__("" : : "r"(ptr) : "memory");
+#endif
+
+#ifdef HAVE_MEMSET_S
+
+void *memwipe(void *ptr, size_t n)
+{
+  if (memset_s(ptr, n, 0, n))
+  {
+    abort();
+  }
+  SCARECROW // might as well...
+  return ptr;
+}
+
+#elif defined HAVE_EXPLICIT_BZERO
+
+void *memwipe(void *ptr, size_t n)
+{
+  explicit_bzero(ptr, n);
+  SCARECROW
+  return ptr;
+}
+
+#else
+
+/* The memory_cleanse implementation is taken from Bitcoin */
+
+/* Compilers have a bad habit of removing "superfluous" memset calls that
+ * are trying to zero memory. For example, when memset()ing a buffer and
+ * then free()ing it, the compiler might decide that the memset is
+ * unobservable and thus can be removed.
+ *
+ * Previously we used OpenSSL which tried to stop this by a) implementing
+ * memset in assembly on x86 and b) putting the function in its own file
+ * for other platforms.
+ *
+ * This change removes those tricks in favour of using asm directives to
+ * scare the compiler away. As best as our compiler folks can tell, this is
+ * sufficient and will continue to be so.
+ *
+ * Adam Langley <agl@google.com>
+ * Commit: ad1907fe73334d6c696c8539646c21b11178f20f
+ * BoringSSL (LICENSE: ISC)
+ */
+static void memory_cleanse(void *ptr, size_t len)
+{
+    memset(ptr, 0, len);
+
+    /* As best as we can tell, this is sufficient to break any optimisations that
+       might try to eliminate "superfluous" memsets. If there's an easy way to
+       detect memset_s, it would be better to use that. */
+    SCARECROW
+}
+
+void *memwipe(void *ptr, size_t n)
+{
+  memory_cleanse(ptr, n);
+  SCARECROW
+  return ptr;
+}
+
+#endif
diff --git a/core/common/memwipe.h b/core/common/memwipe.h
new file mode 100644
index 0000000000..46cd131f3d
--- /dev/null
+++ b/core/common/memwipe.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2017, The Monero Project
+// Copyrught (c) 2018, DapCash Project
+// 
+// All rights reserved.
+// 
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+// 
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+//    conditions and the following disclaimer.
+// 
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+//    of conditions and the following disclaimer in the documentation and/or other
+//    materials provided with the distribution.
+// 
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+//    used to endorse or promote products derived from this software without specific
+//    prior written permission.
+// 
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// 
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+#ifndef _MEMWIPE_H_
+#define _MEMWIPE_H_
+
+void *memwipe(void *src, size_t n);
+
+#endif
\ No newline at end of file
-- 
GitLab