📄 sign_rw.c
字号:
/****************************************************************************
* *
* Signature Read/Write Routines *
* Copyright Peter Gutmann 1992-2004 *
* *
****************************************************************************/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined( INC_ALL )
#include "pgp.h"
#include "asn1.h"
#include "mechanism.h"
#include "asn1_ext.h"
#include "misc_rw.h"
#elif defined( INC_CHILD )
#include "../envelope/pgp.h"
#include "mechanism.h"
#include "../misc/asn1.h"
#include "../misc/asn1_ext.h"
#include "../misc/misc_rw.h"
#else
#include "envelope/pgp.h"
#include "mechs/mechanism.h"
#include "misc/asn1.h"
#include "misc/asn1_ext.h"
#include "misc/misc_rw.h"
#endif /* Compiler-specific includes */
/* Context-specific tags for the SignerInfo record */
enum { CTAG_SI_SKI };
/* CMS version numbers for various objects */
#define SIGNATURE_VERSION 1
#define SIGNATURE_EX_VERSION 3
/****************************************************************************
* *
* X.509 Signature Routines *
* *
****************************************************************************/
/* Read/write raw signatures */
static int readRawSignature( STREAM *stream, QUERY_INFO *queryInfo )
{
int status;
/* Read the start of the signature */
status = readBitStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
queryInfo->dataStart = sMemBufPtr( stream );
return( status );
}
static int writeRawSignature( STREAM *stream, const CRYPT_CONTEXT iSignContext,
const CRYPT_ALGO_TYPE hashAlgo,
const CRYPT_ALGO_TYPE signAlgo,
const BYTE *signature,
const int signatureLength )
{
/* Write the BIT STRING wrapper and signature */
writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
return( writeRawObject( stream, signature, signatureLength ) );
}
/* Read/write X.509 signatures */
static int readX509Signature( STREAM *stream, QUERY_INFO *queryInfo )
{
int status;
/* Read the signature/hash algorithm information followed by the start
of the signature */
status = readAlgoIDex( stream, &queryInfo->cryptAlgo,
&queryInfo->hashAlgo, NULL );
if( cryptStatusError( status ) )
return( status );
status = readBitStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
queryInfo->dataStart = sMemBufPtr( stream );
return( status );
}
static int writeX509Signature( STREAM *stream,
const CRYPT_CONTEXT iSignContext,
const CRYPT_ALGO_TYPE hashAlgo,
const CRYPT_ALGO_TYPE signAlgo,
const BYTE *signature,
const int signatureLength )
{
/* Write the hash+signature algorithm identifier followed by the BIT
STRING wrapper and signature */
writeContextAlgoID( stream, iSignContext, hashAlgo,
ALGOID_FLAG_ALGOID_ONLY );
writeBitStringHole( stream, signatureLength, DEFAULT_TAG );
return( writeRawObject( stream, signature, signatureLength ) );
}
/****************************************************************************
* *
* CMS Signature Routines *
* *
****************************************************************************/
/* Read/write PKCS #7/CMS (issuerAndSerialNumber) signatures */
static int readCmsSignature( STREAM *stream, QUERY_INFO *queryInfo )
{
long value, endPos;
int status;
value = getStreamObjectLength( stream );
if( cryptStatusError( value ) )
return( value );
endPos = stell( stream ) + value;
/* Read the header */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusOK( status ) && value != SIGNATURE_VERSION )
status = CRYPT_ERROR_BADDATA;
if( cryptStatusError( status ) )
return( status );
/* Read the issuer and serial number and hash algorithm ID */
value = getStreamObjectLength( stream );
if( cryptStatusError( value ) )
return( value );
queryInfo->iAndSStart = sMemBufPtr( stream );
queryInfo->iAndSLength = value;
sSkip( stream, value );
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 ) )
{
int length;
queryInfo->attributeStart = sMemBufPtr( stream );
status = readConstructed( stream, &length, 0 );
if( cryptStatusError( status ) )
return( status );
queryInfo->attributeLength = ( int ) sizeofObject( length );
sSkip( stream, length );
}
/* Read the CMS/cryptlib signature algorithm and start of the signature */
readAlgoID( stream, &queryInfo->cryptAlgo );
status = readOctetStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
{
queryInfo->dataStart = sMemBufPtr( stream );
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 ) )
{
int length;
queryInfo->unauthAttributeStart = sMemBufPtr( stream );
status = readConstructed( stream, &length, 1 );
if( cryptStatusError( status ) )
return( status );
queryInfo->unauthAttributeLength = ( int ) sizeofObject( length );
status = sSkip( stream, length );
}
return( status );
}
static int writeCmsSignature( STREAM *stream,
const CRYPT_CONTEXT iSignContext,
const CRYPT_ALGO_TYPE hashAlgo,
const CRYPT_ALGO_TYPE signAlgo,
const BYTE *signature,
const int signatureLength )
{
/* 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 which present too much
information to pass into a basic writeSignature() call */
writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY );
return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
}
/* Read/write cryptlib/CMS (keyID) signatures */
static int readCryptlibSignature( STREAM *stream, QUERY_INFO *queryInfo )
{
long value;
int status;
/* Read the header */
readSequence( stream, NULL );
status = readShortInteger( stream, &value );
if( cryptStatusOK( status ) && value != SIGNATURE_EX_VERSION )
status = CRYPT_ERROR_BADDATA;
if( cryptStatusError( status ) )
return( status );
/* Read the key ID and hash algorithm identifier */
readOctetStringTag( stream, queryInfo->keyID, &queryInfo->keyIDlength,
CRYPT_MAX_HASHSIZE, CTAG_SI_SKI );
status = readAlgoID( stream, &queryInfo->hashAlgo );
if( cryptStatusError( status ) )
return( status );
/* Read the CMS/cryptlib signature algorithm and start of the signature */
readAlgoID( stream, &queryInfo->cryptAlgo );
status = readOctetStringHole( stream, &queryInfo->dataLength,
DEFAULT_TAG );
if( cryptStatusOK( status ) )
queryInfo->dataStart = sMemBufPtr( stream );
return( status );
}
static int writeCryptlibSignature( STREAM *stream,
const CRYPT_CONTEXT iSignContext,
const CRYPT_ALGO_TYPE hashAlgo,
const CRYPT_ALGO_TYPE signAlgo,
const BYTE *signature,
const int signatureLength )
{
RESOURCE_DATA msgData;
BYTE keyID[ CRYPT_MAX_HASHSIZE ];
/* Get the key ID */
setMessageData( &msgData, keyID, CRYPT_MAX_HASHSIZE );
krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID );
/* Write the header */
writeSequence( stream, ( int ) sizeofShortInteger( SIGNATURE_EX_VERSION ) + \
sizeofObject( msgData.length ) + \
sizeofContextAlgoID( iSignContext, CRYPT_ALGO_NONE, \
ALGOID_FLAG_ALGOID_ONLY ) + \
sizeofAlgoID( hashAlgo ) + \
sizeofObject( signatureLength ) );
/* Write the version, key ID and algorithm identifier */
writeShortInteger( stream, SIGNATURE_EX_VERSION, DEFAULT_TAG );
writeOctetString( stream, msgData.data, msgData.length, CTAG_SI_SKI );
writeAlgoID( stream, hashAlgo );
writeContextAlgoID( stream, iSignContext, CRYPT_ALGO_NONE,
ALGOID_FLAG_ALGOID_ONLY );
return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
}
/****************************************************************************
* *
* Misc Signature Routines *
* *
****************************************************************************/
#ifdef USE_PGP
/* Read signature subpackets */
static int readSignatureSubpackets( STREAM *stream, QUERY_INFO *queryInfo,
const int length,
const BOOLEAN isAuthenticated )
{
const int endPos = stell( stream ) + length;
while( stell( stream ) < endPos )
{
const int subpacketLength = pgpReadShortLength( stream,
PGP_CTB_OPENPGP );
const int type = sgetc( stream );
if( cryptStatusError( subpacketLength ) )
return( subpacketLength );
/* If it's an unrecognised subpacket with the critical flag set,
reject the signature. The range check isn't complete since there
are a few holes in the range, but since the holes presumably exist
because of deprecated subpacket types, any new packets will be
added at the end so it's safe to use */
if( ( type & 0x80 ) && ( ( type & 0x7F ) > PGP_SUBPACKET_LAST ) )
return( CRYPT_ERROR_NOTAVAIL );
/* If it's a key ID and we haven't already set this from a preceding
one-pass signature packet (which can happen with detached sigs),
set it now */
if( type == PGP_SUBPACKET_KEYID && queryInfo->keyIDlength <= 0 )
{
sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
queryInfo->keyIDlength = PGP_KEYID_SIZE;
continue;
}
/* If it's a type-and-value packet, see whether it's one of
ours */
if( type == PGP_SUBPACKET_TYPEANDVALUE )
{
BYTE nameBuffer[ 32 ];
static const char *nameString = "issuerAndSerialNumber";
int nameLength, valueLength;
sSkip( stream, 4 ); /* Flags */
nameLength = readUint16( stream );
valueLength = readUint16( stream );
if( nameLength != strlen( nameString ) || \
valueLength < 16 || valueLength > 2048 )
{
sSkip( stream, nameLength + valueLength );
continue;
}
sread( stream, nameBuffer, nameLength );
if( memcmp( nameBuffer, nameString, nameLength ) )
{
sSkip( stream, valueLength );
continue;
}
/* It's an issuerAndSerialNumber, remember it for later */
queryInfo->iAndSStart = sMemBufPtr( stream );
queryInfo->iAndSLength = valueLength;
sSkip( stream, valueLength );
continue;
}
/* It's something else, skip it and continue */
sSkip( stream, subpacketLength - 1 );
}
return( sGetStatus( stream ) );
}
/* Signature info:
byte ctb = PGP_PACKET_SIGNATURE_ONEPASS
byte[] length
byte version = 3
byte sigType
byte hashAlgo
byte sigAlgo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -