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

📄 cryptmch.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 4 页
字号:

	UNUSED( dummy );

	getHashParameters( CRYPT_ALGO_MD5, &md5HashFunction, &md5HashSize );
	getHashParameters( CRYPT_ALGO_SHA, &shaHashFunction, &shaHashSize );

	/* Find the start of the two halves of the keying info used for the
	   HMAC'ing.  The size of each half is given by
	   ceil( dataInLength / 2 ), so there's a one-byte overlap if the input
	   is an odd number of bytes long */
	s1 = mechanismInfo->dataIn;
	s2 = ( BYTE * ) mechanismInfo->dataIn + ( mechanismInfo->dataInLength - sLen );

	/* The two hash functions have different block sizes which would require
	   complex buffering to handle leftover bytes from SHA-1, a simpler
	   method is to zero the output data block and XOR in the values from
	   each hash mechanism using separate output location indices for MD5 and
	   SHA-1 */
	memset( mechanismInfo->dataOut, 0, mechanismInfo->dataOutLength );

	/* Initialise the MD5 and SHA-1 information with the keying info.  These
	   are reused for any future hashing since they're constant */
	prfInit( md5HashFunction, md5InitialHashInfo, md5HashSize,
			 md5ProcessedKey, &md5ProcessedKeyLength, s1, sLen );
	prfInit( shaHashFunction, shaInitialHashInfo, shaHashSize,
			 shaProcessedKey, &shaProcessedKeyLength, s2, sLen );

	/* Calculate A1 = HMAC( salt ) */
	memcpy( md5HashInfo, md5InitialHashInfo, MAX_HASHINFO_SIZE );
	md5HashFunction( md5HashInfo, NULL, mechanismInfo->salt,
					 mechanismInfo->saltLength, HASH_CONTINUE );
	prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5A,
			md5ProcessedKey, md5ProcessedKeyLength );
	memcpy( shaHashInfo, shaInitialHashInfo, MAX_HASHINFO_SIZE );
	shaHashFunction( shaHashInfo, NULL, mechanismInfo->salt,
					 mechanismInfo->saltLength, HASH_CONTINUE );
	prfEnd( shaHashFunction, shaHashInfo, shaHashSize, shaA,
			shaProcessedKey, shaProcessedKeyLength );

	/* Produce enough blocks of output to fill the key.  We use the MD5 hash
	   size as the loop increment since this produces the smaller output
	   block */
	for( keyIndex = 0; keyIndex < mechanismInfo->dataOutLength;
		 keyIndex += md5HashSize )
		{
		const int md5NoKeyBytes = \
					min( ( dataEndPtr - md5DataOutPtr ), md5HashSize );
		const int shaNoKeyBytes = \
					min( ( dataEndPtr - shaDataOutPtr ), shaHashSize );
		int i;		/* Spurious ()'s needed for broken compilers */

		/* Calculate HMAC( An || salt ) */
		memcpy( md5HashInfo, md5InitialHashInfo, MAX_HASHINFO_SIZE );
		md5HashFunction( md5HashInfo, NULL, md5A, md5HashSize, HASH_CONTINUE );
		memcpy( md5AnHashInfo, md5HashInfo, MAX_HASHINFO_SIZE );
		md5HashFunction( md5HashInfo, NULL, mechanismInfo->salt,
						 mechanismInfo->saltLength, HASH_CONTINUE );
		prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5Hash,
				md5ProcessedKey, md5ProcessedKeyLength );
		memcpy( shaHashInfo, shaInitialHashInfo, MAX_HASHINFO_SIZE );
		shaHashFunction( shaHashInfo, NULL, shaA, shaHashSize, HASH_CONTINUE );
		memcpy( shaAnHashInfo, shaHashInfo, MAX_HASHINFO_SIZE );
		shaHashFunction( shaHashInfo, NULL, mechanismInfo->salt,
						 mechanismInfo->saltLength, HASH_CONTINUE );
		prfEnd( shaHashFunction, shaHashInfo, shaHashSize, shaHash,
				shaProcessedKey, shaProcessedKeyLength );

		/* Calculate An+1 = HMAC( An ) */
		memcpy( md5HashInfo, md5AnHashInfo, MAX_HASHINFO_SIZE );
		prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5A,
				md5ProcessedKey, md5ProcessedKeyLength );
		memcpy( shaHashInfo, shaAnHashInfo, MAX_HASHINFO_SIZE );
		prfEnd( shaHashFunction, shaHashInfo, shaHashSize, shaA,
				shaProcessedKey, shaProcessedKeyLength );

		/* Copy the result to the output */
		for( i = 0; i < md5NoKeyBytes; i++ )
			md5DataOutPtr[ i ] ^= md5Hash[ i ];
		for( i = 0; i < shaNoKeyBytes; i++ )
			shaDataOutPtr[ i ] ^= shaHash[ i ];
		md5DataOutPtr += md5NoKeyBytes;
		shaDataOutPtr += shaNoKeyBytes;
		}
	zeroise( md5HashInfo, MAX_HASHINFO_SIZE );
	zeroise( md5InitialHashInfo, MAX_HASHINFO_SIZE );
	zeroise( md5AnHashInfo, MAX_HASHINFO_SIZE );
	zeroise( shaHashInfo, MAX_HASHINFO_SIZE );
	zeroise( shaInitialHashInfo, MAX_HASHINFO_SIZE );
	zeroise( shaAnHashInfo, MAX_HASHINFO_SIZE );
	zeroise( md5ProcessedKey, HMAC_DATASIZE );
	zeroise( shaProcessedKey, HMAC_DATASIZE );
	zeroise( md5A, CRYPT_MAX_HASHSIZE );
	zeroise( shaA, CRYPT_MAX_HASHSIZE );

	return( CRYPT_OK );
	}

/* Perform CMP/Entrust key derivation */

int deriveCMP( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION hashFunction;
	BYTE hashInfo[ MAX_HASHINFO_SIZE ];
	int hashSize, iterations = mechanismInfo->iterations - 1;

	UNUSED( dummy );

	/* Calculate SHA1( password || salt ) */
	getHashParameters( mechanismInfo->hashAlgo, &hashFunction, &hashSize );
	hashFunction( hashInfo, NULL, mechanismInfo->dataIn,
				  mechanismInfo->dataInLength, HASH_START );
	hashFunction( hashInfo, mechanismInfo->dataOut, mechanismInfo->salt,
				  mechanismInfo->saltLength, HASH_END );

	/* Iterate the hashing the remaining number of times */
	while( iterations-- )
		hashFunction( NULL, mechanismInfo->dataOut, mechanismInfo->dataOut,
					  hashSize, HASH_ALL );
	zeroise( hashInfo, MAX_HASHINFO_SIZE );

	return( CRYPT_OK );
	}

/* Perform OpenPGP S2K key derivation */

int derivePGP( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION hashFunction;
	BYTE hashInfo[ MAX_HASHINFO_SIZE ], hashedKey[ CRYPT_MAX_KEYSIZE ];
	long byteCount = ( long ) mechanismInfo->iterations << 6;
	long secondByteCount = 0;
	int hashSize;

	getHashParameters( mechanismInfo->hashAlgo, &hashFunction, &hashSize );

	/* If it's a non-iterated hash or the count won't allow even a single
	   pass over the 8-byte salt and password, adjust it to make sure we run
	   at least one full iteration */
	if( byteCount < PGP_SALTSIZE + mechanismInfo->dataInLength )
		byteCount = PGP_SALTSIZE + mechanismInfo->dataInLength;

	/* If the hash output size is less than the required key size, run a
	   second round of hashing after the first one to provide the required
	   amount of keying material */
	if( hashSize < mechanismInfo->dataOutLength )
		secondByteCount = byteCount;

	/* Repeatedly hash the salt and password until we've met the byte count */
	hashFunction( hashInfo, NULL, mechanismInfo->salt,
				  mechanismInfo->saltLength, HASH_START );
	byteCount -= mechanismInfo->saltLength;
	do
		{
		if( byteCount <= mechanismInfo->dataInLength )
			hashFunction( hashInfo, hashedKey, mechanismInfo->dataIn,
						  byteCount, HASH_END );
		else
			hashFunction( hashInfo, NULL, mechanismInfo->dataIn,
						  mechanismInfo->dataInLength, HASH_CONTINUE );
		byteCount -= mechanismInfo->dataInLength;
		if( byteCount <= 0 )
			continue;
		if( byteCount <= mechanismInfo->saltLength )
			hashFunction( hashInfo, hashedKey, mechanismInfo->salt,
						  byteCount, HASH_END );
		else
			hashFunction( hashInfo, NULL, mechanismInfo->salt,
						  mechanismInfo->saltLength, HASH_CONTINUE );
		byteCount -= mechanismInfo->saltLength;
		}
	while( byteCount > 0 );
	if( secondByteCount )
		{
		/* Perform a second round of hashing, preloading the hash with a
		   single zero byte */
		hashFunction( hashInfo, NULL, ( const BYTE * ) "\x00", 1, 
					  HASH_START );
		while( secondByteCount )
			{
			if( secondByteCount <= mechanismInfo->saltLength )
				hashFunction( hashInfo, hashedKey + hashSize,
							  mechanismInfo->salt, secondByteCount,
							  HASH_END );
			else
				hashFunction( hashInfo, NULL, mechanismInfo->salt,
							  mechanismInfo->saltLength, HASH_CONTINUE );
			secondByteCount -= mechanismInfo->saltLength;
			if( secondByteCount <= 0 )
				continue;
			if( secondByteCount <= mechanismInfo->dataInLength )
				hashFunction( hashInfo, hashedKey + hashSize,
							  mechanismInfo->dataIn, secondByteCount,
							  HASH_END );
			else
				hashFunction( hashInfo, NULL, mechanismInfo->dataIn,
							  mechanismInfo->dataInLength, HASH_CONTINUE );
			secondByteCount -= mechanismInfo->dataInLength;
			}
		}
	memcpy( mechanismInfo->dataOut, hashedKey, mechanismInfo->dataOutLength );
	zeroise( hashInfo, MAX_HASHINFO_SIZE );
	zeroise( hashedKey, CRYPT_MAX_KEYSIZE );

	return( CRYPT_OK );
	}

/****************************************************************************
*																			*
*								Signature Mechanisms 						*
*																			*
****************************************************************************/

/* Perform PKCS #1 signing/sig.checking */

int signPKCS1( void *dummy, MECHANISM_SIGN_INFO *mechanismInfo )
	{
	CRYPT_ALGO hashAlgo;
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE hash[ CRYPT_MAX_HASHSIZE ];
	int payloadSize, hashSize, length, i, status;

	UNUSED( dummy );

	/* Sanity check the input data */
	assert( ( mechanismInfo->signature == NULL && \
			  mechanismInfo->signatureLength == 0 ) || \
			( mechanismInfo->signatureLength >= 64 ) );

	/* Clear the return value */
	if( mechanismInfo->signature != NULL )
		memset( mechanismInfo->signature, 0,
				mechanismInfo->signatureLength );

	/* Get various algorithm parameters */
	status = krnlSendMessage( mechanismInfo->hashContext,
							  RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->signContext,
								  RESOURCE_IMESSAGE_GETATTRIBUTE, &length,
								  CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* If this is just a length check, we're done */
	if( mechanismInfo->signature == NULL )
		{
		mechanismInfo->signatureLength = length;
		return( CRYPT_OK );
		}

	/* Get the hash data and determine the encoded payload size */
	setResourceData( &msgData, hash, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( mechanismInfo->hashContext,
							  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
							  &msgData, CRYPT_CTXINFO_HASHVALUE );
	hashSize = msgData.length;
	if( cryptStatusError( status ) )
		return( status );
	payloadSize = sizeofMessageDigest( hashAlgo, hashSize );

	/* Encode the payload using the format given in PKCS #1, which for
	   signed data is [ 0 ][ 1 ][ 0xFF padding ][ 0 ][ payload ] */
	sMemOpen( &stream, mechanismInfo->signature,
			  mechanismInfo->signatureLength );
	sputc( &stream, 0 );
	sputc( &stream, 1 );
	for( i = 0; i < length - ( payloadSize + 3 ); i++ )
		sputc( &stream, 0xFF );
	sputc( &stream, 0 );
	writeMessageDigest( &stream, hashAlgo, hash, hashSize );
	sMemDisconnect( &stream );

	/* Sign the data */
	status = krnlSendMessage( mechanismInfo->signContext,
							  RESOURCE_IMESSAGE_CTX_SIGN,
							  mechanismInfo->signature, length );
	if( cryptStatusError( status ) )
		return( status );
	mechanismInfo->signatureLength = length;

	return( CRYPT_OK );
	}

int sigcheckPKCS1( void *dummy, MECHANISM_SIGN_INFO *mechanismInfo )
	{
	CRYPT_ALGO hashAlgo, recoveredHashAlgo;
	STREAM stream;
	BYTE decryptedSignature[ CRYPT_MAX_PKCSIZE ];
	BYTE hash[ CRYPT_MAX_HASHSIZE ], recoveredHash[ CRYPT_MAX_HASHSIZE ];
	int length, hashSize, recoveredHashSize, status;

	UNUSED( dummy );

	/* Sanity check the input data */
	assert( mechanismInfo->signatureLength >= 60 );

	/* Get various algorithm parameters */
	status = krnlSendMessage( mechanismInfo->hashContext,
							  RESOURCE_IMESSAGE_GETATTRIBUTE,
							  &hashAlgo, CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setResourceData( &msgData, hash, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( mechanismInfo->hashContext,
								  RESOURCE_IMESSAGE_GETATTRIBUTE_S,
								  &msgData, CRYPT_CTXINFO_HASHVALUE );
		hashSize = msgData.length;
		}
	if( cryptStatusError( status ) )
		return( status );

	/* Format the input data as required for the sig check to work */
	status = krnlSendMessage( mechanismInfo->signContext,
							  RESOURCE_IMESSAGE_GETATTRIBUTE, &length,
							  CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusOK( status ) )
		status = adjustPKCS1Data( decryptedSignature,
					mechanismInfo->signature, mechanismInfo->signatureLength,
					length );
	if( cryptStatusError( status ) )
		return( status );

	/* Recover the signed data */
	status = krnlSendMessage( mechanismInfo->signContext,
							  RESOURCE_IMESSAGE_CTX_SIGCHECK,
							  decryptedSignature, length );
	if( cryptStatusError( status ) )
		return( status );

	/* Undo the PKCS #1 padding, which for signed data is
	   [ 0 ][ 1 ][ 0xFF padding ][ 0 ][ payload ].  Note that some
	   implementations may have bignum code which zero-truncates the result
	   which produces a CRYPT_ERROR_BADDATA error, it's the responsibility
	   of the lower-level crypto layer to reformat the data to return a
	   correctly-formatted result if necessary */
	sMemConnect( &stream, decryptedSignature, length );
	if( sgetc( &stream ) || sgetc( &stream ) != 1 )
		status = CRYPT_ERROR_BADDATA;
	else
		{
		int ch, i;

		for( i = 0; i < length - 3; i++ )
			if( ( ch = sgetc( &stream ) ) != 0xFF )
				break;
		if( ch != 0 || \
			cryptStatusError( \
				readMessageDigest( &stream, &recoveredHashAlgo,
								   recoveredHash, &recoveredHashSize ) ) )
			status = CRYPT_ERROR_BADDATA;
		}
	sMemClose( &stream );
	if( cryptStatusError( status ) )
		return( status );

	/* Finally, make sure the two hash values match */
	if( hashAlgo != recoveredHashAlgo || hashSize != recoveredHashSize || \
		memcmp( hash, recoveredHash, recoveredHashSize ) )
		status = CRYPT_ERROR_SIGNATURE;

	/* Clean up */
	zeroise( hash, hashSize );
	zeroise( recoveredHash, recoveredHashSize );
	return( status );
	}

/****************************************************************************
*																			*
*							Key Wrap/Unwrap Mechanisms						*
*																			*
****************************************************************************/

/* Perform PKCS #1 wrapping/unwrapping.  There are several variations of
   this which are handled through common PKCS #1 mechanism functions */

typedef enum { PKCS1_WRAP_NORMAL, PKCS1_WRAP_RAW, PKCS1_WRAP_PGP } PKCS1_WRAP_TYPE;

static int pkcs1Wrap( MECHANISM_WRAP_INFO *mechanismInfo,
					  const PKCS1_WRAP_TYPE type )
	{
	STATIC_FN int extractKeyData( const CRYPT_CONTEXT iCryptContext,

⌨️ 快捷键说明

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