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

📄 pgpkeymisc.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				return kPGPError_OutOfMemory;
		} else {
			/* Old <= 2.2 format - no DER prefix */
			len -= sizeof(MD5_prefix);
			in += sizeof(MD5_prefix);
			if (len+3+1 > bytes)
				return kPGPError_PublicKeyTooSmall;	/* won't fit */
			if (bnInsertBigBytes(bn, &pgp22_MD5_byte, bytes-1, 1)
					< 0 ||
			    bnInsertBigBytes(bn, in, bytes-len-2, len) < 0 ||
			    onesPad(bn, bytes-len-2, 1) < 0 ||
			    bnInsertBigBytes(bn, &padtype, 0, 1) < 0)
				return kPGPError_OutOfMemory;
		}
	}
	return 0;
}


/*
 * Searches bytes, beginning with start-1 and progressing to 0,
 * until one that is not 0xff is found.  The idex of the last 0xff
 * byte is returned (or start if start-1 is not 0xff.)
 */
static unsigned
bnSearchNonOneFromHigh(BigNum const *bn, unsigned start)
{
	PGPByte buf[16];	/* Size is arbitrary */
	unsigned l;
	unsigned i;

	while (start) {
		l = start < sizeof(buf) ? start : sizeof(buf);
		start -= l;
		bnExtractBigBytes(bn, buf, start, l);
		for (i = 0; i < l; i++) {
			if (buf[i] != 0xff) {
				pgpClearMemory( buf,  sizeof(buf));
				return start + l - i;
			}
		}
	}
	/* Nothing found */
	pgpClearMemory( buf,  sizeof(buf));
	return 0;
}

/*
 * Searches bytes, beginning with start and going up (towards more
 * significant bytes), until one that is not 0xff is found.  Since the
 * input number is finite, there must be zeros eventually.
 * The index of the first non-0xff byte is returned.
 */
static unsigned
bnSearchNonOneFromLow(BigNum const *bn, unsigned start)
{
	PGPByte buf[16];	/* Size is arbitrary */
	unsigned i;

	for (;;) {
		bnExtractBigBytes(bn, buf, start, sizeof(buf));
		i = sizeof(buf);
		start += i;
		do {
			if (buf[--i] != 0xff) {
				pgpClearMemory( buf,  sizeof(buf));
				return start - i - 1;
			}
		} while (i);
	}
	/*NOTREACHED*/
}



/*
 * Searches bytes, beginning with start-1 and progressing to 0,
 * until finding one that is zero, or the end of the array.
 * The index of the last non-zero byte is returned (0 if the array
 * is all non-zero, or start if start-1 is zero).
 */
static unsigned
bnSearchZeroFromHigh(BigNum const *bn, unsigned start)
{
	PGPByte buf[16];	/* Size is arbitrary */
	unsigned l;
	unsigned i;

	while (start) {
		l = start < sizeof(buf) ? start : sizeof(buf);
		start -= l;
		bnExtractBigBytes(bn, buf, start, l);
		for (i = 0; i < l; i++) {
			if (buf[i] == 0) {
				pgpClearMemory( buf,  sizeof(buf));
				return start + l - i;
			}
		}
	}
	/* Nothing found */
	pgpClearMemory( buf,  sizeof(buf));
	return 0;
}

/*
 * Searches bytes, beginning with start and going up (towards more
 * significant bytes), until one that is zero is found.  Since the
 * input number is finite, there must be zeros eventually.
 * The index of the first zero byte is returned.
 */
static unsigned
bnSearchZeroFromLow(BigNum const *bn, unsigned start)
{
	PGPByte buf[16];	/* Size is arbitrary */
	unsigned i;

	for (;;) {
		bnExtractBigBytes(bn, buf, start, sizeof(buf));
		i = sizeof(buf);
		start += i;
		do {
			if (buf[--i] == 0) {
				pgpClearMemory( buf,  sizeof(buf));
				return start - i - 1;
			}
		} while (i);
	}
	/*NOTREACHED*/
}

/*
 * Performs a PKCS unpack operation.  Returns a prefix of the unwrapped
 * data in the given buf.  Returns the length of the untruncated
 * data, which may exceed "len". Returns <0 on error.
 *
 * For the constant-padding (signature checking) case,
 * it recongizes the PGP 2.2 format, but not in all its generality;
 * only the one case (framing byte = 1, length = 16) which was ever
 * generated.  It fakes the DER prefix in that case.
 */
int
pgpPKCSUnpack(PGPByte *buf, unsigned len, BigNum *bn, PGPByte padtype,
	unsigned bytes)
{
	PGPByte tmp[2];

	bnExtractBigBytes(bn, tmp, bytes-2, 2);
	if (tmp[0] != 0) {
		pgpClearMemory( tmp,  2);
		return kPGPError_CorruptData;
	}

	if (padtype == PKCS_PAD_ENCRYPTED) {
		/* Decryption case, random padding */
		/* Special case: PGP <= 2.2 hack */
		bnExtractBigBytes(bn, tmp, 0, 1);
		if (tmp[1] == 1 && tmp[0] == padtype &&
		    bnSearchZeroFromLow(bn, 1) == bytes-1-1-16-2-1)
		{
			/* Aha, it's PGP <= 2.2 */
			if (len > 1+16+2)
				len = 1+16+2;
			bnExtractBigBytes(bn, buf, bytes-1-len, len);
			return 1+16+2;
		}

		/* Okay, assume it's PKCS.1 */
		if (tmp[1] != 2) {
			pgpClearMemory( tmp,  2);
			return kPGPError_CorruptData;
		}
		pgpClearMemory( tmp,  2);

		bytes = bnSearchZeroFromHigh(bn, bytes-2);
		if (bytes-- == 0)
			return kPGPError_CorruptData;
	} else {
		pgpAssert (padtype==PKCS_PAD_SIGNED);
		/* Signature check, constant padding */
		if (tmp[1] != padtype) {
			pgpClearMemory( tmp,  sizeof(tmp));
			return kPGPError_CorruptData;
		}

		/*
		 * Special-case hack: is is PGP <= 2.2 format?	This is
		 * identified by a least significant byte of 1, a byte
		 * of 0 between the 16-byte MD5 hash and the padding,
		 * and all ones padding.
		 */
		bnExtractBigBytes(bn, tmp, 0, 1);  /* Should be 1 if <= 2.2 */
		bnExtractBigBytes(bn, tmp+1, bytes-19, 1); /* zero if <= 2.2 */

		if (tmp[0] == padtype && tmp[1] == 0 &&
		    bnSearchNonOneFromLow(bn, 1) == bytes-19)
		{
			/* Aha, it's PGP <= 2.2 - fake up the DER prefix */
			if (len <= sizeof(MD5_prefix)) {
				memcpy(buf, MD5_prefix, len);
			} else {
				memcpy(buf, MD5_prefix, sizeof(MD5_prefix));
				buf += sizeof(MD5_prefix);
				len -= sizeof(MD5_prefix);
				if (len > 16)
					len = 16;
				bnExtractBigBytes(bn, buf, bytes-2-len, len);
			}
			return 16 + sizeof(MD5_prefix);
		}

		/* Okay, assume it's PKCS format thing. */

		bytes = bnSearchNonOneFromHigh(bn, bytes-2);
		if (bytes < 1)
			return kPGPError_CorruptData;
		bytes--;
		tmp[1] = 0;
		bnExtractBigBytes(bn, tmp, bytes, 1);
		if (tmp[0] != 0) {
			pgpClearMemory( tmp,  sizeof(tmp));
			return kPGPError_CorruptData;
		}
		/* Note: tmp isn't secret any more because it's a constant! */
	}

	/* Success! Return the data */
	if (len > bytes)
		len = bytes;
	bnExtractBigBytes(bn, buf, bytes-len, len);
	return bytes;
}

/*
 * Convert a big-endian byte buffer (with bit-count prefix) to an MPI.
 * Returns number of bytes read from buffer, or <= 0 on error.
 * (Returns 0 if the buffer is too short.)
 */
int
pgpBnGetPlain(BigNum *bn, PGPByte const *buf, unsigned size)
{
	unsigned t;

	if (size < 2)
		return 0;
	t = ((unsigned)buf[0] << 8) + buf[1];
	t = (t+7)/8;
	if (size < t+2)
		return 0;

	if (bnInsertBigBytes(bn, buf+2, 0, t) < 0)
		return kPGPError_OutOfMemory;
	return (int)t+2;
}

/* Read start of an X.509 object */
PGPByte
pgpBnX509TagLen(PGPByte const **buf, PGPUInt32 *length)
{
	PGPByte tag = *(*buf)++ & 0x1f;
	PGPUInt32 len = *(*buf)++;
	if (len & 0x80) {
		PGPUInt32 lenlen = len & 0x7f;
		len = 0;
		while (lenlen--) {
			len <<= 8;
			len |= *(*buf)++;
		}
	}
	*length = len;
	return tag;
}

PGPUInt32
pgpBnX509LenLen(PGPUInt32 length)
{
	if (length < 0x80)
		return 1;
	if (length < 0x100)
		return 2;
	if (length < 0x10000)
		return 3;
	if (length < 0x1000000)
		return 4;
	return 5;
}

/*
 * Convert a big-endian byte buffer to an MPI.  PGP format uses a
 * bitcount prefix.
 * Returns number of bytes read from buffer, or <= 0 on error.
 * (Returns 0 if the buffer is too short.)
 */
int
pgpBnGetFormatted(BigNum *bn, PGPByte const *buf, unsigned size,
	unsigned modbytes, PGPPublicKeyMessageFormat format)
{
	unsigned extra = 0;

	if (format == kPGPPublicKeyMessageFormat_PGP) {
		return pgpBnGetPlain( bn, buf, size );
	}

	if (format == kPGPPublicKeyMessageFormat_X509) {
		PGPUInt32 len;
		PGPByte const *bp = buf;
		if (pgpBnX509TagLen(&buf, &len) != X509_TAG_INTEGER)
			return kPGPError_MalformedKeyComponent;
		extra = buf - bp;
		size -= extra;
		if (len > size)
			return kPGPError_MalformedKeyComponent;
		modbytes = len;
	} else {
		pgpAssert( format == kPGPPublicKeyMessageFormat_PKCS1 ||
				   format == kPGPPublicKeyMessageFormat_IKE );
	}

	if (size < modbytes)
		return 0;

	if (bnInsertBigBytes(bn, buf, 0, modbytes) < 0)
		return kPGPError_OutOfMemory;
	return (int)(modbytes + extra);
}


/*
 * Helper function for key unlocking.
 * Convert a big-endian byte buffer to an MPI, with optional decryption and
 * checksums.  Accepts cfb == NULL to mean "unencrypted".
 * Returns number of bytes read from buffer, or <= 0 on error.
 * (Returns 0 if the buffer is too short.)
 *
 * If "old" is true, this does it in the PGP 2.x way, where the length
 * of the data is unencrypted and the CFB is resynced each step.
 * If "old" is false, this assumes that just everything is encrypted
 * and 
 */
int
pgpBnGet(BigNum *bn, PGPByte const *buf, unsigned size,
	PGPCFBContext *cfb, unsigned *checksump, int old)
{
	PGPByte tmp[64];	/* This can be any (non-zero) size >= 2 */
	unsigned t, l;

	if (!cfb) {
		int i;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -