summaryrefslogtreecommitdiff
path: root/gcr/gcr-secure-memory.c
blob: 7a1e99d0f57956e238233c6be386a3f981b567b6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
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);
}