rsa: Add FIPS 186-4 compliant RSA probable prime key generator.
[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.
121  */
122 void *
123 _gcry_private_malloc_secure (size_t n)
124 {
125   if (!n)
126     {
127       gpg_err_set_errno (EINVAL);
128       return NULL; /* Allocating 0 bytes is undefined - better return an
129                       error to detect such coding errors.  */
130     }
131
132   if (use_m_guard)
133     {
134       char *p;
135
136       if ( !(p = _gcry_secmem_malloc (n +EXTRA_ALIGN+ 5)) )
137         return NULL;
138       ((byte*)p)[EXTRA_ALIGN+0] = n;
139       ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
140       ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
141       ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
142       p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
143       return p+EXTRA_ALIGN+4;
144     }
145   else
146     {
147       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 _gcry_private_realloc ( void *a, size_t n )
158 {
159   if (use_m_guard)
160     {
161       unsigned char *p = a;
162       char *b;
163       size_t len;
164
165       if (!a)
166         return _gcry_private_malloc(n);
167
168       _gcry_private_check_heap(p);
169       len  = p[-4];
170       len |= p[-3] << 8;
171       len |= p[-2] << 16;
172       if( len >= n ) /* We don't shrink for now. */
173         return a;
174       if (p[-1] == MAGIC_SEC_BYTE)
175         b = _gcry_private_malloc_secure(n);
176       else
177         b = _gcry_private_malloc(n);
178       if (!b)
179         return NULL;
180       memcpy (b, a, len);
181       memset (b+len, 0, n-len);
182       _gcry_private_free (p);
183       return b;
184     }
185   else if ( _gcry_private_is_secure(a) )
186     {
187       return _gcry_secmem_realloc( a, n );
188     }
189   else
190     {
191       return realloc( a, n );
192     }
193 }
194
195
196 void
197 _gcry_private_check_heap (const void *a)
198 {
199   if (use_m_guard)
200     {
201       const byte *p = a;
202       size_t len;
203
204       if (!p)
205         return;
206
207       if ( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
208         _gcry_log_fatal ("memory at %p corrupted (underflow=%02x)\n", p, p[-1]);
209       len  = p[-4];
210       len |= p[-3] << 8;
211       len |= p[-2] << 16;
212       if ( p[len] != MAGIC_END_BYTE )
213         _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 _gcry_private_free (void *a)
223 {
224   unsigned char *p = a;
225
226   if (!p)
227     return;
228   if (use_m_guard )
229     {
230       _gcry_private_check_heap(p);
231       if ( _gcry_private_is_secure(a) )
232         _gcry_secmem_free(p-EXTRA_ALIGN-4);
233       else
234         {
235           free(p-EXTRA_ALIGN-4);
236         }
237     }
238   else if ( _gcry_private_is_secure(a) )
239     _gcry_secmem_free(p);
240   else
241     free(p);
242 }