[gcr] gcr: Expose secure memory API
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcr] gcr: Expose secure memory API
- Date: Mon, 27 Feb 2012 13:32:39 +0000 (UTC)
commit a9e9199acaec4c0af75758cec82bd36612f431ef
Author: Stef Walter <stefw gnome org>
Date: Fri Feb 10 17:02:46 2012 +0100
gcr: Expose secure memory API
* Add gcr_secure_memory_new() and gcr_secure_memory_free()
and friends.
* Exposed so that we can implement secure entry widget in
gnome-shell
docs/reference/gcr/gcr-docs.sgml | 1 +
docs/reference/gcr/gcr-sections.txt | 13 ++
gcr/Makefile.am | 2 +
gcr/gcr-base.h | 1 +
gcr/gcr-base.symbols | 9 ++
gcr/gcr-secure-memory.c | 247 +++++++++++++++++++++++++++++++++++
gcr/gcr-secure-memory.h | 59 +++++++++
gcr/tests/Makefile.am | 1 +
gcr/tests/test-secure-memory.c | 149 +++++++++++++++++++++
9 files changed, 482 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-docs.sgml b/docs/reference/gcr/gcr-docs.sgml
index 9ba537d..8756344 100644
--- a/docs/reference/gcr/gcr-docs.sgml
+++ b/docs/reference/gcr/gcr-docs.sgml
@@ -68,6 +68,7 @@
<xi:include href="xml/gcr-library.xml"/>
<xi:include href="xml/gcr-fingerprint.xml"/>
<xi:include href="xml/gcr-secret-exchange.xml"/>
+ <xi:include href="xml/gcr-secure-memory.xml"/>
<xi:include href="xml/gcr-secure-entry-buffer.xml"/>
</part>
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 6b7f4c0..de8b840 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -663,6 +663,19 @@ GcrSecureEntryBufferPrivate
</SECTION>
<SECTION>
+<FILE>gcr-secure-memory</FILE>
+gcr_secure_memory_new
+gcr_secure_memory_alloc
+gcr_secure_memory_try_alloc
+gcr_secure_memory_realloc
+gcr_secure_memory_try_realloc
+gcr_secure_memory_strdup
+gcr_secure_memory_strfree
+gcr_secure_memory_free
+gcr_secure_memory_is_secure
+</SECTION>
+
+<SECTION>
<FILE>gcr-private</FILE>
<SUBSECTION Private>
GCR_GNUPG_COLLECTION
diff --git a/gcr/Makefile.am b/gcr/Makefile.am
index adda387..7f7528c 100644
--- a/gcr/Makefile.am
+++ b/gcr/Makefile.am
@@ -32,6 +32,7 @@ HEADER_BASE_FILES = \
gcr-pkcs11-certificate.h \
gcr-prompt.h \
gcr-secret-exchange.h \
+ gcr-secure-memory.h \
gcr-simple-certificate.h \
gcr-system-prompt.h \
gcr-system-prompter.h \
@@ -139,6 +140,7 @@ libgcr_base_ GCR_MAJOR@_la_SOURCES = \
gcr-prompt.c gcr-prompt.h \
gcr-record.c gcr-record.h \
gcr-secret-exchange.c gcr-secret-exchange.h \
+ gcr-secure-memory.c gcr-secure-memory.h \
gcr-simple-certificate.c gcr-simple-certificate.h \
gcr-simple-collection.c gcr-simple-collection.h \
gcr-single-collection.c gcr-single-collection.h \
diff --git a/gcr/gcr-base.h b/gcr/gcr-base.h
index c52a747..ddaa6f3 100644
--- a/gcr/gcr-base.h
+++ b/gcr/gcr-base.h
@@ -48,6 +48,7 @@
#include <gcr/gcr-pkcs11-certificate.h>
#include <gcr/gcr-prompt.h>
#include <gcr/gcr-secret-exchange.h>
+#include <gcr/gcr-secure-memory.h>
#include <gcr/gcr-simple-certificate.h>
#include <gcr/gcr-simple-collection.h>
#include <gcr/gcr-system-prompt.h>
diff --git a/gcr/gcr-base.symbols b/gcr/gcr-base.symbols
index efb4f27..69908c4 100644
--- a/gcr/gcr-base.symbols
+++ b/gcr/gcr-base.symbols
@@ -191,6 +191,15 @@ gcr_secret_exchange_get_type
gcr_secret_exchange_new
gcr_secret_exchange_receive
gcr_secret_exchange_send
+gcr_secure_memory_alloc
+gcr_secure_memory_free
+gcr_secure_memory_is_secure
+gcr_secure_memory_new
+gcr_secure_memory_realloc
+gcr_secure_memory_strdup
+gcr_secure_memory_strfree
+gcr_secure_memory_try_alloc
+gcr_secure_memory_try_realloc
gcr_simple_certificate_get_type
gcr_simple_certificate_new
gcr_simple_certificate_new_static
diff --git a/gcr/gcr-secure-memory.c b/gcr/gcr-secure-memory.c
new file mode 100644
index 0000000..7a1e99d
--- /dev/null
+++ b/gcr/gcr-secure-memory.c
@@ -0,0 +1,247 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gcr-secure-memory.c - library for allocating memory that is non-pageable
+
+ Copyright (C) 2007 Stefan Walter
+ Copyright (C) 2012 Red Hat Inc.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stefw gnome org>
+*/
+
+#include "config.h"
+
+#include "gcr-secure-memory.h"
+
+#include "egg/egg-secure-memory.h"
+
+#include <glib.h>
+
+#include <string.h>
+
+/**
+ * SECTION:gcr-secure-memory
+ * @title: Non-pageable Memory
+ * @short_description: Secure non-pageable memory
+ *
+ * Normal allocated memory can be paged to disk at the whim of the operating
+ * system. This can be a problem for sensitive information like passwords, keys
+ * and secrets.
+ *
+ * The Gcr library holds passwords and keys in non-pageable, or locked memory.
+ * This is only possible if the OS contains support for it.
+ *
+ * These functions allow applications to use secure memory to hold passwords
+ * and other sensitive information.
+ */
+
+/**
+ * gcr_secure_memory_new: (skip)
+ * @type: C type of the objects to allocate
+ * @n_objects: number of objects to allocate
+ *
+ * Allocate objects in non-pageable memory.
+ *
+ * Returns: (transfer full): the new block of memory
+ **/
+
+/**
+ * gcr_secure_memory_alloc: (skip)
+ * @size: The new desired size of the memory block.
+ *
+ * Allocate a block of non-pageable memory.
+ *
+ * If non-pageable memory cannot be allocated then normal memory will be
+ * returned.
+ *
+ * Return value: (transfer full): new memory block which should be freed
+ * with gcr_secure_memory_free()
+ **/
+gpointer
+gcr_secure_memory_alloc (gsize size)
+{
+ gpointer memory;
+
+ /* Try to allocate secure memory */
+ memory = egg_secure_alloc_full ("gcr-secure-memory", size,
+ EGG_SECURE_USE_FALLBACK);
+
+ /* Our fallback will always allocate */
+ g_assert (memory != NULL);
+
+ return memory;
+}
+
+/**
+ * gcr_secure_memory_try_alloc: (skip)
+ * @size: new desired size of the memory block
+ *
+ * Allocate a block of non-pageable memory.
+ *
+ * If non-pageable memory cannot be allocated, then %NULL is returned.
+ *
+ * Return value: (transfer full): new block, or %NULL if memory cannot be
+ * allocated; memory block should be freed with gcr_secure_memory_free()
+ */
+gpointer
+gcr_secure_memory_try_alloc (gsize size)
+{
+ return egg_secure_alloc_full ("gcr-secure-memory", size, 0);
+}
+
+/**
+ * gcr_secure_memory_realloc: (skip)
+ * @memory: (allow-none): pointer to reallocate or %NULL to allocate a new block
+ * @size: new desired size of the memory block, or 0 to free the memory
+ *
+ * Reallocate a block of non-pageable memory.
+ *
+ * Glib memory is also reallocated correctly. If called with a null pointer,
+ * then a new block of memory is allocated. If called with a zero size,
+ * then the block of memory is freed.
+ *
+ * If non-pageable memory cannot be allocated then normal memory will be
+ * returned.
+ *
+ * Return value: (transfer full): new block, or %NULL if the block was
+ * freed; memory block should be freed with gcr_secure_memory_free()
+ */
+gpointer
+gcr_secure_memory_realloc (gpointer memory,
+ gsize size)
+{
+ gpointer new_memory;
+
+ if (!memory) {
+ return gcr_secure_memory_alloc (size);
+ } else if (!size) {
+ gcr_secure_memory_free (memory);
+ return NULL;
+ } else if (!egg_secure_check (memory)) {
+ return g_realloc (memory, size);
+ }
+
+ /* First try and ask secure memory to reallocate */
+ new_memory = egg_secure_realloc_full ("gcr-secure-memory", memory,
+ size, EGG_SECURE_USE_FALLBACK);
+
+ g_assert (new_memory != NULL);
+
+ return new_memory;
+}
+
+/**
+ * gcr_secure_memory_try_realloc: (skip)
+ * @memory: (allow-none): pointer to reallocate or %NULL to allocate a new block
+ * @size: new desired size of the memory block
+ *
+ * Reallocate a block of non-pageable memory.
+ *
+ * Glib memory is also reallocated correctly when passed to this function.
+ * If called with a null pointer, then a new block of memory is allocated.
+ * If called with a zero size, then the block of memory is freed.
+ *
+ * If memory cannot be allocated, %NULL is returned and the original block
+ * of memory remains intact.
+ *
+ * Return value: (transfer full): the new block, or %NULL if memory cannot be
+ * allocated; the memory block should be freed with gcr_secure_memory_free()
+ */
+gpointer
+gcr_secure_memory_try_realloc (gpointer memory,
+ gsize size)
+{
+ gpointer new_memory;
+
+ if (!memory) {
+ return gcr_secure_memory_try_alloc (size);
+ } else if (!size) {
+ gcr_secure_memory_free (memory);
+ return NULL;
+ } else if (!egg_secure_check (memory)) {
+ return g_try_realloc (memory, size);
+ }
+
+ /* First try and ask secure memory to reallocate */
+ new_memory = egg_secure_realloc_full ("gcr-secure-memory", memory,
+ size, 0);
+
+ g_assert (new_memory != NULL);
+
+ return new_memory;
+}
+
+/**
+ * gcr_secure_memory_free: (skip)
+ * @memory: (allow-none): pointer to the beginning of the block of memory to free
+ *
+ * Free a block of non-pageable memory.
+ *
+ * Glib memory is also freed correctly when passed to this function. If called
+ * with a %NULL pointer then no action is taken.
+ */
+void
+gcr_secure_memory_free (gpointer memory)
+{
+ if (!memory)
+ return;
+ egg_secure_free_full (memory, EGG_SECURE_USE_FALLBACK);
+}
+
+/**
+ * gcr_secure_memory_is_secure: (skip)
+ * @memory: pointer to check
+ *
+ * Check if a pointer is in non-pageable memory allocated by.
+ *
+ * Returns: whether the memory is secure non-pageable memory allocated by the
+ * Gcr library or not
+ */
+gboolean
+gcr_secure_memory_is_secure (gpointer memory)
+{
+ return egg_secure_check (memory) ? TRUE : FALSE;
+}
+
+/**
+ * gcr_secure_memory_strdup: (skip)
+ * @string: (allow-none): null terminated string to copy
+ *
+ * Copy a string into non-pageable memory. If the input string is %NULL, then
+ * %NULL will be returned.
+ *
+ * Returns: copied string, should be freed with gcr_secure_memory_free()
+ */
+gchar *
+gcr_secure_memory_strdup (const gchar* string)
+{
+ return egg_secure_strdup_full ("gcr-secure-memory", string,
+ EGG_SECURE_USE_FALLBACK);
+}
+
+/**
+ * gcr_secure_memory_strfree: (skip)
+ * @string: (allow-none): null terminated string to fere
+ *
+ * Free a string, whether securely allocated using these functions or not.
+ * This will also clear out the contents of the string so they do not
+ * remain in memory.
+ */
+void
+gcr_secure_memory_strfree (gchar *string)
+{
+ egg_secure_strfree (string);
+}
diff --git a/gcr/gcr-secure-memory.h b/gcr/gcr-secure-memory.h
new file mode 100644
index 0000000..f41f972
--- /dev/null
+++ b/gcr/gcr-secure-memory.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* gcr-secure-memory.h - library for allocating memory that is non-pageable
+
+ Copyright (C) 2007 Stefan Walter
+ Copyright (C) 2012 Red Hat Inc.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stefw gnome org>
+*/
+
+#if !defined (__GCR_INSIDE_HEADER__) && !defined (GCR_COMPILATION)
+#error "Only <gcr/gcr.h> or <gcr/gcr-base.h> can be included directly."
+#endif
+
+#ifndef GCR_SECURE_MEMORY_H
+#define GCR_SECURE_MEMORY_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define gcr_secure_memory_new(type, n_objects) \
+ ((type *)(gcr_secure_memory_alloc (sizeof (type) * (n_objects))))
+
+gpointer gcr_secure_memory_alloc (gsize size);
+
+gpointer gcr_secure_memory_try_alloc (gsize size);
+
+gpointer gcr_secure_memory_realloc (gpointer memory,
+ gsize size);
+
+gpointer gcr_secure_memory_try_realloc (gpointer memory,
+ gulong size);
+
+void gcr_secure_memory_free (gpointer memory);
+
+gboolean gcr_secure_memory_is_secure (gpointer memory);
+
+gchar * gcr_secure_memory_strdup (const gchar *string);
+
+void gcr_secure_memory_strfree (gchar *string);
+
+G_END_DECLS
+
+#endif /* GCR_SECURE_MEMORY_H */
diff --git a/gcr/tests/Makefile.am b/gcr/tests/Makefile.am
index 1a8d6cd..2f87b54 100644
--- a/gcr/tests/Makefile.am
+++ b/gcr/tests/Makefile.am
@@ -31,6 +31,7 @@ TEST_PROGS = \
test-pkcs11-certificate \
test-openpgp \
test-openssh \
+ test-secure-memory \
test-trust \
test-parser \
test-record \
diff --git a/gcr/tests/test-secure-memory.c b/gcr/tests/test-secure-memory.c
new file mode 100644
index 0000000..12fa35a
--- /dev/null
+++ b/gcr/tests/test-secure-memory.c
@@ -0,0 +1,149 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-memory.c: Test memory allocation functionality
+
+ Copyright (C) 2007 Stefan Walter
+ Copyright (C) 2012 Red Hat Inc.
+
+ The Gnome Keyring Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The Gnome Keyring Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+ Author: Stef Walter <stefw gnome org>
+*/
+
+#include "config.h"
+
+#include "gcr/gcr-secure-memory.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define IS_ZERO -1
+
+static int
+find_non_zero (gpointer mem, gsize len)
+{
+ guchar *b, *e;
+ gsize sz = 0;
+ for (b = (guchar*)mem, e = ((guchar*)mem) + len; b != e; ++b, ++sz) {
+ if (*b != 0x00)
+ return (int)sz;
+ }
+
+ return -1;
+}
+
+static void
+test_alloc_free (void)
+{
+ gpointer p;
+ gboolean ret;
+
+ p = gcr_secure_memory_alloc (512);
+ g_assert (p != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p, 512));
+
+ memset (p, 0x67, 512);
+
+ ret = gcr_secure_memory_is_secure (p);
+ g_assert (ret == TRUE);
+
+ gcr_secure_memory_free (p);
+}
+
+static void
+test_alloc_two (void)
+{
+ gpointer p, p2;
+ gboolean ret;
+
+ p2 = gcr_secure_memory_alloc (4);
+ g_assert(p2 != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p2, 4));
+
+ memset (p2, 0x67, 4);
+
+ p = gcr_secure_memory_alloc (16200);
+ g_assert (p != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p, 16200));
+
+ memset (p, 0x67, 16200);
+
+ ret = gcr_secure_memory_is_secure (p);
+ g_assert (ret == TRUE);
+
+ gcr_secure_memory_free (p2);
+ gcr_secure_memory_free (p);
+}
+
+static void
+test_realloc (void)
+{
+ gchar *str = "a test string to see if realloc works properly";
+ gpointer p, p2;
+ gsize len;
+
+ len = strlen (str) + 1;
+
+ p = gcr_secure_memory_realloc (NULL, len);
+ g_assert (p != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p, len));
+
+ strcpy ((gchar*)p, str);
+
+ p2 = gcr_secure_memory_realloc (p, 512);
+ g_assert (p2 != NULL);
+
+ /* "strings not equal after realloc" */
+ g_assert_cmpstr (p2, ==, str);
+
+ p = gcr_secure_memory_realloc (p2, 0);
+ /* "should have freed memory" */
+ g_assert (p == NULL);
+}
+
+static void
+test_realloc_across (void)
+{
+ gpointer p, p2;
+
+ /* Tiny allocation */
+ p = gcr_secure_memory_realloc (NULL, 1088);
+ g_assert (p != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p, 1088));
+
+ /* Reallocate to a large one, will have to have changed blocks */
+ p2 = gcr_secure_memory_realloc (p, 16200);
+ g_assert (p2 != NULL);
+ g_assert_cmpint (IS_ZERO, ==, find_non_zero (p2, 16200));
+
+ gcr_secure_memory_free (p2);
+}
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_set_prgname ("test-memory");
+
+ g_test_add_func ("/memory/alloc-free", test_alloc_free);
+ g_test_add_func ("/memory/alloc-two", test_alloc_two);
+ g_test_add_func ("/memory/realloc", test_realloc);
+ g_test_add_func ("/memory/realloc-across", test_realloc_across);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]