📄 sign_pgp.c
字号:
{
status = writePgpSigPacketHeader( NULL, 0, &extraDataLength,
iSignContext, iHashContext,
iAndSlength );
if( cryptStatusError( status ) )
return( status );
status = createSignature( NULL, 0, &signatureDataLength,
iSignContext, iHashContext, CRYPT_UNUSED,
SIGNATURE_PGP );
if( cryptStatusError( status ) )
return( status );
*signatureLength = 1 + pgpSizeofLength( extraDataLength + 2 + \
signatureDataLength ) + \
extraDataLength + 2 + signatureDataLength;
return( CRYPT_OK );
}
/* If there's an issuerAndSerialNumber present, allocate a larger buffer
for it if necessary (this virtually never occurs, the iAndS would need
to be over 1kB long. Note that we can't use a dynBuf for this
because we're allocating a buffer larger than the attribute, not the
same size as the attribute */
if( iAndSlength > extraDataLength - 128 )
{
extraDataLength = 128 + iAndSlength;
if( ( extraDataPtr = clDynAlloc( "createSignaturePGP", \
extraDataLength ) ) == NULL )
return( CRYPT_ERROR_MEMORY );
}
/* Complete the hashing and create the signature. In theory this could
get ugly because there could be multiple one-pass signature packets
present, however PGP handles multiple signatures by nesting them so
this isn't a problem.
PGP processes the authenticated attributes in an odd way, first
hashing part of the packet from the version number to the end of the
authenticated attributes, then hashing some more (out-of-band) stuff,
and finally signing the result of the overall hashing. Because of
this complex way of handling things we can't write the signature
packet in one go but instead have to write the part that we can
create now, hash the portion that's hashed (all but the last 16 bits,
the length of the unathenticated attributes), and then go back and
assemble the whole thing including the length and signature later on
from the pre-hashed data and the length, hash check, and signature */
status = writePgpSigPacketHeader( extraData, extraDataLength,
&extraDataLength, iSignContext,
iHashContext, iAndSlength );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
extraData, extraDataLength - UINT16_SIZE );
if( status == CRYPT_ERROR_COMPLETE )
{
/* Unlike standard signatures PGP requires that the hashing not
be wrapped up before the signature is generated because it
needs to hash in further data before it can generate the
signature. Since completing the hashing is likely to be a
common error we specifically check for this and return an
appropriate error code */
status = CRYPT_ARGERROR_NUM2;
}
}
if( cryptStatusError( status ) )
{
zeroise( extraDataPtr, extraDataLength );
if( extraDataPtr != extraData )
clFree( "createSignaturePGP", extraDataPtr );
return( status );
}
/* Hash in even more stuff at the end. This is a complex jumble of
items constituting a version number, an 0xFF, and another length.
This was motivated by a concern that something that meant one thing
in a version n sig could mean something different when interpreted as
a version n+1 sig. For this reason a hash-convention version (v4)
was added, along with a disambiguator 0xFF that will never be found
at that position in older (v3) hash-convention sigs (the 0x04 is in
fact redundant but may be needed at some point if the hash
convention moves to a v5 format). The length has something to do
with parsing the packet from the end, so that out-of-band data
doesn't run into payload data, but no-one can quite remember why
it's actually there */
sMemOpen( &stream, extraTrailer, 8 );
sputc( &stream, 0x04 );
sputc( &stream, 0xFF );
status = writeUint32( &stream, extraDataLength - UINT16_SIZE );
if( cryptStatusOK( status ) )
extraTrailerLength = stell( &stream );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
extraTrailer, extraTrailerLength );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, hash, CRYPT_MAX_HASHSIZE );
status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_CTXINFO_HASHVALUE );
}
if( cryptStatusError( status ) )
{
zeroise( extraDataPtr, extraDataLength );
if( extraDataPtr != extraData )
clFree( "createSignaturePGP", extraDataPtr );
return( status );
}
/* We've finally finished with all the hashing, create the signature */
status = createSignature( signatureData, CRYPT_MAX_PKCSIZE + 128,
&signatureDataLength, iSignContext,
iHashContext, CRYPT_UNUSED, SIGNATURE_PGP );
if( cryptStatusOK( status ) )
{
totalLength = 1 + \
pgpSizeofLength( extraDataLength + 2 + \
signatureDataLength ) + \
extraDataLength + 2 + signatureDataLength;
if( totalLength + 64 > sigMaxLength )
status = CRYPT_ERROR_OVERFLOW;
}
if( cryptStatusError( status ) )
{
zeroise( extraDataPtr, extraDataLength );
if( extraDataPtr != extraData )
clFree( "createSignaturePGP", extraDataPtr );
return( status );
}
/* Write the signature packet:
[ signature packet header ]
byte[2] hash check
mpi signature
Since we've already had to write half the packet earlier on in order
to hash it we copy this pre-encoded information across and add the
header and trailer around it */
sMemOpen( &stream, signature, totalLength + 64 );
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 */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int checkSignaturePGP( IN_BUFFER( signatureLength ) const void *signature,
IN_LENGTH_SHORT const int signatureLength,
IN_HANDLE const CRYPT_CONTEXT sigCheckContext,
IN_HANDLE const CRYPT_CONTEXT iHashContext )
{
const READSIG_FUNCTION readSigFunction = getReadSigFunction( SIGNATURE_PGP );
QUERY_INFO queryInfo;
STREAM stream;
int status;
assert( isReadPtr( signature, signatureLength ) );
REQUIRES( signatureLength > 40 && signatureLength < MAX_INTLENGTH );
REQUIRES( isHandleRangeValid( sigCheckContext ) );
REQUIRES( isHandleRangeValid( iHashContext ) );
/* Make sure that the requested signature format is available */
if( readSigFunction == NULL )
return( CRYPT_ERROR_NOTAVAIL );
/* Determine whether there are any authenticated attributes attached to
the signature */
memset( &queryInfo, 0, sizeof( QUERY_INFO ) );
sMemConnect( &stream, signature, signatureLength );
status = readSigFunction( &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, see the earlier comment in createSignaturePGP() */
REQUIRES( rangeCheck( queryInfo.attributeStart,
queryInfo.attributeLength, queryInfo.size ) );
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
( BYTE * ) signature + queryInfo.attributeStart,
queryInfo.attributeLength );
if( cryptStatusOK( status ) && queryInfo.attributeLength != 5 )
{
BYTE buffer[ 8 + 8 ];
int length = DUMMY_INIT;
/* In addition to the standard authenticated attributes OpenPGP
hashes in even more stuff at the end (see the comments for
createSignaturePGP() for more on this) */
sMemOpen( &stream, buffer, 8 );
sputc( &stream, 0x04 );
sputc( &stream, 0xFF );
status = writeUint32( &stream, queryInfo.attributeLength );
if( cryptStatusOK( status ) )
length = stell( &stream );
sMemDisconnect( &stream );
if( cryptStatusOK( status ) )
{
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH,
buffer, length );
}
}
zeroise( &queryInfo, sizeof( QUERY_INFO ) );
if( cryptStatusOK( status ) )
status = krnlSendMessage( iHashContext, IMESSAGE_CTX_HASH, "", 0 );
if( cryptStatusError( status ) )
return( status );
/* Check the signature */
return( checkSignature( signature, signatureLength, sigCheckContext,
iHashContext, CRYPT_UNUSED, SIGNATURE_PGP ) );
}
#endif /* USE_PGP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -