⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgprngpars.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		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 + -