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