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

📄 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 */

#define PKC_CONTEXT		/* Indicate that we're working with PKC context */
#if defined( INC_ALL )
  #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[ 128 ];
	const int eLen; const BYTE e[ 3 ];
	const int dLen; const BYTE d[ 128 ];
	const int pLen; const BYTE p[ 64 ];
	const int qLen; const BYTE q[ 64 ];
	const int uLen; const BYTE u[ 64 ];
	const int e1Len; const BYTE e1[ 64 ];
	const int e2Len; const BYTE e2[ 64 ];
	} RSA_KEY;

static const RSA_KEY FAR_BSS rsaTestKey = {
	/* n */
	128,
	{ 0x9C, 0x4D, 0x98, 0x18, 0x67, 0xF9, 0x45, 0xBC,
	  0xB6, 0x75, 0x53, 0x5D, 0x2C, 0xFA, 0x55, 0xE4,
	  0x51, 0x54, 0x9F, 0x0C, 0x16, 0xB1, 0xAF, 0x89,
	  0xF6, 0xF3, 0xE7, 0x78, 0xB1, 0x2B, 0x07, 0xFB,
	  0xDC, 0xDE, 0x64, 0x23, 0x34, 0x87, 0xDA, 0x0B,
	  0xE5, 0xB3, 0x17, 0x16, 0xA4, 0xE3, 0x7F, 0x23,
	  0xDF, 0x96, 0x16, 0x28, 0xA6, 0xD2, 0xF0, 0x0A,
	  0x59, 0xEE, 0x06, 0xB3, 0x76, 0x6C, 0x64, 0x19,
	  0xD9, 0x76, 0x41, 0x25, 0x66, 0xD1, 0x93, 0x51,
	  0x52, 0x06, 0x6B, 0x71, 0x50, 0x0E, 0xAB, 0x30,
	  0xA5, 0xC8, 0x41, 0xFC, 0x30, 0xBC, 0x32, 0xD7,
	  0x4B, 0x22, 0xF2, 0x45, 0x4C, 0x94, 0x68, 0xF1,
	  0x92, 0x8A, 0x4C, 0xF9, 0xD4, 0x5E, 0x87, 0x92,
	  0xA8, 0x54, 0x93, 0x92, 0x94, 0x48, 0xA4, 0xA3,
	  0xEE, 0x19, 0x7F, 0x6E, 0xD3, 0x14, 0xB1, 0x48,
	  0xCE, 0x93, 0xD1, 0xEA, 0x4C, 0xE1, 0x9D, 0xEF },

	/* e */
	3,
	{ 0x01, 0x00, 0x01 },

	/* d */
	128,
	{ 0x37, 0xE2, 0x66, 0x67, 0x13, 0x85, 0xC4, 0xB1,
	  0x5C, 0x6B, 0x46, 0x8B, 0x21, 0xF1, 0xBF, 0x94,
	  0x0A, 0xA0, 0x3E, 0xDD, 0x8B, 0x9F, 0xAC, 0x2B,
	  0x9F, 0xE8, 0x44, 0xF2, 0x9A, 0x25, 0xD0, 0x8C,
	  0xF4, 0xC3, 0x6E, 0xFA, 0x47, 0x65, 0xEB, 0x48,
	  0x25, 0xB0, 0x8A, 0xA8, 0xC5, 0xFB, 0xB1, 0x11,
	  0x9A, 0x77, 0x87, 0x24, 0xB1, 0xC0, 0xE9, 0xA2,
	  0x49, 0xD5, 0x19, 0x00, 0x41, 0x6F, 0x2F, 0xBA,
	  0x9F, 0x28, 0x47, 0xF9, 0xB8, 0xBA, 0xFF, 0xF4,
	  0x8B, 0x20, 0xC9, 0xC9, 0x39, 0xAB, 0x52, 0x0E,
	  0x8A, 0x5A, 0xAF, 0xB3, 0xA3, 0x93, 0x4D, 0xBB,
	  0xFE, 0x62, 0x9B, 0x02, 0xCC, 0xA7, 0xB4, 0xAE,
	  0x86, 0x65, 0x88, 0x19, 0xD7, 0x44, 0xA7, 0xE4,
	  0x18, 0xB6, 0xCE, 0x01, 0xCD, 0xDF, 0x36, 0x81,
	  0xD5, 0xE1, 0x62, 0xF8, 0xD0, 0x27, 0xF1, 0x86,
	  0xA8, 0x58, 0xA7, 0xEB, 0x39, 0x79, 0x56, 0x41 },

	/* p */
	64,
	{ 0xCF, 0xDA, 0xF9, 0x99, 0x6F, 0x05, 0x95, 0x84,
	  0x09, 0x90, 0xB3, 0xAB, 0x39, 0xB7, 0xDD, 0x1D,
	  0x7B, 0xFC, 0xFD, 0x10, 0x35, 0xA0, 0x18, 0x1D,
	  0x9A, 0x11, 0x30, 0x90, 0xD4, 0x3B, 0xF0, 0x5A,
	  0xC1, 0xA6, 0xF4, 0x53, 0xD0, 0x94, 0xA0, 0xED,
	  0xE0, 0xE4, 0xE0, 0x8E, 0x44, 0x18, 0x42, 0x42,
	  0xE1, 0x2C, 0x0D, 0xF7, 0x30, 0xE2, 0xB8, 0x09,
	  0x73, 0x50, 0x28, 0xF6, 0x55, 0x85, 0x57, 0x03 },

	/* q */
	64,
	{ 0xC0, 0x81, 0xC4, 0x82, 0x6E, 0xF6, 0x1C, 0x92,
	  0x83, 0xEC, 0x17, 0xFB, 0x30, 0x98, 0xED, 0x6E,
	  0x89, 0x92, 0xB2, 0xA1, 0x21, 0x0D, 0xC1, 0x95,
	  0x49, 0x99, 0xD3, 0x79, 0xD3, 0xBD, 0x94, 0x93,
	  0xB9, 0x28, 0x68, 0xFF, 0xDE, 0xEB, 0xE8, 0xD2,
	  0x0B, 0xED, 0x7C, 0x08, 0xD0, 0xD5, 0x59, 0xE3,
	  0xC1, 0x76, 0xEA, 0xC1, 0xCD, 0xB6, 0x8B, 0x39,
	  0x4E, 0x29, 0x59, 0x5F, 0xFA, 0xCE, 0x83, 0xA5 },

	/* u */
	64,
	{ 0x4B, 0x87, 0x97, 0x1F, 0x27, 0xED, 0xAA, 0xAF,
	  0x42, 0xF4, 0x57, 0x82, 0x3F, 0xEC, 0x80, 0xED,
	  0x1E, 0x91, 0xF8, 0xB4, 0x33, 0xDA, 0xEF, 0xC3,
	  0x03, 0x53, 0x0F, 0xCE, 0xB9, 0x5F, 0xE4, 0x29,
	  0xCC, 0xEE, 0x6A, 0x5E, 0x11, 0x0E, 0xFA, 0x66,
	  0x85, 0xDC, 0xFC, 0x48, 0x31, 0x0C, 0x00, 0x97,
	  0xC6, 0x0A, 0xF2, 0x34, 0x60, 0x6B, 0xF7, 0x68,
	  0x09, 0x4E, 0xCF, 0xB1, 0x9E, 0x33, 0x9A, 0x41 },

	/* exponent1 */
	64,
	{ 0x6B, 0x2A, 0x0D, 0xF8, 0x22, 0x7A, 0x71, 0x8C,
	  0xE2, 0xD5, 0x9D, 0x1C, 0x91, 0xA4, 0x8F, 0x37,
	  0x0D, 0x5E, 0xF1, 0x26, 0x73, 0x4F, 0x78, 0x3F,
	  0x82, 0xD8, 0x8B, 0xFE, 0x8F, 0xBD, 0xDB, 0x7D,
	  0x1F, 0x4C, 0xB1, 0xB9, 0xA8, 0xD7, 0x88, 0x65,
	  0x3C, 0xC7, 0x24, 0x53, 0x95, 0x1E, 0x20, 0xC3,
	  0x94, 0x8E, 0x7F, 0x20, 0xCC, 0x2E, 0x88, 0x0E,
	  0x2F, 0x4A, 0xCB, 0xE3, 0xBD, 0x52, 0x02, 0xFB },

	/* exponent2 */
	64,
	{ 0x10, 0x27, 0xD3, 0xD2, 0x0E, 0x75, 0xE1, 0x17,
	  0xFA, 0xB2, 0x49, 0xA0, 0xEF, 0x07, 0x26, 0x85,
	  0xEC, 0x4D, 0xBF, 0x67, 0xFE, 0x5A, 0x25, 0x30,
	  0xDE, 0x28, 0x66, 0xB3, 0x06, 0xAE, 0x16, 0x55,
	  0xFF, 0x68, 0x00, 0xC7, 0xD8, 0x71, 0x7B, 0xEC,
	  0x84, 0xCB, 0xBD, 0x69, 0x0F, 0xFD, 0x97, 0xB9,
	  0xA1, 0x76, 0xD5, 0x64, 0xC6, 0x5A, 0xD7, 0x7C,
	  0x4B, 0xAE, 0xF4, 0xAD, 0x35, 0x63, 0x37, 0x71 }
	};

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

	/* Make sure that we're recovered the original, including correct
	   handling of leading zeroes */
	return( !memcmp( buffer, "\x00" "abcde" "\x00\x00\x00\x00", 10 ) );
	}

static int selfTest( void )
	{
	CONTEXT_INFO contextInfo;
	PKC_INFO contextData, *pkcInfo = &contextData;
	BYTE buffer[ 128 + 8 ];
	const CAPABILITY_INFO *capabilityInfoPtr;
	int status;

	/* Initialise the key components */
	status = staticInitContext( &contextInfo, CONTEXT_PKC, 
								getRSACapability(), &contextData, 
								sizeof( PKC_INFO ), NULL );
	if( cryptStatusError( status ) )
		return( CRYPT_ERROR_FAILED );
	status = extractBignum( &pkcInfo->rsaParam_n, rsaTestKey.n, 
							rsaTestKey.nLen, RSAPARAM_MIN_N, 
							RSAPARAM_MAX_N, NULL, TRUE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_e, rsaTestKey.e, 
								rsaTestKey.eLen, RSAPARAM_MIN_E, 
								RSAPARAM_MAX_E, &pkcInfo->rsaParam_n, 
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_d, rsaTestKey.d, 
								rsaTestKey.dLen, RSAPARAM_MIN_D, 
								RSAPARAM_MAX_D, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_p, rsaTestKey.p, 
								rsaTestKey.pLen, RSAPARAM_MIN_P, 
								RSAPARAM_MAX_P, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_q, rsaTestKey.q, 
								rsaTestKey.qLen, RSAPARAM_MIN_Q, 
								RSAPARAM_MAX_Q, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_u, rsaTestKey.u, 
								rsaTestKey.uLen, RSAPARAM_MIN_U, 
								RSAPARAM_MAX_U, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_exponent1, rsaTestKey.e1, 
								rsaTestKey.e1Len, RSAPARAM_MIN_EXP1, 
								RSAPARAM_MAX_EXP1, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusOK( status ) )
		status = extractBignum( &pkcInfo->rsaParam_exponent2, rsaTestKey.e2, 
								rsaTestKey.e2Len, RSAPARAM_MIN_EXP2, 
								RSAPARAM_MAX_EXP2, &pkcInfo->rsaParam_n,
								FALSE );
	if( cryptStatusError( status ) )
		retIntError();

	/* Perform the test en/decryption of a block of data */
	capabilityInfoPtr = contextInfo.capabilityInfo;
	status = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );
	if( cryptStatusOK( status ) && \
		!pairwiseConsistencyTest( &contextInfo ) )
		status = CRYPT_ERROR_FAILED;
	else
		{
		/* Try it again with blinding enabled.  Note that this uses the
		   randomness subsystem, which can significantly slow down the self-
		   test if it's being performed before the polling has completed */
		memset( buffer, 0, rsaTestKey.nLen );
		memcpy( buffer, "abcde", 5 );
		contextInfo.flags |= CONTEXT_FLAG_SIDECHANNELPROTECTION;
		status = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );
		if( cryptStatusOK( status ) )
			status = capabilityInfoPtr->encryptFunction( &contextInfo,
														 buffer, rsaTestKey.nLen );
		if( cryptStatusOK( status ) )
			status = capabilityInfoPtr->decryptFunction( &contextInfo,
														 buffer, rsaTestKey.nLen );
		if( cryptStatusError( status ) || memcmp( buffer, "abcde", 5 ) )
			status = CRYPT_ERROR_FAILED;
		else
			{
			/* And one last time to ensure that the blinding value update
			   works */
			memset( buffer, 0, rsaTestKey.nLen );
			memcpy( buffer, "abcde", 5 );
			status = capabilityInfoPtr->initKeyFunction( &contextInfo, NULL, 0 );
			if( cryptStatusOK( status ) )
				status = capabilityInfoPtr->encryptFunction( &contextInfo,
															 buffer, rsaTestKey.nLen );
			if( cryptStatusOK( status ) )
				status = capabilityInfoPtr->decryptFunction( &contextInfo,
															 buffer, rsaTestKey.nLen );
			if( cryptStatusError( status ) || memcmp( buffer, "abcde", 5 ) )
				status = CRYPT_ERROR_FAILED;
			}
		}

	/* Clean up */
	staticDestroyContext( &contextInfo );

	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 offset, dummy, bnStatus = BN_STATUS, status;

	assert( noBytes == length );

	/* Move the data from the buffer into a bignum */
	status = extractBignum( data, buffer, length, 
							MIN_PKCSIZE - 8, CRYPT_MAX_PKCSIZE, n, FALSE );
	if( cryptStatusError( status ) )
		return( status );

	/* Perform the modexp and move the result back into the buffer.  Since 
	   the bignum code performs leading-zero truncation, we have to adjust 
	   where we copy the result to in the buffer to take into account extra 
	   zero bytes that aren't extracted from the bignum.  In addition we 

⌨️ 快捷键说明

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