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

📄 mech_privk.c

📁 cryptlib安全工具包
💻 C
📖 第 1 页 / 共 2 页
字号:
	if( cryptStatusError( status ) )
		return( status );
	padSize = roundUp( payloadSize + 1, blockSize ) - payloadSize;
	
	ENSURES( !( ( payloadSize + padSize ) & ( blockSize - 1 ) ) );
	ENSURES( padSize >= 1 && padSize <= CRYPT_MAX_IVSIZE );

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

	/* Make sure that the wrapped key fits in the output buffer */
	if( payloadSize + padSize > mechanismInfo->wrappedDataLength )
		return( CRYPT_ERROR_OVERFLOW );

	/* Write the private key data, PKCS #5-pad it, and encrypt it */
	sMemOpen( &stream, mechanismInfo->wrappedData,
			  mechanismInfo->wrappedDataLength );
	status = exportPrivateKeyData( &stream, mechanismInfo->keyContext,
								   formatType, "private_key", 11 );
	sMemDisconnect( &stream );
	if( cryptStatusOK( status ) )
		{
		BYTE startSample[ 8 + 8 ], endSample[ 8 + 8 ];
		BYTE *dataPtr = mechanismInfo->wrappedData;
		const void *dataEndPtr = dataPtr + payloadSize + padSize - 8;
		int i;

		/* Sample the first and last 8 bytes of data so that we can check
		   that they really have been encrypted */
		memcpy( startSample, dataPtr, 8 );
		memcpy( endSample, dataEndPtr, 8 );

		/* Add the PKCS #5 padding and encrypt the data */
		for( i = 0; i < padSize; i++ )
			dataPtr[ payloadSize + i ] = padSize;
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_ENCRYPT,
								  mechanismInfo->wrappedData,
								  payloadSize + padSize );

		/* Make sure that the original data samples differ from the final
		   data.  We don't perform a retIntError() exit at this point because
		   we need to continue and zeroise the data that we're working with */
		if( cryptStatusOK( status ) && \
			( !memcmp( startSample, dataPtr, 8 ) || \
			  !memcmp( endSample, dataEndPtr, 8 ) ) )
			{
			assert( DEBUG_WARN );
			status = CRYPT_ERROR_FAILED;
			}
		zeroise( startSample, 8 );
		zeroise( endSample, 8 );
		}
	if( cryptStatusError( status ) )
		{
		zeroise( mechanismInfo->wrappedData,
				 mechanismInfo->wrappedDataLength );
		return( status );
		}
	mechanismInfo->wrappedDataLength = payloadSize + padSize;

	return( CRYPT_OK );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
static int privateKeyUnwrap( STDC_UNUSED void *dummy, 
							 INOUT MECHANISM_WRAP_INFO *mechanismInfo,
							 IN_ENUM( PRIVATEKEY_WRAP ) \
								const PRIVATEKEY_WRAP_TYPE type )
	{
	const KEYFORMAT_TYPE formatType = ( type == PRIVATEKEY_WRAP_NORMAL ) ? \
								KEYFORMAT_PRIVATE : KEYFORMAT_PRIVATE_OLD;
	void *buffer;
	int blockSize, status;

	UNUSED_ARG( dummy );

	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );
	
	REQUIRES( type > PRIVATEKEY_WRAP_NONE && type < PRIVATEKEY_WRAP_LAST );

	/* Make sure that the data has a sane length and is a multiple of the
	   cipher block size.  Since we force the use of CBC mode we know that 
	   it has to have this property.  Any required length checks have 
	   already been enforced by the kernel ACLs */
	status = krnlSendMessage( mechanismInfo->wrapContext,
							  IMESSAGE_GETATTRIBUTE, &blockSize,
							  CRYPT_CTXINFO_IVSIZE );
	if( cryptStatusError( status ) )
		return( status );
	if( mechanismInfo->wrappedDataLength & ( blockSize - 1 ) )
		return( CRYPT_ERROR_BADDATA );

	/* Copy the encrypted private key data to a temporary pagelocked buffer, 
	   decrypt it, and read it into the context.  If we get a corrupted-data 
	   error then it's far more likely to be because we decrypted with the 
	   wrong key than because any data was corrupted so we convert it to a 
	   wrong-key error */
	if( ( status = krnlMemalloc( &buffer, \
							mechanismInfo->wrappedDataLength ) ) != CRYPT_OK )
		return( status );
	memcpy( buffer, mechanismInfo->wrappedData,
			mechanismInfo->wrappedDataLength );
	status = krnlSendMessage( mechanismInfo->wrapContext,
							  IMESSAGE_CTX_DECRYPT, buffer,
							  mechanismInfo->wrappedDataLength );
	if( cryptStatusOK( status ) )
		{
		status = checkKeyIntegrity( buffer, 
									mechanismInfo->wrappedDataLength, 
									blockSize );
		}
	if( cryptStatusOK( status ) )
		{
		STREAM stream;

		sMemConnect( &stream, buffer, mechanismInfo->wrappedDataLength );
		status = importPrivateKeyData( &stream, mechanismInfo->keyContext,
									   formatType );
		sMemDisconnect( &stream );
		if( status == CRYPT_ERROR_BADDATA )
			status = CRYPT_ERROR_WRONGKEY;
		}
	zeroise( buffer, mechanismInfo->wrappedDataLength );
	krnlMemfree( &buffer );

	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int exportPrivateKey( STDC_UNUSED void *dummy, 
					  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKey( STDC_UNUSED void *dummy, 
					  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_NORMAL ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int exportPrivateKeyPKCS8( STDC_UNUSED void *dummy, 
						   INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyWrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyPKCS8( STDC_UNUSED void *dummy, 
						   INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyUnwrap( dummy, mechanismInfo, PRIVATEKEY_WRAP_OLD ) );
	}

/****************************************************************************
*																			*
*						PGP Private Key Wrap/Unwrap Mechanisms				*
*																			*
****************************************************************************/

#ifdef USE_PGPKEYS

/* Perform PGP private key wrapping/unwrapping.  There are several variations
   of this that are handled through common private key wrap mechanism
   functions.  The variations are:

	PGP2: mpi_enc( d ), mpi_enc( p ), mpi_enc( q ), mpi_enc( u ),
		  uint16 checksum
	
	OpenPGP_Old: enc( mpi [...], 
					  uint16 checksum )
	
	OpenPGP: enc( mpi [...], 
				  byte[20] mdc ) */

typedef enum { PRIVATEKEYPGP_WRAP_NONE, PRIVATEKEYPGP_WRAP_PGP2, 
			   PRIVATEKEYPGP_WRAP_OPENPGP_OLD,
			   PRIVATEKEYPGP_WRAP_OPENPGP, 
			   PRIVATEKEYPGP_WRAP_LAST } PRIVATEKEYPGP_WRAP_TYPE;

CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int privateKeyUnwrapPGP( STDC_UNUSED void *dummy,
								INOUT MECHANISM_WRAP_INFO *mechanismInfo,
								IN_ENUM( PRIVATEKEYPGP_WRAP ) \
									const PRIVATEKEYPGP_WRAP_TYPE type )
	{
	CRYPT_ALGO_TYPE cryptAlgo;
	STREAM stream;
	void *buffer;
	int bytesToChecksum = DUMMY_INIT, status;

	UNUSED_ARG( dummy );

	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	REQUIRES( type > PRIVATEKEYPGP_WRAP_NONE && \
			  type < PRIVATEKEYPGP_WRAP_LAST );

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

	/* Copy the encrypted private key data to a temporary buffer and decrypt 
	   it */
	if( ( status = krnlMemalloc( &buffer, \
						mechanismInfo->wrappedDataLength ) ) != CRYPT_OK )
		return( status );
	memcpy( buffer, mechanismInfo->wrappedData,
			mechanismInfo->wrappedDataLength );
	if( type == PRIVATEKEYPGP_WRAP_PGP2 )
		{
		status = pgp2DecryptKey( buffer, mechanismInfo->wrappedDataLength,
								 &bytesToChecksum, mechanismInfo->wrapContext, 
								 ( cryptAlgo != CRYPT_ALGO_RSA ) ? \
									TRUE : FALSE );
		}
	else
		{
		status = krnlSendMessage( mechanismInfo->wrapContext,
								  IMESSAGE_CTX_DECRYPT, buffer,
								  mechanismInfo->wrappedDataLength );
		}
	if( cryptStatusError( status ) )
		{
		zeroise( buffer, mechanismInfo->wrappedDataLength );
		krnlMemfree( &buffer );
		return( status );
		}

	/* Perform one of PGP's assorted key checksumming operations and read 
	   the key data into the context */
	if( type == PRIVATEKEYPGP_WRAP_PGP2 || \
		type == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )
		{
		/* Before the use of MDCs for private-key data there was a mutant 
		   halfway stage that use the PGP 2.x checksum but encrypted all of 
		   the key data in the OpenPGP manner.  If we're using this halfway 
		   variant then the amount of data to checksum is the total amount
		   minus the size of the checksum */
		if( type == PRIVATEKEYPGP_WRAP_OPENPGP_OLD )
			bytesToChecksum = mechanismInfo->wrappedDataLength - UINT16_SIZE;
		status = checkPgp2KeyIntegrity( buffer, mechanismInfo->wrappedDataLength,
										bytesToChecksum,
										( cryptAlgo != CRYPT_ALGO_RSA ) ? \
											TRUE : FALSE  );
		}
	else
		{
		status = checkOpenPgpKeyIntegrity( buffer, 
										   mechanismInfo->wrappedDataLength );
		}
	if( cryptStatusOK( status ) )
		{
		sMemConnect( &stream, buffer, mechanismInfo->wrappedDataLength );
		status = importPrivateKeyData( &stream, mechanismInfo->keyContext,
									   KEYFORMAT_PGP );
		sMemDisconnect( &stream );
		if( status == CRYPT_ERROR_BADDATA )
			status = CRYPT_ERROR_WRONGKEY;
		}
	zeroise( buffer, mechanismInfo->wrappedDataLength );
	krnlMemfree( &buffer );

	return( status );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyPGP2( STDC_UNUSED void *dummy, 
						  INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyUnwrapPGP( dummy, mechanismInfo,
								 PRIVATEKEYPGP_WRAP_PGP2 ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyOpenPGPOld( STDC_UNUSED void *dummy, 
								INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyUnwrapPGP( dummy, mechanismInfo,
								 PRIVATEKEYPGP_WRAP_OPENPGP_OLD ) );
	}

CHECK_RETVAL STDC_NONNULL_ARG( ( 2 ) ) \
int importPrivateKeyOpenPGP( STDC_UNUSED void *dummy, 
							 INOUT MECHANISM_WRAP_INFO *mechanismInfo )
	{
	assert( isWritePtr( mechanismInfo, sizeof( MECHANISM_WRAP_INFO ) ) );

	return( privateKeyUnwrapPGP( dummy, mechanismInfo,
								 PRIVATEKEYPGP_WRAP_OPENPGP ) );
	}
#endif /* USE_PGPKEYS */

⌨️ 快捷键说明

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