📄 cryptmch.c
字号:
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 + -