📄 sign_rw.c
字号:
/* Write the header */
writeSequence( stream, ( int ) sizeofShortInteger( SIGNATURE_EX_VERSION ) + \
sizeofObject( msgData.length ) + \
signAlgoIdSize + hashAlgoIdSize + \
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 );
return( writeOctetString( stream, signature, signatureLength, DEFAULT_TAG ) );
}
/****************************************************************************
* *
* PGP Signature Routines *
* *
****************************************************************************/
#ifdef USE_PGP
/* Read a PGP type-and-value packet and check whether it's one of ours */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readTypeAndValue( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo,
IN_LENGTH_Z const int startPos )
{
BYTE nameBuffer[ 32 + 8 ];
static const char FAR_BSS *nameString = "issuerAndSerialNumber";
int nameLength, valueLength, status; /* length = 21 */
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
REQUIRES( startPos < stell( stream ) );
/* Skip the flags */
status = sSkip( stream, UINT32_SIZE );
if( cryptStatusError( status ) )
return( status );
/* Read the attribute length information and make sure that it looks
valid */
nameLength = readUint16( stream );
valueLength = readUint16( stream );
if( cryptStatusError( valueLength ) )
return( valueLength );
if( nameLength != 21 || valueLength < 16 || valueLength > 2048 )
return( sSkip( stream, nameLength + valueLength ) );
/* Read the name and check whether it's one that we recognise */
status = sread( stream, nameBuffer, nameLength );
if( cryptStatusError( status ) )
return( status );
if( !memcmp( nameBuffer, nameString, nameLength ) )
{
/* It's an issuerAndSerialNumber, remember it for later */
queryInfo->iAndSStart = stell( stream ) - startPos;
queryInfo->iAndSLength = valueLength;
}
return( sSkip( stream, valueLength ) );
}
/* Read signature subpackets. In theory we could do something with the
isAuthenticated flag but at the moment we don't rely on any attributes
that require authentication. The most that an attacker can do by
changing the keyID/iAndS field is cause the signature check to fail,
which they can do just as easily by flipping a bit */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readSignatureSubpackets( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo,
IN_LENGTH_SHORT const int length,
IN_LENGTH const int startPos,
const BOOLEAN isAuthenticated )
{
const int endPos = stell( stream ) + length;
int iterationCount = 0;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES( length > 0 && length < MAX_INTLENGTH_SHORT );
REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
REQUIRES( startPos < stell( stream ) );
while( stell( stream ) < endPos && \
iterationCount++ < FAILSAFE_ITERATIONS_MED )
{
int subpacketLength, type = DUMMY_INIT, status;
/* Read the subpacket length and type */
status = pgpReadShortLength( stream, &subpacketLength,
PGP_CTB_OPENPGP );
if( cryptStatusOK( status ) )
status = type = sgetc( stream );
if( cryptStatusError( status ) )
return( status );
/* 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 );
switch( type )
{
case PGP_SUBPACKET_KEYID:
/* Make sure that the length is valid */
if( subpacketLength != PGP_KEYID_SIZE + 1 )
return( CRYPT_ERROR_BADDATA );
/* 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( queryInfo->keyIDlength <= 0 )
{
status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
queryInfo->keyIDlength = PGP_KEYID_SIZE;
}
else
{
/* We've already got the ID, skip it and continue. The
-1 is for the packet type, which we've already read */
status = sSkip( stream, subpacketLength - 1 );
}
break;
case PGP_SUBPACKET_TYPEANDVALUE:
/* It's a type-and-value packet, check whether it's one of
ours */
status = readTypeAndValue( stream, queryInfo, startPos );
break;
default:
/* It's something else, skip it and continue. The -1 is for
the packet type, which we've already read */
status = sSkip( stream, subpacketLength - 1 );
}
if( cryptStatusError( status ) )
return( status );
}
ENSURES( iterationCount < FAILSAFE_ITERATIONS_MED );
return( CRYPT_OK );
}
/* Signature info:
byte ctb = PGP_PACKET_SIGNATURE_ONEPASS
byte[] length
byte version = 3 (= OpenPGP, not the expected PGP3)
byte sigType
byte hashAlgo
byte sigAlgo
byte[8] keyID
byte 1 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readPgpOnepassSigPacket( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
/* Make sure that the packet header is in order and check the packet
version. This is an OpenPGP-only packet */
status = getPgpPacketInfo( stream, queryInfo );
if( cryptStatusError( status ) )
return( status );
if( sgetc( stream ) != 3 )
return( CRYPT_ERROR_BADDATA );
queryInfo->version = PGP_VERSION_OPENPGP;
/* Skip the sig.type and get the hash algorithm and signature
algorithms */
status = sgetc( stream ); /* Skip signature type */
if( cryptStatusOK( status ) )
status = readPgpAlgo( stream, &queryInfo->hashAlgo,
PGP_ALGOCLASS_HASH );
if( cryptStatusOK( status ) )
status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
PGP_ALGOCLASS_SIGN );
if( cryptStatusError( status ) )
return( status );
queryInfo->type = CRYPT_OBJECT_SIGNATURE;
/* Get the PGP key ID and make sure that this isn't a nested signature */
status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
if( cryptStatusError( status ) )
return( status );
queryInfo->keyIDlength = PGP_KEYID_SIZE;
return( ( sgetc( stream ) != 1 ) ? CRYPT_ERROR_BADDATA : CRYPT_OK );
}
/* Read/write PGP signatures.
byte ctb = PGP_PACKET_SIGNATURE
byte[] length
v3: byte version = PGP_2,3 v4: byte version = PGP_VERSION_OPENPGP
byte infoLen = 5 byte sigType
byte sigType byte sigAlgo
byte[4] sig.time byte hashAlgo
byte[8] keyID uint16 length of auth.attributes
byte sigAlgo byte[] authenticated attributes
byte hashAlgo uint16 length of unauth.attributes
byte[2] hash check byte[] unauthenticated attributes
mpi(s) signature -- Contains keyID
byte[2] hash check
mpi(s) signature */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readPgp2SigInfo( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo,
IN_LENGTH_Z const int startPos )
{
int status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
REQUIRES( startPos < stell( stream ) );
/* Read PGP 2.x additional signature information */
if( sgetc( stream ) != 5 )
return( CRYPT_ERROR_BADDATA );
queryInfo->attributeStart = stell( stream ) - startPos;
queryInfo->attributeLength = 5;
status = sSkip( stream, 5 );
if( cryptStatusError( status ) )
return( status );
/* Read the signer keyID and signature and hash algorithms */
status = sread( stream, queryInfo->keyID, PGP_KEYID_SIZE );
if( cryptStatusError( status ) )
return( status );
queryInfo->keyIDlength = PGP_KEYID_SIZE;
status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
PGP_ALGOCLASS_SIGN );
if( cryptStatusOK( status ) )
status = readPgpAlgo( stream, &queryInfo->hashAlgo,
PGP_ALGOCLASS_HASH );
return( status );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readOpenPgpSigInfo( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo,
IN_LENGTH_Z const int startPos )
{
int length, status;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isWritePtr( queryInfo, sizeof( QUERY_INFO ) ) );
REQUIRES( startPos >= 0 && startPos < MAX_INTLENGTH );
REQUIRES( startPos < stell( stream ) );
/* Remember the extra data to be hashed and read the signature and hash
algorithms. Since the extra data starts at the version byte that
we've already read, we add a -1 offset to the start position, as well
as including it in the overall length calculation */
queryInfo->attributeStart = ( stell( stream ) - 1 ) - startPos;
queryInfo->attributeLength = PGP_VERSION_SIZE + 1 + \
PGP_ALGOID_SIZE + PGP_ALGOID_SIZE;
status = sgetc( stream ); /* Skip signature type */
if( cryptStatusOK( status ) )
status = readPgpAlgo( stream, &queryInfo->cryptAlgo,
PGP_ALGOCLASS_SIGN );
if( cryptStatusOK( status ) )
status = readPgpAlgo( stream, &queryInfo->hashAlgo,
PGP_ALGOCLASS_HASH );
if( cryptStatusError( status ) )
return( status );
/* Process the authenticated attributes */
length = readUint16( stream );
if( cryptStatusError( length ) )
return( length );
if( length < 0 || length > 2048 )
return( CRYPT_ERROR_BADDATA );
queryInfo->attributeLength += UINT16_SIZE + length;
if( length > 0 )
{
status = readSignatureSubpackets( stream, queryInfo, length,
startPos, TRUE );
if( cryptStatusError( status ) )
return( status );
}
/* Process the unauthenticated attributes */
queryInfo->unauthAttributeStart = stell( stream ) - startPos;
length = readUint16( stream );
if( cryptStatusError( length ) )
return( length );
if( length < 0 || length > 2048 )
return( CRYPT_ERROR_BADDATA );
queryInfo->unauthAttributeLength = UINT16_SIZE + length;
if( length > 0 )
{
status = readSignatureSubpackets( stream, queryInfo, length,
startPos, FALSE );
if( cryptStatusError( status ) )
return( status );
}
return( CRYPT_OK );
}
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
static int readPgpSignature( INOUT STREAM *stream,
INOUT QUERY_INFO *queryInfo )
{
const int startPos = stell( stream );
int value, status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -