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

📄 cryptmch.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
							  HASH_END );
			else
				hashFunction( hashInfo, NULL, mechanismInfo->dataIn,
							  mechanismInfo->dataInLength, HASH_CONTINUE );
			secondByteCount -= mechanismInfo->dataInLength;
			}
		}
	memcpy( mechanismInfo->dataOut, hashedKey, mechanismInfo->dataOutLength );
	zeroise( hashInfo, sizeof( HASHINFO ) );
	zeroise( hashedKey, CRYPT_MAX_KEYSIZE );

	return( CRYPT_OK );
	}
#endif /* USE_PGP || USE_PGPKEYS */

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

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

int signPKCS1( void *dummy, MECHANISM_SIGN_INFO *mechanismInfo )
	{
	CRYPT_ALGO_TYPE hashAlgo;
	RESOURCE_DATA msgData;
	STREAM stream;
	BYTE hash[ CRYPT_MAX_HASHSIZE ], preSigData[ CRYPT_MAX_PKCSIZE ];
	BOOLEAN useSideChannelProtection;
	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 and config parameters */
	status = krnlSendMessage( mechanismInfo->hashContext,
							  IMESSAGE_GETATTRIBUTE, &hashAlgo,
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->signContext,
								  IMESSAGE_GETATTRIBUTE, &length,
								  CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->signContext, 
								  IMESSAGE_GETATTRIBUTE, 
								  &useSideChannelProtection,
								  CRYPT_OPTION_MISC_SIDECHANNELPROTECTION );
	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 */
	setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
	status = krnlSendMessage( mechanismInfo->hashContext,
							  IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_CTXINFO_HASHVALUE );
	if( cryptStatusError( status ) )
		return( status );
	hashSize = msgData.length;
	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, length );
	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 );
	if( useSideChannelProtection )
		/* Remember a copy of the signature data for later so we can check it
		   against the recovered signature data */
		memcpy( preSigData, mechanismInfo->signature, length );

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

	/* If we're using side-channel protection, check that the signature 
	   verifies */
	if( useSideChannelProtection )
		{
		BYTE recoveredSignature[ CRYPT_MAX_PKCSIZE ];

		/* Make sure that the recovered signature data matches what we 
		   signed, unless we're in the unlikely situation that the key
		   isn't valid for sig.checking.  The rationale behind this 
		   operation is covered (in great detail) in lib_rsa.c */
		memcpy( recoveredSignature, mechanismInfo->signature, length );
		status = krnlSendMessage( mechanismInfo->signContext,
								  IMESSAGE_CTX_SIGCHECK, recoveredSignature,
								  length );
		if( status != CRYPT_ERROR_PERMISSION && \
			status != CRYPT_ERROR_NOTAVAIL && \
			memcmp( preSigData, recoveredSignature, length ) )
			{
			assert( NOTREACHED );
			zeroise( mechanismInfo->signature, length );
			mechanismInfo->signatureLength = 0;
			return( CRYPT_ERROR_FAILED );
			}
		zeroise( recoveredSignature, length );
		zeroise( preSigData, length );
		}

	return( CRYPT_OK );
	}

int sigcheckPKCS1( void *dummy, MECHANISM_SIGN_INFO *mechanismInfo )
	{
	CRYPT_ALGO_TYPE 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,
							  IMESSAGE_GETATTRIBUTE, &hashAlgo,
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
		status = krnlSendMessage( mechanismInfo->hashContext,
								  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,
							  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,
							  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 that 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 = 1, 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;
		}
	sMemDisconnect( &stream );
	zeroise( decryptedSignature, CRYPT_MAX_PKCSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Finally, make sure that 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 that 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 )
	{
	int extractKeyData( const CRYPT_CONTEXT iCryptContext, void *keyData );
	CRYPT_ALGO_TYPE cryptAlgo;
	RESOURCE_DATA msgData;
	BYTE *wrappedData = mechanismInfo->wrappedData, *dataPtr;
	int payloadSize, length, padSize, status;
#ifdef USE_PGP
	int pgpAlgoID;
#endif /* USE_PGP */

	assert( type == PKCS1_WRAP_NORMAL || type == PKCS1_WRAP_RAW || \
			type == PKCS1_WRAP_PGP );

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

	/* Get various algorithm parameters */
	status = krnlSendMessage( mechanismInfo->wrapContext,
							  IMESSAGE_GETATTRIBUTE, &cryptAlgo,
							  CRYPT_CTXINFO_ALGO );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_GETATTRIBUTE, &length,
								  CRYPT_CTXINFO_KEYSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* If this is just a length check, we're done */
	if( mechanismInfo->wrappedData == NULL )
		{
		/* Determine how long the encrypted value will be.  In the case of
		   Elgamal it's just an estimate since it can change by up to two
		   bytes depending on whether the values have the high bit set or
		   not, which requires zero-padding of the ASN.1-encoded integers.
		   This is rather nasty because it means we can't tell how large an
		   encrypted value will be without actually creating it.  The 10-byte
		   length at the start is for the ASN.1 SEQUENCE (4) and 2 *
		   INTEGER (2*3) encoding */
		mechanismInfo->wrappedDataLength = ( cryptAlgo == CRYPT_ALGO_ELGAMAL ) ? \
										   10 + ( 2 * ( length + 1 ) ) : length;
		return( CRYPT_OK );
		}

	/* Get the payload details, either as data passed in by the caller or
	   from the key context */
	if( type == PKCS1_WRAP_RAW )
		payloadSize = mechanismInfo->keyDataLength;
	else
		{
		status = krnlSendMessage( mechanismInfo->keyContext,
								  IMESSAGE_GETATTRIBUTE, &payloadSize,
								  CRYPT_CTXINFO_KEYSIZE );
		if( cryptStatusError( status ) )
			return( status );
		}
#ifdef USE_PGP
	if( type == PKCS1_WRAP_PGP )
		{
		CRYPT_ALGO_TYPE sessionKeyAlgo;

		/* PGP includes an additional algorithm specifier and checksum with
		   the wrapped key so we adjust the length to take this into
		   account */
		status = krnlSendMessage( mechanismInfo->keyContext,
								  IMESSAGE_GETATTRIBUTE, &sessionKeyAlgo,
								  CRYPT_CTXINFO_ALGO );
		if( cryptStatusError( status ) )
			return( status );
		pgpAlgoID = cryptlibToPgpAlgo( sessionKeyAlgo );
		if( cryptStatusError( pgpAlgoID ) )
			return( CRYPT_ERROR_NOTAVAIL );
		payloadSize += 3;
		}
#endif /* USE_PGP */

	/* Determine PKCS #1 padding parameters and make sure that the key is 
	   long enough to encrypt the payload.  PKCS #1 requires that the 
	   maximum payload size be 11 bytes less than the length (to give a 
	   minimum of 8 bytes of random padding) */
	padSize = length - ( payloadSize + 3 );
	if( payloadSize > length - 11 )
		return( CRYPT_ERROR_OVERFLOW );

	/* Encode the payload using the format given in PKCS #1, which for
	   encrypted data is [ 0 ][ 2 ][ nonzero random padding ][ 0 ][ payload ].
	   Note that the random padding is a nice place for a subliminal channel,
	   especially with large public key sizes where you can communicate more
	   information in the padding than in the payload */
	wrappedData[ 0 ] = 0;
	wrappedData[ 1 ] = 2;
	setMessageData( &msgData, wrappedData + 2, padSize );
	status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
							  IMESSAGE_GETATTRIBUTE_S, &msgData,
							  CRYPT_IATTRIBUTE_RANDOM_NZ );
	wrappedData[ 2 + padSize ] = 0;
	if( cryptStatusError( status ) )
		{
		zeroise( wrappedData, length );
		return( status );
		}

	/* Copy the payload in at the last possible moment, then encrypt it */
	dataPtr = wrappedData + 2 + padSize + 1;
	switch( type )
		{
		case PKCS1_WRAP_NORMAL:
			status = extractKeyData( mechanismInfo->keyContext, dataPtr );
			break;

		case PKCS1_WRAP_RAW:
			memcpy( dataPtr, mechanismInfo->keyData, payloadSize );
			break;

#ifdef USE_PGP
		case PKCS1_WRAP_PGP:
			*dataPtr++ = pgpAlgoID;
			status = extractKeyData( mechanismInfo->keyContext, dataPtr );
			pgpCalculateChecksum( dataPtr, payloadSize - 3, TRUE );
			break;
#endif /* USE_PGP */

		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR_NOTAVAIL );
		}
	if( cryptStatusError( status ) )
		return( status );
	if( cryptAlgo == CRYPT_ALGO_RSA )
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_ENCRYPT, wrappedData, length );
	else
		{
		DLP_PARAMS dlpParams;

		assert( cryptAlgo == CRYPT_ALGO_ELGAMAL );

⌨️ 快捷键说明

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