Completed the RNG implementaion switching.
[libgcrypt.git] / src / stdmem.c
1 /* stdmem.c  -  private memory allocator
2  *      Copyright (C) 1998, 2000, 2002, 2005 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 /*
22  * Description of the layered memory management in Libgcrypt:
23  *
24  *                                    [User]
25  *                                      |
26  *                                      |
27  *                                     \ /
28  *                      global.c: [MM entrance points]   -----> [user callbacks]
29  *                                  |          |    
30  *                                  |          |    
31  *                                 \ /        \ /
32  *
33  *      stdmem.c: [non-secure handlers] [secure handlers]
34  *
35  *                               |         |
36  *                               |         |
37  *                              \ /       \ /
38  *
39  *                  stdmem.c: [ memory guard ]
40  *
41  *                               |         |
42  *                               |         |
43  *                              \ /       \ /
44  *
45  *           libc: [ MM functions ]     secmem.c: [ secure MM functions]
46  */
47
48 #include <config.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <stdarg.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  * Allocate memory of size n.
85  * Return NULL if we are out of memory.
86  */
87 void *
88 _gcry_private_malloc( size_t n)
89 {
90     if(!n) 
91       return NULL; /* allocating 0 bytes is undefined - better return
92                       an error */
93     if( use_m_guard ) {
94         char *p;
95
96         if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
97             return NULL;
98         ((byte*)p)[EXTRA_ALIGN+0] = n;
99         ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
100         ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
101         ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
102         p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
103         return p+EXTRA_ALIGN+4;
104     }
105     else {
106         return malloc( n );
107     }
108 }
109
110 /****************
111  * Allocate memory of size n from the secure memory pool.
112  * Return NULL if we are out of memory.
113  */
114 void *
115 _gcry_private_malloc_secure( size_t n)
116 {
117     if(!n) 
118       return NULL; /* allocating 0 bytes is undefined - better return
119                       an error */
120     if( use_m_guard ) {
121         char *p;
122
123         if( !(p = _gcry_secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
124             return NULL;
125         ((byte*)p)[EXTRA_ALIGN+0] = n;
126         ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
127         ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
128         ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
129         p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
130         return p+EXTRA_ALIGN+4;
131     }
132     else {
133         return _gcry_secmem_malloc( n );
134     }
135 }
136
137
138 /****************
139  * Realloc and clear the old space
140  * Return NULL if there is not enough memory.
141  */
142 void *
143 _gcry_private_realloc( void *a, size_t n )
144 {
145     if( use_m_guard ) {
146         unsigned char *p = a;
147         char *b;
148         size_t len;
149
150         if (!a)
151           return _gcry_private_malloc(n);
152         
153         _gcry_private_check_heap(p);
154         len  = p[-4];
155         len |= p[-3] << 8;
156         len |= p[-2] << 16;
157         if( len >= n ) /* we don't shrink for now */
158             return a;
159         if( p[-1] == MAGIC_SEC_BYTE )
160             b = _gcry_private_malloc_secure(n);
161         else
162             b = _gcry_private_malloc(n);
163         if( !b )
164             return NULL;
165         memcpy(b, a, len );
166         memset(b+len, 0, n-len );
167         _gcry_private_free( p );
168         return b;
169     }
170     else if( _gcry_private_is_secure(a) ) {
171         return _gcry_secmem_realloc( a, n );
172     }
173     else {
174         return realloc( a, n );
175     }
176 }
177
178
179 void
180 _gcry_private_check_heap( const void *a )
181 {
182     if( use_m_guard ) {
183         const byte *p = a;
184         size_t len;
185
186         if( !p )
187             return;
188
189         if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
190             _gcry_log_fatal("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
191         len  = p[-4];
192         len |= p[-3] << 8;
193         len |= p[-2] << 16;
194         if( p[len] != MAGIC_END_BYTE )
195             _gcry_log_fatal("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
196     }
197 }
198
199 /****************
200  * Free a memory block allocated by this opr the secmem module
201  */
202 void
203 _gcry_private_free( void *a )
204 {
205     byte *p = a;
206
207     if( !p )
208         return;
209     if( use_m_guard ) {
210         _gcry_private_check_heap(p);
211         if( _gcry_private_is_secure(a) )
212             _gcry_secmem_free(p-EXTRA_ALIGN-4);
213         else {
214             free(p-EXTRA_ALIGN-4);
215         }
216     }
217     else if( _gcry_private_is_secure(a) )
218         _gcry_secmem_free(p);
219     else
220         free(p);
221 }
222
223