Line data Source code
1 : /* stdmem.c - private memory allocator
2 : * Copyright (C) 1998, 2000, 2002, 2005, 2008 Free Software Foundation, Inc.
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser general Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : /*
21 : * Description of the layered memory management in Libgcrypt:
22 : *
23 : * [User]
24 : * |
25 : * |
26 : * \ /
27 : * global.c: [MM entrance points] -----> [user callbacks]
28 : * | |
29 : * | |
30 : * \ / \ /
31 : *
32 : * stdmem.c: [non-secure handlers] [secure handlers]
33 : *
34 : * | |
35 : * | |
36 : * \ / \ /
37 : *
38 : * stdmem.c: [ memory guard ]
39 : *
40 : * | |
41 : * | |
42 : * \ / \ /
43 : *
44 : * libc: [ MM functions ] secmem.c: [ secure MM functions]
45 : */
46 :
47 : #include <config.h>
48 : #include <stdio.h>
49 : #include <stdlib.h>
50 : #include <string.h>
51 : #include <stdarg.h>
52 : #include <errno.h>
53 :
54 : #include "g10lib.h"
55 : #include "stdmem.h"
56 : #include "secmem.h"
57 :
58 :
59 :
60 : #define MAGIC_NOR_BYTE 0x55
61 : #define MAGIC_SEC_BYTE 0xcc
62 : #define MAGIC_END_BYTE 0xaa
63 :
64 : #if SIZEOF_UNSIGNED_LONG == 8
65 : #define EXTRA_ALIGN 4
66 : #else
67 : #define EXTRA_ALIGN 0
68 : #endif
69 :
70 :
71 : static int use_m_guard = 0;
72 :
73 : /****************
74 : * Warning: Never use this function after any of the functions
75 : * here have been used.
76 : */
77 : void
78 0 : _gcry_private_enable_m_guard (void)
79 : {
80 0 : use_m_guard = 1;
81 0 : }
82 :
83 :
84 : /*
85 : * Allocate memory of size n.
86 : * Return NULL if we are out of memory.
87 : */
88 : void *
89 0 : _gcry_private_malloc (size_t n)
90 : {
91 0 : if (!n)
92 : {
93 0 : gpg_err_set_errno (EINVAL);
94 0 : return NULL; /* Allocating 0 bytes is undefined - we better return
95 : an error to detect such coding errors. */
96 : }
97 :
98 0 : if (use_m_guard)
99 : {
100 : char *p;
101 :
102 0 : if ( !(p = malloc (n + EXTRA_ALIGN+5)) )
103 0 : return NULL;
104 0 : ((byte*)p)[EXTRA_ALIGN+0] = n;
105 0 : ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
106 0 : ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
107 0 : ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
108 0 : p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
109 0 : return p+EXTRA_ALIGN+4;
110 : }
111 : else
112 : {
113 0 : return malloc( n );
114 : }
115 : }
116 :
117 :
118 : /*
119 : * Allocate memory of size N from the secure memory pool. Return NULL
120 : * if we are out of memory. XHINT tells the allocator that the caller
121 : * used an xmalloc style call.
122 : */
123 : void *
124 0 : _gcry_private_malloc_secure (size_t n, int xhint)
125 : {
126 0 : if (!n)
127 : {
128 0 : gpg_err_set_errno (EINVAL);
129 0 : return NULL; /* Allocating 0 bytes is undefined - better return an
130 : error to detect such coding errors. */
131 : }
132 :
133 0 : if (use_m_guard)
134 : {
135 : char *p;
136 :
137 0 : if (!(p = _gcry_secmem_malloc (n + EXTRA_ALIGN + 5, xhint)))
138 0 : return NULL;
139 0 : ((byte*)p)[EXTRA_ALIGN+0] = n;
140 0 : ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
141 0 : ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
142 0 : ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
143 0 : p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
144 0 : return p+EXTRA_ALIGN+4;
145 : }
146 : else
147 : {
148 0 : return _gcry_secmem_malloc (n, xhint);
149 : }
150 : }
151 :
152 :
153 : /*
154 : * Realloc and clear the old space. XHINT tells the allocator that
155 : * the caller used an xmalloc style call. Returns NULL if there is
156 : * not enough memory.
157 : */
158 : void *
159 0 : _gcry_private_realloc (void *a, size_t n, int xhint)
160 : {
161 0 : if (use_m_guard)
162 : {
163 0 : unsigned char *p = a;
164 : char *b;
165 : size_t len;
166 :
167 0 : if (!a)
168 0 : return _gcry_private_malloc(n);
169 :
170 0 : _gcry_private_check_heap(p);
171 0 : len = p[-4];
172 0 : len |= p[-3] << 8;
173 0 : len |= p[-2] << 16;
174 0 : if( len >= n ) /* We don't shrink for now. */
175 0 : return a;
176 0 : if (p[-1] == MAGIC_SEC_BYTE)
177 0 : b = _gcry_private_malloc_secure (n, xhint);
178 : else
179 0 : b = _gcry_private_malloc(n);
180 0 : if (!b)
181 0 : return NULL;
182 0 : memcpy (b, a, len);
183 0 : memset (b+len, 0, n-len);
184 0 : _gcry_private_free (p);
185 0 : return b;
186 : }
187 0 : else if ( _gcry_private_is_secure(a) )
188 : {
189 0 : return _gcry_secmem_realloc (a, n, xhint);
190 : }
191 : else
192 : {
193 0 : return realloc( a, n );
194 : }
195 : }
196 :
197 :
198 : void
199 0 : _gcry_private_check_heap (const void *a)
200 : {
201 0 : if (use_m_guard)
202 : {
203 0 : const byte *p = a;
204 : size_t len;
205 :
206 0 : if (!p)
207 0 : return;
208 :
209 0 : if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
210 0 : _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
211 0 : len = p[-4];
212 0 : len |= p[-3] << 8;
213 0 : len |= p[-2] << 16;
214 0 : if ( p[len] != MAGIC_END_BYTE )
215 0 : _gcry_log_fatal ("memory at %p corrupted (overflow=%02x)\n", p, p[-1]);
216 : }
217 : }
218 :
219 :
220 : /*
221 : * Free a memory block allocated by this or the secmem module
222 : */
223 : void
224 0 : _gcry_private_free (void *a)
225 : {
226 0 : unsigned char *p = a;
227 :
228 0 : if (!p)
229 0 : return;
230 0 : if (use_m_guard )
231 : {
232 0 : _gcry_private_check_heap(p);
233 0 : if (! _gcry_secmem_free (p - EXTRA_ALIGN - 4))
234 : {
235 0 : free (p - EXTRA_ALIGN - 4);
236 : }
237 : }
238 0 : else if (!_gcry_secmem_free (p))
239 : {
240 0 : free(p);
241 : }
242 : }
|