📄 ctx_dh.c
字号:
/****************************************************************************
* *
* cryptlib Diffie-Hellman Key Exchange Routines *
* Copyright Peter Gutmann 1995-2005 *
* *
****************************************************************************/
#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 */
/* The DH key exchange process is somewhat complex because there are two
phases involved for both sides, an "export" and an "import" phase, and
they have to be performed in the correct order. The sequence of
operations is:
A.load: set p, g from fixed or external values
x(A) = rand, x s.t. 0 < x < q-1
A.export y(A) = g^x(A) mod p error if y != 0 at start
output = y(A)
B.load read p, g / set p, g from external values
x(B) = rand, x s.t. 0 < x < q-1
B.import y(A) = input
z = y(A)^x(B) mod p
B.export y(B) = g^x(B) mod p error if y != 0 at start
output = y(B)
A.import y(B) = input
z = y(B)^x(A) mod p
Note that we have to set x when we load p and g because otherwise we'd
have to set x(A) on export and x(B) on import, which is tricky since the
DH code doesn't know whether it's working with A or B */
/****************************************************************************
* *
* Algorithm Self-test *
* *
****************************************************************************/
/* 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 {
const int pLen; const BYTE p[ 64 ];
const int qLen; const BYTE q[ 20 ];
const int gLen; const BYTE g[ 64 ];
const int xLen; const BYTE x[ 20 ];
const int yLen; const BYTE y[ 64 ];
} DLP_PRIVKEY;
static const FAR_BSS DLP_PRIVKEY dlpTestKey = {
/* p */
64,
{ 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 */
20,
{ 0xC7, 0x73, 0x21, 0x8C, 0x73, 0x7E, 0xC8, 0xEE,
0x99, 0x3B, 0x4F, 0x2D, 0xED, 0x30, 0xF4, 0x8E,
0xDA, 0xCE, 0x91, 0x5F },
/* g */
64,
{ 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 },
/* x */
20,
{ 0x20, 0x70, 0xB3, 0x22, 0x3D, 0xBA, 0x37, 0x2F,
0xDE, 0x1C, 0x0F, 0xFC, 0x7B, 0x2E, 0x3B, 0x49,
0x8B, 0x26, 0x06, 0x14 },
/* y */
64,
{ 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 }
};
static BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr,
const BOOLEAN isGeneratedKey )
{
const CAPABILITY_INFO *capabilityInfoPtr = getDHCapability();
CONTEXT_INFO checkContextInfoPtr;
PKC_INFO pkcInfoStorage, *pkcInfo;
KEYAGREE_PARAMS keyAgreeParams1, keyAgreeParams2;
int status;
/* The DH pairwise check is a bit more complex than the one for the
other algorithms because there's no matched public/private key pair,
so we have to load a second DH key to use for key agreement with
the first one */
memset( &checkContextInfoPtr, 0, sizeof( CONTEXT_INFO ) );
memset( &pkcInfoStorage, 0, sizeof( PKC_INFO ) );
checkContextInfoPtr.ctxPKC = pkcInfo = &pkcInfoStorage;
BN_init( &pkcInfo->dlpParam_p );
BN_init( &pkcInfo->dlpParam_g );
BN_init( &pkcInfo->dlpParam_q );
BN_init( &pkcInfo->dlpParam_y );
BN_init( &pkcInfo->dlpParam_x );
BN_init( &pkcInfo->dhParam_yPrime );
BN_init( &pkcInfo->tmp1 );
BN_init( &pkcInfo->tmp2 );
BN_init( &pkcInfo->tmp3 );
pkcInfo->bnCTX = BN_CTX_new();
BN_MONT_CTX_init( &pkcInfo->rsaParam_mont_p );
checkContextInfoPtr.capabilityInfo = capabilityInfoPtr;
initKeyWrite( &checkContextInfoPtr ); /* For calcKeyID() */
if( isGeneratedKey )
{
PKC_INFO *sourcePkcInfo = contextInfoPtr->ctxPKC;
int bnStatus = BN_STATUS;
/* If it's a generated key with random p and g parameters rather
than the fixed test values, we have to make the parameters for
the check context match the ones for the generated key */
CKPTR( BN_copy( &pkcInfo->dlpParam_p, &sourcePkcInfo->dlpParam_p ) );
CKPTR( BN_copy( &pkcInfo->dlpParam_g, &sourcePkcInfo->dlpParam_g ) );
CKPTR( BN_copy( &pkcInfo->dlpParam_q, &sourcePkcInfo->dlpParam_q ) );
CKPTR( BN_copy( &pkcInfo->dlpParam_y, &sourcePkcInfo->dlpParam_y ) );
if( bnStatusError( bnStatus ) )
return( getBnStatus( bnStatus ) );
}
else
{
BN_bin2bn( dlpTestKey.p, dlpTestKey.pLen, &pkcInfo->dlpParam_p );
BN_bin2bn( dlpTestKey.g, dlpTestKey.gLen, &pkcInfo->dlpParam_g );
BN_bin2bn( dlpTestKey.q, dlpTestKey.qLen, &pkcInfo->dlpParam_q );
BN_bin2bn( dlpTestKey.y, dlpTestKey.yLen, &pkcInfo->dlpParam_y );
BN_bin2bn( dlpTestKey.x, dlpTestKey.xLen, &pkcInfo->dlpParam_x );
}
/* Perform the pairwise test using the check key */
status = capabilityInfoPtr->initKeyFunction( &checkContextInfoPtr, NULL, 0 );
if( cryptStatusOK( status ) )
{
memset( &keyAgreeParams1, 0, sizeof( KEYAGREE_PARAMS ) );
status = capabilityInfoPtr->encryptFunction( contextInfoPtr,
( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );
}
if( cryptStatusOK( status ) )
{
memset( &keyAgreeParams2, 0, sizeof( KEYAGREE_PARAMS ) );
status = capabilityInfoPtr->encryptFunction( &checkContextInfoPtr,
( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );
}
if( cryptStatusOK( status ) )
status = capabilityInfoPtr->decryptFunction( contextInfoPtr,
( BYTE * ) &keyAgreeParams2, sizeof( KEYAGREE_PARAMS ) );
if( cryptStatusOK( status ) )
status = capabilityInfoPtr->decryptFunction( &checkContextInfoPtr,
( BYTE * ) &keyAgreeParams1, sizeof( KEYAGREE_PARAMS ) );
if( cryptStatusError( status ) || \
memcmp( keyAgreeParams1.wrappedKey, keyAgreeParams2.wrappedKey, 64 ) )
status = CRYPT_ERROR;
/* Clean up */
BN_clear_free( &pkcInfo->dlpParam_p );
BN_clear_free( &pkcInfo->dlpParam_g );
BN_clear_free( &pkcInfo->dlpParam_q );
BN_clear_free( &pkcInfo->dlpParam_y );
BN_clear_free( &pkcInfo->dlpParam_x );
BN_clear_free( &pkcInfo->dhParam_yPrime );
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->dlpParam_mont_p );
zeroise( &pkcInfoStorage, sizeof( PKC_INFO ) );
zeroise( &checkContextInfoPtr, sizeof( CONTEXT_INFO ) );
return( cryptStatusOK( status ) ? TRUE : FALSE );
}
static int selfTest( void )
{
const CAPABILITY_INFO *capabilityInfoPtr = getDHCapability();
CONTEXT_INFO contextInfoPtr;
PKC_INFO pkcInfoStorage, *pkcInfo;
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->dlpParam_p );
BN_init( &pkcInfo->dlpParam_g );
BN_init( &pkcInfo->dlpParam_q );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -