📄 pgpsig.c
字号:
/*
* $Id: pgpSig.c,v 1.23 1998/08/20 17:32:19 hal Exp $
*/
#include "pgpConfig.h"
#include <string.h>
#include "pgpDebug.h"
#include "pgpMem.h"
#include "pgpPktList.h"
#include "pgpSig.h"
#include "pgpAnnotate.h"
#include "pgpHashPriv.h"
#include "pgpErrors.h"
#include "pgpPubKey.h"
#include "pgpUsuals.h"
#include "pgpKeyIDPriv.h"
#include "pgpRngPars.h"
#define SIGBUF_1PASS(b,l) (((l) == 13) && ((b)[0] == PGPVERSION_3))
#define SIGPKT_1PASS(p) SIGBUF_1PASS((p)->pkt.buf,(p)->pkt.len)
struct PGPSig
{
PktList pkt;
} ;
/*
* Format of one-pass signature packets:
*
* Offset Length Meaning
* 0 1 Version byte (=3)
* 1 1 Signature type
* 2 1 Hash Algorithm
* 3 1 PK Algorithm
* 4 8 KeyID
* 12 1 nested flag
*
*
* Format of regular signature packets:
*
* Offset Length Meaning
* 0 1 Version byte (= 2 or 3).
* 1 1 x, Length of following material included in MD5 (=5)
* 2 1 Signature type (=0 or 1)
* 3 4 32-bit timestamp of signature
* -------- MD5 additional material stops here, at offset 2+x ---------
* 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+y MPI of PK-encrypted integer
* 16+x+y
*/
static int
sigValidate(PGPByte const *sig, size_t len, PGPByte *pkalg)
{
unsigned extra, bits;
PGPByte alg;
PGPHashVTBL const *hash;
if (pkalg)
*pkalg = 0;
if (len < 1)
return kPGPError_BadSignatureSize;
if (SIGBUF_1PASS(sig, len)) {
/* One-pass signature packet */
if (len < 13)
return kPGPError_BadSignatureSize;
if (len > 13)
return kPGPError_BadSignatureSize;
alg = sig[3];
if (pkalg)
*pkalg = alg;
hash = pgpHashByNumber( (PGPHashAlgorithm) sig[2]);
if (!hash)
return kPGPError_BadHashNumber;
return 0;
} else if (sig[0] == PGPVERSION_4) {
/* New-format key signature packet - validated in pgpRngPars.c */
return 0;
}
if (sig[0] != PGPVERSION_2 && sig[0] != PGPVERSION_3)
return kPGPError_UnknownVersion;
if (len < 2)
return kPGPError_BadSignatureSize;
extra = sig[1];
if (len < 11+extra)
return kPGPError_BadSignatureSize;
alg = sig[10+extra];
if (pkalg)
*pkalg = alg;
#if 0
/*
* Don't abort on bad hash as it may be for an alg we don't support yet.
* Aborting here interferes with importing keys which have sigs with bad
* hashes. Even though we can't check those sigs, we should still import
* the key.
*/
hash = pgpHashByNumber( (PGPHashAlgorithm) ( sig[11+extra] ) );
if (!hash)
return kPGPError_BadHashNumber;
#endif
/* This part here gets RSA-specific */
if (len < 16+extra)
return kPGPError_BadSignatureSize;
if (alg==kPGPPublicKeyAlgorithm_RSA) {
bits = ((unsigned)sig[14+extra]<<8) + sig[15+extra];
if (len != 16+extra+(bits+7)/8)
return len < 16+extra+(bits+7)/8 ? kPGPError_BadSignatureSize
: kPGPError_BadSignatureSize;
if (bits && sig[16+extra] >> ((bits-1) & 7) != 1)
return kPGPError_SignatureBitsWrong;
}
return 0;
}
static PGPSig **
sigListTail(PGPSig **head)
{
while (*head)
head = (PGPSig **)&(*head)->pkt.next;
return head;
}
int
pgpSigSigType (PGPByte const *buf, size_t len)
{
int i;
i = sigValidate(buf, len, NULL);
if (i < 0)
return i;
if (SIGBUF_1PASS(buf, len)) {
return buf[1];
} else if (buf[0] == PGPVERSION_4) {
return buf[1];
}
if (buf[1] < 1)
return kPGPError_ExtraDateOnSignature;
return buf[2] & 255;
}
int
pgpSigAdd (
PGPContextRef cdkContext,
PGPSig **siglist, int type, PGPByte const *buf, size_t len)
{
PGPSig *sig;
PGPSig **psig2;
PGPByte pkalg, sigtype, hashalg, keyid[8];
PGPByte *b2;
int err;
switch (type) {
case PGPANN_SIGNED_SIG:
err = sigValidate (buf, len, &pkalg);
if (err)
return err;
sig = (PGPSig *)pgpPktListNew( cdkContext, pkalg, buf, len);
if (!sig)
return kPGPError_OutOfMemory;
*sigListTail(siglist) = sig;
return 0;
case PGPANN_SIGNED_SIG2:
/* Second packet, should be merged with an existing one */
if (SIGBUF_1PASS(buf, len))
return kPGPError_UnknownSignatureType;
if (buf[1] != 5) /* extra bytes must be standard */
return kPGPError_UnknownSignatureType;
err = sigValidate (buf, len, &pkalg);
if (err)
return err;
/* Search for matching 1-pass signature on the list */
if (buf[0] == PGPVERSION_3) {
for (psig2=siglist; *psig2;
psig2 = (PGPSig **)&(*psig2)->pkt.next) {
if (!SIGPKT_1PASS(*psig2))
continue;
b2 = (*psig2)->pkt.buf;
if (b2[1] != buf[2]) /* sig type */
continue;
if (b2[2] != buf[11+buf[1]]) /* hash alg */
continue;
if (b2[3] != buf[10+buf[1]])/* pkalg */
continue;
if (memcmp(b2+4, buf+2+buf[1], 8)) /* key id */
continue;
/* Here we have a match */
break;
}
} else {
/* V4 signatures */
pgpAssert (buf[0] == PGPVERSION_4);
err = ringSigParse(buf, len, &pkalg, keyid, NULL, NULL,
&sigtype, &hashalg, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
if (IsPGPError( err ) )
return err;
for (psig2=siglist; *psig2;
psig2 = (PGPSig **)&(*psig2)->pkt.next) {
if (!SIGPKT_1PASS(*psig2))
continue;
b2 = (*psig2)->pkt.buf;
if (b2[1] != sigtype) /* sig type */
continue;
if (b2[2] != hashalg) /* hash alg */
continue;
if (b2[3] != pkalg) /* pkalg */
continue;
if (memcmp(b2+4, keyid, 8)) /* key id */
continue;
/* Here we have a match */
break;
}
}
/* Error if found no match */
if (!*psig2)
return kPGPError_UnknownSignatureType;
/* Replace *psig2 with new sig */
sig = (PGPSig *)pgpPktListNew( cdkContext, pkalg, buf, len);
if (!sig)
return kPGPError_OutOfMemory;
sig->pkt.next = (*psig2)->pkt.next;
pgpPktListFreeOne((PktList *)*psig2);
*psig2 = sig;
return 0;
}
return kPGPError_UnknownSignatureType;
}
/* Return true if this signature is followed immediately by signed data */
int
pgpSigNestFlag(PGPByte const *buf, size_t len)
{
(void)len;
if (SIGBUF_1PASS(buf, len))
return buf[12]; /* nest flag */
else
return 1; /* always true for old packets */
}
/* How here come some access functions */
PGPByte
pgpSigPKAlg(PGPSig const *sig)
{
pgpAssert(sig);
if (SIGPKT_1PASS(sig))
return sig->pkt.buf[3];
else if (sig->pkt.buf[0] == PGPVERSION_4)
return sig->pkt.buf[2];
else
return sig->pkt.buf[10+sig->pkt.buf[1]];
}
PGPHashVTBL const *
pgpSigHash(PGPSig const *sig)
{
int alg;
pgpAssert(sig);
if (SIGPKT_1PASS(sig))
alg = sig->pkt.buf[2];
else if (sig->pkt.buf[0] == PGPVERSION_4)
alg = sig->pkt.buf[3];
else
alg = sig->pkt.buf[11+sig->pkt.buf[1]];
return pgpHashByNumber( (PGPHashAlgorithm) alg);
}
PGPByte
pgpSigType(PGPSig const *sig)
{
pgpAssert(sig);
return (PGPByte)pgpSigSigType (sig->pkt.buf, sig->pkt.len);
}
PGPByte
pgpSigVersion(PGPSig const *sig)
{
pgpAssert(sig);
return sig->pkt.buf[0];
}
PGPByte const *
pgpSigExtra(PGPSig const *sig, unsigned *len)
{
pgpAssert(sig);
if (SIGPKT_1PASS(sig)) {
*len = 0;
return 0;
} else if (sig->pkt.buf[0] == PGPVERSION_4) {
*len = ((sig->pkt.buf[4] << 8) | sig->pkt.buf[5]) + 6;
return sig->pkt.buf;
} else {
*len = sig->pkt.buf[1];
return sig->pkt.buf+2;
}
}
PGPUInt32
pgpSigTimestamp (PGPSig const *sig)
{
PGPByte const *extra;
unsigned extralen;
pgpAssert (sig);
if (SIGPKT_1PASS(sig))
return 0;
if (sig->pkt.buf[0] == PGPVERSION_4) {
PGPUInt32 tstamp;
PGPError err = ringSigParse(sig->pkt.buf, sig->pkt.len, NULL, NULL,
&tstamp, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (IsPGPError( err ) )
return 0;
return tstamp;
}
extra = pgpSigExtra (sig, &extralen);
if (!extra || extralen < 5)
return 0;
return ((PGPUInt32)extra[1]<<24) + ((PGPUInt32)extra[2]<<16) +
((PGPUInt32)extra[3]<<8) + (PGPUInt32)extra[4];
}
PGPError
pgpGetSigKeyID(
PGPSig const * sig,
PGPKeyID * outID )
{
PGPError err = kPGPError_NoErr;
PGPByte keyidbuf[8];
PGPByte const *rawkeyid;
if (SIGPKT_1PASS(sig)) {
rawkeyid = sig->pkt.buf+4;
} else if (sig->pkt.buf[0] == PGPVERSION_4) {
err = ringSigParse(sig->pkt.buf, sig->pkt.len, NULL, keyidbuf,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if (IsPGPError( err ) )
return err;
rawkeyid = keyidbuf;
} else {
rawkeyid = sig->pkt.buf+2+sig->pkt.buf[1];
}
pgpNewKeyIDFromRawData( rawkeyid, 8, outID );
return( err );
}
/* Return a count of the number of distinct hash algorithms in the list */
unsigned
pgpSigDistinctHashCount(PGPSig const *sig)
{
PktList const *next;
unsigned total;
int alg, nextalg;
for (total = 0; sig; sig = (PGPSig const *)sig->pkt.next) {
total++;
/*
* If another one later on the list has the same alg,
* don't count this one.
*/
if (SIGPKT_1PASS(sig))
alg = sig->pkt.buf[2];
else if (sig->pkt.buf[0] == PGPVERSION_4)
alg = sig->pkt.buf[3];
else
alg = sig->pkt.buf[11+sig->pkt.buf[1]];
for (next = sig->pkt.next; next; next = next->next) {
if (SIGBUF_1PASS(next->buf, next->len))
nextalg = next->buf[2];
else if (next->buf[0] == PGPVERSION_4)
nextalg = next->buf[3];
else
nextalg = next->buf[11+next->buf[1]];
if (nextalg == alg) {
total--;
break;
}
}
}
return total;
}
/*
* Return a buffer full of byte hash identifiers. The buffer must be
* of legnth sigDistincthashCount(len) length, and that number is
* returned for convenience.
*/
unsigned
pgpSigDistinctHashes(PGPSig const *sig, PGPByte *buf)
{
unsigned len;
int alg;
for (len = 0; sig; sig = (PGPSig const *)sig->pkt.next) {
if (SIGPKT_1PASS(sig))
alg = sig->pkt.buf[2];
else if (sig->pkt.buf[0] == PGPVERSION_4)
alg = sig->pkt.buf[3];
else
alg = sig->pkt.buf[11+sig->pkt.buf[1]];
if (!memchr(buf, alg, len))
buf[len++] = (PGPByte)alg;
}
return len;
}
/*
* The internal checking function, not for public use.
*/
int
pgpSigCheckBuf(PGPByte const *sig, PGPSize len, PGPPubKey const *pub,
void const *hash)
{
unsigned extra;
PGPByte type;
PGPHashVTBL const *h;
if (sig[0] == PGPVERSION_4) {
/* New signature format; see pgpMakeSig.c */
extra = (unsigned)sig[4]<<8 | sig[5];
extra += (unsigned)sig[extra+6]<<8 | sig[extra+7];
/* Quick rejection test: check the given two bytes first */
if (memcmp (hash, sig+8+extra, 2) != 0)
return 0;
h = pgpHashByNumber ( (PGPHashAlgorithm) sig[3]);
type = sig[1];
/* Skip to signature data */
extra += 10;
} else {
extra = sig[1];
/* Quick rejection test: check the given two bytes first */
if (memcmp (hash, sig+12+extra, 2) != 0)
return 0;
h = pgpHashByNumber ( (PGPHashAlgorithm) ( sig[11+extra] ));
type = sig[2];
/* Skip to signature data */
extra += 14;
}
/* XXX Should "die" gracefully here */
pgpAssert (pub->verify);
return pgpPubKeyVerify (pub, sig+extra, len-extra, h, (PGPByte *) hash,
kPGPPublicKeyMessageFormat_PGP);
}
/*
* Check a signature against a given public key and hash.
* Returns 0 if it did not check, and 1 if it did.
* Returns <0 on some sort of error.
* (The hash better be the right algorithm.)
*/
int
pgpSigCheck(PGPSig const *sig, PGPPubKey const *pub,
PGPByte const *hash)
{
return pgpSigCheckBuf(sig->pkt.buf, sig->pkt.len, pub, hash);
}
PGPSig *
pgpSigNext (PGPSig const *sig)
{
if (sig)
return (PGPSig *)sig->pkt.next;
return NULL;
}
void
pgpSigFreeList (PGPSig *siglist)
{
pgpPktListFreeList((PktList *)siglist);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -