📄 pgprngpars.c
字号:
return kPGPError_MalformedSignatureInteger;
l += 16 + (t+7)/8;
if (alg == kPGPPublicKeyAlgorithm_RSA ||
alg == kPGPPublicKeyAlgorithm_RSAEncryptOnly ||
alg == kPGPPublicKeyAlgorithm_RSASignOnly) {
if (len != l)
return len < l ? kPGPError_TruncatedSignature : kPGPError_SIG_LONG;
}
return 0;
}
/*
* Version of ringSigParse for the signature packet formats being designed
* for a future version. We do not fully handle them here, but we do a
* basic parse on the sigs and we make sure there are no critical fields
* that we can't handle.
*
* 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
*
*/
static int
ringSigParse3(PGPByte const *buf, size_t len, PGPByte *pkalg, PGPByte keyID[8],
PGPUInt32 *tstamp, PGPUInt32 *validity, PGPByte *type, PGPByte *hashalg,
size_t *extralen, PGPByte *version, PGPBoolean *exportable,
PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
PGPBoolean *hasRegExp, PGPBoolean *isX509, PGPBoolean *primaryUID)
{
unsigned l; /* extralen */
unsigned t; /* bit count of first MPI */
size_t mpiend; /* byte position past first MPI */
PGPByte alg; /* pk alg for sig */
if (version)
*version = buf[0];
if (len < 8)
return kPGPError_TruncatedSignature;
if (type)
*type = buf[1];
alg = buf[2];
if (pkalg)
*pkalg = alg;
if (hashalg)
*hashalg = buf[3];
l = (unsigned)buf[4]<<8 | buf[5]; /* extra material */
if (extralen)
*extralen = l;
if (len < 6+l+2)
return kPGPError_TruncatedSignature;
l += (unsigned)buf[l+6]<<8 | buf[l+7]; /* unhashed extra material */
if (len < 8+l+2+2)
return kPGPError_TruncatedSignature;
t = (unsigned)buf[l+10] << 8 | buf[l+11]; /* first MPI size in bits */
mpiend = 8+l+2+2+(t+7)/8;
if (len < mpiend)
return kPGPError_TruncatedSignature;
if (t && buf[l+12] >> ((t-1)&7) != 1)
return kPGPError_MalformedSignatureInteger;
/* Special checking for RSA sigs */
if (alg == kPGPPublicKeyAlgorithm_RSA ||
alg == kPGPPublicKeyAlgorithm_RSAEncryptOnly ||
alg == kPGPPublicKeyAlgorithm_RSASignOnly) {
if (len > mpiend)
return kPGPError_SIG_LONG;
}
/* Now parse subpackets, pick up keyid, timestamp and validity info */
return ringSigParseSubpackets (buf+4, keyID, tstamp, validity, exportable,
revocable, trustLevel, trustValue, hasRegExp, isX509, primaryUID);
}
/*
* Parse the "extra data" on the new-style signature packets.
*
* This is a chain of subpackets, with the following format:
* Offset,Length Meaning
* 0 x(1-2) Subpacket length (=y)
* x 1 Subpacket type (with critical flag)
* x+1 y-1 Subpacket data
*
* We are only parsing a few of the subpackets now, returning an error
* if we see any critical ones that we don't handle. Also, we require
* there to be a keyid subpacket at present or it is an error.
*
* There are two such chains, each preceded by a two-byte count. The
* first is hashed and the second is not.
*/
static int
ringSigParseSubpackets(PGPByte const *buf, PGPByte keyID[8],
PGPUInt32 *tstamp, PGPUInt32 *validity, PGPBoolean *exportable,
PGPBoolean *revocable, PGPByte *trustLevel, PGPByte *trustValue,
PGPBoolean *hasRegExp, PGPBoolean *isX509, PGPBoolean *primaryUID)
{
unsigned len; /* Length of chain of subpackets */
unsigned sublen; /* Length of subpacket */
unsigned offset; /* Offset to next subpacket */
int type; /* Type of subpacket */
int critical; /* Critical flag on subpacket */
int found_X509 = 0; /* True if found an X509 subpacket */
int found_keyid = 0; /* True if found a keyid subpacket */
int hashed; /* True if parsing hashed subpackets */
int hashedExportable=0; /* True if exportable in hashed portion */
PGPUInt32 creationtime = 0; /* Creation time from subpacket */
PGPUInt32 expirationtime = 0; /* Expiration time from subpacket */
hashed = 1;
/* Loop twice, once with hashed = 1 and once with hashed = 0 */
do {
len = (unsigned)buf[0]<<8 | buf[1];
buf += 2;
while (len) {
if (len < 2)
return kPGPError_ExtraDateOnSignature;
/* Subpacket length may be one or two bytes */
sublen = (unsigned)buf[0];
if (sublen < 0xc0) {
/* sublen is the length */
offset = sublen;
len -= 1;
buf += 1;
} else if ((sublen & 0xe0) == 0xc0) {
sublen &= 0x3f;
sublen = (sublen << 8) + (unsigned)buf[1] + 192;
offset = sublen;
len -= 2;
buf += 2;
} else if (sublen == 0xff) {
if (len < 5)
return kPGPError_ExtraDateOnSignature;
sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
offset = sublen;
len -= 5;
buf += 5;
} else {
/*
* Variable length subpacket; add up sizes of parts.
* We don't consolidate them, so these can't be used for
* the types we are scanning for below.
*/
unsigned partlen;
PGPByte const *bp;
PGPBoolean final = FALSE;
len -= 1;
buf += 1;
sublen = 1 << (sublen & 0x1f);
partlen = sublen;
bp = buf + partlen;
while (!final) {
partlen = (unsigned)*bp++;
if (partlen < 0xe0) {
final = TRUE;
if (partlen >= 0xc0)
partlen = ((partlen&0x3f) << 8)
+ (unsigned)*bp++ + 192;
} else {
partlen = 1 << (partlen & 0x1f);
}
sublen += partlen;
bp += partlen;
}
offset = bp - buf;
}
if (len < 1)
return kPGPError_ExtraDateOnSignature;
type = buf[0];
critical = type & SIGSUBF_CRITICAL;
type &= ~SIGSUBF_CRITICAL;
buf += 1;
len -= 1;
sublen -= 1;
offset -= 1;
if (len < sublen)
return kPGPError_ExtraDateOnSignature;
/* Illegal to have critical packets in unhashed region */
if (critical && !hashed)
return kPGPError_ExtraDateOnSignature;
switch (type) {
case SIGSUB_CREATION:
if (sublen != 4)
return kPGPError_ExtraDateOnSignature;
if (!tstamp && critical)
return kPGPError_ExtraDateOnSignature;
creationtime = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
if (tstamp)
*tstamp = creationtime;
break;
case SIGSUB_EXPIRATION:
if (sublen != 4 || !hashed)
return kPGPError_ExtraDateOnSignature;
if (!validity && critical)
return kPGPError_ExtraDateOnSignature;
expirationtime = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
/* Store it as seconds. It is really validity period */
if (validity && creationtime)
*validity = expirationtime;
break;
case SIGSUB_KEYID:
/* Allow longer than 8 byte keyid's unless critical */
if (sublen < 8)
return kPGPError_ExtraDateOnSignature;
if (critical && (!keyID || sublen != 8))
return kPGPError_ExtraDateOnSignature;
if (keyID)
memcpy(keyID, buf + sublen - 8, 8);
found_keyid = 1;
break;
case SIGSUB_EXPORTABLE:
/* Allow exportability attribute not to be hashed */
if (sublen != 1)
return kPGPError_ExtraDateOnSignature;
/* hashed version overrides unhashed */
if (hashedExportable && !hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( exportable ) ) {
*exportable = *buf != 0;
hashedExportable = hashed;
}
break;
case SIGSUB_REVOCABLE:
if (sublen != 1 || !hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( revocable ) )
*revocable = *buf != 0;
break;
case SIGSUB_TRUST:
/* Packet format not fully decided, use 1st two bytes */
if (sublen < 2 || !hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( trustLevel ) )
*trustLevel = buf[0];
if (IsntNull( trustValue ) )
*trustValue = buf[1];
break;
case SIGSUB_REGEXP:
if (!hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( hasRegExp ) )
*hasRegExp = TRUE;
break;
case SIGSUB_NAI:
if (!hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( isX509 ) && *buf == SIGSUBSUB_X509)
*isX509 = TRUE;
found_X509 = TRUE;
break;
case SIGSUB_PRIMARY_USERID:
if (!hashed)
return kPGPError_ExtraDateOnSignature;
if (IsntNull( primaryUID ) )
*primaryUID = *buf != 0;
break;
default:
if (critical)
return kPGPError_ExtraDateOnSignature;
}
buf += offset;
len -= offset;
}
hashed = !hashed;
} while (!hashed); /* Two iterations */
/* We must have a keyid, unless it is an X509 key */
if (keyID && !found_keyid && !found_X509)
return kPGPError_ExtraDateOnSignature;
return kPGPError_NoErr;
}
/*
* Look for a particular subpacket associated with the given signature.
* See comments above for format of subpackets. Return pointer to the
* subpacket data, after the length and type field.
* Critical and hashed tell whether the packet was critical and/or in the
* hashed region, respectively (return parameters).
* We don't need to do consistency checking, it's already been checked.
*
* This may alter the contents of buf, so should only be called once on
* any given buffer.
*
* nth should be set to 0 to find first match, 1 for second, etc.
* Returns number of matches total in *pmatches.
*/
PGPByte const *
ringSigFindSubpacket(PGPByte *buf, int subpacktype, unsigned nth,
PGPSize *plen, int *pcritical, int *phashed, PGPUInt32 *pcreation,
unsigned *pmatches)
{
unsigned len; /* Length of chain of subpackets */
unsigned sublen; /* Length of subpacket */
unsigned offset; /* Offset to next subpacket */
int type; /* Type of subpacket */
int critical; /* Critical flag on subpacket */
int hashed; /* True if parsing hashed subpackets */
unsigned nmatches = 0; /* Number of matches so far */
PGPByte const *pbuf = NULL; /* Return buffer pointer */
if (buf[0] < PGPVERSION_4)
return NULL;
subpacktype &= ~SIGSUBF_CRITICAL;
buf += 4;
hashed = 1;
/* Loop twice, once with hashed = 1 and once with hashed = 0 */
do {
len = (unsigned)buf[0]<<8 | buf[1];
buf += 2;
while (len) {
if (len < 2)
return NULL;
/* Subpacket length may be one or two bytes */
sublen = (unsigned)buf[0];
if (sublen < 0xc0) {
/* sublen is the length */
offset = sublen;
len -= 1;
buf += 1;
} else if ((sublen & 0xe0) == 0xc0) {
sublen &= 0x3f;
sublen = (sublen << 8) + (unsigned)buf[1] + 192;
offset = sublen;
len -= 2;
buf += 2;
} else if (sublen == 0xff) {
if (len < 5)
return NULL;
sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
offset = sublen;
len -= 5;
buf += 5;
} else {
/* Variable length subpacket; concatenate data */
unsigned partlen;
PGPByte *bp;
PGPBoolean final = FALSE;
len -= 1;
buf += 1;
sublen = 1 << (sublen & 0x1f);
partlen = sublen;
bp = buf + partlen;
while (!final) {
partlen = (unsigned)*bp++;
if (partlen < 0xe0) {
final = TRUE;
if (partlen >= 0xc0)
partlen = ((partlen&0x3f) << 8)
+ (unsigned)*bp++ + 192;
} else {
partlen = 1 << (partlen & 0x1f);
}
pgpCopyMemory (bp, buf+sublen, partlen);
sublen += partlen;
bp += partlen;
}
offset = bp - buf;
}
if (len < 1)
return NULL;
type = buf[0];
critical = type & SIGSUBF_CRITICAL;
type &= ~SIGSUBF_CRITICAL;
buf += 1;
len -= 1;
sublen -= 1;
offset -= 1;
if (type == subpacktype) {
/* Match! */
if (nmatches == nth) {
if (pcritical)
*pcritical = critical;
if (phashed)
*phashed = hashed;
if (plen)
*plen = sublen;
pbuf = buf;
}
nmatches += 1;
}
if (type == SIGSUB_CREATION) {
pgpAssert (sublen == 4);
if (pcreation) {
*pcreation = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
}
}
/* Skip to next packet */
buf += offset;
len -= offset;
}
hashed = !hashed;
} while (!hashed); /* Two iterations */
if (pmatches)
*pmatches = nmatches;
return pbuf; /* Will be non-null if we matched nth */
}
/* Variant on ringSigFindSubpacket which looks within the NAI subpacket
* to find the requested sub-subpacket type. We return the entire NAI
* subpacket.
*/
PGPByte const *
ringSigFindNAISubSubpacket(PGPByte *buf, int subpacktype, unsigned nth,
PGPSize *plen, int *pcritical, int *phashed, PGPUInt32 *pcreation,
unsigned *pmatches)
{
PGPByte const *sigbuf;
unsigned mynth = 0;
for ( ; ; ) {
sigbuf = ringSigFindSubpacket(buf, SIGSUB_NAI, mynth, plen, pcritical,
phashed, pcreation, pmatches);
if( IsNull( sigbuf ) )
return NULL;
if (sigbuf[0] == subpacktype) {
if (nth == 0)
return sigbuf;
nth -= 1;
}
mynth += 1;
}
/* NOTREACHED */
}
#define SFLAGS(critical,hashed) \
(((critical)?kPGPSigFlags_Critical:0)|((hashed)?0:kPGPSigFlags_Unhashed))
/*
* Add info from subpackets to a sigspec structure.
*/
PGPError
ringSigSubpacketsSpec(PGPSigSpec *spec, PGPByte const *buf)
{
unsigned len; /* Length of chain of subpackets */
unsigned sublen; /* Length of subpacket */
unsigned offset; /* Offset to next subpacket */
int type; /* Type of subpacket */
int critical; /* Critical flag on subpacket */
int hashed; /* True if parsing hashed subpackets */
PGPUInt32 dat;
pgpAssert (buf[0] >= PGPVERSION_4);
buf += 4;
hashed = 1;
/* Loop twice, once with hashed = 1 and once with hashed = 0 */
do {
len = (unsigned)buf[0]<<8 | buf[1];
buf += 2;
while (len) {
if (len < 2)
return kPGPError_ExtraDateOnSignature;
/* Subpacket length may be one or two bytes */
sublen = (unsigned)buf[0];
if (sublen < 0xc0) {
/* sublen is the length */
offset = sublen;
len -= 1;
buf += 1;
} else if ((sublen & 0xe0) == 0xc0) {
sublen &= 0x3f;
sublen = (sublen << 8) + (unsigned)buf[1] + 192;
offset = sublen;
len -= 2;
buf += 2;
} else if (sublen == 0xff) {
if (len < 5)
return kPGPError_ExtraDateOnSignature;
sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
offset = sublen;
len -= 5;
buf += 5;
} else {
/*
* Variable length subpacket; add up sizes of parts.
* We don't consolidate them, so these can't be used for
* the types we are scanning for below.
*/
unsigned partlen;
PGPByte const *bp;
PGPBoolean final = FALSE;
len -= 1;
buf += 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -