📄 system.c
字号:
/****************************************************************************
* *
* cryptlib System Device Routines *
* Copyright Peter Gutmann 1995-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "capabil.h"
#include "device.h"
#include "dev_mech.h"
#include "random.h"
#else
#include "crypt.h"
#include "device/capabil.h"
#include "device/device.h"
#include "mechs/dev_mech.h"
#include "random/random.h"
#endif /* Compiler-specific includes */
/* Mechanisms supported by the system device. These are sorted in order of
frequency of use in order to make lookups a bit faster */
static const MECHANISM_FUNCTION_INFO FAR_BSS mechanismFunctions[] = {
#ifdef USE_PKC
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
{ MESSAGE_DEV_SIGN, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_OAEP, ( MECHANISM_FUNCTION ) exportOAEP },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_OAEP, ( MECHANISM_FUNCTION ) importOAEP },
#endif /* USE_PKC */
#ifdef USE_PGP
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
#endif /* USE_PGP */
{ MESSAGE_DEV_EXPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) exportCMS },
{ MESSAGE_DEV_IMPORT, MECHANISM_ENC_CMS, ( MECHANISM_FUNCTION ) importCMS },
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
#if defined( USE_PGP ) || defined( USE_PGPKEYS )
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PGP, ( MECHANISM_FUNCTION ) derivePGP },
#endif /* USE_PGP || USE_PGPKEYS */
#ifdef USE_SSL
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_SSL, ( MECHANISM_FUNCTION ) deriveSSL },
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_TLS, ( MECHANISM_FUNCTION ) deriveTLS },
{ MESSAGE_DEV_SIGN, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) signSSL },
{ MESSAGE_DEV_SIGCHECK, MECHANISM_SIG_SSL, ( MECHANISM_FUNCTION ) sigcheckSSL },
#endif /* USE_SSL */
#ifdef USE_CMP
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
#endif /* USE_CMP */
#ifdef USE_PKCS12
{ MESSAGE_DEV_DERIVE, MECHANISM_DERIVE_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
#endif /* USE_PKCS12 */
#ifdef USE_PKC
{ MESSAGE_DEV_EXPORT, MECHANISM_PRIVATEKEYWRAP, ( MECHANISM_FUNCTION ) exportPrivateKey },
{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP, ( MECHANISM_FUNCTION ) importPrivateKey },
{ MESSAGE_DEV_EXPORT, MECHANISM_PRIVATEKEYWRAP_PKCS8, ( MECHANISM_FUNCTION ) exportPrivateKeyPKCS8 },
{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_PKCS8, ( MECHANISM_FUNCTION ) importPrivateKeyPKCS8 },
#endif /* USE_PKC */
#ifdef USE_PGPKEYS
{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_PGP2, ( MECHANISM_FUNCTION ) importPrivateKeyPGP2 },
{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_OPENPGP_OLD, ( MECHANISM_FUNCTION ) importPrivateKeyOpenPGPOld },
{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_OPENPGP, ( MECHANISM_FUNCTION ) importPrivateKeyOpenPGP },
#endif /* USE_PGPKEYS */
{ MESSAGE_NONE, MECHANISM_NONE, NULL }, { MESSAGE_NONE, MECHANISM_NONE, NULL }
};
/* Object creation functions supported by the system device. These are
sorted in order of frequency of use in order to make lookups a bit
faster */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createCertificate( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createEnvelope( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createSession( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createKeyset( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createDevice( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int createUser( INOUT MESSAGE_CREATEOBJECT_INFO *createInfo,
STDC_UNUSED const void *auxDataPtr,
STDC_UNUSED const int auxValue );
static const CREATEOBJECT_FUNCTION_INFO FAR_BSS createObjectFunctions[] = {
{ OBJECT_TYPE_CONTEXT, createContext },
#ifdef USE_CERTIFICATES
{ OBJECT_TYPE_CERTIFICATE, createCertificate },
#endif /* USE_CERTIFICATES */
#ifdef USE_ENVELOPES
{ OBJECT_TYPE_ENVELOPE, createEnvelope },
#endif /* USE_ENVELOPES */
#ifdef USE_SESSIONS
{ OBJECT_TYPE_SESSION, createSession },
#endif /* USE_SESSIONS */
#ifdef USE_KEYSETS
{ OBJECT_TYPE_KEYSET, createKeyset },
#endif /* USE_KEYSETS */
{ OBJECT_TYPE_DEVICE, createDevice },
{ OBJECT_TYPE_USER, createUser },
{ OBJECT_TYPE_NONE, NULL }, { OBJECT_TYPE_NONE, NULL }
};
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Get a random (but not necessarily cryptographically strong random) nonce.
Some nonces can simply be fresh (for which a monotonically increasing
sequence will do), some should be random (for which a hash of the
sequence is adequate), and some need to be unpredictable. In order to
avoid problems arising from the inadvertent use of a nonce with the wrong
properties we use unpredictable nonces in all cases, even where it isn't
strictly necessary.
This simple generator divides the nonce state into a public section of
the same size as the hash output and a private section that contains 64
bits of data from the crypto RNG, which influences the public section.
The public and private sections are repeatedly hashed to produce the
required amount of output. Note that this leaks a small amount of
information about the crypto RNG output since an attacker knows that
public_state_n = hash( public_state_n - 1, private_state ) but this
isn't a major weakness */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int getNonce( INOUT SYSTEMDEV_INFO *systemInfo,
OUT_BUFFER_FIXED( dataLength ) void *data,
IN_LENGTH_SHORT const int dataLength )
{
BYTE *noncePtr = data;
int nonceLength, iterationCount;
assert( isWritePtr( systemInfo, sizeof( SYSTEMDEV_INFO ) ) );
assert( isWritePtr( data, dataLength ) );
REQUIRES( dataLength > 0 && dataLength < MAX_INTLENGTH_SHORT );
/* If the nonce generator hasn't been initialised yet we set up the
hashing and get 64 bits of private nonce state. What to do if the
attempt to initialise the state fails is somewhat debatable. Since
nonces are only ever used in protocols alongside crypto keys and an
RNG failure will be detected when the key is generated we can
generally ignore a failure at this point. However nonces are
sometimes also used in non-crypto contexts (for example to generate
certificate serial numbers) where this detection in the RNG won't
happen. On the other hand we shouldn't really abort processing just
because we can't get some no-value nonce data so what we do is retry
the fetch of nonce data (in case the system object was busy and the
first attempt timed out) and if that fails too fall back to the
system time. This is no longer unpredictable, but the only location
where unpredictability matters is when used in combination with
crypto operations for which the absence of random data will be
detected during key generation */
if( !systemInfo->nonceDataInitialised )
{
MESSAGE_DATA msgData;
int status;
/* Get the 64-bit private portion of the nonce data */
getHashAtomicParameters( CRYPT_ALGO_SHA1,
&systemInfo->hashFunctionAtomic,
&systemInfo->hashSize );
setMessageData( &msgData, systemInfo->nonceData + \
systemInfo->hashSize, 8 );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM );
if( cryptStatusError( status ) )
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_RANDOM );
if( cryptStatusError( status ) )
{
const time_t theTime = getTime();
memcpy( systemInfo->nonceData + systemInfo->hashSize, &theTime,
sizeof( time_t ) );
}
systemInfo->nonceDataInitialised = TRUE;
}
ENSURES( systemInfo->hashFunctionAtomic != NULL );
ENSURES( systemInfo->hashSize >= 16 && \
systemInfo->hashSize <= CRYPT_MAX_HASHSIZE );
/* Shuffle the public state and copy it to the output buffer until it's
full */
for( nonceLength = dataLength, iterationCount = 0;
nonceLength > 0 && iterationCount < FAILSAFE_ITERATIONS_MED;
iterationCount++ )
{
const int bytesToCopy = min( nonceLength, systemInfo->hashSize );
/* Hash the state and copy the appropriate amount of data to the
output buffer */
systemInfo->hashFunctionAtomic( systemInfo->nonceData,
CRYPT_MAX_HASHSIZE,
systemInfo->nonceData,
systemInfo->hashSize + 8 );
memcpy( noncePtr, systemInfo->nonceData, bytesToCopy );
/* Move on to the next block of the output buffer */
noncePtr += bytesToCopy;
nonceLength -= bytesToCopy;
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
return( CRYPT_OK );
}
/* Perform the algorithm self-test */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int algorithmSelfTest( INOUT \
CAPABILITY_INFO_LIST **capabilityInfoListPtrPtr )
{
CAPABILITY_INFO_LIST *capabilityInfoListPtr = *capabilityInfoListPtrPtr;
CAPABILITY_INFO_LIST *capabilityInfoListPrevPtr = NULL;
BOOLEAN algoTested = FALSE;
int iterationCount, status = CRYPT_OK;
assert( isReadPtr( capabilityInfoListPtrPtr, \
sizeof( CAPABILITY_INFO_LIST * ) ) );
/* Test each available capability */
for( capabilityInfoListPtr = *capabilityInfoListPtrPtr, iterationCount = 0;
capabilityInfoListPtr != NULL && iterationCount < FAILSAFE_ITERATIONS_MED;
capabilityInfoListPtr = capabilityInfoListPtr->next, iterationCount++ )
{
const CAPABILITY_INFO *capabilityInfoPtr = capabilityInfoListPtr->info;
int localStatus;
assert( capabilityInfoPtr->selfTestFunction != NULL );
/* Perform the self-test for this algorithm type */
localStatus = capabilityInfoPtr->selfTestFunction();
if( cryptStatusError( localStatus ) )
{
/* The self-test failed, remember the status if it's the first
failure and disable this algorithm */
if( cryptStatusOK( status ) )
status = localStatus;
deleteSingleListElement( capabilityInfoListPtrPtr,
capabilityInfoListPrevPtr,
capabilityInfoListPtr );
}
else
{
algoTested = TRUE;
/* Remember the last successfully-tested capability */
capabilityInfoListPrevPtr = capabilityInfoListPtr;
}
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
return( algoTested ? status : CRYPT_ERROR_NOTFOUND );
}
/* Perform the mechanism self-test. This is performed in addition to the
algorithm tests if the user requests a test of all algorithms. Currently
only key derivation mechanisms are tested since the others either produce
non-constant results that can't be checked against a fixed value or
require the creation of multiple contexts to hold keys */
typedef struct {
MECHANISM_TYPE mechanismType;
MECHANISM_DERIVE_INFO mechanismInfo;
} MECHANISM_TEST_INFO;
#define MECHANISM_OUTPUT_SIZE 32
#define MECHANISM_INPUT_SIZE 32
#define MECHANISM_SALT_SIZE 16
#define MECHANISM_OUTPUT_SIZE_SSL 48
#define MECHANISM_INPUT_SIZE_SSL 48
#define MECHANISM_SALT_SIZE_SSL 64
static const BYTE FAR_BSS inputValue[] = {
/* More than a single hash block size for SHA-1 */
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
};
static const BYTE FAR_BSS saltValue[] = {
/* At least 64 bytes for SSL/TLS PRF */
0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87,
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
0x78, 0x69, 0x5A, 0x4B, 0x3C, 0x2D, 0x1E, 0x0F,
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x80, 0x91, 0xA2, 0xB3, 0xC4, 0xD5, 0xE6, 0xF7,
0x08, 0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F
};
static const MECHANISM_TEST_INFO FAR_BSS mechanismTestInfo[] = {
{ MECHANISM_DERIVE_PKCS5,
{ "\x73\xF7\x8A\xBE\x3C\x9C\x65\x80\x97\x60\x56\xDE\x04\x2A\x0C\x97"
"\x99\xF5\x06\x0F\x43\x06\xA5\xD0\x74\xC9\xD5\xC5\xA5\x05\xB5\x7F", MECHANISM_OUTPUT_SIZE,
inputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_HMAC_SHA,
saltValue, MECHANISM_SALT_SIZE, 10 } },
#if defined( USE_PGP ) || defined( USE_PGPKEYS )
{ MECHANISM_DERIVE_PGP,
{ "\x4A\x4B\x90\x09\x27\xF8\xD0\x93\x56\x16\xEA\xC1\x45\xCD\xEE\x05"
"\x67\xE1\x09\x38\x66\xEB\xB2\xB2\xB9\x1F\xD3\xF7\x48\x2B\xDC\xCA", MECHANISM_OUTPUT_SIZE,
inputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1,
saltValue, 8, 10 } },
#endif /* USE_PGP || USE_PGPKEYS */
#ifdef USE_SSL
{ MECHANISM_DERIVE_SSL,
{ "\x87\x46\xDD\x7D\xAD\x5F\x48\xB6\xFC\x8D\x92\xC4\xDB\x38\x79\x9A"
"\x3D\xEA\x22\xFA\xCD\x7E\x86\xD5\x23\x6E\x10\x4C\xBD\x84\x89\xDF"
"\x1C\x87\x60\xBF\xFA\x2B\xCA\xFE\xFE\x65\xC7\xA2\xCF\x04\xFF\xEB", MECHANISM_OUTPUT_SIZE_SSL,
inputValue, MECHANISM_INPUT_SIZE_SSL, CRYPT_USE_DEFAULT,
saltValue, MECHANISM_SALT_SIZE_SSL, 1 } },
{ MECHANISM_DERIVE_TLS,
{ "\xD3\xD4\x2F\xD6\xE3\x7D\xC0\x3C\xA6\x9F\x92\xDF\x3E\x40\x0A\x64"
"\x49\xB4\x0E\xC4\x14\x04\x2F\xC8\xDD\x27\xD5\x1C\x62\xD2\x2C\x97"
"\x90\xAE\x08\x4B\xEE\xF4\x8D\x22\xF0\x2A\x1E\x38\x2D\x31\xCB\x68", MECHANISM_OUTPUT_SIZE_SSL,
inputValue, MECHANISM_INPUT_SIZE_SSL, CRYPT_USE_DEFAULT,
saltValue, MECHANISM_SALT_SIZE_SSL, 1 } },
#endif /* USE_SSL */
#ifdef USE_CMP
{ MECHANISM_DERIVE_CMP,
{ "\x80\x0B\x95\x73\x74\x3B\xC1\x63\x6B\x28\x2B\x04\x47\xFD\xF0\x04"
"\x80\x40\x31\xB1", 20,
inputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1,
saltValue, MECHANISM_SALT_SIZE, 10 } },
#endif /* USE_CMP */
#ifdef USE_PKCS12
{ MECHANISM_DERIVE_PKCS12,
{ "", MECHANISM_OUTPUT_SIZE,
inputValue, MECHANISM_INPUT_SIZE, CRYPT_ALGO_SHA1,
saltValue, MECHANISM_SALT_SIZE, 10 } },
#endif /* USE_PKCS12 */
{ MECHANISM_NONE }, { MECHANISM_NONE }
};
CHECK_RETVAL \
static int mechanismSelfTest( void )
{
BYTE buffer[ MECHANISM_OUTPUT_SIZE_SSL + 8 ];
int i, status;
for( i = 0; mechanismTestInfo[ i ].mechanismType != MECHANISM_NONE && \
i < FAILSAFE_ARRAYSIZE( mechanismTestInfo, MECHANISM_TEST_INFO );
i++ )
{
const MECHANISM_TEST_INFO *mechanismTestInfoPtr = \
&mechanismTestInfo[ i ];
MECHANISM_DERIVE_INFO mechanismInfo;
memcpy( &mechanismInfo, &mechanismTestInfoPtr->mechanismInfo,
sizeof( MECHANISM_DERIVE_INFO ) );
mechanismInfo.dataOut = buffer;
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
IMESSAGE_DEV_DERIVE, &mechanismInfo,
mechanismTestInfoPtr->mechanismType );
if( cryptStatusError( status ) )
return( status );
if( memcmp( mechanismTestInfoPtr->mechanismInfo.dataOut, buffer,
mechanismTestInfoPtr->mechanismInfo.dataOutLength ) )
return( CRYPT_ERROR_FAILED );
}
if( i >= FAILSAFE_ARRAYSIZE( mechanismTestInfo, MECHANISM_TEST_INFO ) )
retIntError();
return( CRYPT_OK );
}
/****************************************************************************
* *
* Device Init/Shutdown/Device Control Routines *
* *
****************************************************************************/
/* Initialise and shut down the system device */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -