📄 pgpmakesig.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpMakeSig.c,v 1.12 2002/08/06 20:11:04 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"
#include <string.h>
#include "pgpDebug.h"
#include "pgpMakeSig.h"
#include "pgpContext.h"
#include "pgpHashPriv.h"
#include "pgpErrors.h"
#include "pgpKeyPriv.h"
#include "pgpMem.h"
#include "pgpPktByte.h"
#include "pgpSigSpec.h"
#include "pgpUsuals.h"
#define CRIT(flags) (((flags)&kPGPSigFlags_Critical) ? SIGSUBF_CRITICAL : 0)
/* Forward declaration */
static int
pgpMakeSigSubs (PGPSigSpec const *spec,
PGPHashContext const *hc, PGPByte **buf);
/* True if will need to be done as a V4 sig */
static int
pgpV4Sig (PGPSigSpec const *spec)
{
return pgpSigSpecVersion( spec ) >= PGPVERSION_4;
}
/* The maximum size of the signature packet not counting the sig itself */
static int
pgpMakeSigExtraSize(PGPSigSpec const *spec)
{
PGPSize extralen;
char *regExp;
if (pgpV4Sig (spec)) {
PGPByte *dummyptr;
PGPUInt32 dummyuint;
PGPBoolean dummybool;
PGPByte dummybyte;
PGPSize dummylen;
int i;
if (pgpSigSpecPrefAlgs(spec, &dummyptr, &extralen)
& kPGPSigFlags_Present) {
extralen += 2;
}
extralen += 2 + 8; /* Keyid subpacket */
extralen += 2 + 4; /* Sig creation subpacket */
if (pgpSigSpecSigExpiration(spec, &dummyuint) & kPGPSigFlags_Present)
extralen += 2 + 4;
if (pgpSigSpecExportable(spec, &dummybool) & kPGPSigFlags_Present)
extralen += 2 + 1;
if (pgpSigSpecRevocable(spec, &dummybool) & kPGPSigFlags_Present)
extralen += 2 + 1;
if (pgpSigSpecPrimaryUserID(spec, &dummybool) & kPGPSigFlags_Present)
extralen += 2 + 1;
if (pgpSigSpecTrustLevel(spec, &dummybyte, &dummybyte)
& kPGPSigFlags_Present)
extralen += 2 + 2;
if (pgpSigSpecRegExp(spec, ®Exp) & kPGPSigFlags_Present )
extralen += 2 + strlen(regExp) + 1;
if (pgpSigSpecKeyExpiration(spec, &dummyuint) & kPGPSigFlags_Present)
extralen += 2 + 4;
for (i=0;
pgpSigSpecAdditionalRecipientRequest (spec, &dummyptr,
&dummylen, i) &
kPGPSigFlags_Present;
++i)
extralen += 2 + dummylen;
for (i=0;
pgpSigSpecRevocationKey (spec, &dummyptr, &dummylen, i) &
kPGPSigFlags_Present;
++i)
extralen += 2 + dummylen;
for (i=0;
pgpSigSpecPacket (spec, &dummyptr, &dummylen, i) &
kPGPSigFlags_Present;
++i)
extralen += 5 + dummylen;
if (pgpSigSpecPrefKeyServ (spec, &dummyptr, &dummylen)
& kPGPSigFlags_Present) {
extralen += 2 + dummylen;
}
if (pgpSigSpecKeyServPrefs (spec, &dummyptr, &dummylen)
& kPGPSigFlags_Present) {
extralen += 2 + dummylen;
}
if (pgpSigSpecKeyFlags (spec, &dummyptr, &dummylen)
& kPGPSigFlags_Present) {
extralen += 2 + dummylen;
}
/* packlen includes the type byte */
/* 4 bytes before subpackets, 2*2 length fields, 2 bytes of hash */
return 10 + extralen;
} else {
/* Old format */
(void)pgpSigSpecExtra(spec, &extralen);
return 14 + extralen;
}
}
/*
* Given a buffer of at least "pgpMakeSigMaxSize" bytes, make a signature
* into it and return the size of the signature, or 0.
*
* Format of signature packets:
*
* Offset Length Meaning
* 0 1 Version byte (= 2 or 3).
* 1 1 Length of following material included in MD5 (x, = 5)
* 2 1 Signature type
* 3 4 32-bit timestamp of signature
* -------- MD5 additional material stops here, at offset 7 ----------
* 2+x 8 KeyID
* 10+x 1 PK algorithm type (1 = RSA)
* 11+x 1 MD algorithm type (1 = MD5)
* 12+x 2 First 2 bytes of message digest (16-bit checksum)
* 14+x 2+? MPI of PK-encrypted integer
*/
PGPInt32
pgpMakeSig (PGPSigSpec const *spec, PGPHashContext const *hc, PGPByte **buf)
{
PGPContextRef context;
PGPKeyDBObjRef seckey;
PGPHashContext *temp_hc;
PGPHashVTBL const *h;
PGPSize extralen;
PGPByte const *extra;
PGPByte const *hash;
PGPByte *sigbuf;
PGPByte *pktbuf;
void *vbuf;
PGPSize pktbuflen;
int i;
PGPSize sigsize;
PGPInt32 pkalg;
PGPKeyID keyid;
PGPByte const *keyidbytes;
PGPSize dummy;
PGPByte const *passphrase;
PGPSize passphraseLength;
PGPBoolean hashedPhrase;
/* Use subpacket sig formats if requesting preferred algs */
if (pgpV4Sig (spec)) {
return pgpMakeSigSubs (spec, hc, buf);
}
/* Get buffer to fill with our data */
context = pgpSigSpecContext(spec);
pktbuflen = pgpMakeSigExtraSize( spec );
pktbuf = pgpContextMemAlloc( context, pktbuflen, 0 );
if( IsNull( pktbuf ) )
return kPGPError_OutOfMemory;
/* Get some basic facts about signing key */
seckey = pgpSigSpecSeckey(spec);
pgpGetKeyNumber( seckey, kPGPKeyProperty_AlgorithmID, &pkalg );
pgpGetKeyPropertyBuffer( seckey, kPGPKeyProperty_KeyID, sizeof(keyid),
&keyid, &dummy );
keyidbytes = pgpGetKeyIDBytes( &keyid );
temp_hc = pgpHashCopy (hc);
if (!temp_hc)
return kPGPError_OutOfMemory;
extra = pgpSigSpecExtra(spec, &extralen);
pgpAssert(extralen < 256);
PGPContinueHash (temp_hc, extra, extralen);
hash = (PGPByte *) pgpHashFinal(temp_hc);
/* Copy the first 2 bytes over while they're available */
pgpCopyMemory (hash, pktbuf+12+extralen, 2);
passphrase = pgpSigSpecPassphrase( spec, &passphraseLength, &hashedPhrase);
h = pgpHashGetVTBL( hc );
i = pgpKeySign( seckey, passphrase, passphraseLength, hashedPhrase,
0, FALSE, h->algorithm, hash, h->hashsize,
kPGPPublicKeyMessageFormat_PGP, &sigbuf, &sigsize );
PGPFreeHashContext(temp_hc);
if (i < 0) {
pktbuf[12+extralen] = 0;
pktbuf[13+extralen] = 0;
pgpContextMemFree( context, pktbuf );
return i;
}
/* Resize pktbuf and put sigbuf into it */
vbuf = pktbuf;
if( IsPGPError( pgpContextMemRealloc( context, &vbuf, pktbuflen+sigsize,
0 ) ) )
{
pgpContextMemFree( context, pktbuf );
pgpContextMemFree( context, sigbuf );
return kPGPError_OutOfMemory;
}
pktbuf = vbuf;
pgpCopyMemory( sigbuf, pktbuf+14+extralen, sigsize );
pgpContextMemFree( context, sigbuf );
/* Okay, build the signature packet - lots of magic numbers. */
pktbuf[0] = (PGPByte)PGPVERSION_3; /* Force version 3 as format */
pktbuf[1] = extralen;
pgpCopyMemory(extra, pktbuf+2, extralen);
pgpCopyMemory(keyidbytes, pktbuf+2+extralen, 8);
pktbuf[10+extralen] = (PGPByte) pkalg;
pktbuf[11+extralen] = pgpHashGetVTBL( hc )->algorithm;
/* First 2 bytes of hash are already copied in */
*buf = pktbuf;
return (int)sigsize+14+(int)extralen;
}
/*
* Subpacket Sig layout:
*
* Offset,Length Meaning
* 0 1 Version byte (=4)
* 1 1 Signature type (included in hash) (nested flag)
* 2 1 PK algorithm (1 = RSA) (included in hash)
* 3 1 Hash algorithm (1 = MD5) (included in hash)
* 4 2 Length of extra material included in hash (=y)
* 6 y Subpackets (hashed)
* 6+y 2 Length of extra material not included in hash (=z)
* 8+y z Subpackets (unhashed)
*=====
*remainder not present on sig headers
*=====
* 8+y+z 2 First 2 bytes of message digest (16-bit checksum)
* 10+y+z 2+w MPI of PK-signed integer
* 12+y+z+w
*
* Remember, if adding new subpackets here, that they must go in increasing
* order of type value within each hashed/unhashed block.
*/
static PGPInt32
pgpMakeSigSubs( PGPSigSpec const *spec, PGPHashContext const *hc,
PGPByte **buf )
{
PGPContextRef context;
PGPKeyDBObjRef seckey;
PGPHashContext *temp_hc;
PGPHashVTBL const *h;
PGPSize extralen;
unsigned l, l_init;
PGPUInt32 flags;
PGPSize pktdatalen;
PGPSize adkeylen;
PGPByte const *extra;
PGPByte const *hash;
PGPByte *pktdata;
PGPByte *adkey;
PGPByte *pktbuf;
void *vbuf;
PGPSize pktbuflen;
PGPByte *sigbuf;
PGPByte trustLevel, trustValue;
PGPBoolean bool1;
PGPUInt32 dat;
PGPByte *pack;
PGPSize packlen;
char *regExp;
int i;
PGPSize sigsize;
PGPByte postscript[6];
PGPBoolean hashedpart;
PGPInt32 pkalg;
PGPKeyID keyid;
PGPByte const *keyidbytes;
PGPSize dummy;
PGPByte const *passphrase;
PGPSize passphraseLength;
PGPBoolean hashedPhrase;
/* Get buffer to fill with our data */
context = pgpSigSpecContext(spec);
pktbuflen = pgpMakeSigExtraSize( spec );
pktbuf = pgpContextMemAlloc( context, pktbuflen, 0 );
if( IsNull( pktbuf ) )
return kPGPError_OutOfMemory;
/* Get some basic facts about signing key */
seckey = pgpSigSpecSeckey(spec);
pgpGetKeyNumber( seckey, kPGPKeyProperty_AlgorithmID, &pkalg );
pgpGetKeyPropertyBuffer( seckey, kPGPKeyProperty_KeyID, sizeof(keyid),
&keyid, &dummy );
keyidbytes = pgpGetKeyIDBytes( &keyid );
temp_hc = pgpHashCopy (hc);
if (!temp_hc)
return kPGPError_OutOfMemory;
extra = pgpSigSpecExtra(spec, &extralen);
pgpAssert(extralen == 5);
/* Okay, build the signature packet - lots of magic numbers. */
pktbuf[0] = (PGPByte)PGPVERSION_4;
pktbuf[1] = extra[0]; /* Signature type */
pktbuf[2] = (PGPByte) pkalg;
pktbuf[3] = pgpHashGetVTBL( hc )->algorithm;
/* Fill in extralen after we figure out how much we need */
l = 4;
hashedpart = TRUE;
/* Loop twice, hashedpart then !hashedpart */
do {
/* Remember where length will go, skip past it for now */
l_init = l;
l += 2;
/* Signature creation, always present in hashed portion */
if (hashedpart) {
pktbuf[l+1] = SIGSUB_CREATION;
pktbuf[l] = 4 + 1; /* length */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -