📄 sign.c
字号:
header and trailer around it */
sMemOpen( &stream, signature,
1 + pgpSizeofLength( extraDataLength + 2 + \
signatureDataLength ) + \
extraDataLength + 2 + signatureDataLength );
pgpWritePacketHeader( &stream, PGP_PACKET_SIGNATURE,
extraDataLength + 2 + signatureDataLength );
swrite( &stream, extraData, extraDataLength );
swrite( &stream, hash, 2 ); /* Hash check */
status = swrite( &stream, signatureData, signatureDataLength );
if( cryptStatusOK( status ) )
*signatureLength = stell( &stream );
sMemDisconnect( &stream );
zeroise( extraDataPtr, extraDataLength );
zeroise( signatureData, CRYPT_MAX_PKCSIZE + 128 );
if( extraDataPtr != extraData )
clFree( "createSignaturePGP", extraDataPtr );
return( status );
}
/* Check a PGP signature */
static int checkSignaturePGP( const void *signature, const int signatureLength,
const CRYPT_CONTEXT sigCheckContext,
const CRYPT_CONTEXT iHashContext )
{
QUERY_INFO queryInfo;
STREAM stream;
int status;
/* Determine whether there are any authenticated attributes attached to
the signature */
memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
sMemConnect( &stream, signature, signatureLength );
status = sigReadTable[ SIGNATURE_PGP ]( &stream, &queryInfo );
sMemDisconnect( &stream );
if( cryptStatusError( status ) )
{
zeroise( &queryInfo, sizeof( QUERY_INFO ) );
return( status );
}
/* After hashing the content, PGP also hashes in extra authenticated
attributes */
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
queryInfo.attributeStart,
queryInfo.attributeLength );
if( cryptStatusOK( status ) && queryInfo.attributeLength != 5 )
{
BYTE buffer[ 8 ], *bufPtr = buffer + 2;
/* In addition to the standard authenticated attributes, OpenPGP
hashes in even more stuff at the end */
buffer[ 0 ] = 0x04;
buffer[ 1 ] = 0xFF;
mputLong( bufPtr, queryInfo.attributeLength );
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
buffer, 6 );
}
zeroise( &queryInfo, sizeof( QUERY_INFO ) );
if( cryptStatusOK( status ) )
krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
if( cryptStatusError( status ) )
return( status );
/* Check the signature */
return( checkSignature( signature, signatureLength, sigCheckContext,
iHashContext, SIGNATURE_PGP ) );
}
#endif /* USE_PGP */
/****************************************************************************
* *
* Extended Create/Check a Signature *
* *
****************************************************************************/
/* Create/check an extended signature type */
C_RET cryptCreateSignatureEx( C_OUT void C_PTR signature,
C_OUT int C_PTR signatureLength,
C_IN CRYPT_FORMAT_TYPE formatType,
C_IN CRYPT_CONTEXT signContext,
C_IN CRYPT_CONTEXT hashContext,
C_IN CRYPT_HANDLE extraData )
{
BOOLEAN isCertChain = FALSE;
int certType, 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;
if( formatType <= CRYPT_FORMAT_NONE || \
formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
return( CRYPT_ERROR_PARAM3 );
status = krnlSendMessage( signContext, MESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM4 : status );
if( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME )
{
}
status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
MESSAGE_CHECK_HASH );
if( cryptStatusError( status ) )
return( ( status == CRYPT_ARGERROR_OBJECT ) ? \
CRYPT_ERROR_PARAM5 : status );
/* If the signing context has a cert chain attached, the currently-
selected cert may not be the leaf cert. To ensure that we use the
correct cert, we lock the chain (which both protects us from having
the user select a different cert while we're using it, and saves the
selection state for when we later unlock it) and explicitly select
the leaf cert */
status = krnlSendMessage( signContext, IMESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusOK( status ) && certType == CRYPT_CERTTYPE_CERTCHAIN )
{
status = krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_TRUE,
CRYPT_IATTRIBUTE_LOCKED );
if( cryptStatusError( status ) )
return( status );
krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_CURSORFIRST,
CRYPT_CERTINFO_CURRENT_CERTIFICATE );
isCertChain = TRUE;
}
/* Call the low-level signature create function to create the signature.
Unfortunately the early cryptlib API didn't take length parameters
when it wasn't absolutely necessary so we can't specify the maximum
data length when generating the signature but have to use
STREAMSIZE_UNKNOWN for the output */
switch( formatType )
{
case CRYPT_FORMAT_AUTO:
case CRYPT_FORMAT_CRYPTLIB:
/* If it's a cryptlib-format signature, there can't be any extra
signing attributes present */
if( extraData != CRYPT_USE_DEFAULT )
{
status = CRYPT_ERROR_PARAM6;
break;
}
status = createSignature( signature, signatureLength,
STREAMSIZE_UNKNOWN, signContext,
hashContext, SIGNATURE_CRYPTLIB );
break;
case CRYPT_FORMAT_CMS:
case CRYPT_FORMAT_SMIME:
/* Make sure that the signing context has a cert attached to
it */
status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
( certType != CRYPT_CERTTYPE_CERTIFICATE && \
certType != CRYPT_CERTTYPE_CERTCHAIN ) )
{
status = CRYPT_ERROR_PARAM4;
break;
}
/* Make sure that the extra data object is in order */
if( extraData != CRYPT_USE_DEFAULT )
{
status = krnlSendMessage( extraData, MESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) || \
certType != CRYPT_CERTTYPE_CMS_ATTRIBUTES )
{
status = CRYPT_ERROR_PARAM6;
break;
}
}
status = createSignatureCMS( signature, signatureLength,
STREAMSIZE_UNKNOWN, signContext,
hashContext, extraData,
CRYPT_UNUSED, formatType );
break;
#ifdef USE_PGP
case CRYPT_FORMAT_PGP:
status = createSignaturePGP( signature, signatureLength,
STREAMSIZE_UNKNOWN, signContext,
hashContext );
break;
#endif /* USE_PGP */
default:
assert( NOTREACHED );
status = CRYPT_ERROR_PARAM3;
}
if( isCertChain )
/* We're signing with a cert chain, restore its state and unlock it
to allow others access */
krnlSendMessage( signContext, IMESSAGE_SETATTRIBUTE,
MESSAGE_VALUE_FALSE, CRYPT_IATTRIBUTE_LOCKED );
if( cryptArgError( status ) )
/* Remap the error code to refer to the correct parameter */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM4 : CRYPT_ERROR_PARAM5;
return( status );
}
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;
status = cryptCreateSignatureEx( signature, signatureLength,
CRYPT_FORMAT_CRYPTLIB,
signContext, hashContext,
CRYPT_USE_DEFAULT );
if( cryptStatusError( status ) )
{
/* Remap parameter errors to the correct position */
if( status == CRYPT_ERROR_PARAM4 )
status = CRYPT_ERROR_PARAM3;
if( status == CRYPT_ERROR_PARAM5 )
status = CRYPT_ERROR_PARAM4;
}
return( status );
}
static CRYPT_FORMAT_TYPE getFormatType( const void *data )
{
STREAM stream;
const BYTE *dataPtr = data;
#ifdef USE_PGP
long length;
#endif /* USE_PGP */
int status;
/* Figure out what we've got. A PKCS #7/CMS/SMIME signature begins:
cryptlibSignature ::= SEQUENCE {
version INTEGER (3),
keyID [ 0 ] OCTET STRING
while a CMS signature begins:
cmsSignature ::= SEQUENCE {
version INTEGER (1),
digestAlgo SET OF {
which allows us to determine which type of object we have */
if( *dataPtr == BER_SEQUENCE )
{
CRYPT_FORMAT_TYPE formatType = CRYPT_FORMAT_NONE;
sMemConnect( &stream, data, 16 );
status = readSequence( &stream, NULL );
if( cryptStatusOK( status ) )
{
long version;
if( cryptStatusOK( readShortInteger( &stream, &version ) ) )
formatType = ( version == 1 ) ? CRYPT_FORMAT_CMS : \
( version == 3 ) ? CRYPT_FORMAT_CRYPTLIB : \
CRYPT_FORMAT_NONE;
}
sMemDisconnect( &stream );
return( formatType );
}
#ifdef USE_PGP
/* It's not ASN.1 data, check for PGP data */
sMemConnect( &stream, data, 16 );
status = pgpReadPacketHeader( &stream, NULL, &length );
if( cryptStatusOK( status ) && length > 30 && length < 8192 )
{
sMemDisconnect( &stream );
return( CRYPT_FORMAT_PGP );
}
sMemDisconnect( &stream );
#endif /* USE_PGP */
return( CRYPT_FORMAT_NONE );
}
C_RET cryptCheckSignatureEx( C_IN void C_PTR signature,
C_IN CRYPT_HANDLE sigCheckKey,
C_IN CRYPT_CONTEXT hashContext,
C_OUT CRYPT_HANDLE C_PTR extraData )
{
CRYPT_FORMAT_TYPE formatType;
CRYPT_CONTEXT sigCheckContext;
int signatureLength, status;
/* Perform basic error checking */
if( signature != NULL && checkBadPtrRead( signature, MIN_CRYPT_OBJECTSIZE ) )
return( CRYPT_ERROR_PARAM1 );
if( ( formatType = getFormatType( signature ) ) == CRYPT_FORMAT_NONE )
return( CRYPT_ERROR_BADDATA );
status = krnlSendMessage( sigCheckKey, MESSAGE_GETDEPENDENT,
&sigCheckContext, OBJECT_TYPE_CONTEXT );
if( cryptStatusOK( status ) )
status = krnlSendMessage( sigCheckContext, IMESSAGE_CHECK,
NULL, MESSAGE_CHECK_PKC_SIGCHECK );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
MESSAGE_CHECK_HASH );
if( status == CRYPT_ARGERROR_OBJECT )
status = CRYPT_ERROR_PARAM3;
}
else
if( status == CRYPT_ARGERROR_OBJECT )
status = CRYPT_ERROR_PARAM2;
if( cryptStatusError( status ) )
return( status );
if( formatType == CRYPT_FORMAT_CMS )
{
int certType;
/* Make sure that the sig check key includes a cert */
status = krnlSendMessage( sigCheckKey, MESSAGE_GETATTRIBUTE,
&certType, CRYPT_CERTINFO_CERTTYPE );
if( cryptStatusError( status ) ||
( certType != CRYPT_CERTTYPE_CERTIFICATE && \
certType != CRYPT_CERTTYPE_CERTCHAIN ) )
return( CRYPT_ERROR_PARAM2 );
}
/* Try and determine the length of the signature data. This should be
specified as a user parameter, unfortunately the early cryptlib API
didn't take length parameters when it wasn't absolutely necessary so
we have to take a guess at a safe size limit and hope that the data
isn't all done with an indefinite encoding (this is at least better
than when generating the signature, where we're forced to use
STREAMSIZE_UNKNOWN for the output) */
#ifdef USE_PGP
if( formatType == CRYPT_FORMAT_PGP )
{
STREAM stream;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -