diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-11-17 15:26:55 +0100 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-11-21 10:28:27 +0100 |
commit | f3b9d46c75675e9b4b451164dd32ed9b1af0dfb1 (patch) | |
tree | 5b66cf37d54e3b447e3087cc27b03eeb7ae332f7 /egg | |
parent | 97cd79171dfbba24394f070f3946b20c2d518d2d (diff) | |
download | gcr-f3b9d46c75675e9b4b451164dd32ed9b1af0dfb1.tar.gz |
Add valgrind memory checking and fix up errors
* This is especially necessary after migrating to EggBytes
since it's reference counted and an easy sourc of memory leaks
* Remove threading from testing framework, as gcr isn't threadsafe
in all parts.
* Fix bugs discovered in memory checking.
* Fix up some of the testing stuff.
Diffstat (limited to 'egg')
-rw-r--r-- | egg/Makefile.am | 7 | ||||
-rw-r--r-- | egg/egg-asn1x.c | 25 | ||||
-rw-r--r-- | egg/egg-bytes.c | 1 | ||||
-rw-r--r-- | egg/egg-decimal.c | 2 | ||||
-rw-r--r-- | egg/egg-dh.c | 2 | ||||
-rw-r--r-- | egg/egg-dn.c | 5 | ||||
-rw-r--r-- | egg/egg-hkdf.c | 1 | ||||
-rw-r--r-- | egg/egg-openssl.c | 1 | ||||
-rw-r--r-- | egg/egg-secure-memory.c | 393 | ||||
-rw-r--r-- | egg/egg-secure-memory.h | 38 | ||||
-rw-r--r-- | egg/egg-symkey.c | 1 | ||||
-rw-r--r-- | egg/egg-testing.c | 131 | ||||
-rw-r--r-- | egg/egg-testing.h | 17 | ||||
-rw-r--r-- | egg/tests/Makefile.am | 3 | ||||
-rw-r--r-- | egg/tests/test-asn1.c | 8 | ||||
-rw-r--r-- | egg/tests/test-hex.c | 6 | ||||
-rw-r--r-- | egg/tests/test-openssl.c | 4 | ||||
-rw-r--r-- | egg/tests/test-padding.c | 2 | ||||
-rw-r--r-- | egg/tests/test-secmem.c | 15 | ||||
-rw-r--r-- | egg/tests/test-symkey.c | 7 |
20 files changed, 451 insertions, 218 deletions
diff --git a/egg/Makefile.am b/egg/Makefile.am index 259d522..f00258c 100644 --- a/egg/Makefile.am +++ b/egg/Makefile.am @@ -11,7 +11,9 @@ BUILT_SOURCES = \ INCLUDES = \ -I$(top_srcdir) \ - -I$(top_builddir) + -I$(top_builddir) \ + -I$(top_srcdir)/build \ + -DWITH_VALGRIND libegg_la_CFLAGS = \ $(GLIB_CFLAGS) @@ -90,3 +92,6 @@ libegg_test_la_LIBS = \ # ------------------------------------------------------------------- SUBDIRS = . tests + +check-memory: + make -C tests check-memory diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c index ab862e0..2f481d2 100644 --- a/egg/egg-asn1x.c +++ b/egg/egg-asn1x.c @@ -3164,7 +3164,7 @@ egg_asn1x_take_bits_as_raw (GNode *node, length += 1; ab = g_slice_new0 (Abits); - ab->bits = egg_bytes_ref (value); + ab->bits = value; ab->n_bits = n_bits; anode_encode_tlv_and_enc (node, length + 1, anode_encoder_bit_string, ab, abits_destroy); @@ -4027,6 +4027,27 @@ match_oid_in_definitions (const ASN1_ARRAY_TYPE *defs, const gchar *match) return result; } +static gboolean +is_oid_number (const gchar *p) +{ + gboolean must = TRUE; + gint i; + + for (i = 0; p[i] != '\0'; i++) { + if (g_ascii_isdigit (p[i])) { + must = FALSE; + } else if (must) { + return FALSE; + } else { + if (p[i] != '.') + return FALSE; + must = TRUE; + } + } + + return !must; +} + GNode* egg_asn1x_create (const ASN1_ARRAY_TYPE *defs, const gchar *type) { @@ -4038,7 +4059,7 @@ egg_asn1x_create (const ASN1_ARRAY_TYPE *defs, const gchar *type) g_return_val_if_fail (type, NULL); /* An OID */ - if (strspn (type, "0123456789.") == strlen (type)) { + if (is_oid_number (type)) { def = match_oid_in_definitions (defs, type); /* An Identifier */ diff --git a/egg/egg-bytes.c b/egg/egg-bytes.c index 22bac5e..8f58da2 100644 --- a/egg/egg-bytes.c +++ b/egg/egg-bytes.c @@ -245,6 +245,7 @@ egg_bytes_unref (gpointer bytes) { if (bytes_->free_func != NULL) bytes_->free_func (bytes_->user_data); + g_slice_free (EggBytes, bytes); } } diff --git a/egg/egg-decimal.c b/egg/egg-decimal.c index 6f3921d..422ec0c 100644 --- a/egg/egg-decimal.c +++ b/egg/egg-decimal.c @@ -97,5 +97,7 @@ egg_decimal_decode (const gchar *data, memmove (usg, at_byte, length); if (n_decoded) *n_decoded = length; + + g_free (digits); return usg; } diff --git a/egg/egg-dh.c b/egg/egg-dh.c index 85dec77..0a3ed5b 100644 --- a/egg/egg-dh.c +++ b/egg/egg-dh.c @@ -337,9 +337,9 @@ egg_dh_gen_secret (gcry_mpi_t peer, gcry_mpi_t priv, #if DEBUG_DH_SECRET g_printerr ("DH SECRET: "); gcry_mpi_dump (k); - gcry_mpi_release (k); #endif + gcry_mpi_release (k); *bytes = n_value; #if DEBUG_DH_SECRET diff --git a/egg/egg-dn.c b/egg/egg-dn.c index 1edcd59..1452261 100644 --- a/egg/egg-dn.c +++ b/egg/egg-dn.c @@ -205,6 +205,7 @@ egg_dn_read_part (GNode *asn, const gchar *match) GNode *node; GQuark oid; gint i, j; + gchar *result; g_return_val_if_fail (asn, NULL); g_return_val_if_fail (match, NULL); @@ -236,7 +237,9 @@ egg_dn_read_part (GNode *asn, const gchar *match) value = egg_asn1x_get_raw_element (node); g_return_val_if_fail (value, NULL); - return dn_print_oid_value (oid, egg_oid_get_flags (oid), value); + result = dn_print_oid_value (oid, egg_oid_get_flags (oid), value); + egg_bytes_unref (value); + return result; } } diff --git a/egg/egg-hkdf.c b/egg/egg-hkdf.c index a55ee5d..8cce3af 100644 --- a/egg/egg-hkdf.c +++ b/egg/egg-hkdf.c @@ -105,5 +105,6 @@ egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input, g_free (alloc); gcry_free (buffer); + gcry_md_close (md2); return TRUE; } diff --git a/egg/egg-openssl.c b/egg/egg-openssl.c index dc38e2b..2433f07 100644 --- a/egg/egg-openssl.c +++ b/egg/egg-openssl.c @@ -375,6 +375,7 @@ egg_openssl_prep_dekinfo (GHashTable *headers) g_return_val_if_fail (hex, NULL); dekinfo = g_strdup_printf ("DES-EDE3-CBC,%s", hex); g_free (hex); + g_free (iv); g_hash_table_insert (headers, g_strdup ("DEK-Info"), (void*)dekinfo); g_hash_table_insert (headers, g_strdup ("Proc-Type"), g_strdup ("4,ENCRYPTED")); diff --git a/egg/egg-secure-memory.c b/egg/egg-secure-memory.c index b190573..dca9bac 100644 --- a/egg/egg-secure-memory.c +++ b/egg/egg-secure-memory.c @@ -22,8 +22,8 @@ */ /* - * IMPORTANT: This is pure vanila standard C, no glib. We need this - * because certain consumers of this protocol need to be built + * IMPORTANT: This is pure vanila standard C, no glib. We need this + * because certain consumers of this protocol need to be built * without linking in any special libraries. ie: the PKCS#11 module. */ @@ -46,16 +46,10 @@ #include <valgrind/memcheck.h> #endif -/* - * Use this to force all memory through malloc - * for use with valgrind and the like - */ -#define FORCE_FALLBACK_MEMORY 0 - #define DEBUG_SECURE_MEMORY 0 -#if DEBUG_SECURE_MEMORY -#define DEBUG_ALLOC(msg, n) fprintf(stderr, "%s %lu bytes\n", msg, n); +#if DEBUG_SECURE_MEMORY +#define DEBUG_ALLOC(msg, n) fprintf(stderr, "%s %lu bytes\n", msg, n); #else #define DEBUG_ALLOC(msg, n) #endif @@ -65,33 +59,33 @@ /* Use our own assert to guarantee no glib allocations */ #ifndef ASSERT #ifdef G_DISABLE_ASSERT -#define ASSERT(x) -#else +#define ASSERT(x) +#else #define ASSERT(x) assert(x) #endif #endif #define DO_LOCK() \ - egg_memory_lock (); - + egg_memory_lock (); + #define DO_UNLOCK() \ egg_memory_unlock (); static int lock_warning = 1; int egg_secure_warnings = 1; -/* - * We allocate all memory in units of sizeof(void*). This +/* + * We allocate all memory in units of sizeof(void*). This * is our definition of 'word'. */ typedef void* word_t; -/* The amount of extra words we can allocate */ +/* The amount of extra words we can allocate */ #define WASTE 4 -/* - * Track allocated memory or a free block. This structure is not stored - * in the secure memory area. It is allocated from a pool of other +/* + * Track allocated memory or a free block. This structure is not stored + * in the secure memory area. It is allocated from a pool of other * memory. See meta_pool_xxx (). */ typedef struct _Cell { @@ -103,7 +97,7 @@ typedef struct _Cell { struct _Cell *prev; /* Previous in memory ring */ } Cell; -/* +/* * A block of secure memory. This structure is the header in that block. */ typedef struct _Block { @@ -136,20 +130,20 @@ unused_pop (void **stack) ptr = *stack; *stack = *(void**)ptr; return ptr; - + } static inline void* unused_peek (void **stack) { ASSERT (stack); - return *stack; + return *stack; } /* ----------------------------------------------------------------------------- * POOL META DATA ALLOCATION - * - * A pool for memory meta data. We allocate fixed size blocks. There are actually + * + * A pool for memory meta data. We allocate fixed size blocks. There are actually * two different structures stored in this pool: Cell and Block. Cell is allocated * way more often, and is bigger so we just allocate that size for both. */ @@ -177,13 +171,13 @@ pool_alloc (void) Pool *pool; void *pages, *item; size_t len, i; - + /* A pool with an available item */ for (pool = all_pools; pool; pool = pool->next) { if (unused_peek (&pool->unused)) break; } - + /* Create a new pool */ if (pool == NULL) { len = getpagesize () * 2; @@ -203,7 +197,7 @@ pool_alloc (void) pool->n_items = (len - sizeof (Pool)) / sizeof (Item); for (i = 0; i < pool->n_items; ++i) unused_push (&pool->unused, pool->items + i); - + #ifdef WITH_VALGRIND VALGRIND_CREATE_MEMPOOL(pool, 0, 0); #endif @@ -225,9 +219,9 @@ pool_free (void* item) { Pool *pool, **at; char *ptr, *beg, *end; - + ptr = item; - + /* Find which block this one belongs to */ for (at = &all_pools, pool = *at; pool; at = &pool->next, pool = *at) { beg = (char*)pool->items; @@ -272,17 +266,17 @@ pool_valid (void* item) { Pool *pool; char *ptr, *beg, *end; - + ptr = item; - + /* Find which block this one belongs to */ for (pool = all_pools; pool; pool = pool->next) { beg = (char*)pool->items; end = (char*)pool + pool->length - sizeof (Item); - if (ptr >= beg && ptr <= end) + if (ptr >= beg && ptr <= end) return (pool->used && (ptr - beg) % sizeof (Item) == 0); } - + return 0; } @@ -290,9 +284,9 @@ pool_valid (void* item) /* ----------------------------------------------------------------------------- * SEC ALLOCATION - * + * * Each memory cell begins and ends with a pointer to its metadata. These are also - * used as guards or red zones. Since they're treated as redzones by valgrind we + * used as guards or red zones. Since they're treated as redzones by valgrind we * have to jump through a few hoops before reading and/or writing them. */ @@ -312,11 +306,11 @@ sec_write_guards (Cell *cell) ((void**)cell->words)[0] = (void*)cell; ((void**)cell->words)[cell->n_words - 1] = (void*)cell; - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t)); VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t)); -#endif +#endif } static inline void @@ -324,16 +318,16 @@ sec_check_guards (Cell *cell) { #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (cell->words, sizeof (word_t)); - VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t)); -#endif - + VALGRIND_MAKE_MEM_DEFINED (cell->words + cell->n_words - 1, sizeof (word_t)); +#endif + ASSERT(((void**)cell->words)[0] == (void*)cell); ASSERT(((void**)cell->words)[cell->n_words - 1] == (void*)cell); - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_NOACCESS (cell->words, sizeof (word_t)); VALGRIND_MAKE_MEM_NOACCESS (cell->words + cell->n_words - 1, sizeof (word_t)); -#endif +#endif } static void @@ -344,9 +338,9 @@ sec_insert_cell_ring (Cell **ring, Cell *cell) ASSERT (cell != *ring); ASSERT (cell->next == NULL); ASSERT (cell->prev == NULL); - - /* Insert back into the mix of available memory */ - if (*ring) { + + /* Insert back into the mix of available memory */ + if (*ring) { cell->next = (*ring)->next; cell->prev = *ring; cell->next->prev = cell; @@ -355,7 +349,7 @@ sec_insert_cell_ring (Cell **ring, Cell *cell) cell->next = cell; cell->prev = cell; } - + *ring = cell; ASSERT (cell->next->prev == cell); ASSERT (cell->prev->next == cell); @@ -388,7 +382,7 @@ sec_remove_cell_ring (Cell **ring, Cell *cell) cell->next->prev = cell->prev; cell->prev->next = cell->next; cell->next = cell->prev = NULL; - + ASSERT (*ring != cell); } @@ -404,22 +398,43 @@ sec_is_valid_word (Block *block, word_t *word) return (word >= block->words && word < block->words + block->n_words); } -static inline void* -sec_clear_memory (void *memory, size_t from, size_t to) +static inline void +sec_clear_undefined (void *memory, + size_t from, + size_t to) { + char *ptr = memory; ASSERT (from <= to); - memset ((char*)memory + from, 0, to - from); - return memory; +#ifdef WITH_VALGRIND + VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from); +#endif + memset (ptr + from, 0, to - from); +#ifdef WITH_VALGRIND + VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from); +#endif +} +static inline void +sec_clear_noaccess (void *memory, size_t from, size_t to) +{ + char *ptr = memory; + ASSERT (from <= to); +#ifdef WITH_VALGRIND + VALGRIND_MAKE_MEM_UNDEFINED (ptr + from, to - from); +#endif + memset (ptr + from, 0, to - from); +#ifdef WITH_VALGRIND + VALGRIND_MAKE_MEM_NOACCESS (ptr + from, to - from); +#endif } static Cell* sec_neighbor_before (Block *block, Cell *cell) { word_t *word; - + ASSERT (cell); ASSERT (block); - + word = cell->words - 1; if (!sec_is_valid_word (block, word)) return NULL; @@ -427,7 +442,7 @@ sec_neighbor_before (Block *block, Cell *cell) #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t)); #endif - + cell = *word; sec_check_guards (cell); @@ -438,14 +453,14 @@ sec_neighbor_before (Block *block, Cell *cell) return cell; } -static Cell* +static Cell* sec_neighbor_after (Block *block, Cell *cell) { word_t *word; - + ASSERT (cell); ASSERT (block); - + word = cell->words + cell->n_words; if (!sec_is_valid_word (block, word)) return NULL; @@ -456,7 +471,7 @@ sec_neighbor_after (Block *block, Cell *cell) cell = *word; sec_check_guards (cell); - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_NOACCESS (word, sizeof (word_t)); #endif @@ -472,7 +487,7 @@ sec_alloc (Block *block, Cell *cell, *other; size_t n_words; void *memory; - + ASSERT (block); ASSERT (length); ASSERT (tag); @@ -480,16 +495,16 @@ sec_alloc (Block *block, if (!block->unused_cells) return NULL; - /* - * Each memory allocation is aligned to a pointer size, and + /* + * Each memory allocation is aligned to a pointer size, and * then, sandwidched between two pointers to its meta data. * These pointers also act as guards. * - * We allocate memory in units of sizeof (void*) + * We allocate memory in units of sizeof (void*) */ - + n_words = sec_size_to_words (length) + 2; - + /* Look for a cell of at least our required size */ cell = block->unused_cells; while (cell->n_words < n_words) { @@ -499,7 +514,7 @@ sec_alloc (Block *block, break; } } - + if (!cell) return NULL; @@ -508,7 +523,7 @@ sec_alloc (Block *block, ASSERT (cell->prev); ASSERT (cell->words); sec_check_guards (cell); - + /* Steal from the cell if it's too long */ if (cell->n_words > n_words + WASTE) { other = pool_alloc (); @@ -518,13 +533,13 @@ sec_alloc (Block *block, other->words = cell->words; cell->n_words -= n_words; cell->words += n_words; - + sec_write_guards (other); sec_write_guards (cell); - + cell = other; } - + if (cell->next) sec_remove_cell_ring (&block->unused_cells, cell); @@ -533,11 +548,11 @@ sec_alloc (Block *block, cell->requested = length; sec_insert_cell_ring (&block->used_cells, cell); memory = sec_cell_to_memory (cell); - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_UNDEFINED (memory, length); #endif - + return memset (memory, 0, length); } @@ -546,13 +561,13 @@ sec_free (Block *block, void *memory) { Cell *cell, *other; word_t *word; - + ASSERT (block); ASSERT (memory); - + word = memory; --word; - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t)); #endif @@ -567,7 +582,7 @@ sec_free (Block *block, void *memory) #endif sec_check_guards (cell); - sec_clear_memory (memory, 0, cell->requested); + sec_clear_noaccess (memory, 0, cell->requested); sec_check_guards (cell); ASSERT (cell->requested > 0); @@ -585,8 +600,8 @@ sec_free (Block *block, void *memory) sec_write_guards (other); pool_free (cell); cell = other; - } - + } + /* Find next unallocated neighbor, and merge if possible */ other = sec_neighbor_after (block, cell); if (other && other->requested == 0) { @@ -611,6 +626,34 @@ sec_free (Block *block, void *memory) return NULL; } +static void +memcpy_with_vbits (void *dest, + void *src, + size_t length) +{ +#ifdef WITH_VALGRIND + int vbits_setup = 0; + void *vbits = NULL; + + if (RUNNING_ON_VALGRIND) { + vbits = malloc (length); + if (vbits != NULL) + vbits_setup = VALGRIND_GET_VBITS (src, vbits, length); + VALGRIND_MAKE_MEM_DEFINED (src, length); + } +#endif + + memcpy (dest, src, length); + +#ifdef WITH_VALGRIND + if (vbits_setup == 1) { + VALGRIND_SET_VBITS (dest, vbits, length); + VALGRIND_SET_VBITS (src, vbits, length); + } + free (vbits); +#endif +} + static void* sec_realloc (Block *block, const char *tag, @@ -631,7 +674,7 @@ sec_realloc (Block *block, /* Dig out where the meta should be */ word = memory; --word; - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t)); #endif @@ -639,7 +682,7 @@ sec_realloc (Block *block, ASSERT (sec_is_valid_word (block, word)); ASSERT (pool_valid (*word)); cell = *word; - + /* Validate that it's actually for real */ sec_check_guards (cell); ASSERT (cell->requested > 0); @@ -658,21 +701,17 @@ sec_realloc (Block *block, cell->requested = length; alloc = sec_cell_to_memory (cell); -#ifdef WITH_VALGRIND - VALGRIND_MAKE_MEM_DEFINED (alloc, length); -#endif - - /* + /* * Even though we may be reusing the same cell, that doesn't * mean that the allocation is shrinking. It could have shrunk - * and is now expanding back some. - */ + * and is now expanding back some. + */ if (length < valid) - return sec_clear_memory (alloc, length, valid); - else - return alloc; - } + sec_clear_undefined (alloc, length, valid); + return alloc; + } + /* Need braaaaaiiiiiinsss... */ while (cell->n_words < n_words) { @@ -680,7 +719,7 @@ sec_realloc (Block *block, other = sec_neighbor_after (block, cell); if (!other || other->requested != 0) break; - + /* Eat the whole neighbor if not too big */ if (n_words - cell->n_words + WASTE >= other->n_words) { cell->n_words += other->n_words; @@ -697,26 +736,22 @@ sec_realloc (Block *block, sec_write_guards (cell); } } - + if (cell->n_words >= n_words) { cell->requested = length; cell->tag = tag; alloc = sec_cell_to_memory (cell); - -#ifdef WITH_VALGRIND - VALGRIND_MAKE_MEM_DEFINED (alloc, length); -#endif - - return sec_clear_memory (alloc, valid, length); + sec_clear_undefined (alloc, valid, length); + return alloc; } /* That didn't work, try alloc/free */ alloc = sec_alloc (block, tag, length); if (alloc) { - memcpy (alloc, memory, valid); + memcpy_with_vbits (alloc, memory, valid); sec_free (block, memory); } - + return alloc; } @@ -726,7 +761,7 @@ sec_allocated (Block *block, void *memory) { Cell *cell; word_t *word; - + ASSERT (block); ASSERT (memory); @@ -736,12 +771,12 @@ sec_allocated (Block *block, void *memory) #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (word, sizeof (word_t)); #endif - + /* Lookup the meta for this memory block (using guard pointer) */ ASSERT (sec_is_valid_word (block, word)); ASSERT (pool_valid (*word)); cell = *word; - + sec_check_guards (cell); ASSERT (cell->requested > 0); ASSERT (cell->tag != NULL); @@ -759,6 +794,11 @@ sec_validate (Block *block) Cell *cell; word_t *word, *last; +#ifdef WITH_VALGRIND + if (RUNNING_ON_VALGRIND) + return; +#endif + word = block->words; last = word + block->n_words; @@ -768,10 +808,10 @@ sec_validate (Block *block) ASSERT (sec_is_valid_word (block, word)); ASSERT (pool_valid (*word)); cell = *word; - + /* Validate that it's actually for real */ sec_check_guards (cell); - + /* Is it an allocated block? */ if (cell->requested > 0) { ASSERT (cell->tag != NULL); @@ -780,8 +820,8 @@ sec_validate (Block *block) ASSERT (cell->next->prev == cell); ASSERT (cell->prev->next == cell); ASSERT (cell->requested <= (cell->n_words - 2) * sizeof (word_t)); - - /* An unused block */ + + /* An unused block */ } else { ASSERT (cell->tag == NULL); ASSERT (cell->next != NULL); @@ -789,7 +829,7 @@ sec_validate (Block *block) ASSERT (cell->next->prev == cell); ASSERT (cell->prev->next == cell); } - + word += cell->n_words; if (word == last) break; @@ -806,7 +846,7 @@ sec_acquire_pages (size_t *sz, { void *pages; unsigned long pgsize; - + ASSERT (sz); ASSERT (*sz); ASSERT (during_tag); @@ -814,7 +854,7 @@ sec_acquire_pages (size_t *sz, /* Make sure sz is a multiple of the page size */ pgsize = getpagesize (); *sz = (*sz + pgsize -1) & ~(pgsize - 1); - + #if defined(HAVE_MLOCK) pages = mmap (0, *sz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (pages == MAP_FAILED) { @@ -824,7 +864,7 @@ sec_acquire_pages (size_t *sz, lock_warning = 0; return NULL; } - + if (mlock (pages, *sz) < 0) { if (lock_warning && egg_secure_warnings && errno != EPERM) { fprintf (stderr, "couldn't lock %lu bytes of memory (%s): %s\n", @@ -834,12 +874,12 @@ sec_acquire_pages (size_t *sz, munmap (pages, *sz); return NULL; } - + DEBUG_ALLOC ("gkr-secure-memory: new block ", *sz); - + lock_warning = 1; return pages; - + #else if (lock_warning && egg_secure_warnings) fprintf (stderr, "your system does not support private memory"); @@ -849,21 +889,21 @@ sec_acquire_pages (size_t *sz, } -static void +static void sec_release_pages (void *pages, size_t sz) { ASSERT (pages); ASSERT (sz % getpagesize () == 0); - + #if defined(HAVE_MLOCK) if (munlock (pages, sz) < 0 && egg_secure_warnings) fprintf (stderr, "couldn't unlock private memory: %s\n", strerror (errno)); - + if (munmap (pages, sz) < 0 && egg_secure_warnings) fprintf (stderr, "couldn't unmap private anonymous memory: %s\n", strerror (errno)); - + DEBUG_ALLOC ("gkr-secure-memory: freed block ", sz); - + #else ASSERT (FALSE); #endif @@ -875,7 +915,7 @@ sec_release_pages (void *pages, size_t sz) static Block *all_blocks = NULL; -static Block* +static Block* sec_block_create (size_t size, const char *during_tag) { @@ -884,10 +924,9 @@ sec_block_create (size_t size, ASSERT (during_tag); -#if FORCE_FALLBACK_MEMORY /* We can force all all memory to be malloced */ - return NULL; -#endif + if (getenv ("SECMEM_FORCE_FALLBACK")) + return NULL; block = pool_alloc (); if (!block) @@ -902,7 +941,7 @@ sec_block_create (size_t size, /* The size above is a minimum, we're free to go bigger */ if (size < DEFAULT_BLOCK_SIZE) size = DEFAULT_BLOCK_SIZE; - + block->words = sec_acquire_pages (&size, during_tag); block->n_words = size / sizeof (word_t); if (!block->words) { @@ -910,11 +949,11 @@ sec_block_create (size_t size, pool_free (cell); return NULL; } - + #ifdef WITH_VALGRIND VALGRIND_MAKE_MEM_DEFINED (block->words, size); #endif - + /* The first cell to allocate from */ cell->words = block->words; cell->n_words = block->n_words; @@ -924,7 +963,7 @@ sec_block_create (size_t size, block->next = all_blocks; all_blocks = block; - + return block; } @@ -937,7 +976,7 @@ sec_block_destroy (Block *block) ASSERT (block); ASSERT (block->words); ASSERT (block->n_used == 0); - + /* Remove from the list */ for (at = &all_blocks, bl = *at; bl; at = &bl->next, bl = *at) { if (bl == block) { @@ -945,7 +984,7 @@ sec_block_destroy (Block *block) break; } } - + /* Must have been found */ ASSERT (bl == block); ASSERT (block->used_cells == NULL); @@ -956,7 +995,7 @@ sec_block_destroy (Block *block) sec_remove_cell_ring (&block->unused_cells, cell); pool_free (cell); } - + /* Release all pages of secure memory */ sec_release_pages (block->words, block->n_words * sizeof (word_t)); @@ -980,35 +1019,35 @@ egg_secure_alloc_full (const char *tag, if (length > 0xFFFFFFFF / 2) { if (egg_secure_warnings) - fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", - (unsigned long)length); + fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", + (unsigned long)length); return NULL; } /* Can't allocate zero bytes */ if (length == 0) return NULL; - + DO_LOCK (); - + for (block = all_blocks; block; block = block->next) { memory = sec_alloc (block, tag, length); if (memory) - break; + break; } - + /* None of the current blocks have space, allocate new */ if (!memory) { block = sec_block_create (length, tag); if (block) memory = sec_alloc (block, tag, length); } - + #ifdef WITH_VALGRIND if (memory != NULL) VALGRIND_MALLOCLIKE_BLOCK (memory, length, sizeof (void*), 1); #endif - + DO_UNLOCK (); if (!memory && (flags & EGG_SECURE_USE_FALLBACK)) { @@ -1016,10 +1055,10 @@ egg_secure_alloc_full (const char *tag, if (memory) /* Our returned memory is always zeroed */ memset (memory, 0, length); } - + if (!memory) errno = ENOMEM; - + return memory; } @@ -1039,20 +1078,20 @@ egg_secure_realloc_full (const char *tag, if (length > 0xFFFFFFFF / 2) { if (egg_secure_warnings) - fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", + fprintf (stderr, "tried to allocate an insane amount of memory: %lu\n", (unsigned long)length); return NULL; } - + if (memory == NULL) return egg_secure_alloc_full (tag, length, flags); if (!length) { egg_secure_free_full (memory, flags); return NULL; } - + DO_LOCK (); - + /* Find out where it belongs to */ for (block = all_blocks; block; block = block->next) { if (sec_is_valid_word (block, memory)) { @@ -1067,10 +1106,10 @@ egg_secure_realloc_full (const char *tag, #ifdef WITH_VALGRIND /* Now tell valgrind about either the new block or old one */ - VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory, - alloc ? length : previous, + VALGRIND_MALLOCLIKE_BLOCK (alloc ? alloc : memory, + alloc ? length : previous, sizeof (word_t), 1); -#endif +#endif break; } } @@ -1081,19 +1120,19 @@ egg_secure_realloc_full (const char *tag, if (block && block->n_used == 0) sec_block_destroy (block); - - DO_UNLOCK (); - + + DO_UNLOCK (); + if (!block) { if ((flags & EGG_SECURE_USE_FALLBACK)) { - /* - * In this case we can't zero the returned memory, + /* + * In this case we can't zero the returned memory, * because we don't know what the block size was. */ return egg_memory_fallback (memory, length); } else { if (egg_secure_warnings) - fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", + fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to gnome-keyring"); return NULL; @@ -1103,11 +1142,11 @@ egg_secure_realloc_full (const char *tag, if (donew) { alloc = egg_secure_alloc_full (tag, length, flags); if (alloc) { - memcpy (alloc, memory, previous); + memcpy_with_vbits (alloc, memory, previous); egg_secure_free_full (memory, flags); } } - + if (!alloc) errno = ENOMEM; @@ -1124,12 +1163,12 @@ void egg_secure_free_full (void *memory, int flags) { Block *block = NULL; - + if (memory == NULL) return; - + DO_LOCK (); - + /* Find out where it belongs to */ for (block = all_blocks; block; block = block->next) { if (sec_is_valid_word (block, memory)) @@ -1138,7 +1177,7 @@ egg_secure_free_full (void *memory, int flags) #ifdef WITH_VALGRIND /* We like valgrind's warnings, so give it a first whack at checking for errors */ - if (block != NULL || !(flags & GKR_SECURE_USE_FALLBACK)) + if (block != NULL || !(flags & EGG_SECURE_USE_FALLBACK)) VALGRIND_FREELIKE_BLOCK (memory, sizeof (word_t)); #endif @@ -1147,49 +1186,49 @@ egg_secure_free_full (void *memory, int flags) if (block->n_used == 0) sec_block_destroy (block); } - + DO_UNLOCK (); - + if (!block) { if ((flags & EGG_SECURE_USE_FALLBACK)) { egg_memory_fallback (memory, 0); } else { if (egg_secure_warnings) - fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", + fprintf (stderr, "memory does not belong to gnome-keyring: 0x%08lx\n", (unsigned long)memory); ASSERT (0 && "memory does does not belong to gnome-keyring"); } } -} +} -int +int egg_secure_check (const void *memory) { Block *block = NULL; DO_LOCK (); - + /* Find out where it belongs to */ for (block = all_blocks; block; block = block->next) { if (sec_is_valid_word (block, (word_t*)memory)) break; } - + DO_UNLOCK (); - + return block == NULL ? 0 : 1; -} +} void egg_secure_validate (void) { Block *block = NULL; - + DO_LOCK (); - + for (block = all_blocks; block; block = block->next) sec_validate (block); - + DO_UNLOCK (); } @@ -1272,7 +1311,7 @@ egg_secure_strdup_full (const char *tag, if (!str) return NULL; - len = strlen (str) + 1; + len = strlen (str) + 1; res = (char *)egg_secure_alloc_full (tag, len, options); strcpy (res, str); return res; @@ -1282,10 +1321,10 @@ void egg_secure_clear (void *p, size_t length) { volatile char *vp; - + if (p == NULL) return; - + vp = (volatile char*)p; while (length) { *vp = 0xAA; @@ -1307,10 +1346,10 @@ egg_secure_strfree (char *str) { /* * If we're using unpageable 'secure' memory, then the free call - * should zero out the memory, but because on certain platforms + * should zero out the memory, but because on certain platforms * we may be using normal memory, zero it out here just in case. */ - + egg_secure_strclear (str); egg_secure_free_full (str, EGG_SECURE_USE_FALLBACK); } diff --git a/egg/egg-secure-memory.h b/egg/egg-secure-memory.h index a2d7f04..682811d 100644 --- a/egg/egg-secure-memory.h +++ b/egg/egg-secure-memory.h @@ -27,31 +27,31 @@ #include <stdlib.h> /* ------------------------------------------------------------------- - * Low Level Secure Memory - * - * IMPORTANT: This is pure vanila standard C, no glib. We need this - * because certain consumers of this protocol need to be built + * Low Level Secure Memory + * + * IMPORTANT: This is pure vanila standard C, no glib. We need this + * because certain consumers of this protocol need to be built * without linking in any special libraries. ie: the PKCS#11 module. - * + * * Thread locking - * + * * In order to use these functions in a module the following functions - * must be defined somewhere, and provide appropriate locking for + * must be defined somewhere, and provide appropriate locking for * secure memory between threads: */ - + extern void egg_memory_lock (void); extern void egg_memory_unlock (void); /* * Allocation Fallbacks - * + * * If we cannot allocate secure memory, then this function - * (defined elsewhere) will be called which has a chance to + * (defined elsewhere) will be called which has a chance to * allocate other memory abort or do whatever. - * - * Same call semantics as realloc with regard to NULL and zeros + * + * Same call semantics as realloc with regard to NULL and zeros */ extern void* egg_memory_fallback (void *p, size_t length); @@ -64,12 +64,12 @@ extern void* egg_memory_fallback (void *p, size_t length); void* egg_memory_fallback (void *p, size_t sz) \ { return g_realloc (p, sz); } \ -/* +/* * Main functionality - * + * * Allocations return NULL on failure. - */ - + */ + #define EGG_SECURE_USE_FALLBACK 0x0001 #define EGG_SECURE_DECLARE(tag) \ @@ -87,13 +87,13 @@ void* egg_secure_alloc_full (const char *tag, size_t length, int options); void* egg_secure_realloc_full (const char *tag, void *p, size_t length, int options); -void egg_secure_free (void* p); +void egg_secure_free (void* p); -void egg_secure_free_full (void* p, int fallback); +void egg_secure_free_full (void* p, int fallback); void egg_secure_clear (void *p, size_t length); -int egg_secure_check (const void* p); +int egg_secure_check (const void* p); void egg_secure_validate (void); diff --git a/egg/egg-symkey.c b/egg/egg-symkey.c index 835d4a3..71c1573 100644 --- a/egg/egg-symkey.c +++ b/egg/egg-symkey.c @@ -1196,6 +1196,5 @@ egg_symkey_read_mac (GQuark oid_scheme, if (ret == FALSE) g_message ("unsupported or invalid mac: %s", g_quark_to_string (oid_scheme)); - egg_bytes_unref (data); return ret; } diff --git a/egg/egg-testing.c b/egg/egg-testing.c index cd7f5c2..9f30ec6 100644 --- a/egg/egg-testing.c +++ b/egg/egg-testing.c @@ -30,21 +30,39 @@ #include <errno.h> #include <unistd.h> +#ifdef WITH_VALGRIND +#include <valgrind/valgrind.h> +#endif + +#if 0 static GCond *wait_condition = NULL; static GCond *wait_start = NULL; static GMutex *wait_mutex = NULL; static gboolean wait_waiting = FALSE; +#endif + +gboolean +egg_testing_on_valgrind (void) +{ +#ifdef WITH_VALGRIND + return RUNNING_ON_VALGRIND; +#else + return FALSE +#endif +} + static const char HEXC[] = "0123456789ABCDEF"; -static gchar* -hex_dump (const guchar *data, gsize n_data) +gchar * +egg_test_escape_data (const guchar *data, + gsize n_data) { GString *result; gsize i; guchar j; - g_assert (data); + g_assert (data != NULL); result = g_string_sized_new (n_data * 2 + 1); for (i = 0; i < n_data; ++i) { @@ -72,8 +90,8 @@ egg_assertion_message_cmpmem (const char *domain, gsize n_arg2) { char *a1, *a2, *s; - a1 = arg1 ? hex_dump (arg1, n_arg1) : g_strdup ("NULL"); - a2 = arg2 ? hex_dump (arg2, n_arg2) : g_strdup ("NULL"); + a1 = arg1 ? egg_test_escape_data (arg1, n_arg1) : g_strdup ("NULL"); + a2 = arg2 ? egg_test_escape_data (arg2, n_arg2) : g_strdup ("NULL"); s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2); g_free (a1); g_free (a2); @@ -82,6 +100,29 @@ egg_assertion_message_cmpmem (const char *domain, } void +egg_assertion_not_object (const char *domain, + const char *file, + int line, + const char *func, + const char *expr, + gpointer was_object) +{ + gchar *s; + +#ifdef WITH_VALGRIND + if (RUNNING_ON_VALGRIND) + return; +#endif + + if (G_IS_OBJECT (was_object)) { + s = g_strdup_printf ("assertion failed: %s is still referenced", expr); + g_assertion_message (domain, file, line, func, s); + g_free (s); + } +} + +#if 0 +void egg_test_wait_stop (void) { GTimeVal tv; @@ -132,7 +173,7 @@ testing_thread (gpointer loop) } gint -egg_tests_run_in_thread_with_loop (void) +egg_tests_run_with_loop (void) { GThread *thread; GMainLoop *loop; @@ -153,7 +194,85 @@ egg_tests_run_in_thread_with_loop (void) g_main_loop_unref (loop); g_cond_free (wait_condition); + g_cond_free (wait_start); g_mutex_free (wait_mutex); return GPOINTER_TO_INT (ret); } +#endif + + +static void (*wait_stop_impl) (void); +static gboolean (*wait_until_impl) (int timeout); + +void +egg_test_wait_stop (void) +{ + g_assert (wait_stop_impl != NULL); + (wait_stop_impl) (); +} + +gboolean +egg_test_wait_until (int timeout) +{ + g_assert (wait_until_impl != NULL); + return (wait_until_impl) (timeout); +} + +static GMainLoop *wait_loop = NULL; + +static void +loop_wait_stop (void) +{ + g_assert (wait_loop != NULL); + g_main_loop_quit (wait_loop); +} + +static gboolean +on_loop_wait_timeout (gpointer data) +{ + gboolean *timed_out = data; + *timed_out = TRUE; + + g_assert (wait_loop != NULL); + g_main_loop_quit (wait_loop); + + return TRUE; /* we remove this source later */ +} + +static gboolean +loop_wait_until (int timeout) +{ + gboolean timed_out = FALSE; + guint source; + + g_assert (wait_loop == NULL); + wait_loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE); + + source = g_timeout_add (timeout, on_loop_wait_timeout, &timed_out); + + g_main_loop_run (wait_loop); + + g_source_remove (source); + g_main_loop_unref (wait_loop); + wait_loop = NULL; + return !timed_out; +} + +gint +egg_tests_run_with_loop (void) +{ + gint ret; + + wait_stop_impl = loop_wait_stop; + wait_until_impl = loop_wait_until; + + ret = g_test_run (); + + wait_stop_impl = NULL; + wait_until_impl = NULL; + + while (g_main_context_iteration (NULL, FALSE)); + + return ret; +} diff --git a/egg/egg-testing.h b/egg/egg-testing.h index f6b7a0e..529443f 100644 --- a/egg/egg-testing.h +++ b/egg/egg-testing.h @@ -43,10 +43,25 @@ void egg_assertion_message_cmpmem (const char *domain, const char * gsize n_arg1, const char *cmp, gconstpointer arg2, gsize n_arg2); +#define egg_assert_not_object(p) \ + (egg_assertion_not_object (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #p, (p))) + +void egg_assertion_not_object (const char *domain, + const char *file, + int line, + const char *func, + const char *expr, + gpointer was_object); + +gboolean egg_testing_on_valgrind (void); + +gchar * egg_test_escape_data (const guchar *data, + gsize size); + void egg_test_wait_stop (void); gboolean egg_test_wait_until (int timeout); -gint egg_tests_run_in_thread_with_loop (void); +gint egg_tests_run_with_loop (void); #endif /* EGG_DH_H_ */ diff --git a/egg/tests/Makefile.am b/egg/tests/Makefile.am index 7ea9d25..536958d 100644 --- a/egg/tests/Makefile.am +++ b/egg/tests/Makefile.am @@ -1,3 +1,4 @@ +include $(top_srcdir)/Makefile.decl asn1-def-test.c: test.asn $(ASN1PARSER) -o asn1-def-test.c $(srcdir)/test.asn @@ -38,6 +39,8 @@ test: $(TEST_PROGS) check-local: test +check-memory: perform-memcheck + all-local: $(check_PROGRAMS) EXTRA_DIST = \ diff --git a/egg/tests/test-asn1.c b/egg/tests/test-asn1.c index 2ab9f52..222042b 100644 --- a/egg/tests/test-asn1.c +++ b/egg/tests/test-asn1.c @@ -405,7 +405,7 @@ test_bit_string_encode_decode (void) asn = egg_asn1x_create (test_asn1_tab, "TestBitString"); g_assert (asn); - egg_asn1x_set_bits_as_raw (asn, egg_bytes_new (bits, 3), n_bits); + egg_asn1x_take_bits_as_raw (asn, egg_bytes_new (bits, 3), n_bits); data = egg_asn1x_encode (asn, NULL); g_assert (data); @@ -467,7 +467,7 @@ test_bit_string_encode_decode_zero (void) asn = egg_asn1x_create (test_asn1_tab, "TestBitString"); g_assert (asn); - egg_asn1x_set_bits_as_raw (asn, egg_bytes_new_static ("", 0), 0); + egg_asn1x_take_bits_as_raw (asn, egg_bytes_new_static ("", 0), 0); data = egg_asn1x_encode (asn, NULL); g_assert (data); @@ -911,6 +911,7 @@ test_asn1_integers (Test* test, gconstpointer unused) g_assert ("couldn't read integer from asn1" && ret); g_assert_cmpuint (val, ==, 209384022); + egg_asn1x_destroy (asn); egg_bytes_unref (data); } @@ -1047,11 +1048,12 @@ test_read_element (Test* test, gconstpointer unused) data = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "data", NULL)); g_assert (data != NULL); g_assert_cmpint (egg_bytes_get_size (data), ==, 11); + egg_bytes_unref (data); data = egg_asn1x_get_raw_value (egg_asn1x_node (asn, "data", NULL)); g_assert (data != NULL); - egg_assert_equal_bytes (data, "SOME DATA", 9); + egg_bytes_unref (data); egg_asn1x_destroy (asn); egg_bytes_unref (buffer); diff --git a/egg/tests/test-hex.c b/egg/tests/test-hex.c index e2cb9f0..93ad4bf 100644 --- a/egg/tests/test-hex.c +++ b/egg/tests/test-hex.c @@ -41,6 +41,8 @@ test_encode (void) hex = egg_hex_encode (TEST_DATA, sizeof (TEST_DATA)); g_assert (hex); g_assert_cmpstr (hex, ==, TEST_HEX); + + g_free (hex); } static void @@ -53,10 +55,14 @@ test_encode_spaces (void) g_assert (hex); g_assert_cmpstr (hex, ==, TEST_HEX); + g_free (hex); + /* Encode with spaces */ hex = egg_hex_encode_full (TEST_DATA, sizeof (TEST_DATA), TRUE, ' ', 1); g_assert (hex); g_assert_cmpstr (hex, ==, TEST_HEX_DELIM); + + g_free (hex); } static void diff --git a/egg/tests/test-openssl.c b/egg/tests/test-openssl.c index d3d672e..57b0e8e 100644 --- a/egg/tests/test-openssl.c +++ b/egg/tests/test-openssl.c @@ -142,6 +142,8 @@ test_write_reference (Test *test, gconstpointer unused) g_assert ("data length doesn't match input length" && n_encrypted == test->n_refenc); g_assert ("data doesn't match input" && memcmp (encrypted, test->refenc, n_encrypted) == 0); + + g_free (encrypted); } static void @@ -206,6 +208,8 @@ test_openssl_roundtrip (Test *test, gconstpointer unused) /* Check that the remainder is all zeros */ for (i = TEST_DATA_L; i < n_decrypted; ++i) g_assert ("non null byte in padding" && decrypted[i] == 0); + + egg_secure_free (decrypted); } int diff --git a/egg/tests/test-padding.c b/egg/tests/test-padding.c index 10a6c0e..5e10304 100644 --- a/egg/tests/test-padding.c +++ b/egg/tests/test-padding.c @@ -115,6 +115,8 @@ test_pkcs1_two_padding (void) g_assert (result[5] == 0x00); g_assert (result[6] == 'T'); g_assert (result[7] == 'E'); + + g_free (vesult); } static void diff --git a/egg/tests/test-secmem.c b/egg/tests/test-secmem.c index f5dbb7c..3a66fc4 100644 --- a/egg/tests/test-secmem.c +++ b/egg/tests/test-secmem.c @@ -97,6 +97,8 @@ test_realloc_across (void) p2 = egg_secure_realloc_full ("tests", p, 16200, 0); g_assert (p2 != NULL); g_assert_cmpint (G_MAXSIZE, ==, find_non_zero (p2, 16200)); + + egg_secure_free (p2); } static void @@ -180,26 +182,25 @@ test_multialloc (void) case 0: /* Allocate some memory */ size = g_random_int_range (1, 16384); data = egg_secure_alloc (size); - g_assert (data); + g_assert (data != NULL); memset (data, 0xCAFEBABE, size); g_ptr_array_add (memory, data); break; case 1: /* Reallocate some memory */ index = g_random_int_range (0, memory->len); data = g_ptr_array_index (memory, index); - g_assert (data); + g_assert (data != NULL); size = g_random_int_range (1, 16384); data = egg_secure_realloc (data, size); - g_assert (data); + g_assert (data != NULL); memset (data, 0xCAFEBABE, size); g_ptr_array_index (memory, index) = data; break; case 2: /* Free some memory */ index = g_random_int_range (0, memory->len); - data = g_ptr_array_index (memory, index); - g_assert (data); + data = g_ptr_array_remove_index_fast (memory, index); + g_assert (data != NULL); egg_secure_free (data); - g_ptr_array_remove_index_fast (memory, index); break; default: g_assert_not_reached (); @@ -212,6 +213,8 @@ test_multialloc (void) } g_assert (memory->len == 0); + for (i = 0; i < memory->len; i++) + egg_secure_free (memory->pdata[i]); g_ptr_array_free (memory, TRUE); egg_secure_warnings = 1; diff --git a/egg/tests/test-symkey.c b/egg/tests/test-symkey.c index b65ee30..409ec44 100644 --- a/egg/tests/test-symkey.c +++ b/egg/tests/test-symkey.c @@ -138,6 +138,8 @@ test_generate_key_simple (void) gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0); g_assert (ret && "invalid simple key generated"); + + egg_secure_free (key); } } @@ -165,6 +167,8 @@ test_generate_key_pkcs12 (void) gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0); g_assert ("invalid pkcs12 key generated" && ret); + + egg_secure_free (key); } } @@ -192,6 +196,8 @@ test_generate_key_pbkdf2 (void) gcry_cipher_get_algo_keylen (all_generation_tests[i].cipher_algo)) == 0); g_assert ("invalid pbkdf2 key generated" && ret); + + egg_secure_free (key); } } @@ -220,6 +226,7 @@ test_generate_key_pbe (void) g_assert ("invalid pbe key generated" && ret); + egg_secure_free (key); } } |