📄 init.c
字号:
mutex locked between the two calls to allow external shutdown of
further, non-kernel-related items. The shutdown proceeds as follows:
lock initialisation mutex;
signal internal worker threads (async.init, randomness poll)
to exit (shutdownLevel = SHUTDOWN_LEVEL_THREADS);
signal all non-destroy messages to fail
(shutdownLevel = SHUTDOWN_LEVEL_MESSAGES in destroyObjects());
destroy objects (via destroyObjects());
shut down kernel modules;
shut down kernel mechanisms (semaphores, messages)
(shutdownLevel = SHUTDOWN_LEVEL_MUTEXES);
clear kernel data; */
int krnlBeginShutdown( void )
{
/* Lock the initialisation mutex to make sure that other threads don't
try to access it */
MUTEX_LOCK( initialisation );
/* We can only begin a shutdown if we're fully initialised */
PRE( krnlData->initLevel == INIT_LEVEL_FULL );
/* If we're already shut down, don't to anything */
if( krnlData->initLevel <= INIT_LEVEL_NONE )
{
MUTEX_UNLOCK( initialisation );
return( CRYPT_ERROR_NOTINITED );
}
krnlData->initLevel = INIT_LEVEL_KRNLDATA;
/* Signal all remaining internal threads to exit */
krnlData->shutdownLevel = SHUTDOWN_LEVEL_THREADS;
return( CRYPT_OK );
}
int krnlCompleteShutdown( void )
{
#if 0 /* The object destruction has to be performed between two phases of
the external shutdown, so we can't currently do it here */
destroyObjects();
#endif /* 0 */
/* Once the kernel objects have been destroyed, we're in the closing-down
state in which no more messages are processed. There are a few
special-case situations such as a shutdown that occurs because of a
failure to initialise that we also need to handle */
PRE( ( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \
krnlData->shutdownLevel == SHUTDOWN_LEVEL_NONE ) || \
( krnlData->initLevel == INIT_LEVEL_KRNLDATA && \
krnlData->shutdownLevel == SHUTDOWN_LEVEL_MESSAGES ) || \
( krnlData->initLevel == INIT_LEVEL_FULL && \
krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MESSAGES ) );
/* Shut down all of the kernel modules */
endAllocation();
endAttributeACL();
endCertMgmtACL();
endInternalMsgs();
endKeymgmtACL();
endMechanismACL();
endMessageACL();
endObjects();
endObjectAltAccess();
endSemaphores();
endSendMessage();
/* At this point all kernel services have been shut down */
POST( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_MUTEXES );
/* Turn off the lights on the way out. Note that the kernel data-
clearing operation leaves the shutdown level set to handle any
threads that may still be active */
CLEAR_KERNEL_DATA();
krnlData->shutdownLevel = SHUTDOWN_LEVEL_ALL;
MUTEX_UNLOCK( initialisation );
#ifdef STATIC_INIT
/* We're shutting down, destroy the initialisation lock */
MUTEX_DESTROY( initialisation );
memset( krnlData, 0, sizeof( KERNEL_DATA ) );
#endif /* STATIC_INIT */
return( CRYPT_OK );
}
/* Indicate to a cryptlib-internal worker thread that the kernel is shutting
down and the thread should exit as quickly as possible. We don't protect
this check with a mutex since it can be called after the kernel mutexes
have been destroyed. This lack of mutex protection for the flag isn't a
serious problem, it's checked at regular intervals by worker threads so
if the thread misses the flag update it'll bve caught at the next check */
BOOLEAN krnlIsExiting( void )
{
return( krnlData->shutdownLevel >= SHUTDOWN_LEVEL_THREADS );
}
/****************************************************************************
* *
* Extended Self-test Functions *
* *
****************************************************************************/
/* Self-test code for several general crypto algorithms that are used
internally all over cryptlib: MD5, SHA-1, and 3DES (and by extension
DES) */
#if defined( INC_ALL )
#include "capabil.h"
#else
#include "device/capabil.h"
#endif /* Compiler-specific includes */
CHECK_RETVAL \
static BOOLEAN testGeneralAlgorithms( void )
{
const CAPABILITY_INFO *capabilityInfo;
int status;
/* Test the MD5 functionality */
#ifdef USE_MD5
capabilityInfo = getMD5Capability();
status = capabilityInfo->selfTestFunction();
if( cryptStatusError( status ) )
return( FALSE );
#endif /* USE_MD5 */
/* Test the SHA-1 functionality */
capabilityInfo = getSHA1Capability();
status = capabilityInfo->selfTestFunction();
if( cryptStatusError( status ) )
return( FALSE );
/* Test the 3DES (and DES) functionality */
capabilityInfo = get3DESCapability();
status = capabilityInfo->selfTestFunction();
if( cryptStatusError( status ) )
return( FALSE );
return( TRUE );
}
/* Test the kernel mechanisms to make sure that everything's working as
expected. This performs the following tests:
General:
Object creation.
Access checks:
Inability to access internal object or attribute via external message.
Inability to perform an internal-only action externally, ability to
perform an internal-only action internally
Attribute checks:
Attribute range checking for numeric, string, boolean, and time
attributes.
Inability to write a read-only attribute, read a write-only attribute,
or delete a non-deletable attribute.
Object state checks:
Ability to perform standard operation on object, ability to transition a
state = low object to state = high.
Inability to perform state = high operation on state = low object,
inability to perform state = low operation on state = high object.
Object property checks:
Ability to use an object with a finite usage count, inability to
increment the count, ability to decrement the count, inability to
exceed the usage count.
Ability to lock an object, inability to change security parameters once
it's locked */
CHECK_RETVAL \
static BOOLEAN testKernelMechanisms( void )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
MESSAGE_DATA msgData;
CRYPT_CONTEXT cryptHandle;
static const BYTE FAR_BSS key[] = { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 };
BYTE buffer[ 128 + 8 ];
#ifdef USE_CERTIFICATES
time_t timeVal;
#endif /* USE_CERTIFICATES */
int value, status;
/* Verify object creation */
setMessageCreateObjectInfo( &createInfo, CRYPT_ALGO_DES );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
if( cryptStatusError( status ) )
return( FALSE );
cryptHandle = createInfo.cryptHandle;
/* Verify the inability to access an internal object or attribute using
an external message. The attribute access will be stopped by the
object access check before it even gets to the attribute access check,
so we also re-do the check further on when the object is made
externally visible to verify the attribute-level checks as well */
if( krnlSendMessage( cryptHandle, MESSAGE_GETATTRIBUTE, &value,
CRYPT_CTXINFO_ALGO ) != CRYPT_ARGERROR_OBJECT || \
krnlSendMessage( cryptHandle, MESSAGE_GETATTRIBUTE, &value,
CRYPT_IATTRIBUTE_TYPE ) != CRYPT_ARGERROR_VALUE )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify the ability to perform standard operations and the inability
to perform a state = high operation on a state = low object */
setMessageData( &msgData, ( void * ) key, 8 );
memset( buffer, 0, 16 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_IV ) != CRYPT_OK || \
krnlSendMessage( cryptHandle, IMESSAGE_CTX_ENCRYPT,
buffer, 8 ) != CRYPT_ERROR_NOTINITED )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify the functioning of kernel range checking, phase 1: Numeric
values */
status = CRYPT_OK;
value = -10; /* Below (negative) */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
value = 0; /* Lower bound fencepost error */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
value = 1; /* Lower bound */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )
status = CRYPT_ERROR;
value = 10000; /* Mid-range */
krnlSendMessage( cryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_KEYING_ITERATIONS );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )
status = CRYPT_ERROR;
value = 20000; /* Upper bound */
krnlSendMessage( cryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_KEYING_ITERATIONS );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_OK )
status = CRYPT_ERROR;
value = 20001; /* Upper bound fencepost error */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
value = 32767; /* High */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CTXINFO_KEYING_ITERATIONS ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
if( cryptStatusError( status ) )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify the functioning of kernel range checking, phase 2: String
values. We have to disable the more outrageous out-of-bounds values
in the debug version since they'll cause the debug kernel to throw an
exception if it sees them */
status = CRYPT_OK;
memset( buffer, '*', CRYPT_MAX_HASHSIZE + 1 );
#ifdef NDEBUG
/* Below (negative) */
setMessageData( &msgData, buffer, -10 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
#endif /* NDEBUG */
/* Lower bound fencepost error */
setMessageData( &msgData, buffer, 7 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
/* Lower bound */
setMessageData( &msgData, buffer, 8 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )
status = CRYPT_ERROR;
/* Mid-range */
setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE / 2 );
krnlSendMessage( cryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_KEYING_SALT );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )
status = CRYPT_ERROR;
/* Upper bound */
setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE );
krnlSendMessage( cryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CTXINFO_KEYING_SALT );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_OK )
status = CRYPT_ERROR;
/* Upper bound fencepost error */
setMessageData( &msgData, buffer, CRYPT_MAX_HASHSIZE + 1 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
#ifdef NDEBUG
/* High */
setMessageData( &msgData, buffer, 32767 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEYING_SALT ) != CRYPT_ARGERROR_NUM1 )
status = CRYPT_ERROR;
#endif /* NDEBUG */
if( cryptStatusError( status ) )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -