summary refs log tree commit diff stats
path: root/libotr/libgcrypt-1.8.7/src/stdmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'libotr/libgcrypt-1.8.7/src/stdmem.c')
-rw-r--r--libotr/libgcrypt-1.8.7/src/stdmem.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/libotr/libgcrypt-1.8.7/src/stdmem.c b/libotr/libgcrypt-1.8.7/src/stdmem.c
new file mode 100644
index 0000000..cbda8d8
--- /dev/null
+++ b/libotr/libgcrypt-1.8.7/src/stdmem.c
@@ -0,0 +1,242 @@
+/* stdmem.c  -	private memory allocator
+ * Copyright (C) 1998, 2000, 2002, 2005, 2008 Free Software Foundation, Inc.
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Description of the layered memory management in Libgcrypt:
+ *
+ *                                  [User]
+ *                                    |
+ *                                    |
+ *                                   \ /
+ *                   global.c: [MM entrance points]   -----> [user callbacks]
+ *                               |          |
+ *                               |          |
+ *                              \ /        \ /
+ *
+ *      stdmem.c: [non-secure handlers] [secure handlers]
+ *
+ *                               |         |
+ *                               |         |
+ *                              \ /       \ /
+ *
+ *                  stdmem.c: [ memory guard ]
+ *
+ *                               |         |
+ *                               |         |
+ *                              \ /       \ /
+ *
+ *           libc: [ MM functions ]     secmem.c: [ secure MM functions]
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "stdmem.h"
+#include "secmem.h"
+
+
+
+#define MAGIC_NOR_BYTE 0x55
+#define MAGIC_SEC_BYTE 0xcc
+#define MAGIC_END_BYTE 0xaa
+
+#if SIZEOF_UNSIGNED_LONG == 8
+#define EXTRA_ALIGN 4
+#else
+#define EXTRA_ALIGN 0
+#endif
+
+
+static int use_m_guard = 0;
+
+/****************
+ * Warning: Never use this function after any of the functions
+ * here have been used.
+ */
+void
+_gcry_private_enable_m_guard (void)
+{
+  use_m_guard = 1;
+}
+
+
+/*
+ * Allocate memory of size n.
+ * Return NULL if we are out of memory.
+ */
+void *
+_gcry_private_malloc (size_t n)
+{
+  if (!n)
+    {
+      gpg_err_set_errno (EINVAL);
+      return NULL; /* Allocating 0 bytes is undefined - we better return
+                      an error to detect such coding errors.  */
+    }
+
+  if (use_m_guard)
+    {
+      char *p;
+
+      if ( !(p = malloc (n + EXTRA_ALIGN+5)) )
+        return NULL;
+      ((byte*)p)[EXTRA_ALIGN+0] = n;
+      ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
+      ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
+      ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
+      p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
+      return p+EXTRA_ALIGN+4;
+    }
+  else
+    {
+      return malloc( n );
+    }
+}
+
+
+/*
+ * Allocate memory of size N from the secure memory pool.  Return NULL
+ * if we are out of memory.  XHINT tells the allocator that the caller
+ * used an xmalloc style call.
+ */
+void *
+_gcry_private_malloc_secure (size_t n, int xhint)
+{
+  if (!n)
+    {
+      gpg_err_set_errno (EINVAL);
+      return NULL; /* Allocating 0 bytes is undefined - better return an
+                      error to detect such coding errors.  */
+    }
+
+  if (use_m_guard)
+    {
+      char *p;
+
+      if (!(p = _gcry_secmem_malloc (n + EXTRA_ALIGN + 5, xhint)))
+        return NULL;
+      ((byte*)p)[EXTRA_ALIGN+0] = n;
+      ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
+      ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
+      ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
+      p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
+      return p+EXTRA_ALIGN+4;
+    }
+  else
+    {
+      return _gcry_secmem_malloc (n, xhint);
+    }
+}
+
+
+/*
+ * Realloc and clear the old space.  XHINT tells the allocator that
+ * the caller used an xmalloc style call.  Returns NULL if there is
+ * not enough memory.
+ */
+void *
+_gcry_private_realloc (void *a, size_t n, int xhint)
+{
+  if (use_m_guard)
+    {
+      unsigned char *p = a;
+      char *b;
+      size_t len;
+
+      if (!a)
+        return _gcry_private_malloc(n);
+
+      _gcry_private_check_heap(p);
+      len  = p[-4];
+      len |= p[-3] << 8;
+      len |= p[-2] << 16;
+      if( len >= n ) /* We don't shrink for now. */
+        return a;
+      if (p[-1] == MAGIC_SEC_BYTE)
+        b = _gcry_private_malloc_secure (n, xhint);
+      else
+        b = _gcry_private_malloc(n);
+      if (!b)
+        return NULL;
+      memcpy (b, a, len);
+      memset (b+len, 0, n-len);
+      _gcry_private_free (p);
+      return b;
+    }
+  else if ( _gcry_private_is_secure(a) )
+    {
+      return _gcry_secmem_realloc (a, n, xhint);
+    }
+  else
+    {
+      return realloc( a, n );
+    }
+}
+
+
+void
+_gcry_private_check_heap (const void *a)
+{
+  if (use_m_guard)
+    {
+      const byte *p = a;
+      size_t len;
+
+      if (!p)
+        return;
+
+      if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
+        _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
+      len  = p[-4];
+      len |= p[-3] << 8;
+      len |= p[-2] << 16;
+      if ( p[len] != MAGIC_END_BYTE )
+        _gcry_log_fatal ("memory at %p corrupted (overflow=%02x)\n", p, p[-1]);
+    }
+}
+
+
+/*
+ * Free a memory block allocated by this or the secmem module
+ */
+void
+_gcry_private_free (void *a)
+{
+  unsigned char *p = a;
+
+  if (!p)
+    return;
+  if (use_m_guard )
+    {
+      _gcry_private_check_heap(p);
+      if (! _gcry_secmem_free (p - EXTRA_ALIGN - 4))
+        {
+          free (p - EXTRA_ALIGN - 4);
+	}
+    }
+  else if (!_gcry_secmem_free (p))
+    {
+      free(p);
+    }
+}