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

📄 lib_rsa.c

📁 提供了很多种加密算法和CA认证及相关服务如CMP、OCSP等的开发
💻 C
📖 第 1 页 / 共 2 页
字号:
	for( i = 0; i < length; i++ )
		if( buffer[ i ] )
			break;
	if( length - i < 56 )
		return( CRYPT_ERROR_BADDATA );

	if( ( bnCTX = BN_CTX_new() ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* 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
	   leading-zero truncation, we have to adjust where we copy the result to
	   in the buffer to take into account extra zero bytes which aren't
	   extracted from the bignum */
	n = BN_new();
	BN_bin2bn( buffer, length, n );
	zeroise( buffer, length );	/* Clear buffer while data is in bignum */
	BN_mod_exp_mont( n, n, cryptInfo->ctxPKC.rsaParam_e,
					 cryptInfo->ctxPKC.rsaParam_n, bnCTX,
					 cryptInfo->ctxPKC.rsaParam_mont_n );
	BN_bn2bin( n, buffer + ( length - BN_num_bytes( n ) ) );
	BN_clear_free( n );

	BN_CTX_free( bnCTX );

	return( ( status == -1 ) ? CRYPT_ERROR_FAILED : status );
	}

/* Use the Chinese Remainder Theorem shortcut for RSA decryption/signature
   generation.  M is the output plaintext message, C is the input ciphertext
   message, d is the secret decryption exponent, p and q are the prime
   factors of n, u is the multiplicative inverse of q, mod p.  n, the common
   modulus, is not used because of the Chinese Remainder Theorem shortcut */

int rsaDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
	{
	BN_CTX *bnCTX;
	BIGNUM *p = cryptInfo->ctxPKC.rsaParam_p;
	BIGNUM *q = cryptInfo->ctxPKC.rsaParam_q;
	BIGNUM *u = cryptInfo->ctxPKC.rsaParam_u;
	BIGNUM *e1 = cryptInfo->ctxPKC.rsaParam_exponent1;
	BIGNUM *e2 = cryptInfo->ctxPKC.rsaParam_exponent2;
	BIGNUM *data, *p2, *q2;
	const int length = bitsToBytes( cryptInfo->ctxPKC.keySizeBits );
	int i, status = 0;

	assert( noBytes == length );

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

	if( ( bnCTX = BN_CTX_new() ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* Initialise the bignums */
	p2 = BN_new();
	q2 = BN_new();
	data = BN_new();
	BN_bin2bn( buffer, length, data );
	zeroise( buffer, length );	/* Clear buffer while data is in bignum */

	/* Rather than decrypting by computing modexp with full mod n precision,
	   compute a shorter modexp with mod p and mod q precision:
		p2 = ( ( C mod p ) ** exponent1 ) mod p
		q2 = ( ( C mod q ) ** exponent2 ) mod q */
	BN_mod( p2, data, p, bnCTX );		/* p2 = C mod p  */
	BN_mod_exp_mont( p2, p2, e1, p, bnCTX, cryptInfo->ctxPKC.rsaParam_mont_p );
	BN_mod( q2, data, q, bnCTX );		/* q2 = C mod q  */
	BN_mod_exp_mont( q2, q2, e2, q, bnCTX, cryptInfo->ctxPKC.rsaParam_mont_q );

	/* p2 = p2 - q2; if p2 < 0 then p2 = p2 + p */
	BN_sub( p2, p2, q2 );
	if( p2->neg )
		BN_add( p2, p2, p );

	/* M = ( ( ( p2 * u ) mod p ) * q ) + q2 */
	BN_mod_mul( data, p2, u, p, bnCTX );/* data = ( p2 * u ) mod p */
	BN_mul( p2, data, q );				/* p2 = data * q (bn can't reuse data) */
	BN_add( data, p2, q2 );				/* data = p2 + q2 */

	/* Copy the result to the output buffer and destroy sensitive data.
	   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 which aren't extracted from the bignum */
	BN_bn2bin( data, buffer + ( length - BN_num_bytes( data ) ) );
	BN_clear_free( p2 );
	BN_clear_free( q2 );
	BN_clear_free( data );

	BN_CTX_free( bnCTX );

	return( ( status == -1 ) ? CRYPT_ERROR_FAILED : status );
	}

/****************************************************************************
*																			*
*							RSA Key Management Routines						*
*																			*
****************************************************************************/

/* Load RSA public/private key components into an encryption context */

int rsaInitKey( CRYPT_INFO *cryptInfo, const void *key, const int keyLength )
	{
	CRYPT_PKCINFO_RSA *rsaKey = ( CRYPT_PKCINFO_RSA * ) key;
	BN_CTX *bnCTX;
	int status = CRYPT_OK;

	/* Load the key component from the external representation into the
	   internal BigNums unless we're doing an internal load */
	if( keyLength != sizeof( PKCINFO_LOADINTERNAL ) )
		{
		cryptInfo->ctxPKC.isPublicKey = rsaKey->isPublicKey;
		BN_bin2bn( rsaKey->n, bitsToBytes( rsaKey->nLen ),
				   cryptInfo->ctxPKC.rsaParam_n );
		BN_bin2bn( rsaKey->e, bitsToBytes( rsaKey->eLen ),
				   cryptInfo->ctxPKC.rsaParam_e );
		if( !rsaKey->isPublicKey )
			{
			BN_bin2bn( rsaKey->d, bitsToBytes( rsaKey->dLen ),
					   cryptInfo->ctxPKC.rsaParam_d );
			BN_bin2bn( rsaKey->p, bitsToBytes( rsaKey->pLen ),
					   cryptInfo->ctxPKC.rsaParam_p );
			BN_bin2bn( rsaKey->q, bitsToBytes( rsaKey->qLen ),
					   cryptInfo->ctxPKC.rsaParam_q );
			BN_bin2bn( rsaKey->u, bitsToBytes( rsaKey->uLen ),
					   cryptInfo->ctxPKC.rsaParam_u );
			BN_bin2bn( rsaKey->e1, bitsToBytes( rsaKey->e1Len ),
					   cryptInfo->ctxPKC.rsaParam_exponent1 );
			BN_bin2bn( rsaKey->e2, bitsToBytes( rsaKey->e2Len ),
					   cryptInfo->ctxPKC.rsaParam_exponent2 );
			}
		}

	/* Make sure the necessary key parameters have been initialised */
	if( BN_is_zero( cryptInfo->ctxPKC.rsaParam_n ) || \
		BN_is_zero( cryptInfo->ctxPKC.rsaParam_e ) )
		return( CRYPT_ARGERROR_STR1 );
	if( !cryptInfo->ctxPKC.isPublicKey )
		{
		if( BN_is_zero( cryptInfo->ctxPKC.rsaParam_p ) || \
			BN_is_zero( cryptInfo->ctxPKC.rsaParam_q ) )
			return( CRYPT_ARGERROR_STR1 );
		if( BN_is_zero( cryptInfo->ctxPKC.rsaParam_d ) && \
			BN_is_zero( cryptInfo->ctxPKC.rsaParam_exponent1 ) )
			/* Either d or e1 et al must be present, d isn't needed if we
			   have e1 et al and e1 et al can be reconstructed from d */
			return( CRYPT_ARGERROR_STR1 );
		}

	/* Make sure the key paramters are valid: n > 504 (nominally 512 bits,
	   but some certs contain somewhat shorter keys), e > 2,
	   |p-q| > 128 bits */
	if( BN_num_bits( cryptInfo->ctxPKC.rsaParam_n ) <= 504 || \
		BN_lt_word( cryptInfo->ctxPKC.rsaParam_e, 3 ) )
		return( CRYPT_ARGERROR_STR1 );
	if( !cryptInfo->ctxPKC.isPublicKey )
		{
		BIGNUM *tmp;

		/* Make sure the two differ by at least 128 bits */
		tmp = BN_new();
		BN_copy( tmp, cryptInfo->ctxPKC.rsaParam_p );
		BN_sub( tmp, tmp, cryptInfo->ctxPKC.rsaParam_q );
		if( BN_num_bits( tmp ) < 128 )
			status = CRYPT_ARGERROR_STR1;
		BN_clear_free( tmp );
		if( cryptStatusError( status ) )
			return( status );
		}

	if( ( bnCTX = BN_CTX_new() ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* If we're not using PKCS keys which have exponent1 = d mod ( p - 1 )
	   and exponent2 = d mod ( q - 1 ) precalculated, evaluate them now.
	   If there's no u precalculated, evaluate it now */
	if( !cryptInfo->ctxPKC.isPublicKey )
		{
		if( BN_is_zero( cryptInfo->ctxPKC.rsaParam_exponent1 ) )
			{
			BIGNUM *d = cryptInfo->ctxPKC.rsaParam_d;
			BIGNUM *exponent1 = cryptInfo->ctxPKC.rsaParam_exponent1;
			BIGNUM *exponent2 = cryptInfo->ctxPKC.rsaParam_exponent2;

			BN_copy( exponent1, cryptInfo->ctxPKC.rsaParam_p );
			BN_sub_word( exponent1, 1 );	/* exponent1 = p - 1 */
			BN_mod( exponent1, d, exponent1, bnCTX );
											/* exponent1 = d mod ( p - 1 ) ) */
			BN_copy( exponent2, cryptInfo->ctxPKC.rsaParam_q );
			BN_sub_word( exponent2, 1 );	/* exponent2 = q - 1 */
			BN_mod( exponent2, d, exponent2, bnCTX );
											/* exponent2 = d mod ( q - 1 ) ) */

			/* Check that everything went OK */
			status = ( status == -1 ) ? CRYPT_ARGERROR_STR1 : CRYPT_OK;
			}
		if( cryptStatusOK( status ) && \
			BN_is_zero( cryptInfo->ctxPKC.rsaParam_u ) )
			{
			BN_clear_free( cryptInfo->ctxPKC.rsaParam_u );
			cryptInfo->ctxPKC.rsaParam_u = \
					BN_mod_inverse( cryptInfo->ctxPKC.rsaParam_q,
									cryptInfo->ctxPKC.rsaParam_p, bnCTX );
			}
		if( cryptStatusError( status ) )
			{
			BN_CTX_free( bnCTX );
			return( status );
			}
		}

	/* Make sure that p and q are set up correctly for the CRT decryption and
	   precompute the Montgomery values */
	if( !cryptInfo->ctxPKC.isPublicKey )
		fixCRTvalues( &cryptInfo->ctxPKC, TRUE, bnCTX );
	status = precomputeMontgomery( &cryptInfo->ctxPKC, bnCTX );

	/* Now that we've got the various other values set up, perform further
	   validity checks on the private key */
	if( cryptStatusOK( status ) && !cryptInfo->ctxPKC.isPublicKey && \
		!checkPrivateKeyComponents( &cryptInfo->ctxPKC, bnCTX ) )
		status = CRYPT_ARGERROR_STR1;

	BN_CTX_free( bnCTX );

	/* Set the keysize and generate a key ID for this key */
	cryptInfo->ctxPKC.keySizeBits = BN_num_bits( cryptInfo->ctxPKC.rsaParam_n );
	if( cryptStatusOK( status ) )
		status = calculateKeyID( cryptInfo );

	return( status );
	}

/****************************************************************************
*																			*
*							RSA Key Generation Routines						*
*																			*
****************************************************************************/

/* Generate an RSA key pair into an encryption context */

int rsaGenerateKey( CRYPT_INFO *cryptInfo, const int keySizeBits )
	{
	BN_CTX *bnCTX;
	BIGNUM *tmp;
	int pBits, qBits, status;

	/* Determine how many bits to give to each of p and q */
	pBits = ( keySizeBits + 1 ) / 2;
	qBits = keySizeBits - pBits;
	cryptInfo->ctxPKC.keySizeBits = pBits + qBits;

	/* Set up assorted status information */
	cryptInfo->ctxPKC.isPublicKey = FALSE;

	if( ( bnCTX = BN_CTX_new() ) == NULL )
		return( CRYPT_ERROR_MEMORY );

	/* Generate the primes p and q and set them up so the CRT decrypt will
	   work */
	BN_set_word( cryptInfo->ctxPKC.rsaParam_e, PUBLIC_EXPONENT );
	status = generateRSAPrime( cryptInfo->ctxPKC.rsaParam_p, pBits, 
							   PUBLIC_EXPONENT, cryptInfo );
	if( cryptStatusOK( status ) )
		status = generateRSAPrime( cryptInfo->ctxPKC.rsaParam_q, qBits, 
								   PUBLIC_EXPONENT, cryptInfo );
	if( cryptStatusError( status ) )
		{
		BN_CTX_free( bnCTX );
		return( status );
		}
	fixCRTvalues( &cryptInfo->ctxPKC, FALSE, bnCTX );

	/* If we managed to generate the primes OK, derive everything else from
	   them */
	tmp = BN_new();

	/* Compute d = eInv mod (p - 1)(q - 1), e1 = d mod (p - 1), and
	   e2 = d mod (q - 1) */
	BN_sub_word( cryptInfo->ctxPKC.rsaParam_p, 1 );
	BN_sub_word( cryptInfo->ctxPKC.rsaParam_q, 1 );
	BN_mul( tmp, cryptInfo->ctxPKC.rsaParam_p, cryptInfo->ctxPKC.rsaParam_q );
	BN_clear_free( cryptInfo->ctxPKC.rsaParam_d );
	cryptInfo->ctxPKC.rsaParam_d = BN_mod_inverse( cryptInfo->ctxPKC.rsaParam_e,
												   tmp, bnCTX );
	BN_mod( cryptInfo->ctxPKC.rsaParam_exponent1, cryptInfo->ctxPKC.rsaParam_d,
			cryptInfo->ctxPKC.rsaParam_p, bnCTX );
	BN_mod( cryptInfo->ctxPKC.rsaParam_exponent2, cryptInfo->ctxPKC.rsaParam_d,
			cryptInfo->ctxPKC.rsaParam_q, bnCTX );
	BN_add_word( cryptInfo->ctxPKC.rsaParam_p, 1 );
	BN_add_word( cryptInfo->ctxPKC.rsaParam_q, 1 );

	/* Compute n = pq, and u = qInv mod p */
	BN_mul( cryptInfo->ctxPKC.rsaParam_n, cryptInfo->ctxPKC.rsaParam_p,
			cryptInfo->ctxPKC.rsaParam_q );
	BN_clear_free( cryptInfo->ctxPKC.rsaParam_u );
	cryptInfo->ctxPKC.rsaParam_u = \
					BN_mod_inverse( cryptInfo->ctxPKC.rsaParam_q,
									cryptInfo->ctxPKC.rsaParam_p, bnCTX );

	/* Precompute the Montgomery values */
	status = precomputeMontgomery( &cryptInfo->ctxPKC, bnCTX );

	BN_clear_free( tmp );
	BN_CTX_free( bnCTX );

	/* Generate a keyID for the new key */
	if( cryptStatusOK( status ) )
		status = calculateKeyID( cryptInfo );

#if 0	/* For generating test key data, use cryptAddRandom( "", 0 ); */
{
#include <stdio.h>

BYTE buffer[ CRYPT_MAX_PKCSIZE ];
int length, i;

length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_n, buffer );
printf( "\t/* n */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_n ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_e, buffer );
printf( "\r\n\r\n\t/* e */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_e ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_d, buffer );
printf( "\r\n\r\n\t/* d */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_d ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_p, buffer );
printf( "\r\n\r\n\t/* p */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_p ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_q, buffer );
printf( "\r\n\r\n\t/* q */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_q ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_u, buffer );
printf( "\r\n\r\n\t/* u */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_u ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_exponent1, buffer );
printf( "\r\n\r\n\t/* exponent1 */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_exponent1 ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
length = BN_bn2bin( cryptInfo->ctxPKC.rsaParam_exponent2, buffer );
printf( "\r\n\r\n\t/* exponent2 */\r\n\t%d,", BN_num_bits( cryptInfo->ctxPKC.rsaParam_exponent2 ) );
for( i = 0; i < length; i++ )
	{ if( !( i % 8 ) ) printf( "\r\n\t  " );
	printf( "0x%02X, ", buffer[ i ] ); }
puts( "\r\n\t};" );
}
#endif /* 0 */

	return( status );
	}

⌨️ 快捷键说明

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