📄 sign.c
字号:
/****************************************************************************
* *
* Signature Routines *
* Copyright Peter Gutmann 1993-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "mech.h"
#include "asn1.h"
#include "asn1_ext.h"
#include "misc_rw.h"
#include "pgp_rw.h"
#else
#include "crypt.h"
#include "mechs/mech.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#include "misc/misc_rw.h"
#include "misc/pgp_rw.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* Utility Functions *
* *
****************************************************************************/
/* Try and determine the format of the signed data */
CHECK_RETVAL_ENUM( CRYPT_FORMAT ) STDC_NONNULL_ARG( ( 1 ) ) \
static CRYPT_FORMAT_TYPE getFormatType( IN_BUFFER( dataLength ) const void *data,
IN_LENGTH const int dataLength )
{
STREAM stream;
long value;
int status;
assert( isReadPtr( data, dataLength ) );
REQUIRES( dataLength > MIN_CRYPT_OBJECTSIZE && \
dataLength < MAX_INTLENGTH );
sMemConnect( &stream, data, min( 16, dataLength ) );
/* 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. Note that
we use sPeek() rather than peekTag() because we want to continue
processing (or at least checking for) PGP data if it's no ASN.1 */
if( sPeek( &stream ) == BER_SEQUENCE )
{
CRYPT_FORMAT_TYPE formatType;
readSequence( &stream, NULL );
status = readShortInteger( &stream, &value );
if( cryptStatusError( status ) )
{
sMemDisconnect( &stream );
return( CRYPT_FORMAT_NONE );
}
switch( value )
{
case SIGNATURE_VERSION:
formatType = CRYPT_FORMAT_CMS;
break;
case SIGNATURE_EX_VERSION:
formatType = CRYPT_FORMAT_CRYPTLIB;
break;
default:
formatType = CRYPT_FORMAT_NONE;
}
sMemDisconnect( &stream );
return( formatType );
}
#ifdef USE_PGP
/* It's not ASN.1 data, check for PGP data */
status = pgpReadPacketHeader( &stream, NULL, &value, 30 );
if( cryptStatusOK( status ) && value > 30 && value < 8192 )
{
sMemDisconnect( &stream );
return( CRYPT_FORMAT_PGP );
}
#endif /* USE_PGP */
sMemDisconnect( &stream );
return( CRYPT_FORMAT_NONE );
}
/****************************************************************************
* *
* Create a Signature *
* *
****************************************************************************/
/* Create an extended signature type */
C_RET cryptCreateSignatureEx( C_OUT_OPT void C_PTR signature,
C_IN int signatureMaxLength,
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 )
{
int value, status;
/* Perform basic error checking. We have to use an internal message to
check for signing capability because the DLP algorithms have
specialised data-formatting requirements that can't normally be
directly accessed via external messages, and even the non-DLP
algorithms may be internal-use-only if there's a cert attached to
the context. To make sure that the context is OK we first check its
external accessibility by performing a dummy attribute read. Note
that we can't safely use the cert-type read performed later on for
this check because some error conditions (e.g. "not a certificate")
are valid in this case, but we don't want to have mess with trying to
distinguish OK-in-this-instance vs.not-OK error conditions */
if( signature != NULL )
{
if( signatureMaxLength <= MIN_CRYPT_OBJECTSIZE || \
signatureMaxLength >= MAX_INTLENGTH )
return( CRYPT_ERROR_PARAM2 );
if( !isWritePtr( signature, signatureMaxLength ) )
return( CRYPT_ERROR_PARAM1 );
memset( signature, 0, MIN_CRYPT_OBJECTSIZE );
}
else
{
if( signatureMaxLength != 0 )
return( CRYPT_ERROR_PARAM2 );
}
if( !isWritePtr( signatureLength, sizeof( int ) ) )
return( CRYPT_ERROR_PARAM3 );
*signatureLength = 0;
if( formatType <= CRYPT_FORMAT_NONE || \
formatType >= CRYPT_FORMAT_LAST_EXTERNAL )
return( CRYPT_ERROR_PARAM4 );
status = krnlSendMessage( signContext, MESSAGE_GETATTRIBUTE,
&value, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );
status = krnlSendMessage( signContext, IMESSAGE_CHECK, NULL,
MESSAGE_CHECK_PKC_SIGN );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ERROR_PARAM5 : status );
status = krnlSendMessage( hashContext, MESSAGE_CHECK, NULL,
MESSAGE_CHECK_HASH );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ERROR_PARAM6 : status );
/* Perform any required format-specific checking */
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_UNUSED )
return( CRYPT_ERROR_PARAM7 );
break;
case CRYPT_FORMAT_CMS:
case CRYPT_FORMAT_SMIME:
{
CRYPT_CERTTYPE_TYPE certType;
/* 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 ) )
return( CRYPT_ERROR_PARAM5 );
/* 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 )
return( CRYPT_ERROR_PARAM7 );
}
break;
}
#ifdef USE_PGP
case CRYPT_FORMAT_PGP:
/* There's nothing specific to check for PGP signatures */
break;
#endif /* USE_PGP */
default:
retIntError();
}
/* Call the low-level signature create function to create the
signature */
status = iCryptCreateSignature( signature, signatureMaxLength,
signatureLength, formatType, signContext,
hashContext, extraData, CRYPT_UNUSED );
if( cryptArgError( status ) )
{
/* Remap the error code to refer to the correct parameter */
status = ( status == CRYPT_ARGERROR_NUM1 ) ? \
CRYPT_ERROR_PARAM5 : CRYPT_ERROR_PARAM6;
}
return( status );
}
C_RET cryptCreateSignature( C_OUT_OPT void C_PTR signature,
C_IN int signatureMaxLength,
C_OUT int C_PTR signatureLength,
C_IN CRYPT_CONTEXT signContext,
C_IN CRYPT_CONTEXT hashContext )
{
int status;
status = cryptCreateSignatureEx( signature, signatureMaxLength,
signatureLength, CRYPT_FORMAT_CRYPTLIB,
signContext, hashContext,
CRYPT_UNUSED );
if( cryptStatusError( status ) )
{
/* Remap parameter errors to the correct position */
if( status == CRYPT_ERROR_PARAM5 )
status = CRYPT_ERROR_PARAM4;
if( status == CRYPT_ERROR_PARAM6 )
status = CRYPT_ERROR_PARAM5;
}
return( status );
}
/****************************************************************************
* *
* Check a Signature *
* *
****************************************************************************/
/* Check an extended signature type */
C_RET cryptCheckSignatureEx( C_IN void C_PTR signature,
C_IN int signatureLength,
C_IN CRYPT_HANDLE sigCheckKey,
C_IN CRYPT_CONTEXT hashContext,
C_OUT_OPT CRYPT_HANDLE C_PTR extraData )
{
CRYPT_FORMAT_TYPE formatType;
CRYPT_CERTIFICATE iExtraData;
CRYPT_CONTEXT sigCheckContext;
int status;
/* Perform basic error checking */
if( signatureLength <= MIN_CRYPT_OBJECTSIZE || \
signatureLength >= MAX_INTLENGTH_SHORT )
return( CRYPT_ERROR_PARAM2 );
if( !isReadPtr( signature, signatureLength ) )
return( CRYPT_ERROR_PARAM1 );
if( ( formatType = getFormatType( signature, \
signatureLength ) ) == 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( cryptArgError( status ) )
status = CRYPT_ERROR_PARAM4;
}
else
{
if( cryptArgError( status ) )
status = CRYPT_ERROR_PARAM3;
}
if( cryptStatusError( status ) )
return( status );
if( formatType == CRYPT_FORMAT_CMS || \
formatType == CRYPT_FORMAT_SMIME )
{
CRYPT_CERTTYPE_TYPE 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_PARAM3 );
}
/* Perform any required format-specific checking */
switch( formatType )
{
case CRYPT_FORMAT_CRYPTLIB:
/* If it's a cryptlib-format signature there can't be any extra
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -