Blame egg/test-secmem.c

Packit b00eeb
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
Packit b00eeb
/* unit-test-secmem.c: Test low level secure memory allocation functionality
Packit b00eeb
Packit b00eeb
   Copyright (C) 2007 Stefan Walter
Packit b00eeb
Packit b00eeb
   The Gnome Keyring Library is free software; you can redistribute it and/or
Packit b00eeb
   modify it under the terms of the GNU Library General Public License as
Packit b00eeb
   published by the Free Software Foundation; either version 2 of the
Packit b00eeb
   License, or (at your option) any later version.
Packit b00eeb
Packit b00eeb
   The Gnome Keyring Library is distributed in the hope that it will be useful,
Packit b00eeb
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit b00eeb
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit b00eeb
   Library General Public License for more details.
Packit b00eeb
Packit b00eeb
   You should have received a copy of the GNU Library General Public
Packit b00eeb
   License along with the Gnome Library; see the file COPYING.LIB.  If not,
Packit b00eeb
   see <http://www.gnu.org/licenses/>.
Packit b00eeb
Packit b00eeb
   Author: Stef Walter <stef@memberwebs.com>
Packit b00eeb
*/
Packit b00eeb
Packit b00eeb
#include "config.h"
Packit b00eeb
Packit b00eeb
#include "egg/egg-secure-memory.h"
Packit b00eeb
Packit b00eeb
#include <glib.h>
Packit b00eeb
Packit b00eeb
#include <stdlib.h>
Packit b00eeb
#include <stdio.h>
Packit b00eeb
#include <string.h>
Packit b00eeb
Packit b00eeb
Packit b00eeb
EGG_SECURE_DEFINE_GLIB_GLOBALS ();
Packit b00eeb
Packit b00eeb
/* Declared in egg-secure-memory.c */
Packit b00eeb
extern int egg_secure_warnings;
Packit b00eeb
Packit b00eeb
EGG_SECURE_DECLARE (tests);
Packit b00eeb
Packit b00eeb
/*
Packit b00eeb
 * Each test looks like (on one line):
Packit b00eeb
 *     void unit_test_xxxxx (CuTest* cu)
Packit b00eeb
 *
Packit b00eeb
 * Each setup looks like (on one line):
Packit b00eeb
 *     void unit_setup_xxxxx (void);
Packit b00eeb
 *
Packit b00eeb
 * Each teardown looks like (on one line):
Packit b00eeb
 *     void unit_teardown_xxxxx (void);
Packit b00eeb
 *
Packit b00eeb
 * Tests be run in the order specified here.
Packit b00eeb
 */
Packit b00eeb
Packit b00eeb
static gsize
Packit b00eeb
find_non_zero (gpointer mem, gsize len)
Packit b00eeb
{
Packit b00eeb
	guchar *b, *e;
Packit b00eeb
	gsize sz = 0;
Packit b00eeb
	for (b = (guchar*)mem, e = ((guchar*)mem) + len; b != e; ++b, ++sz) {
Packit b00eeb
		if (*b != 0x00)
Packit b00eeb
			return sz;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	return G_MAXSIZE;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_alloc_free (void)
Packit b00eeb
{
Packit b00eeb
	gpointer p;
Packit b00eeb
	gboolean ret;
Packit b00eeb
Packit b00eeb
	p = egg_secure_alloc_full ("tests", 512, 0);
Packit b00eeb
	g_assert (p != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p, 512));
Packit b00eeb
Packit b00eeb
	memset (p, 0x67, 512);
Packit b00eeb
Packit b00eeb
	ret = egg_secure_check (p);
Packit b00eeb
	g_assert (ret == TRUE);
Packit b00eeb
Packit b00eeb
	egg_secure_free_full (p, 0);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_realloc_across (void)
Packit b00eeb
{
Packit b00eeb
	gpointer p, p2;
Packit b00eeb
Packit b00eeb
	/* Tiny allocation */
Packit b00eeb
	p = egg_secure_realloc_full ("tests", NULL, 1088, 0);
Packit b00eeb
	g_assert (p != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p, 1088));
Packit b00eeb
Packit b00eeb
	/* Reallocate to a large one, will have to have changed blocks */
Packit b00eeb
	p2 = egg_secure_realloc_full ("tests", p, 16200, 0);
Packit b00eeb
	g_assert (p2 != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200));
Packit b00eeb
Packit b00eeb
	egg_secure_free (p2);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_alloc_two (void)
Packit b00eeb
{
Packit b00eeb
	gpointer p, p2;
Packit b00eeb
	gboolean ret;
Packit b00eeb
Packit b00eeb
	p2 = egg_secure_alloc_full ("tests", 4, 0);
Packit b00eeb
	g_assert (p2 != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 4));
Packit b00eeb
Packit b00eeb
	memset (p2, 0x67, 4);
Packit b00eeb
Packit b00eeb
	p = egg_secure_alloc_full ("tests", 16200, 0);
Packit b00eeb
	g_assert (p != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p, 16200));
Packit b00eeb
Packit b00eeb
	memset (p, 0x67, 16200);
Packit b00eeb
Packit b00eeb
	ret = egg_secure_check (p);
Packit b00eeb
	g_assert (ret == TRUE);
Packit b00eeb
Packit b00eeb
	egg_secure_free_full (p2, 0);
Packit b00eeb
	egg_secure_free_full (p, 0);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_realloc (void)
Packit b00eeb
{
Packit b00eeb
	gchar *str = "a test string to see if realloc works properly";
Packit b00eeb
	gpointer p, p2;
Packit b00eeb
	gsize len;
Packit b00eeb
Packit b00eeb
	len = strlen (str) + 1;
Packit b00eeb
Packit b00eeb
	p = egg_secure_realloc_full ("tests", NULL, len, 0);
Packit b00eeb
	g_assert (p != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p, len));
Packit b00eeb
Packit b00eeb
	strcpy ((gchar*)p, str);
Packit b00eeb
Packit b00eeb
	p2 = egg_secure_realloc_full ("tests", p, 512, 0);
Packit b00eeb
	g_assert (p2 != NULL);
Packit b00eeb
	g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (((gchar*)p2) + len, 512 - len));
Packit b00eeb
Packit b00eeb
	g_assert (strcmp (p2, str) == 0);
Packit b00eeb
Packit b00eeb
	p = egg_secure_realloc_full ("tests", p2, 0, 0);
Packit b00eeb
	g_assert (p == NULL);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_multialloc (void)
Packit b00eeb
{
Packit b00eeb
	GPtrArray *memory;
Packit b00eeb
	gpointer data;
Packit b00eeb
	gsize size;
Packit b00eeb
	int i, action, index;
Packit b00eeb
Packit b00eeb
	/* A predetermined seed to get a predetermined pattern */
Packit b00eeb
	g_random_set_seed (15);
Packit b00eeb
	memory = g_ptr_array_new ();
Packit b00eeb
Packit b00eeb
	/* Don't print "can't allocate" warnings */
Packit b00eeb
	egg_secure_warnings = 0;
Packit b00eeb
Packit b00eeb
	for (i = 0; TRUE; ++i) {
Packit b00eeb
Packit b00eeb
		/* Determine what we want to do */
Packit b00eeb
		if (memory->len > 0) {
Packit b00eeb
			if (i > 100000) /* Once we've done 100000 alocations start freeing */
Packit b00eeb
				action = 2;
Packit b00eeb
			else
Packit b00eeb
				action = g_random_int_range (0, 3);
Packit b00eeb
		} else {
Packit b00eeb
			action = 0; /* No allocations, so allocate */
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		switch (action) {
Packit b00eeb
		case 0: /* Allocate some memory */
Packit b00eeb
			size = g_random_int_range (1, 16384);
Packit b00eeb
			data = egg_secure_alloc (size);
Packit b00eeb
			g_assert (data != NULL);
Packit b00eeb
			memset (data, 0xCAFEBABE, size);
Packit b00eeb
			g_ptr_array_add (memory, data);
Packit b00eeb
			break;
Packit b00eeb
		case 1: /* Reallocate some memory */
Packit b00eeb
			index = g_random_int_range (0, memory->len);
Packit b00eeb
			data = g_ptr_array_index (memory, index);
Packit b00eeb
			g_assert (data != NULL);
Packit b00eeb
			size = g_random_int_range (1, 16384);
Packit b00eeb
			data = egg_secure_realloc (data, size);
Packit b00eeb
			g_assert (data != NULL);
Packit b00eeb
			memset (data, 0xCAFEBABE, size);
Packit b00eeb
			g_ptr_array_index (memory, index) = data;
Packit b00eeb
			break;
Packit b00eeb
		case 2: /* Free some memory */
Packit b00eeb
			index = g_random_int_range (0, memory->len);
Packit b00eeb
			data = g_ptr_array_remove_index_fast (memory, index);
Packit b00eeb
			g_assert (data != NULL);
Packit b00eeb
			egg_secure_free (data);
Packit b00eeb
			break;
Packit b00eeb
		default:
Packit b00eeb
			g_assert_not_reached ();
Packit b00eeb
		}
Packit b00eeb
Packit b00eeb
		egg_secure_validate ();
Packit b00eeb
Packit b00eeb
		if (i > 100000 && !memory->len)
Packit b00eeb
			break;
Packit b00eeb
	}
Packit b00eeb
Packit b00eeb
	g_assert (memory->len == 0);
Packit b00eeb
	for (i = 0; i < memory->len; i++)
Packit b00eeb
		egg_secure_free (memory->pdata[i]);
Packit b00eeb
	g_ptr_array_free (memory, TRUE);
Packit b00eeb
Packit b00eeb
	egg_secure_warnings = 1;
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_clear (void)
Packit b00eeb
{
Packit b00eeb
	gpointer p;
Packit b00eeb
Packit b00eeb
	p = egg_secure_alloc_full ("tests", 188, 0);
Packit b00eeb
	g_assert (p != NULL);
Packit b00eeb
	memset (p, 0x89, 188);
Packit b00eeb
	g_assert (memchr (p, 0x89, 188) == p);
Packit b00eeb
Packit b00eeb
	egg_secure_clear (p, 188);
Packit b00eeb
	g_assert (memchr (p, 0x89, 188) == NULL);
Packit b00eeb
Packit b00eeb
	egg_secure_free_full (p, 0);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
static void
Packit b00eeb
test_strclear (void)
Packit b00eeb
{
Packit b00eeb
	gchar *str;
Packit b00eeb
Packit b00eeb
	str = egg_secure_strdup ("secret");
Packit b00eeb
	g_assert (str != NULL);
Packit b00eeb
	g_assert_cmpuint (strlen (str), ==, 6);
Packit b00eeb
	g_assert (strchr (str, 't') == str + 5);
Packit b00eeb
Packit b00eeb
	egg_secure_strclear (str);
Packit b00eeb
	g_assert_cmpuint (strlen (str), ==, 6);
Packit b00eeb
	g_assert (strchr (str, 't') == NULL);
Packit b00eeb
Packit b00eeb
	egg_secure_free_full (str, 0);
Packit b00eeb
}
Packit b00eeb
Packit b00eeb
int
Packit b00eeb
main (int argc, char **argv)
Packit b00eeb
{
Packit b00eeb
	g_test_init (&argc, &argv, NULL);
Packit b00eeb
Packit b00eeb
	g_test_add_func ("/secmem/alloc_free", test_alloc_free);
Packit b00eeb
	g_test_add_func ("/secmem/realloc_across", test_realloc_across);
Packit b00eeb
	g_test_add_func ("/secmem/alloc_two", test_alloc_two);
Packit b00eeb
	g_test_add_func ("/secmem/realloc", test_realloc);
Packit b00eeb
	g_test_add_func ("/secmem/multialloc", test_multialloc);
Packit b00eeb
	g_test_add_func ("/secmem/clear", test_clear);
Packit b00eeb
	g_test_add_func ("/secmem/strclear", test_strclear);
Packit b00eeb
Packit b00eeb
	return g_test_run ();
Packit b00eeb
}