|
Packit Service |
f02b19 |
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
|
|
Packit Service |
f02b19 |
/* gcr-secure-memory.c - library for allocating memory that is non-pageable
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
Copyright (C) 2007 Stefan Walter
|
|
Packit Service |
f02b19 |
Copyright (C) 2012 Red Hat Inc.
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
The Gnome Keyring Library is free software; you can redistribute it and/or
|
|
Packit Service |
f02b19 |
modify it under the terms of the GNU Library General Public License as
|
|
Packit Service |
f02b19 |
published by the Free Software Foundation; either version 2 of the
|
|
Packit Service |
f02b19 |
License, or (at your option) any later version.
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
The Gnome Keyring Library is distributed in the hope that it will be useful,
|
|
Packit Service |
f02b19 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
f02b19 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit Service |
f02b19 |
Library General Public License for more details.
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
You should have received a copy of the GNU Library General Public
|
|
Packit Service |
f02b19 |
License along with the Gnome Library; see the file COPYING.LIB. If not,
|
|
Packit Service |
f02b19 |
see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
Author: Stef Walter <stefw@gnome.org>
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
#include "config.h"
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
#include "gcr-secure-memory.h"
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
#include "egg/egg-secure-memory.h"
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
#include <glib.h>
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
#include <string.h>
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* SECTION:gcr-secure-memory
|
|
Packit Service |
f02b19 |
* @title: Non-pageable Memory
|
|
Packit Service |
f02b19 |
* @short_description: Secure non-pageable memory
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Normal allocated memory can be paged to disk at the whim of the operating
|
|
Packit Service |
f02b19 |
* system. This can be a problem for sensitive information like passwords, keys
|
|
Packit Service |
f02b19 |
* and secrets.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* The Gcr library holds passwords and keys in non-pageable, or locked memory.
|
|
Packit Service |
f02b19 |
* This is only possible if the OS contains support for it.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* These functions allow applications to use secure memory to hold passwords
|
|
Packit Service |
f02b19 |
* and other sensitive information.
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_new: (skip)
|
|
Packit Service |
f02b19 |
* @type: C type of the objects to allocate
|
|
Packit Service |
f02b19 |
* @n_objects: number of objects to allocate
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Allocate objects in non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Returns: (transfer full): the new block of memory
|
|
Packit Service |
f02b19 |
**/
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_alloc: (skip)
|
|
Packit Service |
f02b19 |
* @size: The new desired size of the memory block.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Allocate a block of non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* If non-pageable memory cannot be allocated then normal memory will be
|
|
Packit Service |
f02b19 |
* returned.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Return value: (transfer full): new memory block which should be freed
|
|
Packit Service |
f02b19 |
* with gcr_secure_memory_free()
|
|
Packit Service |
f02b19 |
**/
|
|
Packit Service |
f02b19 |
gpointer
|
|
Packit Service |
f02b19 |
gcr_secure_memory_alloc (gsize size)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
gpointer memory;
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/* Try to allocate secure memory */
|
|
Packit Service |
f02b19 |
memory = egg_secure_alloc_full ("gcr-secure-memory", size,
|
|
Packit Service |
f02b19 |
EGG_SECURE_USE_FALLBACK);
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/* Our fallback will always allocate */
|
|
Packit Service |
f02b19 |
g_assert (memory != NULL);
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
return memory;
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_try_alloc: (skip)
|
|
Packit Service |
f02b19 |
* @size: new desired size of the memory block
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Allocate a block of non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* If non-pageable memory cannot be allocated, then %NULL is returned.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Return value: (transfer full): new block, or %NULL if memory cannot be
|
|
Packit Service |
f02b19 |
* allocated; memory block should be freed with gcr_secure_memory_free()
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
gpointer
|
|
Packit Service |
f02b19 |
gcr_secure_memory_try_alloc (gsize size)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
return egg_secure_alloc_full ("gcr-secure-memory", size, 0);
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_realloc: (skip)
|
|
Packit Service |
f02b19 |
* @memory: (allow-none): pointer to reallocate or %NULL to allocate a new block
|
|
Packit Service |
f02b19 |
* @size: new desired size of the memory block, or 0 to free the memory
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Reallocate a block of non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Glib memory is also reallocated correctly. If called with a null pointer,
|
|
Packit Service |
f02b19 |
* then a new block of memory is allocated. If called with a zero size,
|
|
Packit Service |
f02b19 |
* then the block of memory is freed.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* If non-pageable memory cannot be allocated then normal memory will be
|
|
Packit Service |
f02b19 |
* returned.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Return value: (transfer full): new block, or %NULL if the block was
|
|
Packit Service |
f02b19 |
* freed; memory block should be freed with gcr_secure_memory_free()
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
gpointer
|
|
Packit Service |
f02b19 |
gcr_secure_memory_realloc (gpointer memory,
|
|
Packit Service |
f02b19 |
gsize size)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
gpointer new_memory;
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
if (!memory) {
|
|
Packit Service |
f02b19 |
return gcr_secure_memory_alloc (size);
|
|
Packit Service |
f02b19 |
} else if (!size) {
|
|
Packit Service |
f02b19 |
gcr_secure_memory_free (memory);
|
|
Packit Service |
f02b19 |
return NULL;
|
|
Packit Service |
f02b19 |
} else if (!egg_secure_check (memory)) {
|
|
Packit Service |
f02b19 |
return g_realloc (memory, size);
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/* First try and ask secure memory to reallocate */
|
|
Packit Service |
f02b19 |
new_memory = egg_secure_realloc_full ("gcr-secure-memory", memory,
|
|
Packit Service |
f02b19 |
size, EGG_SECURE_USE_FALLBACK);
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
g_assert (new_memory != NULL);
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
return new_memory;
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_try_realloc: (skip)
|
|
Packit Service |
f02b19 |
* @memory: (allow-none): pointer to reallocate or %NULL to allocate a new block
|
|
Packit Service |
f02b19 |
* @size: new desired size of the memory block
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Reallocate a block of non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Glib memory is also reallocated correctly when passed to this function.
|
|
Packit Service |
f02b19 |
* If called with a null pointer, then a new block of memory is allocated.
|
|
Packit Service |
f02b19 |
* If called with a zero size, then the block of memory is freed.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* If memory cannot be allocated, %NULL is returned and the original block
|
|
Packit Service |
f02b19 |
* of memory remains intact.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Return value: (transfer full): the new block, or %NULL if memory cannot be
|
|
Packit Service |
f02b19 |
* allocated; the memory block should be freed with gcr_secure_memory_free()
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
gpointer
|
|
Packit Service |
f02b19 |
gcr_secure_memory_try_realloc (gpointer memory,
|
|
Packit Service |
f02b19 |
gsize size)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
gpointer new_memory;
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
if (!memory) {
|
|
Packit Service |
f02b19 |
return gcr_secure_memory_try_alloc (size);
|
|
Packit Service |
f02b19 |
} else if (!size) {
|
|
Packit Service |
f02b19 |
gcr_secure_memory_free (memory);
|
|
Packit Service |
f02b19 |
return NULL;
|
|
Packit Service |
f02b19 |
} else if (!egg_secure_check (memory)) {
|
|
Packit Service |
f02b19 |
return g_try_realloc (memory, size);
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/* First try and ask secure memory to reallocate */
|
|
Packit Service |
f02b19 |
new_memory = egg_secure_realloc_full ("gcr-secure-memory", memory,
|
|
Packit Service |
f02b19 |
size, 0);
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/* Might be NULL if reallocation failed. */
|
|
Packit Service |
f02b19 |
return new_memory;
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_free: (skip)
|
|
Packit Service |
f02b19 |
* @memory: (allow-none): pointer to the beginning of the block of memory to free
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Free a block of non-pageable memory.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Glib memory is also freed correctly when passed to this function. If called
|
|
Packit Service |
f02b19 |
* with a %NULL pointer then no action is taken.
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
void
|
|
Packit Service |
f02b19 |
gcr_secure_memory_free (gpointer memory)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
if (!memory)
|
|
Packit Service |
f02b19 |
return;
|
|
Packit Service |
f02b19 |
egg_secure_free_full (memory, EGG_SECURE_USE_FALLBACK);
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_is_secure: (skip)
|
|
Packit Service |
f02b19 |
* @memory: pointer to check
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Check if a pointer is in non-pageable memory allocated by.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Returns: whether the memory is secure non-pageable memory allocated by the
|
|
Packit Service |
f02b19 |
* Gcr library or not
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
gboolean
|
|
Packit Service |
f02b19 |
gcr_secure_memory_is_secure (gpointer memory)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
return egg_secure_check (memory) ? TRUE : FALSE;
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_strdup: (skip)
|
|
Packit Service |
f02b19 |
* @string: (allow-none): null terminated string to copy
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Copy a string into non-pageable memory. If the input string is %NULL, then
|
|
Packit Service |
f02b19 |
* %NULL will be returned.
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Returns: copied string, should be freed with gcr_secure_memory_free()
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
gchar *
|
|
Packit Service |
f02b19 |
gcr_secure_memory_strdup (const gchar* string)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
return egg_secure_strdup_full ("gcr-secure-memory", string,
|
|
Packit Service |
f02b19 |
EGG_SECURE_USE_FALLBACK);
|
|
Packit Service |
f02b19 |
}
|
|
Packit Service |
f02b19 |
|
|
Packit Service |
f02b19 |
/**
|
|
Packit Service |
f02b19 |
* gcr_secure_memory_strfree: (skip)
|
|
Packit Service |
f02b19 |
* @string: (allow-none): null terminated string to fere
|
|
Packit Service |
f02b19 |
*
|
|
Packit Service |
f02b19 |
* Free a string, whether securely allocated using these functions or not.
|
|
Packit Service |
f02b19 |
* This will also clear out the contents of the string so they do not
|
|
Packit Service |
f02b19 |
* remain in memory.
|
|
Packit Service |
f02b19 |
*/
|
|
Packit Service |
f02b19 |
void
|
|
Packit Service |
f02b19 |
gcr_secure_memory_strfree (gchar *string)
|
|
Packit Service |
f02b19 |
{
|
|
Packit Service |
f02b19 |
egg_secure_strfree (string);
|
|
Packit Service |
f02b19 |
}
|