⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sec_mem.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*																			*
*							Secure Memory Management						*
*						Copyright Peter Gutmann 1995-2005					*
*																			*
****************************************************************************/

#include <stdlib.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "acl.h"
  #include "kernel.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "acl.h"
  #include "kernel.h"
#else
  #include "crypt.h"
  #include "kernel/acl.h"
  #include "kernel/kernel.h"
#endif /* Compiler-specific includes */

/* A pointer to the kernel data block */

static KERNEL_DATA *krnlData = NULL;

/* The minimum and maximum amount of secure memory that we can ever allocate.
   A more normal upper bound is 8K, however the SSL session cache constitutes
   a single large chunk of secure memory that goes way over this limit */

#define MIN_ALLOC_SIZE		8
#define MAX_ALLOC_SIZE		65536L

/* Get the start address of a page and, given an address in a page and a
   size, determine on which page the data ends.  These are used to determine
   which pages a memory block covers.

   These macros have portability problems since they assume that
   sizeof( long ) == sizeof( void * ), but there's no easy way to avoid this
   since for some strange reason C doesn't allow the perfectly sensible use
   of logical operations on addresses */

#if defined( __WIN32__ )
  /* This assumes Intel hardware, which is virtually always the case */
  #define getPageSize()			4096
#elif defined( __UNIX__ )
  #if defined( __hpux ) || defined( _M_XENIX ) || defined( __aux )
	#define getPageSize()		4096
  #else
	#define getPageSize()		getpagesize()
  #endif /* Unix variant-specific brokenness */
#endif /* OS-specifc page size determination */
#define getPageStartAddress( address ) \
			( ( long ) ( address ) & ~( getPageSize() - 1 ) )
#define getPageEndAddress( address, size ) \
			getPageStartAddress( ( long ) address + ( size ) - 1 )

/* To support page locking we need to store some additional information with
   the memory block.  We do this by reserving an extra memory block at the
   start of the allocated block and saving the information there.

   The information stored in the extra block is a flag indicating whether the
   block is pagelocked (so we can call the unlock function when we free it),
   the size of the block, and pointers to the next and previous pointers in
   the list of allocated blocks (this is used by the thread that walks the
   block list touching each one) */

#if INT_MAX <= 32767
  #define MEMLOCK_HEADERSIZE	16
#elif INT_MAX <= 0xFFFFFFFFUL
  #define MEMLOCK_HEADERSIZE	32
#else
  #define MEMLOCK_HEADERSIZE	64
#endif /* 16/32/64-bit systems */

/* If it's a debug build we also insert a canary at the start and end of each
   block to detect memory overwrites, the block size is adjusted accordingly
   to handle this extra data */

#define CANARY_STARTVALUE	"\xC0\xED\xBA\xBE"	/* More fun than dead beef */
#define CANARY_ENDVALUE		"\x36\xDD\x24\x36"

#ifndef NDEBUG
  #define adjustMemCanary( size ) \
		  size += CANARY_SIZE
  #define insertMemCanary( memBlockPtr, memPtr ) \
		  memcpy( memBlockPtr->canary, CANARY_STARTVALUE, CANARY_SIZE ); \
		  memcpy( memPtr + memBlockPtr->size - CANARY_SIZE, CANARY_ENDVALUE, \
				  CANARY_SIZE )
  #define checkMemCanary( memBlockPtr, memPtr ) \
		  assert( !memcmp( memBlockPtr->canary, CANARY_STARTVALUE, CANARY_SIZE ) ); \
		  assert( !memcmp( memPtr + memBlockPtr->size - CANARY_SIZE, \
						   CANARY_ENDVALUE, CANARY_SIZE ) );
#else
  #define adjustMemCanary( size )
  #define insertMemCanary( memBlockPtr, memPtr )
  #define checkMemCanary( memBlockPtr, memPtr )
#endif /* NDEBUG */

/* Insert and unlink a memory block from a list of memory blocks */

#define insertMemBlock( allocatedListHead, allocatedListTail, memBlockPtr ) \
		if( allocatedListHead == NULL ) \
			allocatedListHead = allocatedListTail = memBlockPtr; \
		else \
			{ \
			allocatedListTail->next = memBlockPtr; \
			memBlockPtr->prev = allocatedListTail; \
			allocatedListTail = memBlockPtr; \
			}

#define unlinkMemBlock( allocatedListHead, allocatedListTail, memBlockPtr ) \
		{ \
		MEMLOCK_INFO *nextBlockPtr, *prevBlockPtr; \
		\
		nextBlockPtr = memBlockPtr->next; \
		prevBlockPtr = memBlockPtr->prev; \
		if( memBlockPtr == allocatedListHead ) \
			allocatedListHead = nextBlockPtr; \
		else \
			prevBlockPtr->next = nextBlockPtr; \
		if( nextBlockPtr != NULL ) \
			nextBlockPtr->prev = prevBlockPtr; \
		if( memBlockPtr == allocatedListTail ) \
			allocatedListTail = prevBlockPtr; \
		}

/* Prepare to allocate/free a block of secure memory */

#define checkInitAlloc( ptr, size ) \
		if( !isWritePtr( ptr, sizeof( void * ) ) || \
			( size ) < MIN_ALLOC_SIZE || ( size ) > MAX_ALLOC_SIZE ) \
			{ \
			assert( NOTREACHED ); \
			return( CRYPT_ERROR_MEMORY ); \
			} \
		*( ptr ) = NULL; \

#define checkInitFree( ptr, memPtr, memBlockPtr ) \
		if( !isReadPtr( ptr, sizeof( void * ) ) || \
			!isReadPtr( *( ptr ), sizeof( MIN_ALLOC_SIZE ) ) ) \
			{ \
			assert( NOTREACHED ); \
			return; \
			} \
		memPtr = ( ( BYTE * ) *( ptr ) ) - MEMLOCK_HEADERSIZE; \
		if( !isReadPtr( memPtr, sizeof( MEMLOCK_INFO ) ) ) \
			{ \
			assert( NOTREACHED ); \
			return; \
			} \
		memBlockPtr = ( MEMLOCK_INFO * ) memPtr; \
		if( memBlockPtr->size < sizeof( MEMLOCK_INFO ) + MIN_ALLOC_SIZE || \
			memBlockPtr->size > sizeof( MEMLOCK_INFO ) + MAX_ALLOC_SIZE || \
			( memBlockPtr->isLocked != FALSE && \
			  memBlockPtr->isLocked != TRUE ) ) \
			{ \
			assert( NOTREACHED ); \
			return; \
			}

/****************************************************************************
*																			*
*								Misc Functions								*
*																			*
****************************************************************************/

#if 0	/* Currently unused, in practice would be called from a worker thread
		   that periodically touches all secure-data pages */

/* Walk the allocated block list touching each page.  In most cases we don't
   need to explicitly touch the page since the allocated blocks are almost
   always smaller than the MMU's page size and simply walking the list
   touches them, but in some rare cases we need to explicitly touch each
   page */

static void touchAllocatedPages( void )
	{
	MEMLOCK_INFO *memBlockPtr;

	/* Lock the allocation object to ensure that other threads don't try to
	   access them */
	MUTEX_LOCK( allocation );

	/* Walk down the list (which implicitly touches each page).  If the
	   allocated region is larger than 4K, explicitly touch each 4K page.
	   This assumes a page size of 4K which is usually true (and difficult
	   to determine otherwise), in any case it doesn't make much difference
	   since nothing ever allocates more than two 4K pages */
	for( memBlockPtr = krnlData->allocatedListHead; memBlockPtr != NULL;
		 memBlockPtr = memBlockPtr->next )
		{
		if( memBlockPtr->size > 4096 )
			{
			BYTE *memPtr = ( BYTE * ) memBlockPtr + 4096;
			int memSize = memBlockPtr->size;

			/* Touch each page.  The rather convoluted expression is to try
			   and stop it from being optimised away - it always evaluates to
			   true since we only get here if allocatedListHead != NULL, but
			   hopefully the compiler won't be able to figure that out */
			while( memSize > 4096 )
				{
				if( *memPtr || krnlData->allocatedListHead != NULL )
					memPtr += 4096;
				memSize -= 4096;
				}
			}
		}

	/* Unlock the allocation object to allow access by other threads */
	MUTEX_UNLOCK( allocation );
	}
#endif /* 0 */

#if 0	/* 9/3/04 No longer needed since the kernel tracks allocated obj.data */

/* Determine the size of a krnlMemalloc()'d memory block */

int krnlMemsize( const void *pointer )
	{
	MEMLOCK_INFO *memBlockPtr;
	BYTE *memPtr = ( BYTE * ) pointer;

	/* Make sure that it's a valid pointer */
	if( !isReadPtr( memPtr, sizeof( MEMLOCK_INFO ) ) )
		{
		assert( NOTREACHED );
		return( 0 );
		}

	/* Find out how big the memory block is */
	memPtr -= MEMLOCK_HEADERSIZE;
	memBlockPtr = ( MEMLOCK_INFO * ) memPtr;

	/* Make sure that nothing's overwritten our memory */
	assert( !memcmp( memBlockPtr->canary, CANARY_STARTVALUE, CANARY_SIZE ) );
	assert( !memcmp( memPtr + memBlockPtr->size - CANARY_SIZE,
					 CANARY_ENDVALUE, CANARY_SIZE ) );

	return( memBlockPtr->size - MEMLOCK_HEADERSIZE );
	}
#endif /* 0 */

/****************************************************************************
*																			*
*							Init/Shutdown Functions							*
*																			*
****************************************************************************/

/* Create and destroy the secure allocation information */

int initAllocation( KERNEL_DATA *krnlDataPtr )
	{
	/* Set up the reference to the kernel data block */
	krnlData = krnlDataPtr;

	/* Clear the list head and tail pointers */
	krnlData->allocatedListHead = krnlData->allocatedListTail = NULL;

	/* Initialize any data structures required to make the allocation thread-
	   safe */
	MUTEX_CREATE( allocation );

	return( CRYPT_OK );
	}

void endAllocation( void )
	{
	/* Destroy any data structures required to make the allocation thread-
	   safe */
	MUTEX_DESTROY( allocation );

	krnlData = NULL;
	}

/****************************************************************************
*																			*
*					Windows Secure Memory Allocation Functions				*
*																			*
****************************************************************************/

#if defined( __WIN32__ )

#if !defined( NDEBUG ) && !defined( NT_DRIVER )
  #include <crtdbg.h>	/* For heap checking in debug version */
#endif /* Win32 debug version */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -