📄 pgprngpars.c
字号:
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;
dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
pgpSigSpecSetTimestamp (spec, dat);
break;
case SIGSUB_EXPIRATION:
if (sublen != 4)
return kPGPError_ExtraDateOnSignature;
dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
pgpSigSpecSetSigExpiration (spec, SFLAGS(critical, hashed),
dat);
break;
case SIGSUB_KEY_EXPIRATION:
if (sublen != 4)
return kPGPError_ExtraDateOnSignature;
dat = (PGPUInt32)((unsigned)buf[0]<<8|buf[1]) << 16 |
((unsigned)buf[2]<<8|buf[3]);
pgpSigSpecSetKeyExpiration (spec, SFLAGS(critical, hashed),
dat);
break;
case SIGSUB_KEYID:
/* This was processed beforehand to set up the sigspec */
if (sublen != 8)
return kPGPError_ExtraDateOnSignature;
break;
case SIGSUB_EXPORTABLE:
/* Allow exportability attribute not to be hashed */
if (sublen != 1)
return kPGPError_ExtraDateOnSignature;
pgpSigSpecSetExportable (spec, SFLAGS(critical, hashed),
(PGPBoolean)(buf[0]!=0));
break;
case SIGSUB_REVOCABLE:
if (sublen != 1)
return kPGPError_ExtraDateOnSignature;
pgpSigSpecSetRevocable (spec, SFLAGS(critical, hashed),
(PGPBoolean)(buf[0]!=0));
break;
case SIGSUB_PRIMARY_USERID:
pgpSigSpecSetPrimaryUserID (spec,
SFLAGS(critical, hashed),
(PGPBoolean)(buf[0]!=0));
break;
case SIGSUB_TRUST:
/* Packet format not fully decided, use 1st two bytes */
if (sublen != 2)
return kPGPError_ExtraDateOnSignature;
pgpSigSpecSetTrustLevel (spec, SFLAGS(critical, hashed),
(PGPBoolean)(buf[0]!=0),
(PGPBoolean)(buf[1]!=0));
break;
case SIGSUB_REGEXP:
pgpSigSpecSetRegExp (spec, SFLAGS(critical, hashed),
(char *)buf);
break;
case SIGSUB_PREFERRED_ENCRYPTION_ALGS:
pgpSigSpecSetPrefAlgs (spec, SFLAGS(critical, hashed),
buf, sublen);
break;
case SIGSUB_KEY_ADDITIONAL_RECIPIENT_REQUEST:
pgpSigSpecSetAdditionalRecipientRequest (spec,
SFLAGS(critical, hashed), buf, sublen);
break;
case SIGSUB_KEY_REVOCATION_KEY:
pgpSigSpecSetRevocationKey (spec,
SFLAGS(critical, hashed), buf, sublen);
break;
default:
pgpSigSpecSetPacket (spec, SFLAGS(critical, hashed),
buf-1, sublen+1);
break;
}
buf += offset;
len -= offset;
}
hashed = !hashed;
} while (!hashed); /* Two iterations */
return kPGPError_NoErr;
}
/*
* Return data for nth subpacket in an attribute object.
* Data is in buf.
* Format is as for signature subpacket portion:
* 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
*
* 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 subpacket, 1 for second, etc.
* Returns type of subpacket and its size.
*/
PGPByte const *
ringAttrSubpacket(PGPByte *buf, PGPSize len, PGPUInt32 nth,
PGPUInt32 *subpacktype, PGPSize *plen)
{
PGPSize sublen; /* Length of subpacket */
PGPSize offset; /* Offset to next subpacket */
PGPUInt32 type; /* Type of subpacket */
PGPUInt32 npackets = 0; /* Number of matches so far */
while (len) {
if (len < 2)
return NULL;
/* Subpacket length may be one or two bytes, or variable-length */
sublen = (PGPSize)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) + (PGPSize)buf[1] + 192;
offset = sublen;
len -= 2;
buf += 2;
} else if (sublen == 0xff) {
sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
offset = sublen;
len -= 5;
buf += 5;
} else {
/* Variable length subpacket; concatenate data */
PGPSize partlen;
PGPByte *bp;
PGPBoolean final = FALSE;
len -= 1;
buf += 1;
sublen = 1 << (sublen & 0x1f);
partlen = sublen;
bp = buf + partlen;
while (!final) {
partlen = (PGPSize)*bp++;
if (partlen < 0xe0) {
final = TRUE;
if (partlen >= 0xc0)
partlen = ((partlen&0x3f) << 8) + (PGPSize)*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];
buf += 1;
len -= 1;
sublen -= 1;
offset -= 1;
if (npackets++ == nth) {
if (plen)
*plen = sublen;
if (subpacktype)
*subpacktype = type;
return buf;
}
}
/* Get here if fewer than n+1 subpackets */
return NULL;
}
/* Return the number of subpackets in the buffer */
PGPUInt32
ringAttrCountSubpackets(PGPByte const *buf, PGPSize len)
{
PGPSize sublen; /* Length of subpacket */
PGPSize offset; /* Offset to next subpacket */
PGPUInt32 type; /* Type of subpacket */
PGPUInt32 npackets = 0; /* Number of matches so far */
while (len) {
if (len < 2)
return 0;
/* Subpacket length may be 1/2/4 bytes, or variable-length */
sublen = (PGPSize)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) + (PGPSize)buf[1] + 192;
offset = sublen;
len -= 2;
buf += 2;
} else if (sublen == 0xff) {
sublen = (((((buf[1]<<8)|buf[2])<<8)|buf[3])<<8)|buf[4];
offset = sublen;
len -= 5;
buf += 5;
} else {
/* Variable length subpacket */
PGPSize partlen;
PGPByte const *bp;
PGPBoolean final = FALSE;
len -= 1;
buf += 1;
sublen = 1 << (sublen & 0x1f);
partlen = sublen;
bp = buf + partlen;
while (!final) {
partlen = (PGPSize)*bp++;
if (partlen < 0xe0) {
final = TRUE;
if (partlen >= 0xc0)
partlen = ((partlen&0x3f) << 8) + (PGPSize)*bp++ + 192;
} else {
partlen = 1 << (partlen & 0x1f);
}
sublen += partlen;
bp += partlen;
}
offset = bp - buf;
}
if (len < 1)
return 0;
type = buf[0];
buf += 1;
len -= 1;
sublen -= 1;
offset -= 1;
++npackets;
}
return npackets;
}
/*
* Return the length of the prefix of a secret key which is a public key,
* or 0 if it can't be determined. A key's prefix is:
* 0 1 - Version
* 1 4 - Creation time
* 5 2 - Vaidity period (days)
* 7 1 - Algorithm
* 8 ? - Algorithm-specific parameters
*/
size_t
ringKeyParsePublicPrefix(PGPByte const *buf, size_t len)
{
size_t size;
unsigned vsize;
if (buf[0] == PGPVERSION_4) {
vsize = 0;
} else {
vsize = 2;
}
/* Check version bytes */
if (!KNOWN_PGP_VERSION(buf[0]) || len < 6+vsize)
return 0;
size = pgpPubKeyPrefixSize(buf[5+vsize], buf+6+vsize, len-6-vsize);
if (size)
size += 6+vsize;
return size;
}
int
ringKeyParseFingerprint16(PGPContextRef context, PGPByte const *kbuf,
size_t klen, PGPByte *fingerprint)
{
PGPHashVTBL const *h;
PGPHashContext *hc;
PGPByte const *buf;
unsigned len;
PGPMemoryMgrRef memoryMgr = PGPGetContextMemoryMgr( context );
h = pgpHashByNumber (kPGPHashAlgorithm_MD5);
if (!h)
return kPGPError_BadHashNumber;
hc = pgpHashCreate( memoryMgr, h);
if (!hc)
return kPGPError_OutOfMemory;
buf = ringKeyParseModulus(kbuf, klen, &len);
if (!buf)
goto error;
PGPContinueHash(hc, buf, len);
buf = ringKeyParseExponent(kbuf, klen, &len);
if (!buf)
goto error;
PGPContinueHash(hc, buf, len);
buf = (PGPByte *) pgpHashFinal(hc);
memcpy(fingerprint, buf, h->hashsize);
PGPFreeHashContext(hc);
return h->hashsize; /* Success */
error:
PGPFreeHashContext(hc);
pgpClearMemory( fingerprint, 16);
return ringKeyParse(context, kbuf, klen, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, 0);
/* Pkalg KeyID KeybitTstampValid */
}
/* Return the size which will be used to create the key prefix buffer */
size_t
ringKeyBufferLength(PGPKeySpec const *ks, PGPByte pkalg)
{
(void)pkalg;
if (pgpKeySpecVersion(ks)==PGPVERSION_4)
return 6; /* version(1)+timestamp(4)+pkalg(1) */
else
return 8; /* version(1)+timestamp(4)+validity(2)+pkalg(1) */
}
/* Create the key prefix buffer */
int
ringKeyToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg)
{
PGPUInt32 tstamp;
PGPUInt16 validity;
unsigned vsize;
buf[0] = pgpKeySpecVersion(ks);
if (buf[0] == PGPVERSION_4) {
vsize = 0;
} else {
vsize = 2;
}
tstamp = pgpKeySpecCreation(ks);
buf[1] = (PGPByte)(tstamp>>24);
buf[2] = (PGPByte)(tstamp>>16);
buf[3] = (PGPByte)(tstamp>> 8);
buf[4] = (PGPByte)(tstamp );
if (vsize) {
validity = pgpKeySpecValidity(ks);
buf[5] = (PGPByte)(validity>>8);
buf[6] = (PGPByte)(validity );
}
buf[5+vsize] = pkalg;
return 0;
}
/* Return the size of a prefix buffer for a secret key */
size_t
ringSecBufferLength(PGPKeySpec const *ks, PGPByte pkalg)
{
return ringKeyBufferLength(ks, pkalg);
}
/* Create the prefix buffer for a secret key */
int
ringSecToBuffer(PGPByte *buf, PGPKeySpec const *ks, PGPByte pkalg)
{
return ringKeyToBuffer(buf, ks, pkalg);
}
/* Parse a CRL packet */
PGPError
ringCRLParse( RingPool *pool, PGPByte const *buf, PGPSize len,
PGPByte *version, PGPByte *type, PGPUInt32 *tstamp, PGPUInt32 *tstampnext,
PGPByte const **dpoint, PGPSize *dpointlen )
{
PGPASN_CertificateRevocationList *crl509;
PGPSize dpoff;
PGPError err = kPGPError_NoErr;
/* Defaults in case of error */
if (version)
*version = 0;
if (type)
*type = 0;
if (tstamp)
*tstamp = 0;
if (tstampnext)
*tstampnext = 0;
if (dpoint)
*dpoint = NULL;
if (dpointlen)
*dpointlen = 0;
/* First two bytes are version, type */
if (len < 2)
goto short_err;
if (version)
*version = buf[0];
if (type)
*type = buf[1];
if (buf[0] == PGPVERSION_4) {
dpoff = 0;
if (buf[1] == PGPCRLTYPE_X509DPOINT) {
dpoff = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
if (dpoint)
*dpoint = buf+6;
if (dpointlen)
*dpointlen = dpoff;
dpoff += 4;
}
err = pgpX509BufferToCRL(pool->context, (PGPByte *)buf+2+dpoff,
len-2-dpoff, &crl509);
if( IsPGPError( err ) )
return err;
if (tstamp)
(void)pgpX509DecodeTime (&crl509->tbsCertList.thisUpdate, tstamp);
if (tstampnext && IsntNull(crl509->tbsCertList.nextUpdate))
(void)pgpX509DecodeTime (crl509->tbsCertList.nextUpdate,
tstampnext);
pgpX509FreeCRL( pool->context, crl509 );
}
return kPGPError_NoErr;
short_err:
return kPGPError_CRLPacketTruncated;
}
/* Find the DistributionPoint information in the packet */
PGPByte const *
ringCRLFindDPoint( PGPByte const *buf, PGPSize buflen, PGPSize *len )
{
PGPSize dplen;
if (buf[0] != PGPVERSION_4 || buf[1] != PGPCRLTYPE_X509DPOINT)
return NULL;
if (buflen < 6)
return NULL;
dplen = (buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
if (dplen + 6 < buflen)
return NULL;
if (len)
*len = dplen;
return buf + 6;
}
/* Find the CRL information in the packet */
PGPByte const *
ringCRLFindCRL( PGPByte const *buf, PGPSize buflen, PGPSize *len )
{
PGPSize dplen = 0;
if (buf[0] != PGPVERSION_4 || (buf[1] != PGPCRLTYPE_X509
&& buf[1] != PGPCRLTYPE_X509DPOINT))
return NULL;
if (buf[1] == PGPCRLTYPE_X509DPOINT)
dplen = ((buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5]) + 4;
if (len)
*len = buflen - 2 - dplen;
return buf + 2 + dplen;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -