📄 cryptlib.c
字号:
/****************************************************************************
* *
* cryptlib Core Routines *
* Copyright Peter Gutmann 1992-2003 *
* *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "crypt.h"
/* Prototypes for functions in cryptkrn.c */
BOOLEAN beginInitialisation( const BOOLEAN checkState );
void endInitialisation( const BOOLEAN newState );
int initInternalFunctions( void );
void endInternalFunctions( void );
int destroyObjects( void );
/****************************************************************************
* *
* Internal Self-test Routines *
* *
****************************************************************************/
/* Self-test code for several general crypto algorithms that are used
internally all over cryptlib: MD5, SHA-1, and 3DES (and by extension
DES) */
#define DES_BLOCKSIZE 8
#if defined( INC_ALL )
#include "des.h"
#include "testdes.h"
#else
#include "crypt/des.h"
#include "crypt/testdes.h"
#endif /* Compiler-specific includes */
static BOOLEAN des3TestLoop( const DES_TEST *testData, int iterations )
{
BYTE temp[ DES_BLOCKSIZE ];
BYTE key1[ DES_SCHEDULE_SZ ], key2[ DES_SCHEDULE_SZ ], key3[ DES_SCHEDULE_SZ ];
int i;
for( i = 0; i < iterations; i++ )
{
memcpy( temp, testData[ i ].plaintext, DES_BLOCKSIZE );
des_set_key_unchecked( ( C_Block * ) testData[ i ].key,
*( ( Key_schedule * ) key1 ) );
des_set_key_unchecked( ( C_Block * ) testData[ i ].key,
*( ( Key_schedule * ) key2 ) );
des_set_key_unchecked( ( C_Block * ) testData[ i ].key,
*( ( Key_schedule * ) key3 ) );
des_ecb3_encrypt( ( C_Block * ) temp, ( C_Block * ) temp,
*( ( Key_schedule * ) key1 ),
*( ( Key_schedule * ) key2 ),
*( ( Key_schedule * ) key3 ), DES_ENCRYPT );
if( memcmp( testData[ i ].ciphertext, temp, DES_BLOCKSIZE ) )
return( FALSE );
}
return( TRUE );
}
static BOOLEAN testGeneralAlgorithms( void )
{
static const FAR_BSS struct {
const char *data;
const int length;
const BYTE hashValue[ 16 ];
} md5Vectors[] = { /* RFC 1321 MD5 test vectors */
{ "", 0,
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E } },
{ "a", 1,
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 } },
{ "abc", 3,
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 } },
{ "message digest", 14,
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 } },
{ "abcdefghijklmnopqrstuvwxyz", 26,
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B } },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62,
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F } },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 80,
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } },
{ NULL, 0, { 0 } }
};
static const FAR_BSS struct {
const char *data;
const int length;
const BYTE hashValue[ 20 ];
} sha1Vectors[] = { /* FIPS 180-1 SHA-1 test vectors */
{ "abc", 3,
{ 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A,
0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C,
0x9C, 0xD0, 0xD8, 0x9D } },
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56,
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
0xE5, 0x46, 0x70, 0xF1 } },
{ NULL, 0, { 0 } }
};
HASHFUNCTION hashFunction;
BYTE hashValue[ CRYPT_MAX_HASHSIZE ];
int hashSize, i;
/* Test the MD5 code against the values given in RFC 1321 */
getHashParameters( CRYPT_ALGO_MD5, &hashFunction, &hashSize );
if( hashFunction == NULL || hashSize != 16 )
return( FALSE );
for( i = 0; md5Vectors[ i ].data != NULL; i++ )
{
hashFunction( NULL, hashValue, ( BYTE * ) md5Vectors[ i ].data,
md5Vectors[ i ].length, HASH_ALL );
if( memcmp( hashValue, md5Vectors[ i ].hashValue, 16 ) )
return( FALSE );
}
/* Test the SHA-1 code against the values given in FIPS 180-1 */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
if( hashFunction == NULL || hashSize != 20 )
return( FALSE );
for( i = 0; sha1Vectors[ i ].data != NULL; i++ )
{
hashFunction( NULL, hashValue, ( BYTE * ) sha1Vectors[ i ].data,
sha1Vectors[ i ].length, HASH_ALL );
if( memcmp( hashValue, sha1Vectors[ i ].hashValue, 20 ) )
return( FALSE );
}
/* Test the 3DES code against the values given in NIST Special Pub.800-20,
1999, which are actually the same as NBS Special Pub.500-20, 1980 since
they require that K1 = K2 = K3 */
if( !des3TestLoop( testIP, sizeof( testIP ) / sizeof( DES_TEST ) ) || \
!des3TestLoop( testVP, sizeof( testVP ) / sizeof( DES_TEST ) ) || \
!des3TestLoop( testKP, sizeof( testKP ) / sizeof( DES_TEST ) ) || \
!des3TestLoop( testDP, sizeof( testDP ) / sizeof( DES_TEST ) ) || \
!des3TestLoop( testSB, sizeof( testSB ) / sizeof( DES_TEST ) ) )
return( FALSE );
return( TRUE );
}
/* Test the kernel mechanisms to make sure that everything's working as
expected */
static BOOLEAN testKernelMechanisms( void )
{
MESSAGE_CREATEOBJECT_INFO createInfo;
RESOURCE_DATA msgData;
CRYPT_CONTEXT cryptHandle;
static const BYTE key[] = { 0x10, 0x46, 0x91, 0x34, 0x89, 0x98, 0x01, 0x31 };
BYTE buffer[ 128 ];
time_t timeVal;
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 inability to access internal object or attribute using
external message */
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 ability to perform standard operations, and inability to
perform state=high operation on state=low object */
setMessageData( &msgData, ( void * ) key, 8 );
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 functioning of kernel range checking, phase 1: Numeric values */
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 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 );
/* Below (negative) */
#ifdef NDEBUG
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;
/* High */
#ifdef NDEBUG
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 ) )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify ability to transition state=low object to state=high */
setMessageData( &msgData, ( void * ) key, 8 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY ) != CRYPT_OK )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify inability to read write-only object */
setMessageData( &msgData, NULL, 0 );
if( krnlSendMessage( cryptHandle, IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY ) != CRYPT_ERROR_PERMISSION )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify inability to perform state=low operations on state=high
object */
setMessageData( &msgData, ( void * ) key, 8 );
if( krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY ) != CRYPT_ERROR_PERMISSION || \
krnlSendMessage( cryptHandle, IMESSAGE_CTX_GENKEY, NULL,
FALSE ) != CRYPT_ERROR_PERMISSION )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
/* Verify inability to perform disallowed action externally but still
perform it internally. Note that the object becomes very briefly
visible externally at this point, but there's nothing that can be
done with it because of the permission settings */
value = \
MK_ACTION_PERM( MESSAGE_CTX_ENCRYPT, ACTION_PERM_NONE_EXTERNAL ) | \
MK_ACTION_PERM( MESSAGE_CTX_DECRYPT, ACTION_PERM_NONE_EXTERNAL );
krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_IATTRIBUTE_ACTIONPERMS );
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_INTERNAL );
if( krnlSendMessage( cryptHandle, MESSAGE_CTX_ENCRYPT,
buffer, 8 ) != CRYPT_ERROR_PERMISSION || \
krnlSendMessage( cryptHandle, IMESSAGE_CTX_ENCRYPT,
buffer, 8 ) != CRYPT_OK )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
}
krnlSendMessage( createInfo.cryptHandle, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE, CRYPT_IATTRIBUTE_INTERNAL );
/* Verify ability to use object with a finite usage count and inability
to exceed the usage count */
value = 1;
status = krnlSendMessage( cryptHandle, IMESSAGE_SETATTRIBUTE, &value,
CRYPT_PROPERTY_USAGECOUNT );
if( cryptStatusOK( status ) )
status = krnlSendMessage( cryptHandle, IMESSAGE_CTX_ENCRYPT,
buffer, 8 );
if( cryptStatusError( status ) || \
krnlSendMessage( cryptHandle, IMESSAGE_CTX_ENCRYPT,
buffer, 8 ) != CRYPT_ERROR_PERMISSION )
{
krnlSendNotifier( cryptHandle, IMESSAGE_DECREFCOUNT );
return( FALSE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -