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

📄 ctx_rsa.c

📁 cryptlib是功能强大的安全工具集。允许开发人员快速在自己的软件中集成加密和认证服务。
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
*																			*
*						cryptlib RSA Encryption Routines					*
*						Copyright Peter Gutmann 1993-2005					*
*																			*
****************************************************************************/

/* I suppose if we all used pure RSA, the Illuminati would blackmail God into
   putting a trapdoor into the laws of mathematics.
														-- Lyle Seaman */
#include <stdlib.h>
#define PKC_CONTEXT		/* Indicate that we're working with PKC context */
#if defined( INC_ALL )
  #include "crypt.h"
  #include "context.h"
#elif defined( INC_CHILD )
  #include "../crypt.h"
  #include "context.h"
#else
  #include "crypt.h"
  #include "context/context.h"
#endif /* Compiler-specific includes */

/****************************************************************************
*																			*
*								Algorithm Self-test							*
*																			*
****************************************************************************/

/* Test the RSA implementation using a sample key.  Because a lot of the
   high-level encryption routines don't exist yet, we cheat a bit and set
   up a dummy encryption context with just enough information for the
   following code to work */

typedef struct {
	const int nLen; const BYTE n[ 64 ];
	const int eLen; const BYTE e[ 1 ];
	const int dLen; const BYTE d[ 64 ];
	const int pLen; const BYTE p[ 32 ];
	const int qLen; const BYTE q[ 32 ];
	const int uLen; const BYTE u[ 32 ];
	const int e1Len; const BYTE e1[ 32 ];
	const int e2Len; const BYTE e2[ 32 ];
	} RSA_PRIVKEY;

static const FAR_BSS RSA_PRIVKEY rsaTestKey = {
	/* n */
	64,
	{ 0xE1, 0x95, 0x41, 0x17, 0xB4, 0xCB, 0xDC, 0xD0,
	  0xCB, 0x9B, 0x11, 0x19, 0x9C, 0xED, 0x04, 0x6F,
	  0xBD, 0x70, 0x2D, 0x5C, 0x8A, 0x32, 0xFF, 0x16,
	  0x22, 0x57, 0x30, 0x3B, 0xD4, 0x59, 0x9C, 0x01,
	  0xF0, 0xA3, 0x70, 0xA1, 0x6C, 0x16, 0xAC, 0xCC,
	  0x8C, 0xAD, 0xB0, 0xA0, 0xAF, 0xC7, 0xCC, 0x49,
	  0x4F, 0xD9, 0x5D, 0x32, 0x1C, 0x2A, 0xE8, 0x4E,
	  0x15, 0xE1, 0x26, 0x6C, 0xC4, 0xB8, 0x94, 0xE1 },
	/* e */
	1,
	{ 0x11 },
	/* d */
	64,
	{ 0x13, 0xE7, 0x85, 0xBE, 0x53, 0xB7, 0xA2, 0x8A,
	  0xE4, 0xC9, 0xEA, 0xEB, 0xAB, 0xF6, 0xCB, 0xAF,
	  0x81, 0xA8, 0x04, 0x00, 0xA2, 0xC8, 0x43, 0xAF,
	  0x21, 0x25, 0xCF, 0x8C, 0xCE, 0xF8, 0xD9, 0x0F,
	  0x10, 0x78, 0x4C, 0x1A, 0x26, 0x5D, 0x90, 0x18,
	  0x79, 0x90, 0x42, 0x83, 0x6E, 0xAE, 0x3E, 0x20,
	  0x0B, 0x0C, 0x5B, 0x6B, 0x8E, 0x31, 0xE5, 0xCF,
	  0xD6, 0xE0, 0xBB, 0x41, 0xC1, 0xB8, 0x2E, 0x17 },
	/* p */
	32,
	{ 0xED, 0xE4, 0x02, 0x90, 0xA4, 0xA4, 0x98, 0x0D,
	  0x45, 0xA2, 0xF3, 0x96, 0x09, 0xED, 0x7B, 0x40,
	  0xCD, 0xF6, 0x21, 0xCC, 0xC0, 0x1F, 0x83, 0x09,
	  0x56, 0x37, 0x97, 0xFB, 0x05, 0x5B, 0x87, 0xB7 },
	/* q */
	32,
	{ 0xF2, 0xC1, 0x64, 0xE8, 0x69, 0xF8, 0x5E, 0x54,
	  0x8F, 0xFD, 0x20, 0x8E, 0x6A, 0x23, 0x90, 0xF2,
	  0xAF, 0x57, 0x2F, 0x4D, 0x10, 0x80, 0x8E, 0x11,
	  0x3C, 0x61, 0x44, 0x33, 0x2B, 0xE0, 0x58, 0x27 },
	/* u */
	32,
	{ 0x68, 0x45, 0x00, 0x64, 0x32, 0x9D, 0x09, 0x6E,
	  0x0A, 0xD3, 0xF3, 0x8A, 0xFE, 0x15, 0x8C, 0x79,
	  0xAD, 0x84, 0x35, 0x05, 0x19, 0x2C, 0x19, 0x51,
	  0xAB, 0x83, 0xC7, 0xE8, 0x5C, 0xAC, 0xAD, 0x7A },
	/* exponent1 */
	32,
	{ 0x99, 0xED, 0xE3, 0x8A, 0xC4, 0xE2, 0xF8, 0xF9,
	  0x87, 0x69, 0x70, 0x70, 0x24, 0x8A, 0x9B, 0x0B,
	  0xD0, 0x90, 0x33, 0xFC, 0xF4, 0xC9, 0x18, 0x8D,
	  0x92, 0x23, 0xF8, 0xED, 0xB8, 0x2C, 0x2A, 0xA3 },
	/* exponent2 */
	32,
	{ 0xB9, 0xA2, 0xF2, 0xCF, 0xD8, 0x90, 0xC0, 0x9B,
	  0x04, 0xB2, 0x82, 0x4E, 0xC9, 0xA2, 0xBA, 0x22,
	  0xFE, 0x8D, 0xF6, 0xFE, 0xB2, 0x44, 0x30, 0x67,
	  0x88, 0x86, 0x9D, 0x90, 0x8A, 0xF6, 0xD9, 0xFF }
	};

static BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = getRSACapability();
	BYTE buffer[ CRYPT_MAX_PKCSIZE + 8 ];
	int status;

	/* Encrypt with the public key */
	memset( buffer, 0, CRYPT_MAX_PKCSIZE );
	memcpy( buffer + 1, "abcde", 5 );
	status = capabilityInfoPtr->encryptFunction( contextInfoPtr, buffer, 
						 bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ) );
	if( cryptStatusError( status ) )
		return( FALSE );

	/* Decrypt with the private key */
	status = capabilityInfoPtr->decryptFunction( contextInfoPtr, buffer, 
						 bitsToBytes( contextInfoPtr->ctxPKC->keySizeBits ) );
	if( cryptStatusError( status ) )
		return( FALSE );
	return( !memcmp( buffer + 1, "abcde", 5 ) );
	}

static int selfTest( void )
	{
	const CAPABILITY_INFO *capabilityInfoPtr = getRSACapability();
	CONTEXT_INFO contextInfoPtr;
	PKC_INFO pkcInfoStorage, *pkcInfo;
	BYTE buffer[ 64 ];
	int status;

	/* Initialise the key components */
	memset( &contextInfoPtr, 0, sizeof( CONTEXT_INFO ) );
	memset( &pkcInfoStorage, 0, sizeof( PKC_INFO ) );
	contextInfoPtr.ctxPKC = pkcInfo = &pkcInfoStorage;
	BN_init( &pkcInfo->rsaParam_n );
	BN_init( &pkcInfo->rsaParam_e );
	BN_init( &pkcInfo->rsaParam_d );
	BN_init( &pkcInfo->rsaParam_p );
	BN_init( &pkcInfo->rsaParam_q );
	BN_init( &pkcInfo->rsaParam_u );
	BN_init( &pkcInfo->rsaParam_exponent1 );
	BN_init( &pkcInfo->rsaParam_exponent2 );
	BN_init( &pkcInfo->tmp1 );
	BN_init( &pkcInfo->tmp2 );
	BN_init( &pkcInfo->tmp3 );
	pkcInfo->bnCTX = BN_CTX_new();
	BN_MONT_CTX_init( &pkcInfo->rsaParam_mont_n );
	BN_MONT_CTX_init( &pkcInfo->rsaParam_mont_p );
	BN_MONT_CTX_init( &pkcInfo->rsaParam_mont_q );
	contextInfoPtr.capabilityInfo = capabilityInfoPtr;
	initKeyWrite( &contextInfoPtr );	/* For calcKeyID() */
	BN_bin2bn( rsaTestKey.n, rsaTestKey.nLen, &pkcInfo->rsaParam_n );
	BN_bin2bn( rsaTestKey.e, rsaTestKey.eLen, &pkcInfo->rsaParam_e );
	BN_bin2bn( rsaTestKey.d, rsaTestKey.dLen, &pkcInfo->rsaParam_d );
	BN_bin2bn( rsaTestKey.p, rsaTestKey.pLen, &pkcInfo->rsaParam_p );
	BN_bin2bn( rsaTestKey.q, rsaTestKey.qLen, &pkcInfo->rsaParam_q );
	BN_bin2bn( rsaTestKey.u, rsaTestKey.uLen, &pkcInfo->rsaParam_u );
	BN_bin2bn( rsaTestKey.e1, rsaTestKey.e1Len, &pkcInfo->rsaParam_exponent1 );
	BN_bin2bn( rsaTestKey.e2, rsaTestKey.e2Len, &pkcInfo->rsaParam_exponent2 );

	/* Perform the test en/decryption of a block of data */
	status = capabilityInfoPtr->initKeyFunction( &contextInfoPtr, NULL, 0 );
	if( cryptStatusOK( status ) && \
		!pairwiseConsistencyTest( &contextInfoPtr ) )
		status = CRYPT_ERROR;
	else
		{
		/* Try it again with blinding enabled */
		memset( buffer, 0, 64 );
		memcpy( buffer, "abcde", 5 );
		contextInfoPtr.flags |= CONTEXT_SIDECHANNELPROTECTION;
		status = capabilityInfoPtr->initKeyFunction( &contextInfoPtr, NULL, 0 );
		if( cryptStatusOK( status ) )
			status = capabilityInfoPtr->encryptFunction( &contextInfoPtr, 
														 buffer, 64 );
		if( cryptStatusOK( status ) )
			status = capabilityInfoPtr->decryptFunction( &contextInfoPtr, 
														 buffer, 64 );
		if( cryptStatusError( status ) || memcmp( buffer, "abcde", 5 ) )
			status = CRYPT_ERROR;
		else
			{
			/* And one last time to ensure that the blinding value update 
			   works */
			memset( buffer, 0, 64 );
			memcpy( buffer, "abcde", 5 );
			status = capabilityInfoPtr->initKeyFunction( &contextInfoPtr, NULL, 0 );
			if( cryptStatusOK( status ) )
				status = capabilityInfoPtr->encryptFunction( &contextInfoPtr, 
															 buffer, 64 );
			if( cryptStatusOK( status ) )
				status = capabilityInfoPtr->decryptFunction( &contextInfoPtr, 
															 buffer, 64 );
			if( cryptStatusError( status ) || memcmp( buffer, "abcde", 5 ) )
				status = CRYPT_ERROR;
			}
		}

	/* Clean up */
	BN_clear_free( &pkcInfo->rsaParam_n );
	BN_clear_free( &pkcInfo->rsaParam_e );
	BN_clear_free( &pkcInfo->rsaParam_d );
	BN_clear_free( &pkcInfo->rsaParam_p );
	BN_clear_free( &pkcInfo->rsaParam_q );
	BN_clear_free( &pkcInfo->rsaParam_u );
	BN_clear_free( &pkcInfo->rsaParam_exponent1 );
	BN_clear_free( &pkcInfo->rsaParam_exponent2 );
	BN_clear_free( &pkcInfo->tmp1 );
	BN_clear_free( &pkcInfo->tmp2 );
	BN_clear_free( &pkcInfo->tmp3 );
	BN_CTX_free( pkcInfo->bnCTX );
	BN_MONT_CTX_free( &pkcInfo->rsaParam_mont_n );
	BN_MONT_CTX_free( &pkcInfo->rsaParam_mont_p );
	BN_MONT_CTX_free( &pkcInfo->rsaParam_mont_q );
	zeroise( &pkcInfoStorage, sizeof( PKC_INFO ) );
	zeroise( &contextInfoPtr, sizeof( CONTEXT_INFO ) );

	return( status );
	}

/****************************************************************************
*																			*
*							Encrypt/Decrypt a Data Block					*
*																			*
****************************************************************************/

/* Encrypt/signature check a single block of data.  We have to append the 
   distinguisher 'Fn' to the name since some systems already have 'encrypt' 
   and 'decrypt' in their standard headers */

static int encryptFn( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
	{
	PKC_INFO *pkcInfo = contextInfoPtr->ctxPKC;
	BIGNUM *n = &pkcInfo->rsaParam_n, *e = &pkcInfo->rsaParam_e;
	BIGNUM *data = &pkcInfo->tmp1;
	const int length = bitsToBytes( pkcInfo->keySizeBits );
	int i, bnStatus = BN_STATUS;

	assert( noBytes == length );

	/* Make sure that we're not being fed suspiciously short data 
	   quantities */
	for( i = 0; i < length; i++ )
		if( buffer[ i ] )
			break;
	if( length - i < 56 )
		return( CRYPT_ERROR_BADDATA );

	/* Move the data from the buffer into a bignum, perform the modexp, and
	   move the result back into the buffer.  Since the bignum code performs

⌨️ 快捷键说明

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