📄 ctx_rsa.c
字号:
/****************************************************************************
* *
* 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 + -