📄 lib_dh.c
字号:
};
/* The structure for storing the DH public values */
typedef struct {
const int baseLen; const BYTE base[ 1 ];
const int primeLen; const BYTE *prime;
} DH_PUBLIC_VALUES;
static const DH_PUBLIC_VALUES dhPublicValues[] = {
{ 2, { 0x02 }, 512, prime512 },
{ 2, { 0x02 }, 768, prime768 },
{ 2, { 0x02 }, 1024, prime1024 },
{ 2, { 0x02 }, 1280, prime1280 },
{ 2, { 0x02 }, 1536, prime1536 },
{ 2, { 0x02 }, 2048, prime2048 },
{ 2, { 0x02 }, 3072, prime3072 },
{ 2, { 0x02 }, 4096, prime4096 },
{ 0, { 0 }, 0, NULL }
};
#endif /* 0 */
/****************************************************************************
* *
* Diffie-Hellman Self-test Routines *
* *
****************************************************************************/
/* Test the Diffie-Hellman implementation using the sample key from FIPS 186.
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 {
int pLen; BYTE p[ 64 ];
int qLen; BYTE q[ 20 ];
int gLen; BYTE g[ 64 ];
int xLen; BYTE x[ 20 ];
int yLen; BYTE y[ 64 ];
} DLP_PRIVKEY;
static const DLP_PRIVKEY dlpTestKey = {
/* p */
512,
{ 0x8D, 0xF2, 0xA4, 0x94, 0x49, 0x22, 0x76, 0xAA,
0x3D, 0x25, 0x75, 0x9B, 0xB0, 0x68, 0x69, 0xCB,
0xEA, 0xC0, 0xD8, 0x3A, 0xFB, 0x8D, 0x0C, 0xF7,
0xCB, 0xB8, 0x32, 0x4F, 0x0D, 0x78, 0x82, 0xE5,
0xD0, 0x76, 0x2F, 0xC5, 0xB7, 0x21, 0x0E, 0xAF,
0xC2, 0xE9, 0xAD, 0xAC, 0x32, 0xAB, 0x7A, 0xAC,
0x49, 0x69, 0x3D, 0xFB, 0xF8, 0x37, 0x24, 0xC2,
0xEC, 0x07, 0x36, 0xEE, 0x31, 0xC8, 0x02, 0x91 },
/* q */
160,
{ 0xC7, 0x73, 0x21, 0x8C, 0x73, 0x7E, 0xC8, 0xEE,
0x99, 0x3B, 0x4F, 0x2D, 0xED, 0x30, 0xF4, 0x8E,
0xDA, 0xCE, 0x91, 0x5F },
/* g */
512,
{ 0x62, 0x6D, 0x02, 0x78, 0x39, 0xEA, 0x0A, 0x13,
0x41, 0x31, 0x63, 0xA5, 0x5B, 0x4C, 0xB5, 0x00,
0x29, 0x9D, 0x55, 0x22, 0x95, 0x6C, 0xEF, 0xCB,
0x3B, 0xFF, 0x10, 0xF3, 0x99, 0xCE, 0x2C, 0x2E,
0x71, 0xCB, 0x9D, 0xE5, 0xFA, 0x24, 0xBA, 0xBF,
0x58, 0xE5, 0xB7, 0x95, 0x21, 0x92, 0x5C, 0x9C,
0xC4, 0x2E, 0x9F, 0x6F, 0x46, 0x4B, 0x08, 0x8C,
0xC5, 0x72, 0xAF, 0x53, 0xE6, 0xD7, 0x88, 0x02 },
/* y */
160,
{ 0x20, 0x70, 0xB3, 0x22, 0x3D, 0xBA, 0x37, 0x2F,
0xDE, 0x1C, 0x0F, 0xFC, 0x7B, 0x2E, 0x3B, 0x49,
0x8B, 0x26, 0x06, 0x14 },
/* x */
512,
{ 0x19, 0x13, 0x18, 0x71, 0xD7, 0x5B, 0x16, 0x12,
0xA8, 0x19, 0xF2, 0x9D, 0x78, 0xD1, 0xB0, 0xD7,
0x34, 0x6F, 0x7A, 0xA7, 0x7B, 0xB6, 0x2A, 0x85,
0x9B, 0xFD, 0x6C, 0x56, 0x75, 0xDA, 0x9D, 0x21,
0x2D, 0x3A, 0x36, 0xEF, 0x16, 0x72, 0xEF, 0x66,
0x0B, 0x8C, 0x7C, 0x25, 0x5C, 0xC0, 0xEC, 0x74,
0x85, 0x8F, 0xBA, 0x33, 0xF4, 0x4C, 0x06, 0x69,
0x96, 0x30, 0xA7, 0x6B, 0x03, 0x0E, 0xE3, 0x33 }
};
int dhInitKey( CRYPT_INFO *cryptInfo, const void *key, const int keyLength );
int dhEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
int dhDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes );
int dhSelfTest( void )
{
CRYPT_INFO cryptInfo1, cryptInfo2;
CRYPT_PKCINFO_DLP *dhKey;
KEYAGREE_PARAMS keyAgreeParams1, keyAgreeParams2;
static const CAPABILITY_INFO capabilityInfo = { CRYPT_ALGO_DH, 0, NULL,
64, 128, 512, 0 };
int status = CRYPT_OK;
/* Set up the key components */
if( ( dhKey = ( CRYPT_PKCINFO_DLP * ) malloc( sizeof( CRYPT_PKCINFO_DLP ) ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
cryptInitComponents( dhKey, CRYPT_KEYTYPE_PRIVATE );
cryptSetComponent( dhKey->p, dlpTestKey.p, dlpTestKey.pLen );
cryptSetComponent( dhKey->q, dlpTestKey.q, dlpTestKey.qLen );
cryptSetComponent( dhKey->g, dlpTestKey.g, dlpTestKey.gLen );
cryptSetComponent( dhKey->y, dlpTestKey.y, dlpTestKey.yLen );
cryptSetComponent( dhKey->x, dlpTestKey.x, dlpTestKey.xLen );
/* Initialise the BigNum information and components */
cryptInitComponents( dhKey, CRYPT_UNUSED );
memset( &cryptInfo1, 0, sizeof( CRYPT_INFO ) );
cryptInfo1.ctxPKC.param1 = BN_new();
cryptInfo1.ctxPKC.param2 = BN_new();
cryptInfo1.ctxPKC.param3 = BN_new();
cryptInfo1.ctxPKC.param4 = BN_new();
cryptInfo1.ctxPKC.param5 = BN_new();
cryptInfo1.capabilityInfo = &capabilityInfo;
memset( &cryptInfo2, 0, sizeof( CRYPT_INFO ) );
cryptInfo2.ctxPKC.param1 = BN_new();
cryptInfo2.ctxPKC.param2 = BN_new();
cryptInfo2.ctxPKC.param3 = BN_new();
cryptInfo2.ctxPKC.param4 = BN_new();
cryptInfo2.ctxPKC.param5 = BN_new();
cryptInfo2.capabilityInfo = ( CAPABILITY_INFO * ) &capabilityInfo;
/* Perform the test key exchange on a block of data */
memset( &keyAgreeParams1, 0, sizeof( KEYAGREE_PARAMS ) );
memset( &keyAgreeParams2, 0, sizeof( KEYAGREE_PARAMS ) );
#if 0 /* 18/10/99 Disabled until X9.42-compatible mechanism can be found */
if( dhInitKey( &cryptInfo1, dhKey, 42 ) != CRYPT_OK ||
dhInitKey( &cryptInfo2, dhKey, 43 ) != CRYPT_OK ||
cryptStatusError( dhEncrypt( &cryptInfo1, ( BYTE * ) &keyAgreeParams1,
CRYPT_USE_DEFAULT ) ) ||
cryptStatusError( dhEncrypt( &cryptInfo2, ( BYTE * ) &keyAgreeParams2,
CRYPT_USE_DEFAULT ) ) ||
cryptStatusError( dhDecrypt( &cryptInfo1, ( BYTE * ) &keyAgreeParams2,
CRYPT_USE_DEFAULT ) ) ||
cryptStatusError( dhDecrypt( &cryptInfo2, ( BYTE * ) &keyAgreeParams1,
CRYPT_USE_DEFAULT ) ) ||
memcmp( keyAgreeParams1.wrappedKey, keyAgreeParams2.wrappedKey, 64 ) )
status = CRYPT_ERROR;
#endif /* 0 */
/* Clean up */
cryptDestroyComponents( dhKey );
BN_clear_free( cryptInfo1.ctxPKC.param1 );
BN_clear_free( cryptInfo1.ctxPKC.param2 );
BN_clear_free( cryptInfo1.ctxPKC.param3 );
BN_clear_free( cryptInfo1.ctxPKC.param4 );
BN_clear_free( cryptInfo1.ctxPKC.param5 );
zeroise( &cryptInfo1, sizeof( CRYPT_INFO ) );
BN_clear_free( cryptInfo2.ctxPKC.param1 );
BN_clear_free( cryptInfo2.ctxPKC.param2 );
BN_clear_free( cryptInfo2.ctxPKC.param3 );
BN_clear_free( cryptInfo2.ctxPKC.param4 );
BN_clear_free( cryptInfo2.ctxPKC.param5 );
zeroise( &cryptInfo2, sizeof( CRYPT_INFO ) );
free( dhKey );
return( status );
}
/****************************************************************************
* *
* Init/Shutdown Routines *
* *
****************************************************************************/
/* Not needed for the DH routines */
/****************************************************************************
* *
* Diffie-Hellman Key Exchange Routines *
* *
****************************************************************************/
/* Perform phase 1 of Diffie-Hellman ("export") */
int dhEncrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
{
KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
BN_CTX *bnCTX;
int status = CRYPT_OK;
UNUSED( noBytes );
/* Usually y is generated as a side-effect of the implicit generation of
the x value, so if y is already set we just return its value */
if( !BN_is_zero( cryptInfo->ctxPKC.dlpParam_y ) )
{
keyAgreeParams->publicValueLen = \
BN_bn2bin( cryptInfo->ctxPKC.dlpParam_y,
keyAgreeParams->publicValue );
return( CRYPT_OK );
}
if( ( bnCTX = BN_CTX_new() ) == NULL )
return( CRYPT_ERROR_MEMORY );
/* Export y = g^x mod p. There is no input data since x was set when the
DH values were loaded */
BN_mod_exp( cryptInfo->ctxPKC.dlpParam_y, cryptInfo->ctxPKC.dlpParam_g,
cryptInfo->ctxPKC.dlpParam_x, cryptInfo->ctxPKC.dlpParam_p,
bnCTX );
keyAgreeParams->publicValueLen = \
BN_bn2bin( cryptInfo->ctxPKC.dlpParam_y,
keyAgreeParams->publicValue );
BN_CTX_free( bnCTX );
return( ( status == -1 ) ? CRYPT_ERROR_FAILED : status );
}
/* Perform phase 2 of Diffie-Hellman ("import") */
int dhDecrypt( CRYPT_INFO *cryptInfo, BYTE *buffer, int noBytes )
{
KEYAGREE_PARAMS *keyAgreeParams = ( KEYAGREE_PARAMS * ) buffer;
BN_CTX *bnCTX;
BIGNUM *z;
const int length = bitsToBytes( cryptInfo->ctxPKC.keySizeBits );
int i, status = CRYPT_OK;
/* Make sure we're not being fed suspiciously short data quantities */
for( i = 0; i < length; i++ )
if( keyAgreeParams->publicValue[ i ] )
break;
if( length - i < 56 )
return( CRYPT_ERROR_BADDATA );
if( ( bnCTX = BN_CTX_new() ) == NULL )
return( CRYPT_ERROR_MEMORY );
/* The other parties y value will be stored with the key agreement info
rather than having been read in when we read the DH public key */
BN_bin2bn( keyAgreeParams->publicValue, keyAgreeParams->publicValueLen,
cryptInfo->ctxPKC.dhParam_yPrime );
/* Export z = y^x mod p. We need to use separate y and z values because
the bignum code can't handle modexp with the first two parameters the
same */
z = BN_new();
BN_mod_exp( z, cryptInfo->ctxPKC.dhParam_yPrime,
cryptInfo->ctxPKC.dlpParam_x, cryptInfo->ctxPKC.dlpParam_p,
bnCTX );
keyAgreeParams->wrappedKeyLen = BN_bn2bin( z, keyAgreeParams->wrappedKey );
BN_clear_free( z );
#if 0
y = BN_new();
BN_bin2bn( buffer, length, y );
zeroise( buffer, length ); /* Clear buffer while data is in bignum */
BN_mod_exp( y, y, cryptInfo->ctxPKC.dlpParam_x,
cryptInfo->ctxPKC.dlpParam_p, bnCTX );
length = BN_bn2bin( y, buffer );
BN_clear_free( y );
#endif
BN_CTX_free( bnCTX );
return( ( status == -1 ) ? CRYPT_ERROR_FAILED : status );
}
/****************************************************************************
* *
* Diffie-Hellman Key Management Routines *
* *
****************************************************************************/
/* Load DH public key components into an encryption context */
int dhInitKey( CRYPT_INFO *cryptInfo, const void *key, const int keyLength )
{
CRYPT_PKCINFO_DLP *dhKey = ( CRYPT_PKCINFO_DLP * ) key;
int status;
/* 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 = dhKey->isPublicKey;
BN_bin2bn( dhKey->p, bitsToBytes( dhKey->pLen ),
cryptInfo->ctxPKC.dlpParam_p );
BN_bin2bn( dhKey->g, bitsToBytes( dhKey->gLen ),
cryptInfo->ctxPKC.dlpParam_g );
BN_bin2bn( dhKey->q, bitsToBytes( dhKey->qLen ),
cryptInfo->ctxPKC.dlpParam_q );
BN_bin2bn( dhKey->y, bitsToBytes( dhKey->yLen ),
cryptInfo->ctxPKC.dlpParam_y );
if( !dhKey->isPublicKey )
BN_bin2bn( dhKey->x, bitsToBytes( dhKey->xLen ),
cryptInfo->ctxPKC.dlpParam_x );
else
{
/* If there's no x value present, generate one implicitly. This
is needed because all DH keys are effectively private keys */
status = generateDLPKey( cryptInfo, CRYPT_UNUSED, CRYPT_UNUSED,
FALSE );
if( cryptStatusError( status ) )
return( status );
}
}
/* Check the parameters and calculate the key ID */
status = checkDLParams( cryptInfo, TRUE );
if( cryptStatusError( status ) )
return( status );
cryptInfo->ctxPKC.keySizeBits = BN_num_bits( cryptInfo->ctxPKC.dlpParam_p );
return( calculateKeyID( cryptInfo ) );
}
/* Generate a Diffie-Hellman key into an encryption context */
int dhGenerateKey( CRYPT_INFO *cryptInfo, const int keySizeBits )
{
int status;
status = generateDLPKey( cryptInfo, keySizeBits, CRYPT_USE_DEFAULT,
TRUE );
if( cryptStatusError( status ) )
return( status );
return( calculateKeyID( cryptInfo ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -