📄 sign_pgp.c
字号:
/****************************************************************************
* *
* PGP Signature Routines *
* Copyright Peter Gutmann 1993-2007 *
* *
****************************************************************************/
#if defined( INC_ALL )
#include "crypt.h"
#include "mech.h"
#include "pgp_rw.h"
#else
#include "crypt.h"
#include "mechs/mech.h"
#include "misc/pgp_rw.h"
#endif /* Compiler-specific includes */
#ifdef USE_PGP
/****************************************************************************
* *
* Utility Routines *
* *
****************************************************************************/
/* Write a PGP signature packet header:
-- Start of hashed data --
byte version = 4
byte sigType
byte sigAlgo
byte hashAlgo
uint16 length of auth.attributes
byte[] authenticated attributes
-- End of hashed data --
uint16 length of unauth.attributes = 0
[ byte[2] hash check ]
[ mpi(s) signature ]
See the comment in createSignaturePGP() for the use of this function */
CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
static int writePgpSigPacketHeader( OUT_BUFFER_OPT( dataMaxLen, *dataLen ) \
void *data,
IN_LENGTH_SHORT_Z const int dataMaxLen,
OUT_LENGTH_SHORT_Z int *dataLen,
IN_HANDLE const CRYPT_CONTEXT iSignContext,
IN_HANDLE const CRYPT_CONTEXT iHashContext,
IN_LENGTH_SHORT_Z const int iAndSlength )
{
CRYPT_ALGO_TYPE cryptAlgo;
STREAM stream;
MESSAGE_DATA msgData;
BYTE keyID[ PGP_KEYID_SIZE + 8 ];
BYTE iAndSHeader[ 64 + 8 ];
const time_t currentTime = getApproxTime();
int pgpHashAlgo, pgpSignAlgo, iAndSHeaderLength = 0, length, status;
assert( ( data == NULL && dataMaxLen == 0 ) || \
isWritePtr( data, dataMaxLen ) );
assert( isWritePtr( dataLen, sizeof( int ) ) );
REQUIRES( ( data == NULL && dataMaxLen == 0 ) || \
( data != NULL && \
dataMaxLen > MIN_CRYPT_OBJECTSIZE && \
dataMaxLen < MAX_INTLENGTH_SHORT ) );
REQUIRES( isHandleRangeValid( iSignContext ) );
REQUIRES( isHandleRangeValid( iHashContext ) );
REQUIRES( iAndSlength >= 0 && iAndSlength < MAX_INTLENGTH_SHORT );
/* Clear return value */
*dataLen = 0;
/* Get the signature information */
status = krnlSendMessage( iHashContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM2 : status );
if( cryptStatusError( cryptlibToPgpAlgo( cryptAlgo, &pgpHashAlgo ) ) )
return( CRYPT_ARGERROR_NUM2 );
status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE,
&cryptAlgo, CRYPT_CTXINFO_ALGO );
if( cryptStatusOK( status ) )
{
setMessageData( &msgData, keyID, PGP_KEYID_SIZE );
status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S,
&msgData, CRYPT_IATTRIBUTE_KEYID_OPENPGP );
}
if( cryptStatusError( status ) )
return( cryptArgError( status ) ? CRYPT_ARGERROR_NUM1 : status );
if( cryptStatusError( cryptlibToPgpAlgo( cryptAlgo, &pgpSignAlgo ) ) )
return( CRYPT_ARGERROR_NUM1 );
/* Write the issuerAndSerialNumber packet header if necessary. Since
this is a variable-length packet we need to pre-encode it before we
can write the main packet data:
byte[] length
byte subpacketType
uint32 flags = 0
uint16 typeLength
uint16 valueLength
byte[] type
byte[] value */
if( iAndSlength > 0 )
{
STREAM headerStream;
sMemOpen( &headerStream, iAndSHeader, 64 );
pgpWriteLength( &headerStream, \
1 + UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + \
21 + iAndSlength );
sputc( &headerStream, PGP_SUBPACKET_TYPEANDVALUE );
writeUint32( &headerStream, 0 );
writeUint16( &headerStream, 21 );
writeUint16( &headerStream, iAndSlength );
status = swrite( &headerStream, "issuerAndSerialNumber", 21 );
if( cryptStatusOK( status ) )
iAndSHeaderLength = stell( &headerStream );
sMemDisconnect( &headerStream );
ENSURES( cryptStatusOK( status ) );
}
/* Write the general header information */
sMemOpenOpt( &stream, data, dataMaxLen );
sputc( &stream, PGP_VERSION_OPENPGP );
sputc( &stream, PGP_SIG_DATA );
sputc( &stream, pgpSignAlgo );
status = sputc( &stream, pgpHashAlgo );
if( cryptStatusError( status ) )
{
sMemClose( &stream );
return( status );
}
/* Write the authenticated attributes:
uint16 authAttrLength
byte subpacketLength = 1 + UINT32_SIZE
byte ID = PGP_SUBPACKET_TIME
uint32 time
byte subpacketLength = 1 + PGP_KEYID_SIZE
byte ID = PGP_SUBPACKET_KEYID
byte[8] signerID
[ byte[] typeAndValue packet for iAndS ]
The signer ID is optional, but if we omit it GPG fails the signature
check so we always include it */
length = ( 1 + 1 + UINT32_SIZE ) + ( 1 + 1 + PGP_KEYID_SIZE );
if( iAndSlength > 0 )
length += iAndSHeaderLength + iAndSlength;
writeUint16( &stream, length );
sputc( &stream, 1 + UINT32_SIZE ); /* Time */
sputc( &stream, PGP_SUBPACKET_TIME );
writeUint32Time( &stream, currentTime );
sputc( &stream, 1 + PGP_KEYID_SIZE ); /* Signer ID */
sputc( &stream, PGP_SUBPACKET_KEYID );
status = swrite( &stream, keyID, PGP_KEYID_SIZE );
if( cryptStatusOK( status ) && iAndSlength > 0 )
{ /* TypeAndValue */
status = swrite( &stream, iAndSHeader, iAndSHeaderLength );
if( cryptStatusOK( status ) )
{
status = exportAttributeToStream( &stream, iSignContext,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
}
}
if( cryptStatusError( status ) )
{
sMemClose( &stream );
return( status );
}
/* Write the unauthenticated attributes:
uint16 unauthAttrLength = 0 */
status = writeUint16( &stream, 0 );
if( cryptStatusOK( status ) )
*dataLen = stell( &stream );
sMemDisconnect( &stream );
return( status );
}
/****************************************************************************
* *
* Create/Check a PGP Signature *
* *
****************************************************************************/
/* Create a PGP signature */
CHECK_RETVAL STDC_NONNULL_ARG( ( 3 ) ) \
int createSignaturePGP( OUT_BUFFER_OPT( sigMaxLength, *signatureLength ) \
void *signature,
IN_LENGTH_Z const int sigMaxLength,
OUT_LENGTH_Z int *signatureLength,
IN_HANDLE const CRYPT_CONTEXT iSignContext,
IN_HANDLE const CRYPT_CONTEXT iHashContext )
{
MESSAGE_DATA msgData;
STREAM stream;
BYTE hash[ CRYPT_MAX_HASHSIZE + 8 ];
BYTE signatureData[ CRYPT_MAX_PKCSIZE + 128 + 8 ];
BYTE extraData[ 1024 + 8 ], *extraDataPtr = extraData;
BYTE extraTrailer[ 8 + 8 ];
int extraDataLength = 1024, extraTrailerLength = DUMMY_INIT;
int signatureDataLength, iAndSlength = 0, totalLength = DUMMY_INIT;
int status;
assert( ( signature == NULL && sigMaxLength == 0 ) || \
isWritePtr( signature, sigMaxLength ) );
assert( isWritePtr( signatureLength, sizeof( int ) ) );
REQUIRES( ( signature == NULL && sigMaxLength == 0 ) || \
( signature != NULL && \
sigMaxLength > MIN_CRYPT_OBJECTSIZE && \
sigMaxLength < MAX_INTLENGTH ) );
REQUIRES( isHandleRangeValid( iSignContext ) );
REQUIRES( isHandleRangeValid( iHashContext ) );
/* Check whether there's an issuerAndSerialNumber present */
setMessageData( &msgData, NULL, 0 );
status = krnlSendMessage( iSignContext, IMESSAGE_GETATTRIBUTE_S, &msgData,
CRYPT_IATTRIBUTE_ISSUERANDSERIALNUMBER );
if( cryptStatusOK( status ) )
iAndSlength = msgData.length;
/* If it's a length check only, determine how large the signature data
will be and exit */
if( signature == NULL )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -