📄 cryptos.h
字号:
/****************************************************************************
* *
* cryptlib OS-specific Macros *
* Copyright Peter Gutmann 1992-2003 *
* *
****************************************************************************/
#ifndef _CRYPTOS_DEFINED
#define _CRYPTOS_DEFINED
/* Check the validity of a pointer passed to a cryptlib function. Usually
the best we can do is check that it's not null, but some OSes allow for
better checking than this, for example that it points to a block of
readable or writeable memory. Under Windows IsBadReadPtr() will always
succeed if the size is 0, so we have to add a separate check to make sure
it's non-NULL */
#if defined( __WIN32__ )
#define checkBadPtrRead( ptr, size ) ( ( ptr ) == NULL || \
IsBadReadPtr( ( ptr ), ( size ) ) )
#define checkBadPtrWrite( ptr, size ) ( ( ptr ) == NULL || \
IsBadWritePtr( ( ptr ), ( size ) ) )
#else
#define checkBadPtrRead( ptr, size ) ( ( ptr ) == NULL )
#define checkBadPtrWrite( ptr, size ) ( ( ptr ) == NULL )
#endif /* Pointer check macros */
#define isReadPtr( ptr, dataType ) \
!checkBadPtrRead( ptr, sizeof( dataType ) )
#define isReadPtrEx( ptr, dataType, count ) \
!checkBadPtrRead( ptr, sizeof( dataType ) * count )
#define isWritePtr( ptr, dataType ) \
!checkBadPtrWrite( ptr, sizeof( dataType ) )
#define isWritePtrEx( ptr, dataType, count ) \
!checkBadPtrWrite( ptr, sizeof( dataType ) * count )
/* When working with secure memory we need to take the OS page size into
account. The following macro obtains the OS page size */
#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 */
/* Under OSF/1 pthread.h includes c_asm.h which contains a declaration
long asm( const char *,...);
which conflicts with the gcc asm keyword. This asm stuff is only used
when inline asm alternatives to the Posix threading functions are enabled,
which isn't done by default so in theory we could also fix this by
defining asm to something else before including pthread.h, but it's safer
to just disable inclusion of c_asm.h by pre-defining the guard define,
which should result in a more useful warning if for some reason inline
threading functions with asm are enabled */
#if defined( __osf__ ) || defined( __alpha__ )
#define __C_ASM_H
#endif /* Alpha */
/* 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 */
#define getPageStartAddress( address ) \
( ( long ) ( address ) & ~( getPageSize() - 1 ) )
#define getPageEndAddress( address, size ) \
getPageStartAddress( ( long ) address + ( size ) - 1 )
/****************************************************************************
* *
* Object Handling Macros *
* *
****************************************************************************/
/* In multithreaded environments we need to protect the information inside
cryptlib data structures from access by other threads while we use it.
The following macros handle this object protection when we enter and
exit cryptlib functions. The initResourceLock() and deleteResourceLock()
macros initialise the data structure needed to perform the object
locking. Note the before deleting the resource lock we lock and unlock
it again to ensure that if some other thread is holding the resource,
they'll release it before we delete the lock */
#if defined( __WIN32__ ) && !defined( NT_DRIVER )
#include <process.h>
/* Some variables are protected by locks. Before we can read or write these
variables in a multithreaded environment we need to lock them so they
can't be accessed or modified by other threads while we're using them.
The following macros provide this locking capability */
#define DECLARE_LOCKING_VARS( name ) \
static CRITICAL_SECTION name##CriticalSection; \
static BOOLEAN name##CriticalSectionInitialised = FALSE;
#define initResourceLock( name ) \
if( !name##CriticalSectionInitialised ) \
{ \
InitializeCriticalSection( &name##CriticalSection ); \
name##CriticalSectionInitialised = TRUE; \
}
#define deleteResourceLock( name ) \
if( name##CriticalSectionInitialised ) \
{ \
EnterCriticalSection( &name##CriticalSection ); \
LeaveCriticalSection( &name##CriticalSection ); \
DeleteCriticalSection( &name##CriticalSection ); \
name##CriticalSectionInitialised = FALSE; \
}
#define lockResource( name ) \
EnterCriticalSection( &name##CriticalSection )
#define unlockResource( name ) \
LeaveCriticalSection( &name##CriticalSection )
/* Handles to threads and system synchronisation objects */
#define THREAD_HANDLE HANDLE
#define SEMAPHORE_HANDLE HANDLE
/* Define a thread function */
#define THREADFUNC_DEFINE( name, arg ) \
unsigned __stdcall name( void *arg )
/* Thread management functions. There are two functions that we can call to
get the current thread ID, GetCurrentThread() and GetCurrentThreadId().
These are actually implemented as the same function (once you get past
the outer wrapper), and the times for calling either are identical - a
significant 10 us per call on a P5/166. The only difference between the
two is that GetCurrentThread() returns a per-process pseudohandle while
GetCurrentThreadId() returns a systemwide, unique handle.
Note that after we wait for the thread, we need to close the handle.
This is complicated by the fact that we can only close it once all
threads have exited the wait, which requires further calisthenics in
the function that uses it to ensure that the last thread out closes the
handle */
#define THREAD_CREATE( function, arg, handle ) \
( !( handle = ( HANDLE ) _beginthreadex( NULL, 0, \
( function ), ( arg ), 0, \
( unsigned * ) &dummy ) ) ? \
CRYPT_ERROR : CRYPT_OK )
#define THREAD_EXIT() _endthreadex( 0 ); return( 0 )
#define THREAD_CREATE_VARS int dummy
#define THREAD_INITIALISER 0
#define THREAD_SELF() ( THREAD_HANDLE ) GetCurrentThreadId()
#define THREAD_SAME( thread1, thread2 ) \
( ( thread1 ) == ( thread2 ) )
#define THREAD_SLEEP( ms ) Sleep( ms )
#define THREAD_YIELD() Sleep( 0 )
#define THREAD_WAIT( thread ) WaitForSingleObject( thread, INFINITE );
#define THREAD_CLOSE( thread ) CloseHandle( thread )
/* Remember that we're using threaded functions */
#define USE_THREADS
#elif defined( __WIN32__ ) && defined( NT_DRIVER )
/* Some variables are protected by locks. Before we can read or write these
variables in a multithreaded environment we need to lock them so they
can't be accessed or modified by other threads while we're using them.
The following macros provide this locking capability */
#define DECLARE_LOCKING_VARS( name ) \
static KMUTEX name##CriticalSection; \
static BOOLEAN name##CriticalSectionInitialised = FALSE;
#define initResourceLock( name ) \
if( !name##CriticalSectionInitialised ) \
{ \
KeInitializeMutex( &name##CriticalSection, 1 ); \
name##CriticalSectionInitialised = TRUE; \
}
#define deleteResourceLock( name )
#define lockResource( name ) \
KeWaitForMutexObject( &name##CriticalSection, Executive, \
KernelMode, FALSE, NULL )
#define unlockResource( name ) \
KeReleaseMutex( &name##CriticalSection, FALSE )
/* Handles to threads and system synchronisation objects */
#define THREAD_HANDLE HANDLE
#define SEMAPHORE_HANDLE HANDLE
#elif defined( __OS2__ )
#define INCL_DOSSEMAPHORES
#define INCL_DOSMISC
#define INCL_DOSFILEMGR
#define INCL_DOSMISC
#define INCL_DOSDATETIME
#define INCL_DOSPROCESS
#define INCL_WINWINDOWMGR
#define INCL_WINSYS
#include <os2.h>
ULONG DosGetThreadID( void );
/* Some variables are protected by locks. Before we can read or write these
variables in a multithreaded environment we need to lock them so they
can't be accessed or modified by other threads while we're using them.
The following macros provide this locking capability */
#define DECLARE_LOCKING_VARS( name ) \
static HMTX name##Mutex; \
static BOOLEAN name##MutexInitialised = FALSE;
#define initResourceLock( name ) \
if( !name##MutexInitialised ) \
{ \
DosCreateMutexSem( NULL, &name##Mutex, 0L, FALSE ); \
name##MutexInitialised = TRUE; \
}
#define deleteResourceLock( name ) \
if( name##MutexInitialised ) \
{ \
DosRequestMutexSem( name##Mutex, ( ULONG ) SEM_INDEFINITE_WAIT ); \
DosReleaseMutexSem( name##Mutex ); \
DosCloseMutexSem( name##Mutex ); \
name##MutexInitialised = FALSE; \
}
#define lockResource( name ) \
DosRequestMutexSem( name##Mutex, ( ULONG ) SEM_INDEFINITE_WAIT )
#define unlockResource( name ) \
DosReleaseMutexSem( name##Mutex )
/* Handles to threads and system synchronisation objects */
#define THREAD_HANDLE TID
#define SEMAPHORE_HANDLE HEV
/* Define a thread function */
#define THREADFUNC_DEFINE( name, arg ) \
void _Optlink name( void *arg )
/* Thead management functions */
#define THREAD_CREATE( function, arg, handle ) \
( ( handle = _beginthread( ( function ), NULL, 8192, \
( arg ) ) ) == -1 ? \
CRYPT_ERROR : CRYPT_OK )
#define THREAD_EXIT() _endthread()
#define THREAD_CREATE_VARS
#define THREAD_INITIALISER 0
#define THREAD_SELF() DosGetThreadID()
#define THREAD_SAME( thread1, thread2 ) \
( ( thread1 ) == ( thread2 ) )
#define THREAD_SLEEP( ms ) DosWait( ms )
#define THREAD_YIELD() DosWait( 0 )
#define THREAD_WAIT( thread ) DosWaitThread( thread, INFINITE )
#define THREAD_CLOSE( thread )
/* Remember that we're using threaded functions */
#define USE_THREADS
#elif defined( __UNIX__ ) && defined( USE_THREADS )
/* Handles to threads and system synchronisation objects */
#define THREAD_HANDLE THREAD
#define SEMAPHORE_HANDLE THREAD
/* Define a thread function */
#define THREADFUNC_DEFINE( name, arg ) \
void *name( void *arg )
/* Thead management functions. Most Unix mutex implementations are non-
re-entrant, which means that re-locking a mutex leads to deadlock (nice
design, guys). Some implementations can fix this by setting a mutex
attribute to ensure that it doesn't deadlock:
pthread_mutexattr_settype( attr, PTHREAD_MUTEX_RECURSIVE );
but this isn't universal. To fix the problem, we implement our own
re-entrant mutexes on top of the Posix ones using mutex_trylock(), which
doesn't re-lock the mutex if it's already locked (as a side-benefit,
trylock() is roughly twice as fast as lock(), depending on the OS). This
works as follows:
// Try and lock the mutex
if( mutex_trylock( mutex ) == error )
{
// The mutex is already locked, see who owns it
if( thread_self() != mutex_owner )
// Someone else has it locked, wait for it to become available
mutex_lock( mutex );
else
// We have it locked, increment its lock count
mutex_lockcount++;
}
mutex_owner = thread_self();
// ....
// Decrement the lock count and if we reach zero, unlock the mutex
if( mutex_lockcount > 0 )
mutex_lockcount--;
else
mutex_unlock( mutex );
Putting a thread to sleep for a number of milliseconds can be done with
select() because it should be a thread-safe one in the presence of
pthreads. Yielding a thread's timeslice is rather more tricky and is done
further on. In addition there are some system-specific quirks, these are
handled by re-defining the macros below in a system-specific manner further
on */
#include <pthread.h>
#include <sys/time.h>
#define MUTEX pthread_mutex_t
#define MUTEX_INIT( mutex ) pthread_mutex_init( mutex, NULL )
#define MUTEX_DESTROY pthread_mutex_destroy
#define MUTEX_LOCK pthread_mutex_lock
#define MUTEX_TRYLOCK pthread_mutex_trylock
#define MUTEX_UNLOCK pthread_mutex_unlock
#define THREAD pthread_t
#define THREAD_CREATE( function, arg, handle ) \
( pthread_create( &handle, NULL, function, arg ) ? \
CRYPT_ERROR : CRYPT_OK )
#define THREAD_EXIT() pthread_exit( ( void * ) 0 )
#define THREAD_CREATE_VARS
#define THREAD_INITIALISER 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -