AES-NI/OCB: Perform checksumming inline with encryption
[libgcrypt.git] / src / stdmem.c
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 \f
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 _gcry_private_enable_m_guard (void)
79 {
80   use_m_guard = 1;
81 }
82
83
84 /*
85  * Allocate memory of size n.
86  * Return NULL if we are out of memory.
87  */
88 void *
89 _gcry_private_malloc (size_t n)
90 {
91   if (!n)
92     {
93       gpg_err_set_errno (EINVAL);
94       return NULL; /* Allocating 0 bytes is undefined - we better return
95                       an error to detect such coding errors.  */
96     }
97
98   if (use_m_guard)
99     {
100       char *p;
101
102       if ( !(p = malloc (n + EXTRA_ALIGN+5)) )
103         return NULL;
104       ((byte*)p)[EXTRA_ALIGN+0] = n;
105       ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
106       ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
107       ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
108       p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
109       return p+EXTRA_ALIGN+4;
110     }
111   else
112     {
113       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 _gcry_private_malloc_secure (size_t n, int xhint)
125 {
126   if (!n)
127     {
128       gpg_err_set_errno (EINVAL);
129       return NULL; /* Allocating 0 bytes is undefined - better return an
130                       error to detect such coding errors.  */
131     }
132
133   if (use_m_guard)
134     {
135       char *p;
136
137       if (!(p = _gcry_secmem_malloc (n + EXTRA_ALIGN + 5, xhint)))
138         return NULL;
139       ((byte*)p)[EXTRA_ALIGN+0] = n;
140       ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
141       ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
142       ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
143       p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
144       return p+EXTRA_ALIGN+4;
145     }
146   else
147     {
148       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 _gcry_private_realloc (void *a, size_t n, int xhint)
160 {
161   if (use_m_guard)
162     {
163       unsigned char *p = a;
164       char *b;
165       size_t len;
166
167       if (!a)
168         return _gcry_private_malloc(n);
169
170       _gcry_private_check_heap(p);
171       len  = p[-4];
172       len |= p[-3] << 8;
173       len |= p[-2] << 16;
174       if( len >= n ) /* We don't shrink for now. */
175         return a;
176       if (p[-1] == MAGIC_SEC_BYTE)
177         b = _gcry_private_malloc_secure (n, xhint);
178       else
179         b = _gcry_private_malloc(n);
180       if (!b)
181         return NULL;
182       memcpy (b, a, len);
183       memset (b+len, 0, n-len);
184       _gcry_private_free (p);
185       return b;
186     }
187   else if ( _gcry_private_is_secure(a) )
188     {
189       return _gcry_secmem_realloc (a, n, xhint);
190     }
191   else
192     {
193       return realloc( a, n );
194     }
195 }
196
197
198 void
199 _gcry_private_check_heap (const void *a)
200 {
201   if (use_m_guard)
202     {
203       const byte *p = a;
204       size_t len;
205
206       if (!p)
207         return;
208
209       if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
210         _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
211       len  = p[-4];
212       len |= p[-3] << 8;
213       len |= p[-2] << 16;
214       if ( p[len] != MAGIC_END_BYTE )
215         _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 _gcry_private_free (void *a)
225 {
226   unsigned char *p = a;
227   unsigned char *freep;
228
229   if (!p)
230     return;
231   if (use_m_guard)
232     {
233       _gcry_private_check_heap (p);
234       freep = p - EXTRA_ALIGN - 4;
235     }
236   else
237     {
238       freep = p;
239     }
240
241   if (!_gcry_private_is_secure (freep) ||
242       !_gcry_secmem_free (freep))
243     {
244       free (freep);
245     }
246 }