📄 asn1keys.c
字号:
requires the presence of data which isn't present in a non-PGP key, we
can't calculate a real OpenPGP ID but have to use the next-best thing.
This shouldn't be a major problem because it's really only going to be
used with private keys, public keys will be in PGP format and selected
by user ID (for encryption) or PGP ID/genuine OpenPGP ID (signing).
For private keys, the cryptlib keyset code knows about the way these
IDs are constructed and will return the correct key, leaving only
crypto tokens unhandled. Since PKCS #11 isn't compatible with PGP
because the ways of identifying keys differ, this problem isn't
solveable anyway */
if( !cryptInfo->ctxPKC.openPGPKeyIDSet )
{
memcpy( cryptInfo->ctxPKC.openPGPKeyID, cryptInfo->ctxPKC.keyID,
PGP_KEYID_SIZE );
cryptInfo->ctxPKC.openPGPKeyIDSet = TRUE;
}
return( status );
}
/****************************************************************************
* *
* sizeof() methods for ASN.1 Types *
* *
****************************************************************************/
/* Determine the size of the DLP key info */
static int sizeofDLPparameters( const PKC_INFO *dlpKey )
{
return( ( int ) sizeofObject( \
sizeofEncodedBignum( dlpKey->dlpParam_p ) +
sizeofEncodedBignum( dlpKey->dlpParam_q ) +
sizeofEncodedBignum( dlpKey->dlpParam_g ) ) );
}
static int sizeofDLPcomponents( const PKC_INFO *dlpKey,
const KEYFORMAT_TYPE formatType )
{
assert( formatType == KEYFORMAT_CERT );
return( sizeofEncodedBignum( dlpKey->dlpParam_y ) );
}
/* Determine the size of the RSA key info */
static int sizeofRSAcomponents( const PKC_INFO *rsaKey,
const KEYFORMAT_TYPE formatType )
{
assert( formatType == KEYFORMAT_CERT );
return( ( int ) sizeofObject( \
sizeofEncodedBignum( rsaKey->rsaParam_n ) +
sizeofEncodedBignum( rsaKey->rsaParam_e ) ) );
}
/* Determine the size of the payload of a SubjectPublicKeyInfo record (not
including the SEQUENCE encapsulation) */
static int sizeofPublicParameters( const CRYPT_ALGO cryptAlgo,
const PKC_INFO *pkcInfo )
{
if( isDLPAlgorithm( cryptAlgo ) )
return( sizeofDLPparameters( pkcInfo ) );
assert( cryptAlgo == CRYPT_ALGO_RSA );
return( 0 );
}
static int sizeofPublicComponents( const CRYPT_ALGO cryptAlgo,
const PKC_INFO *pkcInfo )
{
if( isDLPAlgorithm( cryptAlgo ) )
return( sizeofDLPcomponents( pkcInfo, KEYFORMAT_CERT ) );
assert( cryptAlgo == CRYPT_ALGO_RSA );
return( sizeofRSAcomponents( pkcInfo, KEYFORMAT_CERT ) );
}
/****************************************************************************
* *
* Read/Write X.509 Key Records *
* *
****************************************************************************/
/* Read a public key from an X.509 SubjectPublicKeyInfo record */
int readPublicKey( STREAM *stream, CRYPT_CONTEXT *iCryptContext,
const READKEY_OPTION_TYPE option, const int tag )
{
CRYPT_ALGO cryptAlgo;
MESSAGE_CREATEOBJECT_INFO createInfo;
CRYPT_INFO *cryptInfoPtr;
int extraLength, status;
assert( option >= READKEY_OPTION_NONE && option < READKEY_OPTION_LAST );
/* Clear the return value */
*iCryptContext = CRYPT_ERROR;
/* Read the SubjectPublicKeyInfo header field and create a context to
read the public key information into */
if( tag == DEFAULT_TAG )
readSequence( stream, NULL );
else
readConstructed( stream, NULL, tag );
status = readAlgoIDex( stream, &cryptAlgo, NULL, &extraLength );
if( cryptStatusOK( status ) )
{
setMessageCreateObjectInfo( &createInfo, cryptAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusError( status ) )
return( status );
getCheckInternalResource( createInfo.cryptHandle, cryptInfoPtr,
OBJECT_TYPE_CONTEXT );
/* If there's parameter data present, read it now */
if( extraLength )
{
assert( isDLPAlgorithm( cryptAlgo ) );
status = readDLPparameters( stream, &cryptInfoPtr->ctxPKC,
hasReversedParams( cryptAlgo ) );
}
/* Read the BITSTRING encapsulation of the public key fields */
status = readBitStringHole( stream, NULL, DEFAULT_TAG );
if( cryptStatusError( status ) )
{
unlockResource( cryptInfoPtr );
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/* Finally, read the PKC information */
if( isDLPAlgorithm( cryptAlgo ) )
status = readDLPcomponents( stream, &cryptInfoPtr->ctxPKC,
KEYFORMAT_CERT );
else
{
assert( cryptAlgo == CRYPT_ALGO_RSA );
status = readRSAcomponents( stream, &cryptInfoPtr->ctxPKC,
KEYFORMAT_CERT );
}
unlockResource( cryptInfoPtr );
if( cryptStatusOK( status ) && option != READKEY_OPTION_DEFERREDLOAD )
{
PKCINFO_LOADINTERNAL dummy;
RESOURCE_DATA msgData;
/* If everything went OK, perform an internal load which uses the
values already present in the context */
setResourceData( &msgData, &dummy, sizeof( PKCINFO_LOADINTERNAL ) );
status = krnlSendMessage( createInfo.cryptHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_KEY_COMPONENTS );
if( cryptArgError( status ) )
status = CRYPT_ERROR_BADDATA; /* Map to a more appropriate code */
}
if( cryptStatusError( status ) )
krnlSendNotifier( createInfo.cryptHandle,
RESOURCE_IMESSAGE_DECREFCOUNT );
else
*iCryptContext = createInfo.cryptHandle;
return( status );
}
/* Write a public key to an X.509 SubjectPublicKeyInfo record */
static int writeSubjectPublicKey( STREAM *stream, const CRYPT_ALGO cryptAlgo,
const PKC_INFO *pkcInfo )
{
/* Write the PKC information */
if( isDLPAlgorithm( cryptAlgo ) )
writeDLPcomponents( stream, pkcInfo, KEYFORMAT_CERT );
else
{
assert( cryptAlgo == CRYPT_ALGO_RSA );
writeRSAcomponents( stream, pkcInfo, KEYFORMAT_CERT );
}
return( sGetStatus( stream ) );
}
int writePublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr )
{
const CRYPT_ALGO cryptAlgo = cryptInfoPtr->capabilityInfo->cryptAlgo;
const PKC_INFO *pkcInfo = &cryptInfoPtr->ctxPKC;
const int parameterSize = sizeofPublicParameters( cryptAlgo, pkcInfo );
const int componentSize = sizeofPublicComponents( cryptAlgo, pkcInfo );
int totalSize;
/* Determine the size of the AlgorithmIdentifier record and the
BITSTRING-encapsulated public-key data (the +1 is for the bitstring) */
totalSize = sizeofAlgoIDex( cryptAlgo, CRYPT_ALGO_NONE, parameterSize ) +
( int ) sizeofObject( componentSize + 1 );
/* Write the SubjectPublicKeyInfo header field */
writeSequence( stream, totalSize );
writeAlgoIDex( stream, cryptAlgo, CRYPT_ALGO_NONE, parameterSize );
/* Write the parameter data if necessary */
if( parameterSize )
{
assert( isDLPAlgorithm( cryptAlgo ) );
writeDLPparameters( stream, pkcInfo, hasReversedParams( cryptAlgo ) );
}
/* Write the BITSTRING wrapper and the PKC information */
writeTag( stream, BER_BITSTRING );
writeLength( stream, componentSize + 1 ); /* +1 for bitstring */
sputc( stream, 0 );
return( writeSubjectPublicKey( stream, cryptAlgo, pkcInfo ) );
}
/****************************************************************************
* *
* Read/Write Private Key Records *
* *
****************************************************************************/
/* Read private key components. This function assumes that the public
portion of the context has already been set up */
int readPrivateKey( STREAM *stream, CRYPT_INFO *cryptInfoPtr )
{
PKCINFO_LOADINTERNAL dummy;
RESOURCE_DATA msgData;
int status;
/* Read the private key information */
if( isDLPAlgorithm( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
status = readDLPcomponents( stream, &cryptInfoPtr->ctxPKC,
KEYFORMAT_PRIVATE );
else
{
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
status = readRSAcomponents( stream, &cryptInfoPtr->ctxPKC,
KEYFORMAT_PRIVATE );
}
if( cryptStatusError( status ) )
return( status );
/* If everything went OK, perform an internal load which uses the values
already present in the context */
setResourceData( &msgData, &dummy, sizeof( PKCINFO_LOADINTERNAL ) );
status = krnlSendMessage( cryptInfoPtr->objectHandle,
RESOURCE_IMESSAGE_SETATTRIBUTE_S, &msgData,
CRYPT_CTXINFO_KEY_COMPONENTS );
if( cryptArgError( status ) )
status = CRYPT_ERROR_BADDATA; /* Map to a more appropriate code */
return( status );
}
/* Write private key components. This is just a wrapper for the various
writeXXXcomponents() functions */
int writePrivateKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr )
{
/* Write the private key information */
if( isDLPAlgorithm( cryptInfoPtr->capabilityInfo->cryptAlgo ) )
writeDLPcomponents( stream, &cryptInfoPtr->ctxPKC, KEYFORMAT_PRIVATE );
else
{
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
writeRSAcomponents( stream, &cryptInfoPtr->ctxPKC, KEYFORMAT_PRIVATE );
}
return( sGetStatus( stream ) );
}
/****************************************************************************
* *
* Write Flat Public Key Data *
* *
****************************************************************************/
/* Generate KEA domain parameters from flat-format values */
static int generateDomainParameters( BYTE *domainParameters,
const void *p, const int pLength,
const void *q, const int qLength,
const void *g, const int gLength )
{
STREAM stream;
BYTE hash[ CRYPT_MAX_HASHSIZE ], dataBuffer[ CRYPT_MAX_PKCSIZE * 3 ];
HASHFUNCTION hashFunction;
const int pSize = sizeofInteger( p, pLength );
const int qSize = sizeofInteger( q, qLength );
const int gSize = sizeofInteger( g, gLength );
int hashSize, dataSize, i;
/* Write the parameters to a stream. The stream length is in case
KEA is at some point be extended up to the max.allowed PKC size */
sMemOpen( &stream, dataBuffer, CRYPT_MAX_PKCSIZE * 3 );
writeSequence( &stream, pSize + qSize + gSize );
writeInteger( &stream, p, pLength, DEFAULT_TAG );
writeInteger( &stream, q, qLength, DEFAULT_TAG );
writeInteger( &stream, g, gLength, DEFAULT_TAG );
assert( !cryptStatusError( sGetStatus( &stream ) ) );
dataSize = ( int ) stell( &stream );
sMemDisconnect( &stream );
/* Hash the DSA/KEA parameters and reduce them down to get the domain
identifier */
getHashParameters( CRYPT_ALGO_SHA, &hashFunction, &hashSize );
hashFunction( NULL, hash, dataBuffer, dataSize, HASH_ALL );
zeroise( dataBuffer, CRYPT_MAX_PKCSIZE * 3 );
hashSize /= 2; /* Output = hash result folded in half */
for( i = 0; i < hashSize; i++ )
domainParameters[ i ] = hash[ i ] ^ hash[ hashSize + i ];
return( hashSize );
}
/* If the keys are stored in a crypto device rather than being held in the
context, all we have available are the public components in flat format.
The following code writes flat-format public components in the X.509
format */
int sizeofFlatPublicKey( const CRYPT_ALGO cryptAlgo,
const void *component1, const int component1Length,
const void *component2, const int component2Length,
const void *component3, const int component3Length,
const void *component4, const int component4Length )
{
const int comp1Size = sizeofInteger( component1, component1Length );
const int comp2Size = sizeofInteger( component2, component2Length );
const int comp3Size = ( component3 == NULL ) ? 0 : \
sizeofInteger( component3, component3Length );
const int comp4Size = ( component4 == NULL ) ? 0 : \
sizeofInteger( component4, component4Length );
const int parameterSize = ( cryptAlgo == CRYPT_ALGO_DSA ) ? \
( int ) sizeofObject( comp1Size + comp2Size + comp3Size ) : \
( cryptAlgo == CRYPT_ALGO_KEA ) ? \
( int) sizeofObject( 10 ) : 0;
const int componentSize = ( cryptAlgo == CRYPT_ALGO_RSA ) ? \
( int ) sizeofObject( comp1Size + comp2Size ) : \
( cryptAlgo == CRYPT_ALGO_KEA ) ? \
component4Length : comp4Size;
int totalSize;
assert( cryptAlgo == CRYPT_ALGO_DSA || cryptAlgo == CRYPT_ALGO_KEA || \
cryptAlgo == CRYPT_ALGO_RSA );
/* Determine the size of the AlgorithmIdentifier record and the
BITSTRING-encapsulated public-key data (the +1 is for the bitstring) */
totalSize = sizeofAlgoIDex( cryptAlgo, CRYPT_ALGO_NONE, parameterSize ) +
( int ) sizeofObject( componentSize + 1 );
return( ( int ) sizeofObject( totalSize ) );
}
int writeFlatPublicKey( void *buffer, const CRYPT_ALGO cryptAlgo,
const void *component1, const int component1Length,
const void *component2, const int component2Length,
const void *component3, const int component3Length,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -