📄 cryptlib.c
字号:
}
/* Verify ability to lock object and inability to change security
parameters once locked */
value = 5;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_OK || \
krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_PROPERTY_HIGHSECURITY ) != CRYPT_OK )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_PROPERTY_LOCKED ) != CRYPT_OK || \
value != TRUE || \
krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_ERROR_PERMISSION )
{
/* Object should be locked, forwardcount should be inaccessible */
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
value = 1;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_PROPERTY_FORWARDCOUNT ) != CRYPT_ERROR_PERMISSION )
{
/* Security parameters shouldn't be writeable */
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
/* Create a cert object for the remaining kernel range checks */
setMessageCreateObjectInfo( &createInfo, CRYPT_CERTTYPE_CERTIFICATE );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CERTIFICATE );
if( cryptStatusError( status ) )
return( FALSE );
cryptHandle = createInfo.cryptHandle;
/* Verify functioning of kernel range checking, phase 3: Boolean values.
Any value should be OK, with conversion to TRUE/FALSE */
value = 0;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )
status = CRYPT_ERROR;
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \
value != FALSE )
status = CRYPT_ERROR;
value = 1;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )
status = CRYPT_ERROR;
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \
value != TRUE )
status = CRYPT_ERROR;
value = 10000;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )
status = CRYPT_ERROR;
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \
value != TRUE )
status = CRYPT_ERROR;
value = -1;
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK )
status = CRYPT_ERROR;
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE, &value,
CRYPT_CERTINFO_SELFSIGNED ) != CRYPT_OK || \
value != TRUE )
status = CRYPT_ERROR;
if( cryptStatusError( status ) )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify functioning of kernel range checking, phase 4: Time values,
Any value above the initial cutoff date should be OK */
setMessageData( &msgData, &timeVal, sizeof( time_t ) );
timeVal = -10; /* Below (negative) */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )
status = CRYPT_ERROR;
timeVal = MIN_TIME_VALUE - 1; /* Lower bound fencepost error */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_VALIDFROM ) != CRYPT_ARGERROR_STR1 )
status = CRYPT_ERROR;
timeVal = MIN_TIME_VALUE; /* Lower bound */
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_VALIDFROM ) != CRYPT_OK )
status = CRYPT_ERROR;
timeVal = 0x40000000L; /* Mid-range */
krnlSendMessage( cryptHandle, IMESSAGE_DELETEATTRIBUTE, NULL,
CRYPT_CERTINFO_VALIDFROM );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CERTINFO_VALIDFROM ) != CRYPT_OK )
status = CRYPT_ERROR;
if( cryptStatusError( status ) )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( TRUE );
}
/****************************************************************************
* *
* Startup/Shutdown Routines *
* *
****************************************************************************/
/* The initialisation and shutdown actions performed for various object
types. The pre-init actions are used to handle various preparatory
actions that are required before the actual init can be performed, for
example to create the system device and user object, which are needed by
the init routines. The pre-shutdown actions are used to signal to various
subsystems that a shutdown is about to occur, for example to allow the
networking subsystem to gracefully exit from any currently occurring
network I/O.
The order of the init/shutdown actions is:
Object type Action
----------- ------
Pre-init: Device Create system object
Init: User Create default user object
Keyset Drivers - keysets
Device Drivers - devices
Session Drivers - networking
Pre-shutdown: Session Networking - signal socket close
Device System object - signal entropy poll end
Shutdown: User Destroy default user object | Done by
Device Destroy system object | kernel
Keyset Drivers - keysets
Device Drivers - devices
Session Drivers - networking
The init order is determined by the following dependencies:
All -> Device (System object handles many message types)
User -> Cert (Default user object reads trusted certs)
The shutdown order is determined by the following dependencies:
Session (Networking needs to shut down to release any objects that are
blocked waiting on network I/O)
Device (System object needs to shut down ongoing entropy poll)
After this the shutdown proper can take place. The shutdown order is
noncritical, provided the pre-shutdown actions have occurred.
In theory the user and system objects are destroyed as part of the
standard shutdown, however the kernel prevents these objects from ever
being explicitly destroyed so they're destroyed implicitly by the
destroyObjects() cleanup call */
int certManagementFunction( const MANAGEMENT_ACTION_TYPE action );
int deviceManagementFunction( const MANAGEMENT_ACTION_TYPE action );
int keysetManagementFunction( const MANAGEMENT_ACTION_TYPE action );
int sessionManagementFunction( const MANAGEMENT_ACTION_TYPE action );
int userManagementFunction( const MANAGEMENT_ACTION_TYPE action );
typedef int ( *MANAGEMENT_FUNCTION )( const MANAGEMENT_ACTION_TYPE action );
static const MANAGEMENT_FUNCTION preInitFunctions[] = {
deviceManagementFunction, NULL
};
static const MANAGEMENT_FUNCTION initFunctions[] = {
userManagementFunction, NULL
};
static const MANAGEMENT_FUNCTION asyncInitFunctions[] = {
#ifdef USE_KEYSETS
keysetManagementFunction,
#endif /* USE_KEYSETS */
deviceManagementFunction,
#ifdef USE_SESSIONS
sessionManagementFunction,
#endif /* USE_SESSIONS */
NULL
};
static const MANAGEMENT_FUNCTION preShutdownFunctions[] = {
#ifdef USE_SESSIONS
sessionManagementFunction,
#endif /* USE_SESSIONS */
deviceManagementFunction, NULL
};
static const MANAGEMENT_FUNCTION shutdownFunctions[] = {
/*userManagementFunction,*/ /*deviceManagementFunction,*/
#ifdef USE_KEYSETS
keysetManagementFunction,
#endif /* USE_KEYSETS */
deviceManagementFunction,
#ifdef USE_SESSIONS
sessionManagementFunction,
#endif /* USE_SESSIONS */
NULL
};
/* Dispatch a set of management actions */
static int dispatchManagementAction( const MANAGEMENT_FUNCTION *mgmtFunctions,
const MANAGEMENT_ACTION_TYPE action )
{
int i, status = CRYPT_OK;
for( i = 0; mgmtFunctions[ i ] != NULL; i++ )
{
const int localStatus = mgmtFunctions[ i ]( action );
if( cryptStatusError( localStatus ) && cryptStatusOK( status ) )
status = localStatus;
}
return( status );
}
/* Under various OSes we bind to a number of drivers at runtime. We can
either do this sychronously or asynchronously depending on the setting of
a config option. By default we use the async init since it speeds up the
startup. Synchronisation is achieved by having the open/init functions in
the modules that require the drivers call waitSemaphore() on the driver
binding semaphore, which blocks until the drivers are bound if an async
bind is in progress, or returns immediately if no bind is in progress */
#ifdef USE_THREADS
THREADFUNC_DEFINE( threadedBind, dummy )
{
UNUSED( dummy );
dispatchManagementAction( asyncInitFunctions, MANAGEMENT_ACTION_INIT );
clearSemaphore( SEMAPHORE_DRIVERBIND );
THREAD_EXIT();
}
#endif /* USE_THREADS */
/* Initialise and shut down the system */
#if defined( __WIN32__ ) && defined( STATIC_LIB )
BOOLEAN isWin95;
#endif /* __WIN32__ && STATIC_LIB */
int initCryptlib( void )
{
int initLevel = 0, status;
/* If the Win32 version is being compiled as a static .lib (not
recommended) we need to perform initialisation here. Note that in
this form cryptlib is no longer fully thread-safe because we can't
guarantee that the thread-locking is automatically set up before
anything else */
#if defined( __WIN32__ ) && defined( STATIC_LIB )
static DWORD dwPlatform = ( DWORD ) CRYPT_ERROR;
/* Figure out which OS we're running under */
if( dwPlatform == CRYPT_ERROR )
{
OSVERSIONINFO osvi = { sizeof( osvi ) };
GetVersionEx( &osvi );
dwPlatform = osvi.dwPlatformId;
isWin95 = ( dwPlatform == VER_PLATFORM_WIN32_WINDOWS ) ? TRUE : FALSE;
/* Check for Win32s just in case someone tries to load the DLL under
it */
if( dwPlatform == VER_PLATFORM_WIN32s )
return( CRYPT_ERROR );
}
#endif /* __WIN32__ && STATIC_LIB */
/* If we've already been initialised, don't do anything */
if( !beginInitialisation( TRUE ) )
return( CRYPT_OK );
/* VisualAge C++ doesn't set the TZ correctly */
#if defined( __IBMC__ ) || defined( __IBMCPP__ )
tzset();
#endif /* VisualAge C++ */
/* Perform the multi-phase bootstrap */
status = initInternalFunctions();
assert( cryptStatusOK( status ) );
if( cryptStatusOK( status ) )
{
initLevel = 1;
status = dispatchManagementAction( preInitFunctions,
MANAGEMENT_ACTION_PRE_INIT );
assert( cryptStatusOK( status ) );
}
if( cryptStatusOK( status ) )
{
initLevel = 2;
status = dispatchManagementAction( initFunctions,
MANAGEMENT_ACTION_INIT );
assert( cryptStatusOK( status ) );
}
if( cryptStatusOK( status ) )
{
#ifdef USE_THREADS
int asyncInit;
#endif /* USE_THREADS */
initLevel = 3;
/* Perform the final init phase asynchronously or synchronously
depending on the config option setting. We always send this
query to the default user object since no other user objects
exist at this time */
#ifdef USE_THREADS
krnlSendMessage( DEFAULTUSER_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE,
&asyncInit, CRYPT_OPTION_MISC_ASYNCINIT );
if( asyncInit )
{
THREAD_HANDLE thread;
THREAD_CREATE_VARS;
/* Fire up the thread. There's no problem with the thread
exiting before we set the semaphore because it's a one-shot,
so if the thread gets there first the attempt to set the
semaphore below is ignored */
status = THREAD_CREATE( threadedBind, NULL, thread );
if( cryptStatusOK( status ) )
setSemaphore( SEMAPHORE_DRIVERBIND, thread );
else
/* The thread couldn't be started, try again with a
synchronous init */
asyncInit = FALSE;
}
if( !asyncInit )
#endif /* USE_THREADS */
status = dispatchManagementAction( asyncInitFunctions,
MANAGEMENT_ACTION_INIT );
assert( cryptStatusOK( status ) );
}
/* Everything's set up, verify that the general crypto algorithms and
kernel security mechanisms are working as required */
if( cryptStatusOK( status ) && \
( !testGeneralAlgorithms() || !testKernelMechanisms() ) )
{
/* We should probably sound klaxons as well at this point */
assert( NOTREACHED );
status = CRYPT_ERROR_FAILED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -