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 89081122 : _gcry_private_malloc (size_t n)
90 : {
91 89081122 : 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 89081122 : 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 89081122 : 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.
121 : */
122 : void *
123 3 : _gcry_private_malloc_secure (size_t n)
124 : {
125 3 : if (!n)
126 : {
127 0 : gpg_err_set_errno (EINVAL);
128 0 : return NULL; /* Allocating 0 bytes is undefined - better return an
129 : error to detect such coding errors. */
130 : }
131 :
132 3 : if (use_m_guard)
133 : {
134 : char *p;
135 :
136 0 : if ( !(p = _gcry_secmem_malloc (n +EXTRA_ALIGN+ 5)) )
137 0 : return NULL;
138 0 : ((byte*)p)[EXTRA_ALIGN+0] = n;
139 0 : ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
140 0 : ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
141 0 : ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
142 0 : p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
143 0 : return p+EXTRA_ALIGN+4;
144 : }
145 : else
146 : {
147 3 : return _gcry_secmem_malloc( n );
148 : }
149 : }
150 :
151 :
152 : /*
153 : * Realloc and clear the old space
154 : * Return NULL if there is not enough memory.
155 : */
156 : void *
157 207248 : _gcry_private_realloc ( void *a, size_t n )
158 : {
159 207248 : if (use_m_guard)
160 : {
161 0 : unsigned char *p = a;
162 : char *b;
163 : size_t len;
164 :
165 0 : if (!a)
166 0 : return _gcry_private_malloc(n);
167 :
168 0 : _gcry_private_check_heap(p);
169 0 : len = p[-4];
170 0 : len |= p[-3] << 8;
171 0 : len |= p[-2] << 16;
172 0 : if( len >= n ) /* We don't shrink for now. */
173 0 : return a;
174 0 : if (p[-1] == MAGIC_SEC_BYTE)
175 0 : b = _gcry_private_malloc_secure(n);
176 : else
177 0 : b = _gcry_private_malloc(n);
178 0 : if (!b)
179 0 : return NULL;
180 0 : memcpy (b, a, len);
181 0 : memset (b+len, 0, n-len);
182 0 : _gcry_private_free (p);
183 0 : return b;
184 : }
185 207248 : else if ( _gcry_private_is_secure(a) )
186 : {
187 0 : return _gcry_secmem_realloc( a, n );
188 : }
189 : else
190 : {
191 207248 : return realloc( a, n );
192 : }
193 : }
194 :
195 :
196 : void
197 0 : _gcry_private_check_heap (const void *a)
198 : {
199 0 : if (use_m_guard)
200 : {
201 0 : const byte *p = a;
202 : size_t len;
203 :
204 0 : if (!p)
205 0 : return;
206 :
207 0 : if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
208 0 : _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
209 0 : len = p[-4];
210 0 : len |= p[-3] << 8;
211 0 : len |= p[-2] << 16;
212 0 : if ( p[len] != MAGIC_END_BYTE )
213 0 : _gcry_log_fatal ("memory at %p corrupted (overflow=%02x)\n", p, p[-1]);
214 : }
215 : }
216 :
217 :
218 : /*
219 : * Free a memory block allocated by this or the secmem module
220 : */
221 : void
222 89079824 : _gcry_private_free (void *a)
223 : {
224 89079824 : unsigned char *p = a;
225 :
226 89079824 : if (!p)
227 89079824 : return;
228 89079824 : if (use_m_guard )
229 : {
230 0 : _gcry_private_check_heap(p);
231 0 : if ( _gcry_private_is_secure(a) )
232 0 : _gcry_secmem_free(p-EXTRA_ALIGN-4);
233 : else
234 : {
235 0 : free(p-EXTRA_ALIGN-4);
236 : }
237 : }
238 89079824 : else if ( _gcry_private_is_secure(a) )
239 2 : _gcry_secmem_free(p);
240 : else
241 89079822 : free(p);
242 : }
|