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

📄 cryptmch.c

📁 老外写的加密库cryptlib(版本3.1)
💻 C
📖 第 1 页 / 共 5 页
字号:
		/* For DLP-based PKC's the output length isn't the same as the key
		   size so we adjust the return length as required */
		setDLPParams( &dlpParams, wrappedData, length, wrappedData,
					  mechanismInfo->wrappedDataLength );
		if( type == PKCS1_WRAP_PGP )
			dlpParams.formatType = CRYPT_FORMAT_PGP;
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_ENCRYPT, &dlpParams,
								  sizeof( DLP_PARAMS ) );
		if( cryptStatusOK( status ) )
			length = dlpParams.outLen;
		}
	if( cryptStatusError( status ) )
		{
		zeroise( wrappedData, length );
		return( status );
		}
	mechanismInfo->wrappedDataLength = length;

	return( CRYPT_OK );
	}

static int pkcs1Unwrap( MECHANISM_WRAP_INFO *mechanismInfo,
						const PKCS1_WRAP_TYPE type )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	STREAM stream;
	RESOURCE_DATA msgData;
	BYTE decryptedData[ CRYPT_MAX_PKCSIZE ];
	int length, status;

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

	/* Clear the return value if we're returning raw data */
	if( type == PKCS1_WRAP_RAW )
		memset( mechanismInfo->keyData, 0, mechanismInfo->keyDataLength );

	/* 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 );

	/* Decrypt the data */
	if( cryptAlgo == CRYPT_ALGO_RSA )
		{
		status = adjustPKCS1Data( decryptedData, mechanismInfo->wrappedData,
								  mechanismInfo->wrappedDataLength, length );
		if( cryptStatusOK( status ) )
			status = krnlSendMessage( mechanismInfo->wrapContext,
									  IMESSAGE_CTX_DECRYPT, decryptedData,
									  length );
		}
	else
		{
		DLP_PARAMS dlpParams;

		assert( cryptAlgo == CRYPT_ALGO_ELGAMAL );

		setDLPParams( &dlpParams, mechanismInfo->wrappedData,
					  mechanismInfo->wrappedDataLength, decryptedData,
					  CRYPT_MAX_PKCSIZE );
		if( type == PKCS1_WRAP_PGP )
			dlpParams.formatType = CRYPT_FORMAT_PGP;
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_DECRYPT, &dlpParams,
								  sizeof( DLP_PARAMS ) );
		length = dlpParams.outLen;
		}
	if( cryptStatusOK( status ) && \
		( length < 11 + bitsToBytes( MIN_KEYSIZE_BITS ) || \
		  length > mechanismInfo->wrappedDataLength ) )
		/* PKCS #1 padding requires at least 11 bytes of padding data, if 
		   there isn't this much present we can't have a valid payload */
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		zeroise( decryptedData, CRYPT_MAX_PKCSIZE );
		return( status );
		}

	/* Undo the PKCS #1 padding, which for encrypted data is
	   [ 0 ][ 2 ][ random nonzero padding ][ 0 ][ payload ] with a minimum of
	   8 bytes padding.  Note that some implementations may have bignum code
	   that zero-truncates the result, producing 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, decryptedData, length );
	if( sgetc( &stream ) || sgetc( &stream ) != 2 )
		status = CRYPT_ERROR_BADDATA;
	else
		{
		int ch = 1, i;

		for( i = 0; i < length - 3; i++ )
			if( ( ch = sgetc( &stream ) ) == 0 )
				break;
		if( ch != 0 || i < 8 )
			status = CRYPT_ERROR_BADDATA;
		else
			length -= 2 + i + 1;	/* [ 0 ][ 2 ] + padding + [ 0 ] */
		}
	if( cryptStatusOK( status ) && length < bitsToBytes( MIN_KEYSIZE_BITS ) )
		status = CRYPT_ERROR_BADDATA;
	if( cryptStatusError( status ) )
		{
		sMemDisconnect( &stream );
		zeroise( decryptedData, CRYPT_MAX_PKCSIZE );
		return( status );
		}

	/* Return the result to the caller or load it into a context as a key */
	switch( type )
		{
#ifdef USE_PGP
		case PKCS1_WRAP_PGP:
			/* PGP includes extra wrapping around the key, so we have to
			   process that before we can load it */
			length -= 3;	/* Subtract extra wrapping length */
			status = pgpExtractKey( &mechanismInfo->keyContext, &stream,
									length );
			if( cryptStatusError( status ) )
				break;
			/* Fall through */
#endif /* USE_PGP */

		case PKCS1_WRAP_NORMAL:
			/* Load the decrypted keying information into the session key
			   context */
			setMessageData( &msgData, sMemBufPtr( &stream ), length );
			status = krnlSendMessage( mechanismInfo->keyContext,
									  IMESSAGE_SETATTRIBUTE_S, &msgData,
									  CRYPT_CTXINFO_KEY );
			if( status == CRYPT_ARGERROR_STR1 || \
				status == CRYPT_ARGERROR_NUM1 )
				/* If there was an error with the key value or size, convert
				   the return value into something more appropriate */
				status = CRYPT_ERROR_BADDATA;
			break;

		case PKCS1_WRAP_RAW:
			/* Return the result to the caller */
			if( length > mechanismInfo->keyDataLength )
				status = CRYPT_ERROR_OVERFLOW;
			else
				{
				memcpy( mechanismInfo->keyData, sMemBufPtr( &stream ),
						length );
				mechanismInfo->keyDataLength = length;
				}
			break;

		default:
			assert( NOTREACHED );
			return( CRYPT_ERROR );
		}
	sMemDisconnect( &stream );
	zeroise( decryptedData, CRYPT_MAX_PKCSIZE );

	return( status );
	}

int exportPKCS1( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	UNUSED( dummy );

	return( pkcs1Wrap( mechanismInfo,
					   ( mechanismInfo->keyContext == CRYPT_UNUSED ) ? \
					   PKCS1_WRAP_RAW : PKCS1_WRAP_NORMAL ) );
	}

int importPKCS1( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	UNUSED( dummy );

	return( pkcs1Unwrap( mechanismInfo,
						 ( mechanismInfo->keyData != NULL ) ? \
						 PKCS1_WRAP_RAW : PKCS1_WRAP_NORMAL ) );
	}

#ifdef USE_PGP

int exportPKCS1PGP( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	UNUSED( dummy );

	return( pkcs1Wrap( mechanismInfo, PKCS1_WRAP_PGP ) );
	}

int importPKCS1PGP( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	UNUSED( dummy );

	return( pkcs1Unwrap( mechanismInfo, PKCS1_WRAP_PGP ) );
	}
#endif /* USE_PGP */

/* Perform CMS data wrapping.  Returns an error code or the number of output
   bytes */

#define CMS_KEYBLOCK_HEADERSIZE		4

static int cmsGetPadSize( const CRYPT_CONTEXT iExportContext,
						  const int payloadSize )
	{
	int blockSize, totalSize, status;

	status = krnlSendMessage( iExportContext, IMESSAGE_GETATTRIBUTE,
							  &blockSize, CRYPT_CTXINFO_IVSIZE );
	if( cryptStatusError( status ) )
		return( status );

	/* Determine the padding size, which is the amount of padding required to
	   bring the total data size up to a multiple of the block size with a
	   minimum size of two blocks */
	totalSize = roundUp( payloadSize, blockSize );
	if( totalSize < blockSize * 2 )
		totalSize = blockSize * 2;

	return( totalSize - payloadSize );
	}

int exportCMS( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	int extractKeyData( const CRYPT_CONTEXT iCryptContext, void *keyData );
	BYTE *keyBlockPtr = ( BYTE * ) mechanismInfo->wrappedData;
	int payloadSize, padSize, status = CRYPT_OK;

	UNUSED( dummy );

	/* Sanity check the input data */
	assert( ( mechanismInfo->wrappedData == NULL && \
			  mechanismInfo->wrappedDataLength == 0 ) || \
			( mechanismInfo->wrappedDataLength >= 16 && \
			  mechanismInfo->wrappedDataLength >= mechanismInfo->keyDataLength ) );
	assert( mechanismInfo->keyData == NULL );
	assert( mechanismInfo->keyDataLength == 0 );
	assert( mechanismInfo->keyContext != CRYPT_UNUSED );
	assert( mechanismInfo->auxContext == CRYPT_UNUSED );

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

	/* Get the payload details, either as data passed in by the caller or
	   from the key context */
	if( mechanismInfo->keyContext == CRYPT_UNUSED )
		payloadSize = mechanismInfo->keyDataLength;
	else
		{
		status = krnlSendMessage( mechanismInfo->keyContext,
								  IMESSAGE_GETATTRIBUTE, &payloadSize,
								  CRYPT_CTXINFO_KEYSIZE );
		if( cryptStatusError( status ) )
			return( status );
		}
	payloadSize += CMS_KEYBLOCK_HEADERSIZE;
	padSize = cmsGetPadSize( mechanismInfo->wrapContext, payloadSize );

	/* If this is just a length check, we're done */
	if( mechanismInfo->wrappedData == NULL )
		{
		mechanismInfo->wrappedDataLength = payloadSize + padSize;
		return( CRYPT_OK );
		}

	/* Pad the payload out with a random nonce if required */
	if( padSize > 0 )
		{
		RESOURCE_DATA msgData;

		setMessageData( &msgData, keyBlockPtr + payloadSize, padSize );
		status = krnlSendMessage( SYSTEM_OBJECT_HANDLE, IMESSAGE_GETATTRIBUTE_S, 
								  &msgData, CRYPT_IATTRIBUTE_RANDOM_NONCE );
		if( cryptStatusError( status ) )
			return( status );
		}

	/* Format the key block: [length][check value][key][padding], copy the
	   payload in at the last possible moment, then perform two passes of
	   encryption retaining the IV from the first pass for the second pass */
	keyBlockPtr[ 0 ] = payloadSize - CMS_KEYBLOCK_HEADERSIZE;
	if( mechanismInfo->keyContext != CRYPT_UNUSED )
		status = extractKeyData( mechanismInfo->keyContext,
								 keyBlockPtr + CMS_KEYBLOCK_HEADERSIZE );
	else
		memcpy( keyBlockPtr + CMS_KEYBLOCK_HEADERSIZE,
				mechanismInfo->keyData, payloadSize );
	keyBlockPtr[ 1 ] = keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE ] ^ 0xFF;
	keyBlockPtr[ 2 ] = keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE + 1 ] ^ 0xFF;
	keyBlockPtr[ 3 ] = keyBlockPtr[ CMS_KEYBLOCK_HEADERSIZE + 2 ] ^ 0xFF;
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_ENCRYPT,
								  mechanismInfo->wrappedData,
								  payloadSize + padSize );
	if( cryptStatusOK( status ) )
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_ENCRYPT,
								  mechanismInfo->wrappedData,
								  payloadSize + padSize );
	if( cryptStatusError( status ) )
		{
		zeroise( mechanismInfo->wrappedData,
				 mechanismInfo->wrappedDataLength );
		return( status );
		}
	mechanismInfo->wrappedDataLength = payloadSize + padSize;

	return( CRYPT_OK );
	}

/* Perform CMS data unwrapping */

int importCMS( void *dummy, MECHANISM_WRAP_INFO *mechanismInfo )
	{
	RESOURCE_DATA msgData;
	BYTE buffer[ CRYPT_MAX_KEYSIZE + 16 ], ivBuffer[ CRYPT_MAX_IVSIZE ];
	BYTE *dataEndPtr = buffer + mechanismInfo->wrappedDataLength;
	int blockSize, status;

	UNUSED( dummy );

	/* Sanity check the input data */
	assert( mechanismInfo->wrappedData != NULL );
	assert( mechanismInfo->wrappedDataLength >= 16 );
	assert( mechanismInfo->keyData == NULL );
	assert( mechanismInfo->keyDataLength == 0 );
	assert( mechanismInfo->keyContext != CRYPT_UNUSED );
	assert( mechanismInfo->auxContext == CRYPT_UNUSED );

	/* Make sure that the data is a multiple of the cipher block size */
	status = krnlSendMessage( mechanismInfo->wrapContext,
							  IMESSAGE_GETATTRIBUTE, &blockSize,
							  CRYPT_CTXINFO_IVSIZE );
	if( cryptStatusError( status ) )
		return( status );
	if( mechanismInfo->wrappedDataLength & ( blockSize - 1 ) )
		return( CRYPT_ERROR_BADDATA );

	/* Save the current IV for the inner decryption */
	setMessageData( &msgData, ivBuffer, CRYPT_MAX_IVSIZE );
	krnlSendMessage( mechanismInfo->wrapContext, IMESSAGE_GETATTRIBUTE_S,
					 &msgData, CRYPT_CTXINFO_IV );

	/* Using the n-1'th ciphertext block as the new IV, decrypt the n'th block.
	   Then, using the decrypted n'th ciphertext block as the IV, decrypt the
	   remainder of the ciphertext blocks */
	memcpy( buffer, mechanismInfo->wrappedData,
			mechanismInfo->wrappedDataLength );
	setMessageData( &msgData, dataEndPtr - 2 * blockSize, blockSize );
	krnlSendMessage( mechanismInfo->wrapContext,
					 IMESSAGE_SETATTRIBUTE_S, &msgData, CRYPT_CTXINFO_IV );
	status = krnlSendMessage( mechanismInfo->wrapContext,
							  IMESSAGE_CTX_DECRYPT, dataEndPtr - blockSize,
							  blockSize );
	if( cryptStatusOK( status ) )
		{
		setMessageData( &msgData, dataEndPtr - blockSize, blockSize );
		krnlSendMessage( mechanismInfo->wrapContext,

⌨️ 快捷键说明

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