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

📄 cryptmch.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
	zeroise( initialHashInfo, sizeof( HASHINFO ) );
	zeroise( processedKey, HMAC_DATASIZE );
	zeroise( block, CRYPT_MAX_HASHSIZE );

	return( CRYPT_OK );
	}

#ifdef USE_PKCS12

/* Perform PKCS #12 derivation */

#define P12_BLOCKSIZE	64

int derivePKCS12( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION hashFunction;
	BYTE p12_DSP[ P12_BLOCKSIZE + P12_BLOCKSIZE + ( P12_BLOCKSIZE * 3 ) ];
	BYTE p12_Ai[ P12_BLOCKSIZE ], p12_B[ P12_BLOCKSIZE ];
	BYTE *bmpPtr = p12_DSP + P12_BLOCKSIZE + P12_BLOCKSIZE;
	BYTE *dataOutPtr = mechanismInfo->dataOut;
	const BYTE *dataInPtr = mechanismInfo->dataIn;
	const BYTE *saltPtr = mechanismInfo->salt;
	const int bmpLen = ( mechanismInfo->dataInLength * 2 ) + 2;
	const int p12_PLen = ( mechanismInfo->dataInLength <= 30 ) ? \
							P12_BLOCKSIZE : \
						 ( mechanismInfo->dataInLength <= 62 ) ? \
							( P12_BLOCKSIZE * 2 ) : ( P12_BLOCKSIZE * 3 );
	int hashSize, keyIndex, i;

	UNUSED( dummy );

	getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );

	/* Set up the diversifier in the first P12_BLOCKSIZE bytes, the salt in
	   the next P12_BLOCKSIZE bytes, and the password as a Unicode null-
	   terminated string in the final bytes */
	for( i = 0; i < P12_BLOCKSIZE; i++ )
		p12_DSP[ i ] = saltPtr[ 0 ];
	expandData( p12_DSP + P12_BLOCKSIZE, P12_BLOCKSIZE, saltPtr + 1,
				mechanismInfo->saltLength - 1 );
	for( i = 0; i < mechanismInfo->dataInLength; i++ )
		{
		*bmpPtr++ = '\0';
		*bmpPtr++ = dataInPtr[ i ];
		}
	*bmpPtr++ = '\0';
	*bmpPtr++ = '\0';
	expandData( p12_DSP + ( P12_BLOCKSIZE * 2 ) + bmpLen, p12_PLen - bmpLen,
				p12_DSP + ( P12_BLOCKSIZE * 2 ), bmpLen );

	/* Produce enough blocks of output to fill the key */
	for( keyIndex = 0; keyIndex < mechanismInfo->dataOutLength;
		 keyIndex += hashSize, dataOutPtr += hashSize )
		{
		const int noKeyBytes = \
			( mechanismInfo->dataOutLength - keyIndex > hashSize ) ? \
			hashSize : mechanismInfo->dataOutLength - keyIndex;
		BYTE *p12_DSPj;

		/* Hash the keying material the required number of times to obtain the
		   output value */
		hashFunction( NULL, p12_Ai, p12_DSP,
					  P12_BLOCKSIZE + P12_BLOCKSIZE + p12_PLen, HASH_ALL );
		for( i = 1; i < mechanismInfo->iterations; i++ )
			hashFunction( NULL, p12_Ai, p12_Ai, hashSize, HASH_ALL );
		memcpy( dataOutPtr, p12_Ai, noKeyBytes );
		if( noKeyBytes <= hashSize)
			break;

		/* Update the input keying material for the next iteration */
		expandData( p12_B, P12_BLOCKSIZE, p12_Ai, hashSize );
		for( p12_DSPj = p12_DSP + P12_BLOCKSIZE; 
			 p12_DSPj < p12_DSP + ( 2 * P12_BLOCKSIZE ) + p12_PLen; 
			 p12_DSPj += P12_BLOCKSIZE )
			{
			int dspIndex = P12_BLOCKSIZE - 1, bIndex = P12_BLOCKSIZE - 1;
			int carry = 1;

			/* Ij = (Ij + B + 1) mod 2^BLOCKSIZE */
			for( dspIndex = P12_BLOCKSIZE - 1, bIndex = P12_BLOCKSIZE - 1;
				 dspIndex >= 0; dspIndex--, bIndex-- )
				{
				const int value = p12_DSPj[ dspIndex ] + p12_B[ bIndex ] + carry;
				p12_DSPj[ dspIndex ] = value & 0xFF;
				carry = value >> 8;
				}
			}
		}
	zeroise( p12_DSP, P12_BLOCKSIZE + P12_BLOCKSIZE + ( P12_BLOCKSIZE * 3 ) );
	zeroise( p12_Ai, P12_BLOCKSIZE );
	zeroise( p12_B, P12_BLOCKSIZE );

	return( CRYPT_OK );
	}
#endif /* USE_PKCS12 */

#ifdef USE_SSL

/* Perform SSL key derivation */

int deriveSSL( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION md5HashFunction, shaHashFunction;
	HASHINFO hashInfo;
	BYTE hash[ CRYPT_MAX_HASHSIZE ], counterData[ 16 ];
	int md5HashSize, shaHashSize, counter = 0, keyIndex;

	UNUSED( dummy );

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

	/* Produce enough blocks of output to fill the key */
	for( keyIndex = 0; keyIndex < mechanismInfo->dataOutLength;
		 keyIndex += md5HashSize )
		{
		const int noKeyBytes = \
			( mechanismInfo->dataOutLength - keyIndex > md5HashSize ) ? \
			md5HashSize : mechanismInfo->dataOutLength - keyIndex;
		int i;

		/* Set up the counter data */
		for( i = 0; i <= counter; i++ )
			counterData[ i ] = 'A' + counter;
		counter++;

		/* Calculate SHA1( 'A'/'BB'/'CCC'/... || keyData || salt ) */
		shaHashFunction( hashInfo, NULL, counterData, counter, HASH_START );
		shaHashFunction( hashInfo, NULL, mechanismInfo->dataIn,
						 mechanismInfo->dataInLength, HASH_CONTINUE );
		shaHashFunction( hashInfo, hash, mechanismInfo->salt,
						 mechanismInfo->saltLength, HASH_END );

		/* Calculate MD5( keyData || SHA1-hash ) */
		md5HashFunction( hashInfo, NULL, mechanismInfo->dataIn,
						 mechanismInfo->dataInLength, HASH_START );
		md5HashFunction( hashInfo, hash, hash, shaHashSize, HASH_END );

		/* Copy the result to the output */
		memcpy( ( BYTE * )( mechanismInfo->dataOut ) + keyIndex, hash, noKeyBytes );
		}
	zeroise( hashInfo, sizeof( HASHINFO ) );
	zeroise( hash, CRYPT_MAX_HASHSIZE );

	return( CRYPT_OK );
	}

/* Perform TLS key derivation (this is the function described as PRF() in the
   TLS spec) */

int deriveTLS( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION md5HashFunction, shaHashFunction;
	HASHINFO md5HashInfo, md5InitialHashInfo, md5AnHashInfo;
	HASHINFO shaHashInfo, shaInitialHashInfo, shaAnHashInfo;
	BYTE md5ProcessedKey[ HMAC_DATASIZE ], shaProcessedKey[ HMAC_DATASIZE ];
	BYTE md5A[ CRYPT_MAX_HASHSIZE ], shaA[ CRYPT_MAX_HASHSIZE ];
	BYTE md5Hash[ CRYPT_MAX_HASHSIZE ], shaHash[ CRYPT_MAX_HASHSIZE ];
	BYTE *md5DataOutPtr = mechanismInfo->dataOut;
	BYTE *shaDataOutPtr = mechanismInfo->dataOut;
	const BYTE *dataEndPtr = ( BYTE * ) mechanismInfo->dataOut + \
							 mechanismInfo->dataOutLength;
	const void *s1, *s2;
	const int sLen = ( mechanismInfo->dataInLength + 1 ) / 2;
	int md5ProcessedKeyLength, shaProcessedKeyLength;
	int md5HashSize, shaHashSize, keyIndex;

	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 that 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, sizeof( HASHINFO ) );
	md5HashFunction( md5HashInfo, NULL, mechanismInfo->salt,
					 mechanismInfo->saltLength, HASH_CONTINUE );
	prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5A,
			md5ProcessedKey, md5ProcessedKeyLength );
	memcpy( shaHashInfo, shaInitialHashInfo, sizeof( HASHINFO ) );
	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, sizeof( HASHINFO ) );
		md5HashFunction( md5HashInfo, NULL, md5A, md5HashSize, HASH_CONTINUE );
		memcpy( md5AnHashInfo, md5HashInfo, sizeof( HASHINFO ) );
		md5HashFunction( md5HashInfo, NULL, mechanismInfo->salt,
						 mechanismInfo->saltLength, HASH_CONTINUE );
		prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5Hash,
				md5ProcessedKey, md5ProcessedKeyLength );
		memcpy( shaHashInfo, shaInitialHashInfo, sizeof( HASHINFO ) );
		shaHashFunction( shaHashInfo, NULL, shaA, shaHashSize, HASH_CONTINUE );
		memcpy( shaAnHashInfo, shaHashInfo, sizeof( HASHINFO ) );
		shaHashFunction( shaHashInfo, NULL, mechanismInfo->salt,
						 mechanismInfo->saltLength, HASH_CONTINUE );
		prfEnd( shaHashFunction, shaHashInfo, shaHashSize, shaHash,
				shaProcessedKey, shaProcessedKeyLength );

		/* Calculate An+1 = HMAC( An ) */
		memcpy( md5HashInfo, md5AnHashInfo, sizeof( HASHINFO ) );
		prfEnd( md5HashFunction, md5HashInfo, md5HashSize, md5A,
				md5ProcessedKey, md5ProcessedKeyLength );
		memcpy( shaHashInfo, shaAnHashInfo, sizeof( HASHINFO ) );
		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, sizeof( HASHINFO ) );
	zeroise( md5InitialHashInfo, sizeof( HASHINFO ) );
	zeroise( md5AnHashInfo, sizeof( HASHINFO ) );
	zeroise( shaHashInfo, sizeof( HASHINFO ) );
	zeroise( shaInitialHashInfo, sizeof( HASHINFO ) );
	zeroise( shaAnHashInfo, sizeof( HASHINFO ) );
	zeroise( md5ProcessedKey, HMAC_DATASIZE );
	zeroise( shaProcessedKey, HMAC_DATASIZE );
	zeroise( md5A, CRYPT_MAX_HASHSIZE );
	zeroise( shaA, CRYPT_MAX_HASHSIZE );
	zeroise( md5Hash, CRYPT_MAX_HASHSIZE );
	zeroise( shaHash, CRYPT_MAX_HASHSIZE );

	return( CRYPT_OK );
	}
#endif /* USE_SSL */

#ifdef USE_CMP

/* Perform CMP/Entrust key derivation */

int deriveCMP( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION hashFunction;
	HASHINFO hashInfo;
	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, sizeof( HASHINFO ) );

	return( CRYPT_OK );
	}
#endif /* USE_CMP */

#if defined( USE_PGP ) || defined( USE_PGPKEYS )

/* Perform OpenPGP S2K key derivation */

int derivePGP( void *dummy, MECHANISM_DERIVE_INFO *mechanismInfo )
	{
	HASHFUNCTION hashFunction;
	HASHINFO hashInfo;
	BYTE 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 that 
	   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,

⌨️ 快捷键说明

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