📄 sign_rw.c
字号:
/****************************************************************************
* *
* Signature Read/Write Routines *
* Copyright Peter Gutmann 1992-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "asn1.h"
#include "mech.h"
#include "asn1_ext.h"
#include "misc_rw.h"
#include "pgp_rw.h"
#else
#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 */
/* Context-specific tags for the SignerInfo record */
enum { CTAG_SI_SKI };
/****************************************************************************
* *
* X.509 Signature Routines *
* *
****************************************************************************/
/* Read/write raw signatures */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readRawSignature( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
/* Read the start of the signature */
status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
DEFAULT_TAG );
if( cryptStatusError( status ) )
return( status );
queryInfo->dataStart = stell( stream ) - startPos;
/* Make sure that the remaining signature data is present */
return( sSkip( stream, queryInfo->dataLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeRawSignature( INOUT STREAM *stream,
STDC_UNUSED const CRYPT_CONTEXT iSignContext,
STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
IN_BUFFER( signatureLength ) const BYTE *signature,
IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( signature, signatureLength ) );
/* Other parameters aren't used for this format */
REQUIRES( signatureLength >= 40 && \
signatureLength < MAX_INTLENGTH_SHORT );
/* Write the BIT STRING wrapper and signature */
writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
return( writeRawObject( stream, signature, signatureLength ) );
}
/* Read/write X.509 signatures */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readX509Signature( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
/* Read the signature/hash algorithm information followed by the start
of the signature */
status = readAlgoIDext( stream, &queryInfo->cryptAlgo,
&queryInfo->hashAlgo );
if( cryptStatusOK( status ) )
{
status = readBitStringHole( stream, &queryInfo->dataLength, 18 + 18,
DEFAULT_TAG );
}
if( cryptStatusError( status ) )
return( status );
queryInfo->dataStart = stell( stream ) - startPos;
/* Make sure that the remaining signature data is present */
return( sSkip( stream, queryInfo->dataLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeX509Signature( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iSignContext,
IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
IN_BUFFER( signatureLength ) const BYTE *signature,
IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( signature, signatureLength ) );
/* Other parameters aren't used for this format */
REQUIRES( isHandleRangeValid( iSignContext ) );
REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
hashAlgo <= CRYPT_ALGO_LAST_HASH );
REQUIRES( signatureLength >= 40 && \
signatureLength < MAX_INTLENGTH_SHORT );
/* Write the hash+signature algorithm identifier followed by the BIT
STRING wrapper and signature */
writeContextAlgoID( stream, iSignContext, hashAlgo );
writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
return( writeRawObject( stream, signature, signatureLength ) );
}
/****************************************************************************
* *
* CMS Signature Routines *
* *
****************************************************************************/
/* Read/write PKCS #7/CMS (issuerAndSerialNumber) signatures */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCmsSignature( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
long value, endPos;
int length, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
status = getStreamObjectLength( stream, &length );
if( cryptStatusError( status ) )
return( status );
endPos = startPos + length;
/* Read the header */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value != SIGNATURE_VERSION )
return( CRYPT_ERROR_BADDATA );
/* Read the issuer and serial number and hash algorithm ID. Since we're
recording the position of the issuerAndSerialNumber as a blob we have
to use getStreamObjectLength() to get the overall blob data size */
status = getStreamObjectLength( stream, &length );
if( cryptStatusError( status ) )
return( status );
queryInfo->iAndSStart = stell( stream ) - startPos;
queryInfo->iAndSLength = length;
sSkip( stream, length );
status = readAlgoID( stream, &queryInfo->hashAlgo );
if( cryptStatusError( status ) )
return( status );
/* Read the authenticated attributes if there are any present */
if( peekTag( stream ) == MAKE_CTAG( 0 ) )
{
status = getStreamObjectLength( stream, &length );
if( cryptStatusError( status ) )
return( status );
queryInfo->attributeStart = stell( stream ) - startPos;
queryInfo->attributeLength = length;
status = sSkip( stream, length );
if( cryptStatusError( status ) )
return( status );
}
/* Read the CMS/cryptlib signature algorithm and the start of the
signature */
status = readAlgoID( stream, &queryInfo->cryptAlgo );
if( cryptStatusOK( status ) )
{
status = readOctetStringHole( stream, &queryInfo->dataLength,
18 + 18, DEFAULT_TAG );
}
if( cryptStatusOK( status ) )
{
queryInfo->dataStart = stell( stream ) - startPos;
status = sSkip( stream, queryInfo->dataLength );
}
if( cryptStatusError( status ) )
return( status );
/* Read the unauthenticated attributes if there are any present */
if( stell( stream ) < endPos && peekTag( stream ) == MAKE_CTAG( 1 ) )
{
status = getStreamObjectLength( stream, &length );
if( cryptStatusError( status ) )
return( status );
queryInfo->unauthAttributeStart = stell( stream ) - startPos;
queryInfo->unauthAttributeLength = length;
status = sSkip( stream, length );
if( cryptStatusError( status ) )
return( status );
}
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeCmsSignature( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iSignContext,
STDC_UNUSED const CRYPT_ALGO_TYPE hashAlgo,
STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
IN_BUFFER( signatureLength ) const BYTE *signature,
IN_LENGTH_SHORT_MIN( 40 ) const int signatureLength )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( signature, signatureLength ) );
/* Other parameters aren't used for this format */
REQUIRES( isHandleRangeValid( iSignContext ) );
REQUIRES( signatureLength >= 40 && \
signatureLength < MAX_INTLENGTH_SHORT );
/* Write the signature algorithm identifier and signature data. The
handling of CMS signatures is non-orthogonal to readCmsSignature()
because creating a CMS signature involves adding assorted additional
data like iAndS and signed attributes that present too much
information to pass into a basic writeSignature() call */
writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE );
return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
}
/* Read/write cryptlib/CMS (keyID) signatures */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readCryptlibSignature( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
long value;
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
/* Read the header */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusError( status ) )
return( status );
if( value != SIGNATURE_EX_VERSION )
return( CRYPT_ERROR_BADDATA );
/* Read the key ID and hash algorithm identifier */
readOctetStringTag( stream, queryInfo->keyID, &queryInfo->keyIDlength,
8, CRYPT_MAX_HASHSIZE, CTAG_SI_SKI );
status = readAlgoID( stream, &queryInfo->hashAlgo );
if( cryptStatusError( status ) )
return( status );
/* Read the CMS/cryptlib signature algorithm and the start of the
signature */
status = readAlgoID( stream, &queryInfo->cryptAlgo );
if( cryptStatusOK( status ) )
{
status = readOctetStringHole( stream, &queryInfo->dataLength,
18 + 18, DEFAULT_TAG );
}
if( cryptStatusError( status ) )
return( status );
queryInfo->dataStart = stell( stream ) - startPos;
/* Make sure that the remaining signature data is present */
return( sSkip( stream, queryInfo->dataLength ) );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 5 ) ) \
static int writeCryptlibSignature( INOUT STREAM *stream,
IN_HANDLE const CRYPT_CONTEXT iSignContext,
IN_ALGO const CRYPT_ALGO_TYPE hashAlgo,
STDC_UNUSED const CRYPT_ALGO_TYPE signAlgo,
IN_BUFFER( signatureLength ) \
const BYTE *signature,
IN_LENGTH_SHORT_MIN( 40 ) \
const int signatureLength )
{
MESSAGE_DATA msgData;
BYTE keyID[ CRYPT_MAX_HASHSIZE + 8 ];
const int signAlgoIdSize = \
sizeofContextAlgoID( iSignContext, CRYPT_ALGO_NONE );
const int hashAlgoIdSize = sizeofAlgoID( hashAlgo );
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( signature, signatureLength ) );
/* Other parameters aren't used for this format */
REQUIRES( isHandleRangeValid( iSignContext ) );
REQUIRES( hashAlgo >= CRYPT_ALGO_FIRST_HASH && \
hashAlgo <= CRYPT_ALGO_LAST_HASH );
REQUIRES( signatureLength >= 40 && \
signatureLength < MAX_INTLENGTH_SHORT );
if( cryptStatusError( signAlgoIdSize ) )
return( signAlgoIdSize );
if( cryptStatusError( hashAlgoIdSize ) )
return( hashAlgoIdSize );
/* Get the key ID */
setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
if( cryptStatusError( status ) )
return( status );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -