(_gcry_module_release): Don't act if module is NULL.
[libgcrypt.git] / src / stdmem.c
1 /* stdmem.c  -  private memory allocator
2  *      Copyright (C) 1998, 2000, 2002 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 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26
27 #include "g10lib.h"
28 #include "stdmem.h"
29 #include "secmem.h"
30
31
32 #define MAGIC_NOR_BYTE 0x55
33 #define MAGIC_SEC_BYTE 0xcc
34 #define MAGIC_END_BYTE 0xaa
35
36 #if SIZEOF_UNSIGNED_LONG == 8
37 #define EXTRA_ALIGN 4
38 #else
39 #define EXTRA_ALIGN 0
40 #endif
41
42
43 static int use_m_guard = 0;
44
45 /****************
46  * Warning: Never use this function after any of the functions
47  * here have been used.
48  */
49 void
50 _gcry_private_enable_m_guard(void)
51 {
52     use_m_guard = 1;
53 }
54
55 /****************
56  * Allocate memory of size n.
57  * Return NULL if we are out of memory.
58  */
59 void *
60 _gcry_private_malloc( size_t n)
61 {
62     if(!n) 
63       return NULL; /* allocating 0 bytes is undefined - better return
64                       an error */
65     if( use_m_guard ) {
66         char *p;
67
68         if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
69             return NULL;
70         ((byte*)p)[EXTRA_ALIGN+0] = n;
71         ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
72         ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
73         ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_NOR_BYTE;
74         p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
75         return p+EXTRA_ALIGN+4;
76     }
77     else {
78         return malloc( n );
79     }
80 }
81
82 /****************
83  * Allocate memory of size n from the secure memory pool.
84  * Return NULL if we are out of memory.
85  */
86 void *
87 _gcry_private_malloc_secure( size_t n)
88 {
89     if(!n) 
90       return NULL; /* allocating 0 bytes is undefined - better return
91                       an error */
92     if( use_m_guard ) {
93         char *p;
94
95         if( !(p = _gcry_secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
96             return NULL;
97         ((byte*)p)[EXTRA_ALIGN+0] = n;
98         ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ;
99         ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ;
100         ((byte*)p)[EXTRA_ALIGN+3] = MAGIC_SEC_BYTE;
101         p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
102         return p+EXTRA_ALIGN+4;
103     }
104     else {
105         return _gcry_secmem_malloc( n );
106     }
107 }
108
109
110 /****************
111  * realloc and clear the old space
112  * Return NULL if there is not enoug memory.
113  */
114 void *
115 _gcry_private_realloc( void *a, size_t n )
116 {
117     if( use_m_guard ) {
118         unsigned char *p = a;
119         char *b;
120         size_t len;
121
122         if (!a)
123           return _gcry_private_malloc(n);
124         
125         _gcry_private_check_heap(p);
126         len  = p[-4];
127         len |= p[-3] << 8;
128         len |= p[-2] << 16;
129         if( len >= n ) /* we don't shrink for now */
130             return a;
131         if( p[-1] == MAGIC_SEC_BYTE )
132             b = _gcry_private_malloc_secure(n);
133         else
134             b = _gcry_private_malloc(n);
135         if( !b )
136             return NULL;
137         memcpy(b, a, len );
138         memset(b+len, 0, n-len );
139         _gcry_private_free( p );
140         return b;
141     }
142     else if( _gcry_private_is_secure(a) ) {
143         return _gcry_secmem_realloc( a, n );
144     }
145     else {
146         return realloc( a, n );
147     }
148 }
149
150
151 void
152 _gcry_private_check_heap( const void *a )
153 {
154     if( use_m_guard ) {
155         const byte *p = a;
156         size_t len;
157
158         if( !p )
159             return;
160
161         if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
162             _gcry_log_fatal("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
163         len  = p[-4];
164         len |= p[-3] << 8;
165         len |= p[-2] << 16;
166         if( p[len] != MAGIC_END_BYTE )
167             _gcry_log_fatal("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
168     }
169 }
170
171 /****************
172  * Free a memory block allocated by this opr the secmem module
173  */
174 void
175 _gcry_private_free( void *a )
176 {
177     byte *p = a;
178
179     if( !p )
180         return;
181     if( use_m_guard ) {
182         _gcry_private_check_heap(p);
183         if( _gcry_private_is_secure(a) )
184             _gcry_secmem_free(p-EXTRA_ALIGN-4);
185         else {
186             free(p-EXTRA_ALIGN-4);
187         }
188     }
189     else if( _gcry_private_is_secure(a) )
190         _gcry_secmem_free(p);
191     else
192         free(p);
193 }
194
195