📄 ctx_dsa.c
字号:
/****************************************************************************
* *
* cryptlib DSA Encryption Routines *
* Copyright Peter Gutmann 1995-2005 *
* *
****************************************************************************/
#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 */
/****************************************************************************
* *
* Predefined DSA p, q, and g Parameters *
* *
****************************************************************************/
/* We never use shared DSA parameters because they allow forgery of
signatures on certificates. This works as follows: Suppose that the
certificate contains a copy of the certificate signer's DSA parameters,
and the verifier of the certificate has a copy of the signer's public key
but not the signer's DSA parameters (which are shared with other keys).
If the verifier uses the DSA parameters from the certificate along with
the signer's public key to verify the signature on the certificate, then
an attacker can create bogus certificates by choosing a random u and
finding its inverse v modulo q (uv is congruent to 1 modulo q). Then
take the certificate signer's public key g^x and compute g' = (g^x)^u.
Then g'^v = g^x. Using the DSA parameters p, q, g', the signer's public
key corresponds to the private key v, which the attacker knows. The
attacker can then create a bogus certificate, put parameters (p, q, g')
in it, and sign it with the DSA private key v to create an apparently
valid certificate. This works with the DSA OID that makes p, q, and g
unauthenticated public parameters and y the public key, but not the one
that makes p, q, g, and y the public key */
/****************************************************************************
* *
* Algorithm Self-test *
* *
****************************************************************************/
/* Test the DSA implementation using the sample key and hash from FIPS 186
(we actually use a generated 1024-bit key because the FIPS 186 key at
512 bits is too short to load). 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[ 128 ];
const int qLen; const BYTE q[ 20 ];
const int gLen; const BYTE g[ 128 ];
const int xLen; const BYTE x[ 20 ];
const int yLen; const BYTE y[ 128 ];
} DLP_KEY;
#if 0 /* FIPS 186 test key is too small to be loaded */
static const DLP_PRIVKEY FAR_BSS 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 }
};
#endif /* 0 */
static const DLP_KEY FAR_BSS dlpTestKey = {
/* p */
128,
{ 0x04, 0x4C, 0xDD, 0x5D, 0xB6, 0xED, 0x23, 0xAE,
0xB2, 0xA7, 0x59, 0xE6, 0xF8, 0x3D, 0xA6, 0x27,
0x85, 0xF2, 0xFE, 0xE2, 0xE8, 0xF3, 0xDA, 0xA3,
0x7B, 0xD6, 0x48, 0xD4, 0x44, 0xCA, 0x6E, 0x10,
0x97, 0x6C, 0x1D, 0x6C, 0x39, 0xA7, 0x0C, 0x88,
0x8E, 0x1F, 0xDD, 0xF7, 0x59, 0x69, 0xDA, 0x36,
0xDD, 0xB8, 0x3E, 0x1A, 0xD2, 0x91, 0x3E, 0x30,
0xB1, 0xB5, 0xC2, 0xBC, 0xA9, 0xA3, 0xA5, 0xDE,
0xC7, 0xCF, 0x51, 0x2C, 0x1B, 0x89, 0xD0, 0x71,
0xE3, 0x71, 0xBB, 0x50, 0x86, 0x26, 0x32, 0x9F,
0xF5, 0x4A, 0x9C, 0xB1, 0x78, 0x7B, 0x47, 0x1F,
0x19, 0xC7, 0x26, 0x22, 0x15, 0x62, 0x71, 0xAB,
0xD7, 0x25, 0xA5, 0xE4, 0x68, 0x71, 0x93, 0x5D,
0x1F, 0x29, 0x01, 0x05, 0x9C, 0x57, 0x3A, 0x09,
0xB0, 0xB8, 0xE4, 0xD2, 0x37, 0x90, 0x36, 0x2F,
0xBF, 0x1E, 0x74, 0xB4, 0x6B, 0xE4, 0x66, 0x07 },
/* q */
20,
{ 0xFD, 0xD9, 0xC8, 0x5F, 0x73, 0x62, 0xC9, 0x79,
0xEF, 0xD5, 0x09, 0x07, 0x02, 0xE7, 0xF2, 0x90,
0x97, 0x13, 0x26, 0x1D },
/* g */
128,
{ 0x02, 0x4E, 0xDD, 0x0D, 0x7F, 0x4D, 0xB1, 0x42,
0x01, 0x50, 0xE7, 0x9A, 0x65, 0x73, 0x8B, 0x31,
0x24, 0x6B, 0xC6, 0x74, 0xA7, 0x68, 0x26, 0x11,
0x06, 0x3C, 0x96, 0xA9, 0xA6, 0x23, 0x12, 0x79,
0xC4, 0xEE, 0x21, 0x88, 0xDD, 0xE3, 0xF0, 0x37,
0xCE, 0x3E, 0x54, 0x53, 0x57, 0x03, 0x30, 0xE4,
0xD3, 0xAB, 0x39, 0x4E, 0x39, 0xDC, 0xA2, 0x88,
0x82, 0xF6, 0xE8, 0xBA, 0xAC, 0xF5, 0x7D, 0x2F,
0x23, 0x9A, 0x09, 0x94, 0xB2, 0x89, 0xA2, 0xC9,
0x7C, 0xBE, 0x4D, 0x48, 0x0E, 0x59, 0x51, 0xB8,
0x7D, 0x99, 0x88, 0x79, 0xA8, 0x13, 0x0E, 0x12,
0x56, 0x9D, 0x4B, 0x2E, 0xE0, 0xE1, 0x37, 0x78,
0x6F, 0xCC, 0x4D, 0x97, 0xA9, 0x02, 0x0E, 0xD2,
0x43, 0x83, 0xEC, 0x4F, 0xC2, 0x70, 0xEF, 0x16,
0xDE, 0xBF, 0xBA, 0xD1, 0x6C, 0x8A, 0x36, 0xEE,
0x42, 0x41, 0xE9, 0xE7, 0x66, 0xAE, 0x46, 0x3B },
/* x */
20,
{ 0xD9, 0x41, 0x29, 0xF7, 0x40, 0x32, 0x09, 0x71,
0xB8, 0xE2, 0xB8, 0xCB, 0x74, 0x46, 0x0B, 0xD4,
0xF2, 0xAB, 0x54, 0xA1 },
/* y */
128,
{ 0x01, 0x7E, 0x16, 0x5B, 0x65, 0x51, 0x0A, 0xDA,
0x82, 0x1A, 0xD9, 0xF4, 0x1E, 0x66, 0x6D, 0x7D,
0x23, 0xA6, 0x28, 0x2F, 0xE6, 0xC2, 0x03, 0x8E,
0x8C, 0xAB, 0xC2, 0x08, 0x87, 0xC9, 0xE8, 0x51,
0x0A, 0x37, 0x1E, 0xD4, 0x41, 0x7F, 0xA2, 0xC5,
0x48, 0x26, 0xB7, 0xF6, 0xC2, 0x6F, 0xB2, 0xF8,
0xF9, 0x43, 0x43, 0xF9, 0xDA, 0xAB, 0xA2, 0x59,
0x27, 0xBA, 0xC9, 0x1C, 0x8C, 0xAB, 0xC4, 0x90,
0x27, 0xE1, 0x10, 0x39, 0x6F, 0xD2, 0xCD, 0x7C,
0xD1, 0x0B, 0xFA, 0x28, 0xD2, 0x7A, 0x7B, 0x52,
0x8A, 0xA0, 0x5A, 0x0F, 0x10, 0xF7, 0xBA, 0xFD,
0x33, 0x0C, 0x3C, 0xCE, 0xE5, 0xF2, 0xF6, 0x92,
0xED, 0x04, 0xBF, 0xD3, 0xF8, 0x3D, 0x39, 0xCC,
0xAA, 0xCC, 0x0B, 0xB2, 0x6B, 0xD8, 0xB2, 0x8A,
0x5C, 0xCE, 0xDA, 0xF9, 0xE1, 0xA7, 0x23, 0x50,
0xDC, 0xCE, 0xA4, 0xD5, 0xA5, 0x4F, 0x08, 0x0F }
};
static const BYTE FAR_BSS shaM[] = {
0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A,
0xBA, 0x3E, 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C,
0x9C, 0xD0, 0xD8, 0x9D
};
/* If we're doing a self-test using the FIPS 186 values we use the following
fixed k data rather than a randomly-generated value */
static const BYTE FAR_BSS kVal[] = {
0x35, 0x8D, 0xAD, 0x57, 0x14, 0x62, 0x71, 0x0F,
0x50, 0xE2, 0x54, 0xCF, 0x1A, 0x37, 0x6B, 0x2B,
0xDE, 0xAA, 0xDF, 0xBF
};
static BOOLEAN pairwiseConsistencyTest( CONTEXT_INFO *contextInfoPtr )
{
const CAPABILITY_INFO *capabilityInfoPtr = contextInfoPtr->capabilityInfo;
DLP_PARAMS dlpParams;
BYTE buffer[ 128 + 8 ];
int sigSize, status;
/* Generate a signature with the private key */
setDLPParams( &dlpParams, shaM, 20, buffer, 128 );
dlpParams.inLen2 = -999;
status = capabilityInfoPtr->signFunction( contextInfoPtr,
( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );
if( cryptStatusError( status ) )
return( FALSE );
/* Verify the signature with the public key */
sigSize = dlpParams.outLen;
setDLPParams( &dlpParams, shaM, 20, NULL, 0 );
dlpParams.inParam2 = buffer;
dlpParams.inLen2 = sigSize;
status = capabilityInfoPtr->sigCheckFunction( contextInfoPtr,
( BYTE * ) &dlpParams, sizeof( DLP_PARAMS ) );
return( cryptStatusOK( status ) ? TRUE : FALSE );
}
static int selfTest( void )
{
CONTEXT_INFO contextInfo;
PKC_INFO contextData, *pkcInfo = &contextData;
int status;
/* Initialise the key components */
status = staticInitContext( &contextInfo, CONTEXT_PKC,
getDSACapability(), &contextData,
sizeof( PKC_INFO ), NULL );
if( cryptStatusError( status ) )
return( CRYPT_ERROR_FAILED );
status = extractBignum( &pkcInfo->dlpParam_p, dlpTestKey.p,
dlpTestKey.pLen, DLPPARAM_MIN_P,
DLPPARAM_MAX_P, NULL, TRUE );
if( cryptStatusOK( status ) )
status = extractBignum( &pkcInfo->dlpParam_q, dlpTestKey.q,
dlpTestKey.qLen, DLPPARAM_MIN_Q,
DLPPARAM_MAX_Q, &pkcInfo->dlpParam_p,
FALSE );
if( cryptStatusOK( status ) )
status = extractBignum( &pkcInfo->dlpParam_g, dlpTestKey.g,
dlpTestKey.gLen, DLPPARAM_MIN_G,
DLPPARAM_MAX_G, &pkcInfo->dlpParam_p,
FALSE );
if( cryptStatusOK( status ) )
status = extractBignum( &pkcInfo->dlpParam_y, dlpTestKey.y,
dlpTestKey.yLen, DLPPARAM_MIN_Y,
DLPPARAM_MAX_Y, &pkcInfo->dlpParam_p,
TRUE );
if( cryptStatusOK( status ) )
status = extractBignum( &pkcInfo->dlpParam_x, dlpTestKey.x,
dlpTestKey.xLen, DLPPARAM_MIN_X,
DLPPARAM_MAX_X, &pkcInfo->dlpParam_p,
FALSE );
if( cryptStatusError( status ) )
retIntError();
/* Perform the test sign/sig.check of the FIPS 186 test values */
status = contextInfo.capabilityInfo->initKeyFunction( &contextInfo, NULL, 0 );
if( cryptStatusOK( status ) && \
!pairwiseConsistencyTest( &contextInfo ) )
status = CRYPT_ERROR_FAILED;
/* Clean up */
staticDestroyContext( &contextInfo );
return( status );
}
/****************************************************************************
* *
* Create/Check a Signature *
* *
****************************************************************************/
/* Since DSA signature generation produces two values and the cryptEncrypt()
model only provides for passing a byte string in and out (or, more
specifically, the internal bignum data can't be exported to the outside
world), we need to encode the resulting data into a flat format. This is
done by encoding the output as an X9.31 Dss-Sig record:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -