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 71static int use_m_guard = 0; 72 73/**************** 74 * Warning: Never use this function after any of the functions 75 * here have been used. 76 */ 77void 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 */ 88void * 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 */ 122void * 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 */ 156void * 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 196void 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 */ 221void 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} 243