raw
ch1_mpi                 1 /* memory.c  -	memory allocation
ch1_mpi 2 * Modified by No Such Labs. (C) 2015. See README.
ch1_mpi 3 *
ch1_mpi 4 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
ch1_mpi 5 * SHA256(gnupg-1.4.10.tar.gz):
ch1_mpi 6 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
ch1_mpi 7 * (C) 1994-2005 Free Software Foundation, Inc.
ch1_mpi 8 *
ch1_mpi 9 * This program is free software: you can redistribute it and/or modify
ch1_mpi 10 * it under the terms of the GNU General Public License as published by
ch1_mpi 11 * the Free Software Foundation, either version 3 of the License, or
ch1_mpi 12 * (at your option) any later version.
ch1_mpi 13 *
ch1_mpi 14 * This program is distributed in the hope that it will be useful,
ch1_mpi 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ch1_mpi 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ch1_mpi 17 * GNU General Public License for more details.
ch1_mpi 18 *
ch1_mpi 19 * You should have received a copy of the GNU General Public License
ch1_mpi 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
ch1_mpi 21 */
ch1_mpi 22
ch1_mpi 23 /* We use our own memory allocation functions instead of plain malloc(),
ch1_mpi 24 * so that we can provide some special enhancements:
ch1_mpi 25 * a) functions to provide memory from a secure memory.
ch1_mpi 26 * b) by looking at the requested allocation size we
ch1_mpi 27 * can reuse memory very quickly (e.g. MPI storage)
ch1_mpi 28 * (really needed?)
ch1_mpi 29 * c) memory usage reporting if compiled with M_DEBUG
ch1_mpi 30 * d) memory checking if compiled with M_GUARD
ch1_mpi 31 */
ch1_mpi 32
ch1_mpi 33 #include <stdio.h>
ch1_mpi 34 #include <stdlib.h>
ch1_mpi 35 #include <stdarg.h>
ch1_mpi 36 #include <string.h>
ch1_mpi 37
ch1_mpi 38 #include "knobs.h"
ch1_mpi 39 #include "types.h"
ch1_mpi 40 #include "memory.h"
ch1_mpi 41 #include "util.h"
ch1_mpi 42
ch1_mpi 43 #define MAGIC_NOR_BYTE 0x55
ch1_mpi 44 #define MAGIC_SEC_BYTE 0xcc
ch1_mpi 45 #define MAGIC_END_BYTE 0xaa
ch1_mpi 46
ch1_mpi 47 /* This is a very crude alignment check which does not work on all CPUs
ch1_mpi 48 * IIRC, I once introduced it for testing on an Alpha. We should better
ch1_mpi 49 * replace this guard stuff with one provided by a modern malloc library
ch1_mpi 50 */
ch1_mpi 51 #if SIZEOF_UNSIGNED_LONG == 8
ch1_mpi 52 #define EXTRA_ALIGN 4
ch1_mpi 53 #else
ch1_mpi 54 #define EXTRA_ALIGN 0
ch1_mpi 55 #endif
ch1_mpi 56
ch1_mpi 57 #if defined(M_DEBUG) || defined(M_GUARD)
ch1_mpi 58 static void membug( const char *fmt, ... );
ch1_mpi 59 #endif
ch1_mpi 60
ch1_mpi 61 #ifdef M_DEBUG
ch1_mpi 62
ch1_mpi 63 #ifndef M_GUARD
ch1_mpi 64 #define M_GUARD 1
ch1_mpi 65 #endif
ch1_mpi 66 #undef xmalloc
ch1_mpi 67 #undef xtrymalloc
ch1_mpi 68 #undef xmalloc_clear
ch1_mpi 69 #undef xmalloc_secure
ch1_mpi 70 #undef xmalloc_secure_clear
ch1_mpi 71 #undef xrealloc
ch1_mpi 72 #undef xfree
ch1_mpi 73 #undef m_check
ch1_mpi 74 #undef xstrdup
ch1_mpi 75 #undef xtrystrdup
ch1_mpi 76 #define FNAME(a) m_debug_ ##a
ch1_mpi 77 #define FNAMEX(a) m_debug_ ##a
ch1_mpi 78 #define FNAMEXM(a) m_debug_ ##a
ch1_mpi 79 #define FNAMEPRT , const char *info
ch1_mpi 80 #define FNAMEARG , info
ch1_mpi 81
ch1_mpi 82 #define store_len(p,n,m) do { add_entry(p,n,m, \
ch1_mpi 83 info, __FUNCTION__); } while(0)
ch1_mpi 84 #else
ch1_mpi 85 #define FNAME(a) m_ ##a
ch1_mpi 86 #define FNAMEX(a) x ##a
ch1_mpi 87 #define FNAMEXM(a) xm ##a
ch1_mpi 88 #define FNAMEPRT
ch1_mpi 89 #define FNAMEARG
ch1_mpi 90 #define store_len(p,n,m) do { ((byte*)p)[EXTRA_ALIGN+0] = n; \
ch1_mpi 91 ((byte*)p)[EXTRA_ALIGN+1] = n >> 8 ; \
ch1_mpi 92 ((byte*)p)[EXTRA_ALIGN+2] = n >> 16 ; \
ch1_mpi 93 ((byte*)p)[EXTRA_ALIGN+3] = m? MAGIC_SEC_BYTE \
ch1_mpi 94 : MAGIC_NOR_BYTE; \
ch1_mpi 95 } while(0)
ch1_mpi 96 #endif
ch1_mpi 97
ch1_mpi 98
ch1_mpi 99 #ifdef M_GUARD
ch1_mpi 100 static long used_memory;
ch1_mpi 101 #endif
ch1_mpi 102
ch1_mpi 103 #ifdef M_DEBUG /* stuff used for memory debuging */
ch1_mpi 104
ch1_mpi 105 struct info_entry {
ch1_mpi 106 struct info_entry *next;
ch1_mpi 107 unsigned count; /* call count */
ch1_mpi 108 const char *info; /* the reference to the info string */
ch1_mpi 109 };
ch1_mpi 110
ch1_mpi 111 struct memtbl_entry {
ch1_mpi 112 const void *user_p; /* for reference: the pointer given to the user */
ch1_mpi 113 size_t user_n; /* length requested by the user */
ch1_mpi 114 struct memtbl_entry *next; /* to build a list of unused entries */
ch1_mpi 115 const struct info_entry *info; /* points into the table with */
ch1_mpi 116 /* the info strings */
ch1_mpi 117 unsigned inuse:1; /* this entry is in use */
ch1_mpi 118 unsigned count:31;
ch1_mpi 119 };
ch1_mpi 120
ch1_mpi 121
ch1_mpi 122 #define INFO_BUCKETS 53
ch1_mpi 123 #define info_hash(p) ( *(u32*)((p)) % INFO_BUCKETS )
ch1_mpi 124 static struct info_entry *info_strings[INFO_BUCKETS]; /* hash table */
ch1_mpi 125
ch1_mpi 126 static struct memtbl_entry *memtbl; /* the table with the memory info */
ch1_mpi 127 static unsigned memtbl_size; /* number of allocated entries */
ch1_mpi 128 static unsigned memtbl_len; /* number of used entries */
ch1_mpi 129 static struct memtbl_entry *memtbl_unused;/* to keep track of unused entries */
ch1_mpi 130
ch1_mpi 131 static void dump_table_at_exit(void);
ch1_mpi 132 static void dump_table(void);
ch1_mpi 133 static void check_allmem( const char *info );
ch1_mpi 134
ch1_mpi 135 /****************
ch1_mpi 136 * Put the new P into the debug table and return a pointer to the table entry.
ch1_mpi 137 * mode is true for security. BY is the name of the function which called us.
ch1_mpi 138 */
ch1_mpi 139 static void
ch1_mpi 140 add_entry( byte *p, unsigned n, int mode, const char *info, const char *by )
ch1_mpi 141 {
ch1_mpi 142 unsigned index;
ch1_mpi 143 struct memtbl_entry *e;
ch1_mpi 144 struct info_entry *ie;
ch1_mpi 145
ch1_mpi 146 if( memtbl_len < memtbl_size )
ch1_mpi 147 index = memtbl_len++;
ch1_mpi 148 else {
ch1_mpi 149 struct memtbl_entry *e;
ch1_mpi 150 /* look for a used entry in the table. We take the first one,
ch1_mpi 151 * so that freed entries remain as long as possible in the table
ch1_mpi 152 * (free appends a new one)
ch1_mpi 153 */
ch1_mpi 154 if( (e = memtbl_unused) ) {
ch1_mpi 155 index = e - memtbl;
ch1_mpi 156 memtbl_unused = e->next;
ch1_mpi 157 e->next = NULL;
ch1_mpi 158 }
ch1_mpi 159 else { /* no free entries in the table: extend the table */
ch1_mpi 160 if( !memtbl_size ) { /* first time */
ch1_mpi 161 memtbl_size = 100;
ch1_mpi 162 if( !(memtbl = calloc( memtbl_size, sizeof *memtbl )) )
ch1_mpi 163 membug("memory debug table malloc failed\n");
ch1_mpi 164 index = 0;
ch1_mpi 165 memtbl_len = 1;
ch1_mpi 166 atexit( dump_table_at_exit );
ch1_mpi 167 }
ch1_mpi 168 else { /* realloc */
ch1_mpi 169 unsigned n = memtbl_size / 4; /* enlarge by 25% */
ch1_mpi 170 if(!(memtbl = realloc(memtbl, (memtbl_size+n)*sizeof *memtbl)))
ch1_mpi 171 membug("memory debug table realloc failed\n");
ch1_mpi 172 memset(memtbl+memtbl_size, 0, n*sizeof *memtbl );
ch1_mpi 173 memtbl_size += n;
ch1_mpi 174 index = memtbl_len++;
ch1_mpi 175 }
ch1_mpi 176 }
ch1_mpi 177 }
ch1_mpi 178 e = memtbl+index;
ch1_mpi 179 if( e->inuse )
ch1_mpi 180 membug("Ooops: entry %u is flagged as in use\n", index);
ch1_mpi 181 e->user_p = p + EXTRA_ALIGN + 4;
ch1_mpi 182 e->user_n = n;
ch1_mpi 183 e->count++;
ch1_mpi 184 if( e->next )
ch1_mpi 185 membug("Ooops: entry is in free entry list\n");
ch1_mpi 186 /* do we already have this info string */
ch1_mpi 187 for( ie = info_strings[info_hash(info)]; ie; ie = ie->next )
ch1_mpi 188 if( ie->info == info )
ch1_mpi 189 break;
ch1_mpi 190 if( !ie ) { /* no: make a new entry */
ch1_mpi 191 if( !(ie = malloc( sizeof *ie )) )
ch1_mpi 192 membug("can't allocate info entry\n");
ch1_mpi 193 ie->next = info_strings[info_hash(info)];
ch1_mpi 194 info_strings[info_hash(info)] = ie;
ch1_mpi 195 ie->info = info;
ch1_mpi 196 ie->count = 0;
ch1_mpi 197 }
ch1_mpi 198 ie->count++;
ch1_mpi 199 e->info = ie;
ch1_mpi 200 e->inuse = 1;
ch1_mpi 201
ch1_mpi 202 /* put the index at the start of the memory */
ch1_mpi 203 p[EXTRA_ALIGN+0] = index;
ch1_mpi 204 p[EXTRA_ALIGN+1] = index >> 8 ;
ch1_mpi 205 p[EXTRA_ALIGN+2] = index >> 16 ;
ch1_mpi 206 p[EXTRA_ALIGN+3] = mode? MAGIC_SEC_BYTE : MAGIC_NOR_BYTE ;
ch1_mpi 207 if( DBG_MEMORY )
ch1_mpi 208 log_debug( "%s allocates %u bytes using %s\n", info, e->user_n, by );
ch1_mpi 209 }
ch1_mpi 210
ch1_mpi 211
ch1_mpi 212
ch1_mpi 213 /****************
ch1_mpi 214 * Check that the memory block is correct. The magic byte has already been
ch1_mpi 215 * checked. Checks which are done here:
ch1_mpi 216 * - see whether the index points into our memory table
ch1_mpi 217 * - see whether P is the same as the one stored in the table
ch1_mpi 218 * - see whether we have already freed this block.
ch1_mpi 219 */
ch1_mpi 220 struct memtbl_entry *
ch1_mpi 221 check_mem( const byte *p, const char *info )
ch1_mpi 222 {
ch1_mpi 223 unsigned n;
ch1_mpi 224 struct memtbl_entry *e;
ch1_mpi 225
ch1_mpi 226 n = p[EXTRA_ALIGN+0];
ch1_mpi 227 n |= p[EXTRA_ALIGN+1] << 8;
ch1_mpi 228 n |= p[EXTRA_ALIGN+2] << 16;
ch1_mpi 229
ch1_mpi 230 if( n >= memtbl_len )
ch1_mpi 231 membug("memory at %p corrupted: index=%u table_len=%u (%s)\n",
ch1_mpi 232 p+EXTRA_ALIGN+4, n, memtbl_len, info );
ch1_mpi 233 e = memtbl+n;
ch1_mpi 234
ch1_mpi 235 if( e->user_p != p+EXTRA_ALIGN+4 )
ch1_mpi 236 membug("memory at %p corrupted: reference mismatch (%s)\n",
ch1_mpi 237 p+EXTRA_ALIGN+4, info );
ch1_mpi 238 if( !e->inuse )
ch1_mpi 239 membug("memory at %p corrupted: marked as free (%s)\n",
ch1_mpi 240 p+EXTRA_ALIGN+4, info );
ch1_mpi 241
ch1_mpi 242 if( !(p[EXTRA_ALIGN+3] == MAGIC_NOR_BYTE
ch1_mpi 243 || p[EXTRA_ALIGN+3] == MAGIC_SEC_BYTE) )
ch1_mpi 244 membug("memory at %p corrupted: underflow=%02x (%s)\n",
ch1_mpi 245 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+3], info );
ch1_mpi 246 if( p[EXTRA_ALIGN+4+e->user_n] != MAGIC_END_BYTE )
ch1_mpi 247 membug("memory at %p corrupted: overflow=%02x (%s)\n",
ch1_mpi 248 p+EXTRA_ALIGN+4, p[EXTRA_ALIGN+4+e->user_n], info );
ch1_mpi 249 return e;
ch1_mpi 250 }
ch1_mpi 251
ch1_mpi 252
ch1_mpi 253 /****************
ch1_mpi 254 * free the entry and the memory (replaces free)
ch1_mpi 255 */
ch1_mpi 256 static void
ch1_mpi 257 free_entry( byte *p, const char *info )
ch1_mpi 258 {
ch1_mpi 259 struct memtbl_entry *e, *e2;
ch1_mpi 260
ch1_mpi 261 check_allmem("add_entry");
ch1_mpi 262
ch1_mpi 263 e = check_mem(p, info);
ch1_mpi 264 if( DBG_MEMORY )
ch1_mpi 265 log_debug( "%s frees %u bytes alloced by %s\n",
ch1_mpi 266 info, e->user_n, e->info->info );
ch1_mpi 267 if( !e->inuse ) {
ch1_mpi 268 if( e->user_p == p + EXTRA_ALIGN+ 4 )
ch1_mpi 269 membug("freeing an already freed pointer at %p\n", p+EXTRA_ALIGN+4 );
ch1_mpi 270 else
ch1_mpi 271 membug("freeing pointer %p which is flagged as freed\n", p+EXTRA_ALIGN+4 );
ch1_mpi 272 }
ch1_mpi 273
ch1_mpi 274 e->inuse = 0;
ch1_mpi 275 e->next = NULL;
ch1_mpi 276 if( !memtbl_unused )
ch1_mpi 277 memtbl_unused = e;
ch1_mpi 278 else {
ch1_mpi 279 for(e2=memtbl_unused; e2->next; e2 = e2->next )
ch1_mpi 280 ;
ch1_mpi 281 e2->next = e;
ch1_mpi 282 }
ch1_mpi 283 if( m_is_secure(p+EXTRA_ALIGN+4) )
ch1_mpi 284 secmem_free(p);
ch1_mpi 285 else {
ch1_mpi 286 memset(p,'f', e->user_n+5);
ch1_mpi 287 free(p);
ch1_mpi 288 }
ch1_mpi 289 }
ch1_mpi 290
ch1_mpi 291 static void
ch1_mpi 292 dump_entry(struct memtbl_entry *e )
ch1_mpi 293 {
ch1_mpi 294 unsigned n = e - memtbl;
ch1_mpi 295
ch1_mpi 296 fprintf(stderr, "mem %4u%c %5u %p %5u %s (%u)\n",
ch1_mpi 297 n, e->inuse?'a':'u', e->count, e->user_p, e->user_n,
ch1_mpi 298 e->info->info, e->info->count );
ch1_mpi 299
ch1_mpi 300
ch1_mpi 301 }
ch1_mpi 302
ch1_mpi 303
ch1_mpi 304 static void
ch1_mpi 305 dump_table_at_exit( void)
ch1_mpi 306 {
ch1_mpi 307 if( DBG_MEMSTAT )
ch1_mpi 308 dump_table();
ch1_mpi 309 }
ch1_mpi 310
ch1_mpi 311 static void
ch1_mpi 312 dump_table( void)
ch1_mpi 313 {
ch1_mpi 314 unsigned n;
ch1_mpi 315 struct memtbl_entry *e;
ch1_mpi 316 ulong sum = 0, chunks =0;
ch1_mpi 317
ch1_mpi 318 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
ch1_mpi 319 if(e->inuse) {
ch1_mpi 320 dump_entry(e);
ch1_mpi 321 sum += e->user_n;
ch1_mpi 322 chunks++;
ch1_mpi 323 }
ch1_mpi 324 }
ch1_mpi 325 fprintf(stderr, " memory used: %8lu bytes in %ld chunks\n",
ch1_mpi 326 sum, chunks );
ch1_mpi 327 }
ch1_mpi 328
ch1_mpi 329
ch1_mpi 330 static void
ch1_mpi 331 check_allmem( const char *info )
ch1_mpi 332 {
ch1_mpi 333 unsigned n;
ch1_mpi 334 struct memtbl_entry *e;
ch1_mpi 335
ch1_mpi 336 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
ch1_mpi 337 if( e->inuse ) {
ch1_mpi 338 check_mem(e->user_p-4-EXTRA_ALIGN, info);
ch1_mpi 339 }
ch1_mpi 340 }
ch1_mpi 341 }
ch1_mpi 342
ch1_mpi 343 #endif /* M_DEBUG */
ch1_mpi 344
ch1_mpi 345 #if defined(M_DEBUG) || defined(M_GUARD)
ch1_mpi 346 static void
ch1_mpi 347 membug( const char *fmt, ... )
ch1_mpi 348 {
ch1_mpi 349 va_list arg_ptr ;
ch1_mpi 350
ch1_mpi 351 fprintf(stderr, "\nMemory Error: " ) ;
ch1_mpi 352 va_start( arg_ptr, fmt ) ;
ch1_mpi 353 vfprintf(stderr,fmt,arg_ptr) ;
ch1_mpi 354 va_end(arg_ptr);
ch1_mpi 355 fflush(stderr);
ch1_mpi 356 #ifdef M_DEBUG
ch1_mpi 357 if( DBG_MEMSTAT )
ch1_mpi 358 dump_table();
ch1_mpi 359 #endif
ch1_mpi 360 abort();
ch1_mpi 361 }
ch1_mpi 362 #endif
ch1_mpi 363
ch1_mpi 364 void
ch1_mpi 365 m_print_stats( const char *prefix )
ch1_mpi 366 {
ch1_mpi 367 #ifdef M_DEBUG
ch1_mpi 368 unsigned n;
ch1_mpi 369 struct memtbl_entry *e;
ch1_mpi 370 ulong sum = 0, chunks =0;
ch1_mpi 371
ch1_mpi 372 for( e = memtbl, n = 0; n < memtbl_len; n++, e++ ) {
ch1_mpi 373 if(e->inuse) {
ch1_mpi 374 sum += e->user_n;
ch1_mpi 375 chunks++;
ch1_mpi 376 }
ch1_mpi 377 }
ch1_mpi 378
ch1_mpi 379 log_debug( "%s%smemstat: %8lu bytes in %ld chunks used\n",
ch1_mpi 380 prefix? prefix:"", prefix? ": ":"", sum, chunks );
ch1_mpi 381 #elif defined(M_GUARD)
ch1_mpi 382 log_debug( "%s%smemstat: %8ld bytes\n",
ch1_mpi 383 prefix? prefix:"", prefix? ": ":"", used_memory );
ch1_mpi 384 #endif
ch1_mpi 385 }
ch1_mpi 386
ch1_mpi 387 void
ch1_mpi 388 m_dump_table( const char *prefix )
ch1_mpi 389 {
ch1_mpi 390 #ifdef M_DEBUG
ch1_mpi 391 fprintf(stderr,"Memory-Table-Dump: %s\n", prefix);
ch1_mpi 392 dump_table();
ch1_mpi 393 #endif
ch1_mpi 394 m_print_stats( prefix );
ch1_mpi 395 }
ch1_mpi 396
ch1_mpi 397
ch1_mpi 398 static void
ch1_mpi 399 out_of_core(size_t n, int secure)
ch1_mpi 400 {
ch1_mpi 401 log_error ("out of %s memory while allocating %u bytes\n",
ch1_mpi 402 secure? "secure":"" ,(unsigned)n );
ch1_mpi 403 if (secure) {
ch1_mpi 404 /*secmem_dump_stats ();*/
ch1_mpi 405 log_info ("(this may be caused by too many secret keys used "
ch1_mpi 406 "simultaneously or due to excessive large key sizes)\n");
ch1_mpi 407 }
ch1_mpi 408 exit(2);
ch1_mpi 409 }
ch1_mpi 410
ch1_mpi 411 /****************
ch1_mpi 412 * Allocate memory of size n.
ch1_mpi 413 * This function gives up if we do not have enough memory
ch1_mpi 414 */
ch1_mpi 415 void *
ch1_mpi 416 FNAMEXM(alloc)( size_t n FNAMEPRT )
ch1_mpi 417 {
ch1_mpi 418 char *p;
ch1_mpi 419
ch1_mpi 420 #ifdef M_GUARD
ch1_mpi 421 if(!n)
ch1_mpi 422 out_of_core(n,0); /* should never happen */
ch1_mpi 423 if( !(p = malloc( n + EXTRA_ALIGN+5 )) )
ch1_mpi 424 out_of_core(n,0);
ch1_mpi 425 store_len(p,n,0);
ch1_mpi 426 used_memory += n;
ch1_mpi 427 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
ch1_mpi 428 return p+EXTRA_ALIGN+4;
ch1_mpi 429 #else
ch1_mpi 430 /* mallocing zero bytes is undefined by ISO-C, so we better make
ch1_mpi 431 sure that it won't happen */
ch1_mpi 432 if (!n)
ch1_mpi 433 n = 1;
ch1_mpi 434 if( !(p = malloc( n )) )
ch1_mpi 435 out_of_core(n,0);
ch1_mpi 436 return p;
ch1_mpi 437 #endif
ch1_mpi 438 }
ch1_mpi 439
ch1_mpi 440 /* Allocate memory of size n. This function returns NULL if we do not
ch1_mpi 441 have enough memory. */
ch1_mpi 442 void *
ch1_mpi 443 FNAMEX(trymalloc)(size_t n FNAMEPRT)
ch1_mpi 444 {
ch1_mpi 445 #ifdef M_GUARD
ch1_mpi 446 char *p;
ch1_mpi 447
ch1_mpi 448 if (!n)
ch1_mpi 449 n = 1;
ch1_mpi 450 p = malloc (n + EXTRA_ALIGN+5);
ch1_mpi 451 if (!p)
ch1_mpi 452 return NULL;
ch1_mpi 453 store_len(p,n,0);
ch1_mpi 454 used_memory += n;
ch1_mpi 455 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
ch1_mpi 456 return p+EXTRA_ALIGN+4;
ch1_mpi 457 #else
ch1_mpi 458 /* Mallocing zero bytes is undefined by ISO-C, so we better make
ch1_mpi 459 sure that it won't happen. */
ch1_mpi 460 return malloc (n? n: 1);
ch1_mpi 461 #endif
ch1_mpi 462 }
ch1_mpi 463
ch1_mpi 464 /****************
ch1_mpi 465 * Allocate memory of size n from the secure memory pool.
ch1_mpi 466 * This function gives up if we do not have enough memory
ch1_mpi 467 */
ch1_mpi 468 void *
ch1_mpi 469 FNAMEXM(alloc_secure)( size_t n FNAMEPRT )
ch1_mpi 470 {
ch1_mpi 471 char *p;
ch1_mpi 472
ch1_mpi 473 #ifdef M_GUARD
ch1_mpi 474 if(!n)
ch1_mpi 475 out_of_core(n,1); /* should never happen */
ch1_mpi 476 if( !(p = secmem_malloc( n +EXTRA_ALIGN+ 5 )) )
ch1_mpi 477 out_of_core(n,1);
ch1_mpi 478 store_len(p,n,1);
ch1_mpi 479 p[4+EXTRA_ALIGN+n] = MAGIC_END_BYTE;
ch1_mpi 480 return p+EXTRA_ALIGN+4;
ch1_mpi 481 #else
ch1_mpi 482 /* mallocing zero bytes is undefined by ISO-C, so we better make
ch1_mpi 483 sure that it won't happen */
ch1_mpi 484 if (!n)
ch1_mpi 485 n = 1;
ch1_mpi 486 if( !(p = secmem_malloc( n )) )
ch1_mpi 487 out_of_core(n,1);
ch1_mpi 488 return p;
ch1_mpi 489 #endif
ch1_mpi 490 }
ch1_mpi 491
ch1_mpi 492 void *
ch1_mpi 493 FNAMEXM(alloc_clear)( size_t n FNAMEPRT )
ch1_mpi 494 {
ch1_mpi 495 void *p;
ch1_mpi 496 p = FNAMEXM(alloc)( n FNAMEARG );
ch1_mpi 497 memset(p, 0, n );
ch1_mpi 498 return p;
ch1_mpi 499 }
ch1_mpi 500
ch1_mpi 501 void *
ch1_mpi 502 FNAMEXM(alloc_secure_clear)( size_t n FNAMEPRT)
ch1_mpi 503 {
ch1_mpi 504 void *p;
ch1_mpi 505 p = FNAMEXM(alloc_secure)( n FNAMEARG );
ch1_mpi 506 memset(p, 0, n );
ch1_mpi 507 return p;
ch1_mpi 508 }
ch1_mpi 509
ch1_mpi 510
ch1_mpi 511 /****************
ch1_mpi 512 * realloc and clear the old space
ch1_mpi 513 */
ch1_mpi 514 void *
ch1_mpi 515 FNAMEX(realloc)( void *a, size_t n FNAMEPRT )
ch1_mpi 516 {
ch1_mpi 517 void *b;
ch1_mpi 518
ch1_mpi 519 #ifdef M_GUARD
ch1_mpi 520 if( a ) {
ch1_mpi 521 #error "--enable-m-guard does not currently work"
ch1_mpi 522 unsigned char *p = a;
ch1_mpi 523 size_t len = m_size(a);
ch1_mpi 524
ch1_mpi 525 if( len >= n ) /* we don't shrink for now */
ch1_mpi 526 return a;
ch1_mpi 527 if( p[-1] == MAGIC_SEC_BYTE )
ch1_mpi 528 b = FNAME(alloc_secure_clear)(n FNAMEARG);
ch1_mpi 529 else
ch1_mpi 530 b = FNAME(alloc_clear)(n FNAMEARG);
ch1_mpi 531 FNAME(check)(NULL FNAMEARG);
ch1_mpi 532 memcpy(b, a, len );
ch1_mpi 533 FNAME(free)(p FNAMEARG);
ch1_mpi 534 }
ch1_mpi 535 else
ch1_mpi 536 b = FNAME(alloc)(n FNAMEARG);
ch1_mpi 537 #else
ch1_mpi 538 if( m_is_secure(a) ) {
ch1_mpi 539 if( !(b = secmexrealloc( a, n )) )
ch1_mpi 540 out_of_core(n,1);
ch1_mpi 541 }
ch1_mpi 542 else {
ch1_mpi 543 if( !(b = realloc( a, n )) )
ch1_mpi 544 out_of_core(n,0);
ch1_mpi 545 }
ch1_mpi 546 #endif
ch1_mpi 547
ch1_mpi 548 return b;
ch1_mpi 549 }
ch1_mpi 550
ch1_mpi 551
ch1_mpi 552
ch1_mpi 553 /****************
ch1_mpi 554 * Free a pointer
ch1_mpi 555 */
ch1_mpi 556 void
ch1_mpi 557 FNAMEX(free)( void *a FNAMEPRT )
ch1_mpi 558 {
ch1_mpi 559 byte *p = a;
ch1_mpi 560
ch1_mpi 561 if( !p )
ch1_mpi 562 return;
ch1_mpi 563 #ifdef M_DEBUG
ch1_mpi 564 free_entry(p-EXTRA_ALIGN-4, info);
ch1_mpi 565 #elif defined M_GUARD
ch1_mpi 566 m_check(p);
ch1_mpi 567 if( m_is_secure(a) )
ch1_mpi 568 secmem_free(p-EXTRA_ALIGN-4);
ch1_mpi 569 else {
ch1_mpi 570 used_memory -= m_size(a);
ch1_mpi 571 free(p-EXTRA_ALIGN-4);
ch1_mpi 572 }
ch1_mpi 573 #else
ch1_mpi 574 if( m_is_secure(a) )
ch1_mpi 575 secmem_free(p);
ch1_mpi 576 else
ch1_mpi 577 free(p);
ch1_mpi 578 #endif
ch1_mpi 579 }
ch1_mpi 580
ch1_mpi 581
ch1_mpi 582 void
ch1_mpi 583 FNAME(check)( const void *a FNAMEPRT )
ch1_mpi 584 {
ch1_mpi 585 #ifdef M_GUARD
ch1_mpi 586 const byte *p = a;
ch1_mpi 587
ch1_mpi 588 #ifdef M_DEBUG
ch1_mpi 589 if( p )
ch1_mpi 590 check_mem(p-EXTRA_ALIGN-4, info);
ch1_mpi 591 else
ch1_mpi 592 check_allmem(info);
ch1_mpi 593 #else
ch1_mpi 594 if( !p )
ch1_mpi 595 return;
ch1_mpi 596 if( !(p[-1] == MAGIC_NOR_BYTE || p[-1] == MAGIC_SEC_BYTE) )
ch1_mpi 597 membug("memory at %p corrupted (underflow=%02x)\n", p, p[-1] );
ch1_mpi 598 else if( p[m_size(p)] != MAGIC_END_BYTE )
ch1_mpi 599 membug("memory at %p corrupted (overflow=%02x)\n", p, p[-1] );
ch1_mpi 600 #endif
ch1_mpi 601 #endif
ch1_mpi 602 }
ch1_mpi 603
ch1_mpi 604
ch1_mpi 605 size_t
ch1_mpi 606 m_size( const void *a )
ch1_mpi 607 {
ch1_mpi 608 #ifndef M_GUARD
ch1_mpi 609 log_debug("dummy m_size called\n");
ch1_mpi 610 return 0;
ch1_mpi 611 #else
ch1_mpi 612 const byte *p = a;
ch1_mpi 613 size_t n;
ch1_mpi 614
ch1_mpi 615 #ifdef M_DEBUG
ch1_mpi 616 n = check_mem(p-EXTRA_ALIGN-4, "m_size")->user_n;
ch1_mpi 617 #else
ch1_mpi 618 n = ((byte*)p)[-4];
ch1_mpi 619 n |= ((byte*)p)[-3] << 8;
ch1_mpi 620 n |= ((byte*)p)[-2] << 16;
ch1_mpi 621 #endif
ch1_mpi 622 return n;
ch1_mpi 623 #endif
ch1_mpi 624 }
ch1_mpi 625
ch1_mpi 626
ch1_mpi 627 char *
ch1_mpi 628 FNAMEX(strdup)( const char *a FNAMEPRT )
ch1_mpi 629 {
ch1_mpi 630 size_t n = strlen(a);
ch1_mpi 631 char *p = FNAMEXM(alloc)(n+1 FNAMEARG);
ch1_mpi 632 strcpy(p, a);
ch1_mpi 633 return p;
ch1_mpi 634 }
ch1_mpi 635
ch1_mpi 636 char *
ch1_mpi 637 FNAMEX(trystrdup)(const char *a FNAMEPRT)
ch1_mpi 638 {
ch1_mpi 639 size_t n = strlen (a);
ch1_mpi 640 char *p = FNAMEX(trymalloc)(n+1 FNAMEARG);
ch1_mpi 641 if (p)
ch1_mpi 642 strcpy (p, a);
ch1_mpi 643 return p;
ch1_mpi 644 }
ch1_mpi 645
ch1_mpi 646
ch1_mpi 647 /* Wrapper around xmalloc_clear to take the usual 2 arguments of a
ch1_mpi 648 calloc style function. */
ch1_mpi 649 void *
ch1_mpi 650 xcalloc (size_t n, size_t m)
ch1_mpi 651 {
ch1_mpi 652 size_t nbytes;
ch1_mpi 653
ch1_mpi 654 nbytes = n * m;
ch1_mpi 655 if (m && nbytes / m != n)
ch1_mpi 656 out_of_core (nbytes, 0);
ch1_mpi 657 return xmalloc_clear (nbytes);
ch1_mpi 658 }
ch1_mpi 659
ch1_mpi 660 /* Wrapper around xmalloc_csecure_lear to take the usual 2 arguments
ch1_mpi 661 of a calloc style function. */
ch1_mpi 662 void *
ch1_mpi 663 xcalloc_secure (size_t n, size_t m)
ch1_mpi 664 {
ch1_mpi 665 size_t nbytes;
ch1_mpi 666
ch1_mpi 667 nbytes = n * m;
ch1_mpi 668 if (m && nbytes / m != n)
ch1_mpi 669 out_of_core (nbytes, 1);
ch1_mpi 670 return xmalloc_secure_clear (nbytes);
ch1_mpi 671 }