📄 lib_sign.c
字号:
krnlSendNotifier( createInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
if( cryptStatusError( status ) )
return( status );
sMemOpen( &stream, signedObject, startOffset );
writeSequence( &stream, signatureLength + objectLength );
delta = startOffset - ( int ) stell( &stream );
sMemDisconnect( &stream );
if( delta > 0 )
{
/* This only ever really happens for CRLs/OCSP responses with a single
cert and no extensions */
payloadStart -= delta;
memcpy( payloadStart, object, objectLength );
memmove( payloadStart + objectLength,
payloadStart + delta + objectLength, signatureLength );
*signedObjectLength = ( startOffset - delta ) + \
objectLength + signatureLength;
}
else
{
/* Drop the signed data into place */
memcpy( payloadStart, object, objectLength );
*signedObjectLength = startOffset + objectLength + signatureLength;
}
return( status );
}
int checkX509signature( const void *signedObject, const int signedObjectLength,
void **object, int *objectLength,
CRYPT_CONTEXT sigCheckContext )
{
CRYPT_ALGO signAlgo, sigCheckAlgo, hashAlgo;
MESSAGE_CREATEOBJECT_INFO createInfo;
STREAM stream;
void *objectPtr, *sigPtr;
int status, length, signatureLength;
/* Check the start of the object */
sMemConnect( &stream, ( void * ) signedObject, signedObjectLength );
status = readSequence( &stream, NULL );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
/* Record the start and size of the signed object. The use of the
length from readSequence() is safe here because the data has to be DER
if it's signed */
objectPtr = sMemBufPtr( &stream );
status = readSequence( &stream, &length );
if( cryptStatusOK( status ) )
{
status = sSkip( &stream, length ); /* Move past the object */
length = ( int ) sizeofObject( length );/* Include header size */
}
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( status );
}
if( objectLength != NULL )
*objectLength = length;
if( object != NULL )
*object = objectPtr;
/* Create a hash context from the algorithm identifier of the signature */
status = krnlSendMessage( sigCheckContext, RESOURCE_IMESSAGE_GETATTRIBUTE,
&sigCheckAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
{
/* If it's a broken CRMF signature, there's an extra [ 1 ]
encapsulating the signature */
if( peekTag( &stream ) == MAKE_CTAG( 1 ) )
readConstructed( &stream, NULL, 1 );
sigPtr = sMemBufPtr( &stream );
status = readAlgoIDex( &stream, &signAlgo, &hashAlgo, NULL );
}
signatureLength = sMemDataLeft( &stream );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) && sigCheckAlgo != signAlgo )
/* The signature algorithm isn't what we expected, the best we can do
is report a certificate data error */
status = CRYPT_ERROR_BADDATA;
if( cryptStatusOK( status ) )
{
setMessageCreateObjectInfo( &createInfo, hashAlgo );
status = krnlSendMessage( SYSTEM_OBJECT_HANDLE,
RESOURCE_IMESSAGE_DEV_CREATEOBJECT,
&createInfo, OBJECT_TYPE_CONTEXT );
}
if( cryptStatusError( status ) )
return( status );
/* Hash the signed data and check the signature on the object */
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH,
objectPtr, length );
krnlSendMessage( createInfo.cryptHandle, RESOURCE_IMESSAGE_CTX_HASH,
objectPtr, 0 );
status = checkSignature( sigPtr, signatureLength, sigCheckContext,
createInfo.cryptHandle, SIGNATURE_X509 );
/* Clean up */
krnlSendNotifier( createInfo.cryptHandle, RESOURCE_IMESSAGE_DECREFCOUNT );
return( status );
}
/****************************************************************************
* *
* PKI Protocol Signature Functions *
* *
****************************************************************************/
/* The various cert management protocols are built using the twin design
guidelines that nothing should use a standard style of signature and no
two protocols should use the same nonstandard format, the only way to
handle these (without creating dozens of new signature types, each with
their own special-case handling) is to process most of the signature
information at the protocol level and just check the raw signature here */
int createRawSignature( void *signature, int *signatureLength,
const CRYPT_CONTEXT iSignContext,
const CRYPT_CONTEXT iHashContext )
{
return( createSignature( signature, signatureLength, iSignContext,
iHashContext, SIGNATURE_RAW ) );
}
int checkRawSignature( const void *signature, const int signatureLength,
const CRYPT_CONTEXT iSigCheckContext,
const CRYPT_CONTEXT iHashContext )
{
return( checkSignature( signature, signatureLength, iSigCheckContext,
iHashContext, SIGNATURE_RAW ) );
}
/****************************************************************************
* *
* S/MIME Signature Functions *
* *
****************************************************************************/
/* CMS version */
#define CMS_VERSION 1
/* The OID for the timestamp unsigned attribute */
#define OID_TSTOKEN MKOID( "\x06\x0B\x2A\x86\x48\x86\xF7\x0D\x01\x09\x10\x02\x0E" )
/* Write signer information:
SignerInfo ::= SEQUENCE {
version INTEGER (1),
issuerAndSerialNumber IssuerAndSerialNumber,
digestAlgorithm AlgorithmIdentifier,
signedAttrs [ 0 ] IMPLICIT SET OF Attribute OPTIONAL,
signatureAlgorithm AlgorithmIdentifier,
signature OCTET STRING,
unsignedAttrs [ 1 ] IMPLICIT SET OF Attribute OPTIONAL
} */
static int writeSignerInfo( STREAM *stream, const CRYPT_CERTIFICATE certificate,
const CRYPT_ALGO hashAlgorithm,
const void *attributes, const int attributeSize,
const void *signature, const int signatureSize,
const CRYPT_HANDLE unsignedAttrObject )
{
RESOURCE_DATA msgData;
BYTE iAndSBuffer[ 1024 ], *iAndSBufPtr = iAndSBuffer;
int iAndSSize, timeStampSize, unsignedAttributeSize = 0;
int status;
/* Get the signerInfo information */
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( certificate, RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) && msgData.length > 1024 && \
( iAndSBufPtr = malloc( msgData.length ) ) == NULL )
status = CRYPT_ERROR_MEMORY;
if( cryptStatusOK( status ) )
{
msgData.data = iAndSBufPtr;
status = krnlSendMessage( certificate,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
}
if( cryptStatusOK( status ) )
{
iAndSSize = msgData.length;
if( unsignedAttrObject != CRYPT_UNUSED )
{
setResourceData( &msgData, NULL, 0 );
status = krnlSendMessage( unsignedAttrObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ENC_TIMESTAMP );
timeStampSize = msgData.length;
if( cryptStatusOK( status ) )
unsignedAttributeSize = ( int ) sizeofObject( \
sizeofOID( OID_TSTOKEN ) + \
sizeofObject( timeStampSize ) );
}
}
if( cryptStatusError( status ) )
{
if( iAndSBufPtr != iAndSBuffer && iAndSBufPtr != NULL )
free( iAndSBufPtr );
return( status );
}
/* Write the outer SEQUENCE wrapper and version number */
writeSequence( stream, sizeofShortInteger( CMS_VERSION ) + \
iAndSSize + sizeofAlgoID( hashAlgorithm ) + \
attributeSize + signatureSize + \
( ( unsignedAttributeSize ) ? \
( int ) sizeofObject( unsignedAttributeSize ) : 0 ) );
writeShortInteger( stream, CMS_VERSION, DEFAULT_TAG );
/* Write the issuerAndSerialNumber, digest algorithm identifier,
attributes (if there are any) and signature */
swrite( stream, iAndSBufPtr, iAndSSize );
writeAlgoID( stream, hashAlgorithm );
if( attributeSize )
swrite( stream, attributes, attributeSize );
swrite( stream, signature, signatureSize );
if( iAndSBufPtr != iAndSBuffer )
free( iAndSBufPtr );
/* Write the unsigned attributes if there are any */
if( unsignedAttributeSize )
{
RESOURCE_DATA msgData;
/* Write the [1] IMPLICT SET OF attribute wrapper */
writeConstructed( stream, unsignedAttributeSize, 1 );
writeSequence( stream, sizeofOID( OID_TSTOKEN ) + \
sizeofObject( timeStampSize ) );
writeOID( stream, OID_TSTOKEN );
writeSet( stream, timeStampSize );
/* Copy the timestamp data directly into the stream */
setResourceData( &msgData, sMemBufPtr( stream ), MIN_BUFFER_SIZE );
status = krnlSendMessage( unsignedAttrObject,
RESOURCE_IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_ENC_TIMESTAMP );
if( cryptStatusError( status ) )
return( status );
sSkip( stream, msgData.length );
}
return( CRYPT_OK );
}
/****************************************************************************
* *
* Create/Check a Signature *
* *
****************************************************************************/
/* Create/check a signature */
C_RET cryptCreateSignature( C_OUT void C_PTR signature,
C_OUT int C_PTR signatureLength,
C_IN CRYPT_CONTEXT signContext,
C_IN CRYPT_CONTEXT hashContext )
{
int status;
/* Perform basic error checking */
if( signature != NULL )
{
if( checkBadPtrWrite( signature, MIN_CRYPT_OBJECTSIZE ) )
return( CRYPT_ERROR_PARAM1 );
memset( signature, 0, MIN_CRYPT_OBJECTSIZE );
}
if( checkBadPtrWrite( signatureLength, sizeof( int ) ) )
return( CRYPT_ERROR_PARAM2 );
*signatureLength = 0;
status = krnlSendMessage( signContext, RESOURCE_MESSAGE_CHECK, NULL,
RESOURCE_MESSAGE_CHECK_PKC_SIGN );
if( status == CRYPT_ARGERROR_OBJECT )
status = CRYPT_ERROR_PARAM3;
if( cryptStatusOK( status ) )
status = krnlSendMessage( hashContext, RESOURCE_MESSAGE_CHECK, NULL,
RESOURCE_MESSAGE_CHECK_HASH );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : status );
/* Call the low-level signature create function to create the signature */
status = createSignature( signature, signatureLength, signContext,
hashContext, SIGNATURE_CRYPTLIB );
if( cryptArgError( status ) )
/* If we get an argument error from the mechanism-level code, map the
mechanism parameter number to the function argument number */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM4 : CRYPT_ERROR_PARAM3;
return( status );
}
/* Check a signature on a block of data */
C_RET cryptCheckSignature( C_IN void C_PTR signature,
C_IN CRYPT_HANDLE sigCheckKey,
C_IN CRYPT_CONTEXT hashContext )
{
CRYPT_CONTEXT sigCheckContext;
int signatureLength, status;
/* Perform basic error checking */
if( checkBadPtrRead( signature, MIN_CRYPT_OBJECTSIZE ) )
return( CRYPT_ERROR_PARAM1 );
status = krnlSendMessage( sigCheckKey, RESOURCE_MESSAGE_CHECK, NULL,
RESOURCE_MESSAGE_CHECK_PKC_SIGCHECK );
if( status == CRYPT_ARGERROR_OBJECT )
status = CRYPT_ERROR_PARAM2;
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( hashContext, RESOURCE_MESSAGE_CHECK, NULL,
RESOURCE_MESSAGE_CHECK_HASH );
if( status == CRYPT_ARGERROR_OBJECT )
status = CRYPT_ERROR_PARAM3;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -