⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev_sys.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*																			*
*						cryptlib System Device Routines						*
*						Copyright Peter Gutmann 1995-2003					*
*																			*
****************************************************************************/

/* The random pool handling code in this module and the misc/rnd*.c modules
   represent the cryptlib continuously seeded pseudorandom number generator
   (CSPRNG) as described in my 1998 Usenix Security Symposium paper "The
   generation of practically strong random numbers".

   The CSPRNG code is copyright Peter Gutmann (and various others) 1995-2003
   all rights reserved.  Redistribution of the CSPRNG modules and use in
   source and binary forms, with or without modification, are permitted
   provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice
	  and this permission notice in its entirety.

   2. Redistributions in binary form must reproduce the copyright notice in
	  the documentation and/or other materials provided with the distribution.

   3. A copy of any bugfixes or enhancements made must be provided to the
	  author, <pgut001@cs.auckland.ac.nz> to allow them to be added to the
	  baseline version of the code.

   ALTERNATIVELY, the code may be distributed under the terms of the GNU
   General Public License, version 2 or any later version published by the
   Free Software Foundation, in which case the provisions of the GNU GPL are
   required INSTEAD OF the above restrictions.

   Although not required under the terms of the GPL, it would still be nice
   if you could make any changes available to the author to allow a
   consistent code base to be maintained */

#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
  #include "crypt.h"
  #include "des.h"
  #include "capabil.h"
  #include "device.h"
  #include "libs.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "../crypt/des.h"
  #include "capabil.h"
  #include "device.h"
  #include "../libs/libs.h"
#else
  #include "crypt.h"
  #include "crypt/des.h"
  #include "device/capabil.h"
  #include "device/device.h"
  #include "libs/libs.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 FAR_BSS MECHANISM_FUNCTION_INFO mechanismFunctions[] = {
	{ MESSAGE_DEV_EXPORT, MECHANISM_PKCS1, ( MECHANISM_FUNCTION ) exportPKCS1 },
	{ MESSAGE_DEV_IMPORT, MECHANISM_PKCS1, ( MECHANISM_FUNCTION ) importPKCS1 },
	{ MESSAGE_DEV_SIGN, MECHANISM_PKCS1, ( MECHANISM_FUNCTION ) signPKCS1 },
	{ MESSAGE_DEV_SIGCHECK, MECHANISM_PKCS1, ( MECHANISM_FUNCTION ) sigcheckPKCS1 },
	{ MESSAGE_DEV_EXPORT, MECHANISM_PKCS1_RAW, ( MECHANISM_FUNCTION ) exportPKCS1 },
	{ MESSAGE_DEV_IMPORT, MECHANISM_PKCS1_RAW, ( MECHANISM_FUNCTION ) importPKCS1 },
#ifdef USE_PGP
	{ MESSAGE_DEV_EXPORT, MECHANISM_PKCS1_PGP, ( MECHANISM_FUNCTION ) exportPKCS1PGP },
	{ MESSAGE_DEV_IMPORT, MECHANISM_PKCS1_PGP, ( MECHANISM_FUNCTION ) importPKCS1PGP },
#endif /* USE_PGP */
	{ MESSAGE_DEV_EXPORT, MECHANISM_CMS, ( MECHANISM_FUNCTION ) exportCMS },
	{ MESSAGE_DEV_IMPORT, MECHANISM_CMS, ( MECHANISM_FUNCTION ) importCMS },
	{ MESSAGE_DEV_DERIVE, MECHANISM_PKCS5, ( MECHANISM_FUNCTION ) derivePKCS5 },
#if defined( USE_PGP ) || defined( USE_PGPKEYS )
	{ MESSAGE_DEV_DERIVE, MECHANISM_PGP, ( MECHANISM_FUNCTION ) derivePGP },
#endif /* USE_PGP || USE_PGPKEYS */
#ifdef USE_SSL
	{ MESSAGE_DEV_DERIVE, MECHANISM_SSL, ( MECHANISM_FUNCTION ) deriveSSL },
	{ MESSAGE_DEV_DERIVE, MECHANISM_TLS, ( MECHANISM_FUNCTION ) deriveTLS },
#endif /* USE_SSL */
#ifdef USE_CMP
	{ MESSAGE_DEV_DERIVE, MECHANISM_CMP, ( MECHANISM_FUNCTION ) deriveCMP },
#endif /* USE_CMP */
#ifdef USE_PKCS12
	{ MESSAGE_DEV_DERIVE, MECHANISM_PKCS12, ( MECHANISM_FUNCTION ) derivePKCS12 },
#endif /* USE_PKCS12 */
	{ 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 },
#ifdef USE_PGPKEYS
	{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_PGP, ( MECHANISM_FUNCTION ) importPrivateKeyPGP },
	{ MESSAGE_DEV_IMPORT, MECHANISM_PRIVATEKEYWRAP_OPENPGP, ( MECHANISM_FUNCTION ) importPrivateKeyOpenPGP },
#endif /* USE_PGPKEYS */
	{ 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 */

int createContext( MESSAGE_CREATEOBJECT_INFO *createInfo,
				   const void *auxDataPtr, const int auxValue );
int createCertificate( MESSAGE_CREATEOBJECT_INFO *createInfo,
					   const void *auxDataPtr, const int auxValue );
int createEnvelope( MESSAGE_CREATEOBJECT_INFO *createInfo,
					const void *auxDataPtr, const int auxValue );
int createSession( MESSAGE_CREATEOBJECT_INFO *createInfo,
				   const void *auxDataPtr, const int auxValue );
int createKeyset( MESSAGE_CREATEOBJECT_INFO *createInfo,
				  const void *auxDataPtr, const int auxValue );
int createDevice( MESSAGE_CREATEOBJECT_INFO *createInfo,
				  const void *auxDataPtr, const int auxValue );
int createUser( MESSAGE_CREATEOBJECT_INFO *createInfo,
				const void *auxDataPtr, const int auxValue );

static const FAR_BSS CREATEOBJECT_FUNCTION_INFO createObjectFunctions[] = {
	{ OBJECT_TYPE_CONTEXT, createContext },
	{ OBJECT_TYPE_CERTIFICATE, createCertificate },
#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 }
	};

/****************************************************************************
*																			*
*						Randomness Interface Definitions					*
*																			*
****************************************************************************/

/* If we don't have a defined randomness interface, complain */

#if !( defined( __BEOS__ ) || defined( __IBM4758__ ) || \
	   defined( __MAC__ ) || defined( __MSDOS__ ) || defined( __OS2__ ) || \
	   defined( __TANDEMNSK__ ) || defined( __TANDEMOSS__ ) || \
	   defined( __UNIX__ ) || defined( __VMCMS__ ) || \
	   defined( __WIN16__ ) || defined( __WIN32__ ) )
  #error You need to create OS-specific randomness-gathering functions in misc/rnd<os-name>.c
#endif /* Various OS-specific defines */

/* Some systems systems require special-case initialisation to allow 
   background randomness gathering, where this doesn't apply the routines to 
   do this are nop'd out */

#if defined( __WIN32__ )
  void initRandomPolling( void );
  void endRandomPolling( void );
  void waitforRandomCompletion( const BOOLEAN force );
#elif defined( __UNIX__ ) && !defined( __MVS__ )
  void initRandomPolling( void );
  #define endRandomPolling()
  void waitforRandomCompletion( const BOOLEAN force );
#else
  #define initRandomPolling()
  #define endRandomPolling()
  #define waitforRandomCompletion( dummy )
#endif /* !( __WIN32__ || __UNIX__ ) */

/* On Unix systems the randomness pool may be duplicated at any point if
   the process forks (qualis pater, talis filius), so we need to perform a 
   complex check to make sure that we're running with a unique copy of the 
   pool contents rather than a clone of data held in another process.  The 
   following function checks whether we've forked or not, which is used as a 
   signal to adjust the pool contents */

#if defined( __UNIX__ ) && !defined( __MVS__ )
  BOOLEAN checkForked( void );
#else
  #define checkForked()		FALSE
#endif /* __UNIX__ */

/* Prototypes for functions in the OS-specific randomness polling routines */

void slowPoll( void );
void fastPoll( void );

/* The size in bytes of the randomness pool and the size of the X9.17 
   post-processor generator pool */

#define RANDOMPOOL_SIZE			256
#define X917_POOLSIZE			8

/* The allocated size of the randomness pool, which allows for the overflow
   created by the fact that the hash function blocksize isn't any useful
   multiple of a power of 2 */

#define RANDOMPOOL_ALLOCSIZE	( ( ( RANDOMPOOL_SIZE + 20 - 1 ) / 20 ) * 20 )

/* In order to avoid the pool startup problem (where initial pool data may
   consist of minimally-mixed entropy samples) we require that the pool be
   mixed at least the following number of times before we can draw data from
   it.  This usually happens automatically because a slow poll adds enough
   data to cause many mixing iterations, however if this doesn't happen we
   manually mix it the appropriate number of times to get it up to the
   correct level */

#define RANDOMPOOL_MIXES		10

/* The number of samples of previous output that we keep for the FIPS 140
   continuous tests, and the number of retries we perform if we detect a
   repeat of a previous output */

#define RANDOMPOOL_SAMPLES		16
#define RANDOMPOOL_RETRIES		5

/* The number of times that we cycle the X9.17 generator before we load new 
   key and state variables.  This means that we re-seed for every 
   X917_MAX_BYTES of output produced */

#define X917_MAX_BYTES			8192
#define X917_MAX_CYCLES			( X917_MAX_BYTES / X917_POOLSIZE )

/* The scheduled DES keys for the X9.17 generator */

typedef struct {
	Key_schedule desKey1, desKey2, desKey3;
	} X917_3DES_KEY;

#define DES_KEYSIZE		sizeof( Key_schedule )

/* The size of the X9.17 generator key (112 bits for EDE 3DES) */

#define X917_KEYSIZE	16

/* Random pool information, pagelocked in memory to ensure that it never gets
   swapped to disk.  We keep track of the write position in the pool, which
   tracks where new data is added.  Whenever we add new data the write
   position is updated, once we reach the end of the pool we mix the pool
   and start again at the beginning.  We track the pool status by recording 
   the quality of the pool contents (1-100) and the number of times the pool 
   has been mixed, we can't draw data from the pool unless both of these 
   values have reached an acceptable level.  In addition to the pool state 
   information we keep track of the previous RANDOMPOOL_SAMPLES output 
   samples to check for stuck-at faults or (short) cyles */

typedef struct {
	/* Pool state information */
	BYTE randomPool[ RANDOMPOOL_ALLOCSIZE ];	/* Random byte pool */
	int randomPoolPos;		/* Current write position in the pool */

	/* Pool status information */
	int randomQuality;		/* Level of randomness in the pool */
	int randomPoolMixes;	/* Number of times pool has been mixed */

	/* X9.17 generator state information */
	BYTE x917Pool[ X917_POOLSIZE ];	/* Generator state */
	X917_3DES_KEY x917Key;	/* Scheduled 3DES key */
	BOOLEAN x917Inited;		/* Whether generator has been inited */
	int x917Count;			/* No.of times generator has been cycled */

	/* Information for the FIPS 140 continuous tests */
	unsigned long prevOutput[ RANDOMPOOL_SAMPLES ];
	unsigned long x917PrevOutput[ RANDOMPOOL_SAMPLES ];
	int prevOutputIndex;

	/* Other status information used to check the pool's operation */
	int entropyByteCount;	/* Number of bytes entropy added */
	} RANDOM_INFO;

/****************************************************************************
*																			*
*						Randomness Utility Functions						*
*																			*
****************************************************************************/

/* Convenience functions used by the system-specific randomness-polling
   routines to send data to the system device.  These just accumulate as
   close to bufSize bytes of data as possible in a user-provided buffer and
   then forward them to the device object.  Note that addRandomData() 
   assumes that the quantity of data being added is small (a fixed-size 
   struct or something similar), it shouldn't be used to add large buffers 
   full of data since information at the end of the buffer will be lost (in 
   the debug build this will trigger an exception telling the caller to use 
   a direct krnlSendMessage() instead) */

typedef struct {
	void *buffer;			/* Entropy buffer */
	int bufPos, bufSize;	/* Current buffer pos.and total size */
	int updateStatus;		/* Error status if update failed */
	} RANDOM_STATE_INFO;

void initRandomData( void *statePtr, void *buffer, const int maxSize )
	{
	RANDOM_STATE_INFO *state = ( RANDOM_STATE_INFO * ) statePtr;

	assert( isWritePtr( state, sizeof( RANDOM_STATE_INFO ) ) );
	assert( sizeof( RANDOM_STATE_INFO ) <= sizeof( RANDOM_STATE ) );
	assert( isWritePtr( buffer, maxSize ) );
	assert( maxSize >= 16 );

	memset( state, 0, sizeof( RANDOM_STATE_INFO ) );
	state->buffer = buffer;
	state->bufSize = maxSize;
	}

int addRandomData( void *statePtr, const void *value, 
				   const int valueLength )
	{
	RANDOM_STATE_INFO *state = ( RANDOM_STATE_INFO * ) statePtr;
	RESOURCE_DATA msgData;
	const BYTE *valuePtr = value;
	int length = min( valueLength, state->bufSize - state->bufPos );
	int totalLength = valueLength, status;

	assert( isWritePtr( state, sizeof( RANDOM_STATE_INFO ) ) );
	assert( isReadPtr( value, valueLength ) );
	assert( state->bufPos >= 0 && state->bufPos <= state->bufSize );
	assert( valueLength > 0 && valueLength <= state->bufSize );

	/* Sanity check on inputs (the length check checks both the input data
	   length and that bufSize > bugPos) */
	if( state->bufPos < 0 || length < 0 || state->bufSize < 16 )
		{
		/* Some type of fatal data corruption has occurred */
		state->updateStatus = CRYPT_ERROR_FAILED;
		assert( NOTREACHED );
		return( CRYPT_ERROR_FAILED );
		}

	/* Copy as much of the input as we can into the accumulator */
	if( length > 0 )
		{
		memcpy( ( BYTE * ) state->buffer + state->bufPos, valuePtr, length );
		state->bufPos += length;
		valuePtr += length;
		totalLength -= length;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -