Commit 6e339b52 authored by Paul Bakker's avatar Paul Bakker

Memory-allocation abstraction layer and buffer-based allocator added

parent f863485f
......@@ -8,6 +8,8 @@ Features
(ECDHE-based ciphersuites)
* Ability to specify allowed ciphersuites based on the protocol version.
* PSK and DHE-PSK based ciphersuites added
* Memory allocation abstraction layer added
* Buffer-based memory allocator added (no malloc() / free() / HEAP usage)
Changes
* Introduced separate SSL Ciphersuites module that is based on
......
......@@ -401,6 +401,32 @@
#define POLARSSL_NO_PLATFORM_ENTROPY
*/
/**
* \def POLARSSL_MEMORY_DEBUG
*
* Enable debugging of buffer allocator memory issues. Automatically prints
* (to stderr) all (fatal) messages on memory allocation issues. Enables
* function for 'debug output' of allocated memory.
*
* Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C
* fprintf()
*
* Uncomment this macro to let the buffer allocator print out error messages.
#define POLARSSL_MEMORY_DEBUG
*/
/**
* \def POLARSSL_MEMORY_BACKTRACE
*
* Include backtrace information with each allocated block.
*
* Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C
* GLIBC-compatible backtrace() an backtrace_symbols() support
*
* Uncomment this macro to include backtrace information
#define POLARSSL_MEMORY_BACKTRACE
*/
/**
* \def POLARSSL_PKCS1_V21
*
......@@ -899,6 +925,32 @@
*/
#define POLARSSL_MD5_C
/**
* \def POLARSSL_MEMORY_C
*
* Enable the memory allocation layer.
* By default PolarSSL uses the system-provided malloc() and free().
* (As long as POLARSSL_MEMORY_STDMALLOC and POLARSSL_MEMORY_STDFREE
* are defined and unmodified)
*
* This allows different allocators (self-implemented or provided)
*
* Enable this layer to allow use of alternative memory allocators.
#define POLARSSL_MEMORY_C
*/
/**
* The buffer allocator implementation that makes use of a (stack) based
* buffer to 'allocate' dynamic memory. (replaces malloc() and free() calls)
*
* Module: library/memory_buffer_alloc.c
*
* Requires: POLARSSL_MEMORY_C
*
* Enable this module to enable the buffer memory allocator.
#define POLARSSL_MEMORY_BUFFER_ALLOC_C
*/
/**
* \def POLARSSL_NET_C
*
......@@ -1231,6 +1283,11 @@
#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */
#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
// Memory options
#define MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#define POLARSSL_MEMORY_STDMALLOC malloc /**< Default allocator to use, can be undefined */
#define POLARSSL_MEMORY_STDFREE free /**< Default free to use, can be undefined */
// SSL Cache options
//
#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
......@@ -1301,6 +1358,10 @@
#error "POLARSSL_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) && !defined(POLARSSL_MEMORY_C)
#error "POLARSSL_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
#endif
#if defined(POLARSSL_PBKDF2_C) && !defined(POLARSSL_MD_C)
#error "POLARSSL_PBKDF2_C defined, but not all prerequisites"
#endif
......
/**
* \file memory.h
*
* \brief Memory allocation layer
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_MEMORY_H
#define POLARSSL_MEMORY_H
#include "config.h"
#include <stdlib.h>
#if !defined(POLARSSL_CONFIG_OPTIONS)
#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#define POLARSSL_MEMORY_STDMALLOC malloc /**< Default allocator to use, can be undefined */
#define POLARSSL_MEMORY_STDFREE free /**< Default free to use, can be undefined */
#endif /* POLARSSL_CONFIG_OPTIONS */
#define MEMORY_VERIFY_NONE 0
#define MEMORY_VERIFY_ALLOC (1 << 0)
#define MEMORY_VERIFY_FREE (1 << 1)
#define MEMORY_VERIFY_ALWAYS (MEMORY_VERIFY_ALLOC | MEMORY_VERIFY_FREE)
#ifdef __cplusplus
extern "C" {
#endif
/*
* The function pointers for malloc and free
*/
extern void * (*polarssl_malloc)( size_t len );
extern void (*polarssl_free)( void *ptr );
/**
* \brief Set your own memory implementation function pointers
*
* \param malloc_func the malloc function implementation
* \param free_func the free function implementation
*
* \return 0 if successful
*/
int memory_set_own( void * (*malloc_func)( size_t ),
void (*free_func)( void * ) );
#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
/**
* \brief Initialize use of stack-based memory allocator.
* The stack-based allocator does memory management inside the
* presented buffer and does not call malloc() and free().
* It sets the global polarssl_malloc() and polarssl_free() pointers
* to its own functions.
*
* \note This code is not optimized and provides a straight-forward
* implementation of a stack-based memory allocator.
*
* \param buf buffer to use as heap
* \param len size of the buffer
*
* \return 0 if successful
*/
int memory_buffer_alloc_init( unsigned char *buf, size_t len );
/**
* \brief Determine when the allocator should automatically verify the state
* of the entire chain of headers / meta-data.
* (Default: MEMORY_VERIFY_NONE)
*
* \param verify One of MEMORY_VERIFY_NONE, MEMORY_VERIFY_ALLOC,
* MEMORY_VERIFY_FREE or MEMORY_VERIFY_ALWAYS
*/
void memory_buffer_set_verify( int verify );
#if defined(POLARSSL_MEMORY_DEBUG)
/**
* \brief Print out the status of the allocated memory (primarily for use
* after a program should have de-allocated all memory)
* Prints out a list of 'still allocated' blocks and their stack
* trace if POLARSSL_MEMORY_BACKTRACE is defined.
*/
void memory_buffer_alloc_status();
#endif /* POLARSSL_MEMORY_DEBUG */
/**
* \brief Verifies that all headers in the memory buffer are correct
* and contain sane values. Helps debug buffer-overflow errors.
*
* Prints out first failure if POLARSSL_MEMORY_DEBUG is defined.
* Prints out full header information if POLARSSL_MEMORY_DEBUG_HEADERS
* is defined. (Includes stack trace information for each block if
* POLARSSL_MEMORY_BACKTRACE is defined as well).
*
* \returns 0 if verified, 1 otherwise
*/
int memory_buffer_alloc_verify();
#endif /* POLARSSL_MEMORY_BUFFER_ALLOC_C */
#ifdef __cplusplus
}
#endif
#endif /* memory.h */
......@@ -29,6 +29,8 @@ set(src
md2.c
md4.c
md5.c
memory.c
memory_buffer_alloc.c
net.c
oid.c
padlock.c
......
......@@ -44,7 +44,8 @@ OBJS= aes.o arc4.o asn1parse.o \
entropy.o entropy_poll.o \
error.o gcm.o havege.o \
md.o md_wrap.o md2.o \
md4.o md5.o net.o \
md4.o md5.o memory.o \
memory_buffer_alloc.c net.o \
oid.o \
padlock.o pbkdf2.o pem.o \
pkcs5.o pkcs11.o pkcs12.o \
......
......@@ -33,6 +33,13 @@
#include "polarssl/bignum.h"
#endif
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
......@@ -238,7 +245,7 @@ int asn1_get_sequence_of( unsigned char **p,
/* Allocate and assign next pointer */
if (*p < end)
{
cur->next = (asn1_sequence *) malloc(
cur->next = (asn1_sequence *) polarssl_malloc(
sizeof( asn1_sequence ) );
if( cur->next == NULL )
......
......@@ -37,6 +37,13 @@
#include "polarssl/bignum.h"
#include "polarssl/bn_mul.h"
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <stdlib.h>
#define ciL (sizeof(t_uint)) /* chars in limb */
......@@ -73,7 +80,7 @@ void mpi_free( mpi *X )
if( X->p != NULL )
{
memset( X->p, 0, X->n * ciL );
free( X->p );
polarssl_free( X->p );
}
X->s = 1;
......@@ -93,7 +100,7 @@ int mpi_grow( mpi *X, size_t nblimbs )
if( X->n < nblimbs )
{
if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL )
if( ( p = (t_uint *) polarssl_malloc( nblimbs * ciL ) ) == NULL )
return( POLARSSL_ERR_MPI_MALLOC_FAILED );
memset( p, 0, nblimbs * ciL );
......@@ -102,7 +109,7 @@ int mpi_grow( mpi *X, size_t nblimbs )
{
memcpy( p, X->p, X->n * ciL );
memset( X->p, 0, X->n * ciL );
free( X->p );
polarssl_free( X->p );
}
X->n = nblimbs;
......
......@@ -49,6 +49,13 @@
#include "polarssl/blowfish.h"
#endif
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <stdlib.h>
#if defined(POLARSSL_AES_C)
......@@ -109,12 +116,12 @@ static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned in
static void * aes_ctx_alloc( void )
{
return malloc( sizeof( aes_context ) );
return polarssl_malloc( sizeof( aes_context ) );
}
static void aes_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
const cipher_base_t aes_info = {
......@@ -304,12 +311,12 @@ static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, unsign
static void * camellia_ctx_alloc( void )
{
return malloc( sizeof( camellia_context ) );
return polarssl_malloc( sizeof( camellia_context ) );
}
static void camellia_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
const cipher_base_t camellia_info = {
......@@ -506,17 +513,17 @@ static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, unsigned
static void * des_ctx_alloc( void )
{
return malloc( sizeof( des_context ) );
return polarssl_malloc( sizeof( des_context ) );
}
static void * des3_ctx_alloc( void )
{
return malloc( sizeof( des3_context ) );
return polarssl_malloc( sizeof( des3_context ) );
}
static void des_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
const cipher_base_t des_info = {
......@@ -641,12 +648,12 @@ static int blowfish_setkey_enc_wrap( void *ctx, const unsigned char *key, unsign
static void * blowfish_ctx_alloc( void )
{
return malloc( sizeof( blowfish_context ) );
return polarssl_malloc( sizeof( blowfish_context ) );
}
static void blowfish_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
const cipher_base_t blowfish_info = {
......
......@@ -37,6 +37,14 @@
#if defined(POLARSSL_ECP_C)
#include "polarssl/ecp.h"
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <limits.h>
#include <stdlib.h>
......@@ -793,7 +801,7 @@ static int ecp_normalize_many( const ecp_group *grp,
if( t_len < 2 )
return( ecp_normalize( grp, T ) );
if( ( c = (mpi *) malloc( t_len * sizeof( mpi ) ) ) == NULL )
if( ( c = (mpi *) polarssl_malloc( t_len * sizeof( mpi ) ) ) == NULL )
return( POLARSSL_ERR_ECP_GENERIC );
mpi_init( &u ); mpi_init( &Zi ); mpi_init( &ZZi );
......@@ -848,7 +856,7 @@ cleanup:
mpi_free( &u ); mpi_free( &Zi ); mpi_free( &ZZi );
for( i = 0; i < t_len; i++ )
mpi_free( &c[i] );
free( c );
polarssl_free( c );
return( ret );
}
......
......@@ -57,6 +57,13 @@
#include "polarssl/sha512.h"
#endif
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <stdlib.h>
#if defined(POLARSSL_MD2_C)
......@@ -109,12 +116,12 @@ static void md2_hmac_reset_wrap( void *ctx )
static void * md2_ctx_alloc( void )
{
return malloc( sizeof( md2_context ) );
return polarssl_malloc( sizeof( md2_context ) );
}
static void md2_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void md2_process_wrap( void *ctx, const unsigned char *data )
......@@ -195,12 +202,12 @@ static void md4_hmac_reset_wrap( void *ctx )
static void *md4_ctx_alloc( void )
{
return malloc( sizeof( md4_context ) );
return polarssl_malloc( sizeof( md4_context ) );
}
static void md4_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void md4_process_wrap( void *ctx, const unsigned char *data )
......@@ -279,12 +286,12 @@ static void md5_hmac_reset_wrap( void *ctx )
static void * md5_ctx_alloc( void )
{
return malloc( sizeof( md5_context ) );
return polarssl_malloc( sizeof( md5_context ) );
}
static void md5_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void md5_process_wrap( void *ctx, const unsigned char *data )
......@@ -363,12 +370,12 @@ static void sha1_hmac_reset_wrap( void *ctx )
static void * sha1_ctx_alloc( void )
{
return malloc( sizeof( sha1_context ) );
return polarssl_malloc( sizeof( sha1_context ) );
}
static void sha1_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void sha1_process_wrap( void *ctx, const unsigned char *data )
......@@ -463,12 +470,12 @@ static void sha224_hmac_wrap( const unsigned char *key, size_t keylen,
static void * sha224_ctx_alloc( void )
{
return malloc( sizeof( sha256_context ) );
return polarssl_malloc( sizeof( sha256_context ) );
}
static void sha224_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void sha224_process_wrap( void *ctx, const unsigned char *data )
......@@ -556,12 +563,12 @@ static void sha256_hmac_wrap( const unsigned char *key, size_t keylen,
static void * sha256_ctx_alloc( void )
{
return malloc( sizeof( sha256_context ) );
return polarssl_malloc( sizeof( sha256_context ) );
}
static void sha256_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void sha256_process_wrap( void *ctx, const unsigned char *data )
......@@ -653,12 +660,12 @@ static void sha384_hmac_wrap( const unsigned char *key, size_t keylen,
static void * sha384_ctx_alloc( void )
{
return malloc( sizeof( sha512_context ) );
return polarssl_malloc( sizeof( sha512_context ) );
}
static void sha384_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void sha384_process_wrap( void *ctx, const unsigned char *data )
......@@ -746,12 +753,12 @@ static void sha512_hmac_wrap( const unsigned char *key, size_t keylen,
static void * sha512_ctx_alloc( void )
{
return malloc( sizeof( sha512_context ) );
return polarssl_malloc( sizeof( sha512_context ) );
}
static void sha512_ctx_free( void *ctx )
{
free( ctx );
polarssl_free( ctx );
}
static void sha512_process_wrap( void *ctx, const unsigned char *data )
......
/*
* Memory allocation layer
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "polarssl/config.h"
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#if !defined(POLARSSL_MEMORY_STDMALLOC)
static void *memory_malloc_uninit( size_t len )
{
((void) len);
return( NULL );
}
#define POLARSSL_MEMORY_STDMALLOC memory_malloc_uninit
#endif /* !POLARSSL_MEMORY_STDMALLOC */
#if !defined(POLARSSL_MEMORY_STDFREE)
static void memory_free_uninit( void *ptr )
{
((void) ptr);
}
#define POLARSSL_MEMORY_STDFREE memory_free_uninit
#endif /* !POLARSSL_MEMORY_STDFREE */
void * (*polarssl_malloc)( size_t ) = POLARSSL_MEMORY_STDMALLOC;
void (*polarssl_free)( void * ) = POLARSSL_MEMORY_STDFREE;
int memory_set_own( void * (*malloc_func)( size_t ),
void (*free_func)( void * ) )
{
polarssl_malloc = malloc_func;
polarssl_free = free_func;
return( 0 );
}
#endif /* POLARSSL_MEMORY_C */
/*
* Buffer-based memory allocator
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "polarssl/config.h"
#if defined(POLARSSL_MEMORY_C) && defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
#include "polarssl/memory.h"
#include <string.h>
#if defined(POLARSSL_MEMORY_DEBUG)
#include <stdio.h>
#if defined(POLARSSL_MEMORY_BACKTRACE)
#include <execinfo.h>
#endif
#endif
#define MAGIC1 0xFF00AA55
#define MAGIC2 0xEE119966
#define MAX_BT 20
typedef struct _memory_header memory_header;
struct _memory_header
{
size_t magic1;
size_t size;
size_t alloc;
memory_header *prev;
memory_header *next;
#if defined(POLARSSL_MEMORY_BACKTRACE)
char **trace;
size_t trace_count;
#endif
size_t magic2;
};
typedef struct
{
unsigned char *buf;
size_t len;
memory_header *first;
size_t largest_free;
size_t current_alloc_size;
int verify;
}
buffer_alloc_ctx;
static buffer_alloc_ctx heap;
#if defined(POLARSSL_MEMORY_DEBUG)
static void debug_header( memory_header *hdr )
{
#if defined(POLARSSL_MEMORY_BACKTRACE)
size_t i;
#endif
fprintf(stderr, "HDR: PTR(%10u), PREV(%10u), NEXT(%10u), ALLOC(%u), SIZE(%10u)\n",
(size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
hdr->alloc, hdr->size );
#if defined(POLARSSL_MEMORY_BACKTRACE)
fprintf(stderr, "TRACE: \n");
for( i = 0; i < hdr->trace_count; i++ )
fprintf(stderr, "%s\n", hdr->trace[i]);
#endif
}
static void debug_chain()
{
memory_header *cur = heap.first;
while( cur != NULL )
{
debug_header( cur );
fprintf(stderr, "\n");
cur = cur->next;
}
}
#endif /* POLARSSL_MEMORY_DEBUG */
static int verify_header( memory_header *hdr )
{
if( hdr->magic1 != MAGIC1 )
{
#if defined(POLARSSL_MEMORY_DEBUG)
fprintf(stderr, "FATAL: MAGIC1 mismatch\n");
#endif
return( 1 );
}
if( hdr->magic2 != MAGIC2 )
{
#if defined(POLARSSL_MEMORY_DEBUG)
fprintf(stderr, "FATAL: MAGIC2 mismatch\n");
#endif
return( 1 );
}
if( hdr->alloc > 1 )
{
#if defined(POLARSSL_MEMORY_DEBUG)
fprintf(stderr, "FATAL: alloc has illegal value\n");
#endif
return( 1 );
}
return( 0 );
}
static int verify_chain()
{
memory_header *prv = heap.first, *cur = heap.first->next;
if( verify_header( heap.first ) != 0 )
{
#if defined(POLARSSL_MEMORY_DEBUG)
fprintf(stderr, "FATAL: verification of first header failed\n");
#endif
return( 1 );
}
if( heap.first->prev != NULL )
{
#if defined(POLARSSL_MEMORY_DEBUG)
fprintf(stderr, "FATAL: verification failed: first->prev != NULL\n");
#endif
return( 1 );
}