Hello,
while playing with compiler optimization and reading the norm to write a
nice wipe_memory(char* mem, size_t len) function, I stumbled upon issue
23[1]. It seems that libgcrypt can now provide secure memory to
application running as non-root. What about using this in libotr instead
of a custom implementation?

I pushed a patch on the `secmem` branch, that you can find attached to
this mail.

Cheers,

1. https://bugs.otr.im/issues/23
From 576a33bed3d89e61d02a44795aa5c191de9fa529 Mon Sep 17 00:00:00 2001
From: jvoisin <julien.voi...@dustri.org>
Date: Sun, 12 Apr 2015 00:34:35 +0200
Subject: [PATCH] Use libgcrypt secure memory

---
 src/mem.c   | 138 +++---------------------------------------------------------
 src/mem.h   |   2 -
 src/proto.c |   4 +-
 3 files changed, 7 insertions(+), 137 deletions(-)

diff --git a/src/mem.c b/src/mem.c
index f703606..6b1b927 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -20,24 +20,13 @@
 
 /* Memory allocation routines for libgcrypt.  All of the session key
  * information gets allocated through here, so we can wipe it out when
- * it's free()d.  We don't use the built-in secmem functions of
- * libgcrypt because you need to declare a fixed amount of it when you
- * start up.
+ * it's free()d.  We use the built-in secmem functions of
+ * libgcrypt because since Linux 2.6.9, you don't need to be root anymore
+ * to use use mlock and other goodies. And if you're not running Linux,
+ * libgcrypt will do its best to make the memory "safe" anyway.
  *
- * Because "secure" and "insecure" allocations from libgcrypt will get
- * handled the same way (since we're not going to be running as root,
- * and so won't actually have pinned memory), pretend all allocated
- * memory (but just from libgcrypt) is requested secure, and wipe it on
- * free(). */
-
-/* Uncomment the following to add a check that our free() and realloc() only
- * get called on things returned from our malloc(). */
-/* #define OTRL_MEM_MAGIC 0x31415926 */
+ */
 
-/* system headers */
-#ifdef OTRL_MEM_MAGIC
-#include <stdio.h>
-#endif
 #include <stdlib.h>
 
 /* libgcrypt headers */
@@ -46,123 +35,6 @@
 /* libotr headers */
 #include "mem.h"
 
-static size_t header_size;
-
-static void *otrl_mem_malloc(size_t n)
-{
-    void *p;
-    size_t new_n = n;
-    new_n += header_size;
-
-    /* Check for overflow attack */
-    if (new_n < n) return NULL;
-    p = malloc(new_n);
-    if (p == NULL) return NULL;
-
-    ((size_t *)p)[0] = new_n;  /* Includes header size */
-#ifdef OTRL_MEM_MAGIC
-    ((size_t *)p)[1] = OTRL_MEM_MAGIC;
-#endif
-
-    return (void *)((char *)p + header_size);
-}
-
-static int otrl_mem_is_secure(const void *p)
-{
-    return 1;
-}
-
-static void otrl_mem_free(void *p)
-{
-    void *real_p = (void *)((char *)p - header_size);
-    size_t n = ((size_t *)real_p)[0];
-#ifdef OTRL_MEM_MAGIC
-    if (((size_t *)real_p)[1] != OTRL_MEM_MAGIC) {
-	fprintf(stderr, "Illegal free!\n");
-	return;
-    }
-#endif
-
-    /* Wipe the memory (in the same way the built-in deallocator in
-     * libgcrypt would) */
-    memset(real_p, 0xff, n);
-    memset(real_p, 0xaa, n);
-    memset(real_p, 0x55, n);
-    memset(real_p, 0x00, n);
-
-    free(real_p);
-}
-
-static void *otrl_mem_realloc(void *p, size_t n)
-{
-    if (p == NULL) {
-	return otrl_mem_malloc(n);
-    } else if (n == 0) {
-	otrl_mem_free(p);
-	return NULL;
-    } else {
-	void *real_p = (void *)((char *)p - header_size);
-	void *new_p;
-	size_t old_n = ((size_t *)real_p)[0];
-#ifdef OTRL_MEM_MAGIC
-	size_t magic = ((size_t *)real_p)[1];
-#endif
-	size_t new_n = n;
-	new_n += header_size;
-
-	/* Check for overflow attack */
-	if (new_n < n) return NULL;
-
-#ifdef OTRL_MEM_MAGIC
-	if (magic != OTRL_MEM_MAGIC) {
-	    fprintf(stderr, "Illegal realloc!\n");
-	    return NULL;
-	}
-#endif
-
-	if (new_n < old_n) {
-	    /* Overwrite the space we're about to stop using */
-	    void *p = (void *)((char *)real_p + new_n);
-	    size_t excess = old_n - new_n;
-	    memset(p, 0xff, excess);
-	    memset(p, 0xaa, excess);
-	    memset(p, 0x55, excess);
-	    memset(p, 0x00, excess);
-
-	    /* We don't actually need to realloc() */
-	    new_p = real_p;
-	} else {
-	    new_p = realloc(real_p, new_n);
-	    if (new_p == NULL) return NULL;
-	}
-
-	((size_t *)new_p)[0] = new_n;  /* Includes header size */
-	return (void *)((char *)new_p + header_size);
-    }
-}
-
-void otrl_mem_init(void)
-{
-    header_size = 8;
-#ifdef OTRL_MEM_MAGIC
-    if (header_size < 2*sizeof(size_t)) {
-	header_size = 2*sizeof(size_t);
-    }
-#else
-    if (header_size < sizeof(size_t)) {
-	header_size = sizeof(size_t);
-    }
-#endif
-
-    gcry_set_allocation_handler(
-	    otrl_mem_malloc,
-	    otrl_mem_malloc,
-	    otrl_mem_is_secure,
-	    otrl_mem_realloc,
-	    otrl_mem_free
-	);
-}
-
 /* Compare two memory blocks in time dependent on the length of the
  * blocks, but not their contents.  Returns 1 if they differ, 0 if they
  * are the same. */
diff --git a/src/mem.h b/src/mem.h
index 0601200..864ba1d 100644
--- a/src/mem.h
+++ b/src/mem.h
@@ -23,8 +23,6 @@
 
 #include <stdlib.h>
 
-void otrl_mem_init(void);
-
 /* Compare two memory blocks in time dependent on the length of the
  * blocks, but not their contents.  Returns 1 if they differ, 0 if they
  * are the same. */
diff --git a/src/proto.c b/src/proto.c
index f3fb10c..817e2fa 100644
--- a/src/proto.c
+++ b/src/proto.c
@@ -70,8 +70,8 @@ gcry_error_t otrl_init(unsigned int ver_major, unsigned int ver_minor,
 	otrl_api_version = api_version;
     }
 
-    /* Initialize the memory module */
-    otrl_mem_init();
+    /* Initialize 32k of secure memory */
+	gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
 
     /* Initialize the DH module */
     otrl_dh_init();
-- 
2.1.0

_______________________________________________
OTR-dev mailing list
OTR-dev@lists.cypherpunks.ca
http://lists.cypherpunks.ca/mailman/listinfo/otr-dev

Reply via email to