📄 asn1keys.c
字号:
const void *component4, const int component4Length )
{
STREAM stream;
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, status;
sMemOpen( &stream, buffer, ( buffer == NULL ) ? 0 : STREAMSIZE_UNKNOWN );
/* 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( cryptAlgo == CRYPT_ALGO_DSA )
{
writeSequence( &stream, comp1Size + comp2Size + comp3Size );
writeInteger( &stream, component1, component1Length, DEFAULT_TAG );
writeInteger( &stream, component2, component2Length, DEFAULT_TAG );
writeInteger( &stream, component3, component3Length, DEFAULT_TAG );
}
if( cryptAlgo == CRYPT_ALGO_KEA )
{
BYTE domainParameters[ 10 ];
const int domainParameterLength = \
generateDomainParameters( domainParameters,
component1, component1Length,
component2, component2Length,
component3, component3Length );
writeOctetString( &stream, domainParameters, domainParameterLength,
DEFAULT_TAG );
}
/* Write the BITSTRING wrapper and the PKC information */
writeTag( &stream, BER_BITSTRING );
writeLength( &stream, componentSize + 1 ); /* +1 for bitstring */
sputc( &stream, 0 );
if( cryptAlgo == CRYPT_ALGO_RSA )
{
writeSequence( &stream, comp1Size + comp2Size );
writeInteger( &stream, component1, component1Length, DEFAULT_TAG );
writeInteger( &stream, component2, component2Length, DEFAULT_TAG );
}
else
if( cryptAlgo == CRYPT_ALGO_DSA )
writeInteger( &stream, component4, component4Length, DEFAULT_TAG );
else
swrite( &stream, component4, component4Length );
/* Clean up */
status = sGetStatus( &stream );
sMemDisconnect( &stream );
return( status );
}
/****************************************************************************
* *
* Read/Write DL Value Record *
* *
****************************************************************************/
/* Prototypes for functions in pgp_misc.c */
int pgpReadMPI( STREAM *stream, BYTE *data );
int pgpWriteMPI( STREAM *stream, const BYTE *data, const int length );
/* Unlike the simpler RSA PKC, DL-based PKC's produce a pair of values which
need to be encoded as ASN.1 records. The following two functions perform
this en/decoding */
int encodeDLValues( BYTE *buffer, const int bufSize, BIGNUM *value1,
BIGNUM *value2, const CRYPT_FORMAT_TYPE formatType )
{
STREAM stream;
BYTE dataBuffer[ CRYPT_MAX_PKCSIZE ];
int length, status;
sMemOpen( &stream, buffer, bufSize );
/* Write the DL components to the buffer */
if( formatType == CRYPT_FORMAT_CRYPTLIB )
{
writeTag( &stream, BER_SEQUENCE );
writeLength( &stream, sizeofEncodedBignum( value1 ) +
sizeofEncodedBignum( value2 ) );
length = BN_bn2bin( value1, dataBuffer );
writeInteger( &stream, dataBuffer, length, DEFAULT_TAG );
length = BN_bn2bin( value2, dataBuffer );
writeInteger( &stream, dataBuffer, length, DEFAULT_TAG );
}
else
{
assert( formatType == CRYPT_FORMAT_PGP );
length = BN_bn2bin( value1, dataBuffer );
pgpWriteMPI( &stream, dataBuffer, length );
length = BN_bn2bin( value2, dataBuffer );
pgpWriteMPI( &stream, dataBuffer, length );
}
/* Clean up */
status = ( int ) stell( &stream );
sMemDisconnect( &stream );
zeroise( dataBuffer, CRYPT_MAX_PKCSIZE );
return( status );
}
int decodeDLValues( const BYTE *buffer, const int bufSize, BIGNUM **value1,
BIGNUM **value2, const CRYPT_FORMAT_TYPE formatType )
{
STREAM stream;
BYTE dataBuffer[ CRYPT_MAX_PKCSIZE ];
int length, status;
sMemConnect( &stream, buffer, bufSize );
/* Read the DL components from the buffer */
if( formatType == CRYPT_FORMAT_CRYPTLIB )
{
readSequence( &stream, NULL );
status = readInteger( &stream, dataBuffer, &length,
CRYPT_MAX_PKCSIZE );
if( cryptStatusError( status ) )
return( status );
*value1 = BN_new();
BN_bin2bn( dataBuffer, length, *value1 );
status = readInteger( &stream, dataBuffer, &length,
CRYPT_MAX_PKCSIZE );
if( cryptStatusError( status ) )
{
BN_clear_free( *value1 );
return( CRYPT_ERROR_BADDATA );
}
*value2 = BN_new();
BN_bin2bn( dataBuffer, length, *value2 );
}
else
{
assert( formatType == CRYPT_FORMAT_PGP );
status = length = pgpReadMPI( &stream, dataBuffer );
if( cryptStatusError( status ) )
return( status );
*value1 = BN_new();
BN_bin2bn( dataBuffer, bitsToBytes( length ), *value1 );
status = length = pgpReadMPI( &stream, dataBuffer );
if( cryptStatusError( status ) )
{
BN_clear_free( *value1 );
return( CRYPT_ERROR_BADDATA );
}
*value2 = BN_new();
BN_bin2bn( dataBuffer, bitsToBytes( length ), *value2 );
}
/* Clean up */
sMemDisconnect( &stream );
zeroise( dataBuffer, CRYPT_MAX_PKCSIZE );
return( CRYPT_OK );
}
/****************************************************************************
* *
* Read/Write Ad Hoc-format Key Records *
* *
****************************************************************************/
/* Read/write an SSHv1 public key */
static int readSsh1Bignum( STREAM *stream, BIGNUM *value,
const int minBits, const int maxBits )
{
int length;
/* Read the length and make sure it's within acceptable limits */
length = ( sgetc( stream ) << 8 ) | sgetc( stream );
if( length < minBits || length > maxBits )
return( CRYPT_ERROR_BADDATA );
/* Read the bignum */
length = bitsToBytes( length );
BN_bin2bn( sMemBufPtr( stream ), length, value );
return( sSkip( stream, length ) );
}
static int writeSsh1Bignum( STREAM *stream, BIGNUM *bignum )
{
BYTE buffer[ CRYPT_MAX_PKCSIZE ];
int bnLength;
bnLength = BN_num_bits( bignum );
sputc( stream, bnLength >> 8 );
sputc( stream, bnLength & 0xFF );
bnLength = BN_bn2bin( bignum, buffer );
return( swrite( stream, buffer, bnLength ) );
}
int readSsh1PublicKey( STREAM *stream, CRYPT_INFO *cryptInfoPtr )
{
PKC_INFO *rsaKey = &cryptInfoPtr->ctxPKC;
PKCINFO_LOADINTERNAL dummy;
RESOURCE_DATA msgData;
int status;
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
/* Read the SSH public key information */
rsaKey->isPublicKey = TRUE;
status = readSsh1Bignum( stream, rsaKey->rsaParam_e, 2, 256 );
if( cryptStatusOK( status ) )
status = readSsh1Bignum( stream, rsaKey->rsaParam_n,
504, bytesToBits( CRYPT_MAX_PKCSIZE ) );
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 );
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
int writeSsh1PublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr )
{
const PKC_INFO *rsaKey = &cryptInfoPtr->ctxPKC;
long length;
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA );
/* Write the nominal keysize, which is the length of the modulus in
bits */
length = BN_num_bits( rsaKey->rsaParam_n );
sputc( stream, 0 );
sputc( stream, 0 );
sputc( stream, length >> 8 );
sputc( stream, length & 0xFF );
/* Write the exponent and modulus */
writeSsh1Bignum( stream, rsaKey->rsaParam_e );
return( writeSsh1Bignum( stream, rsaKey->rsaParam_n ) );
}
/* Read/write an SSHv2 public key */
static int readSsh2Bignum( STREAM *stream, BIGNUM *value,
const int minBytes, const int maxBytes )
{
int length;
/* Read the length and make sure it's within acceptable limits */
if( sgetc( stream ) || sgetc( stream ) )
return( CRYPT_ERROR_BADDATA );
length = ( sgetc( stream ) << 8 ) | sgetc( stream );
if( length < minBytes || length > maxBytes )
return( CRYPT_ERROR_BADDATA );
/* Read the bignum */
BN_bin2bn( sMemBufPtr( stream ), length, value );
return( sSkip( stream, length ) );
}
static int writeSsh2Bignum( STREAM *stream, BIGNUM *bignum )
{
BYTE buffer[ CRYPT_MAX_PKCSIZE ];
int bnLength;
bnLength = BN_num_bytes( bignum );
sputc( stream, 0 );
sputc( stream, 0 );
sputc( stream, bnLength >> 8 );
sputc( stream, bnLength & 0xFF );
bnLength = BN_bn2bin( bignum, buffer );
return( swrite( stream, buffer, bnLength ) );
}
int readSsh2PublicKey( STREAM *stream, CRYPT_INFO *cryptInfoPtr )
{
PKCINFO_LOADINTERNAL dummy;
RESOURCE_DATA msgData;
int status;
assert( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA || \
cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_DSA );
/* Read the SSH public key information */
if( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA )
{
PKC_INFO *rsaKey = &cryptInfoPtr->ctxPKC;
rsaKey->isPublicKey = TRUE;
status = readSsh2Bignum( stream, rsaKey->rsaParam_e, 1, 16 );
if( cryptStatusOK( status ) )
status = readSsh2Bignum( stream, rsaKey->rsaParam_n,
bitsToBytes( 504 ), CRYPT_MAX_PKCSIZE );
}
else
{
PKC_INFO *dsaKey = &cryptInfoPtr->ctxPKC;
dsaKey->isPublicKey = TRUE;
status = readSsh2Bignum( stream, dsaKey->dlpParam_p,
bitsToBytes( 504 ), CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readSsh2Bignum( stream, dsaKey->dlpParam_q,
bitsToBytes( 128 ), CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readSsh2Bignum( stream, dsaKey->dlpParam_g,
bitsToBytes( 504 ), CRYPT_MAX_PKCSIZE );
if( cryptStatusOK( status ) )
status = readSsh2Bignum( stream, dsaKey->dlpParam_y,
bitsToBytes( 128 ), CRYPT_MAX_PKCSIZE );
}
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 );
return( cryptArgError( status ) ? CRYPT_ERROR_BADDATA : status );
}
int writeSsh2PublicKey( STREAM *stream, const CRYPT_INFO *cryptInfoPtr )
{
/* Write the SSH public key information */
if( cryptInfoPtr->capabilityInfo->cryptAlgo == CRYPT_ALGO_RSA )
{
const PKC_INFO *rsaKey = &cryptInfoPtr->ctxPKC;
writeSsh2Bignum( stream, rsaKey->rsaParam_e );
return( writeSsh2Bignum( stream, rsaKey->rsaParam_n ) );
}
else
{
const PKC_INFO *dsaKey = &cryptInfoPtr->ctxPKC;
writeSsh2Bignum( stream, dsaKey->dlpParam_p );
writeSsh2Bignum( stream, dsaKey->dlpParam_q );
writeSsh2Bignum( stream, dsaKey->dlpParam_g );
return( writeSsh2Bignum( stream, dsaKey->dlpParam_y ) );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -