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

📄 pgprngpkt.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
字号:
/*____________________________________________________________________________
        Copyright (C) 2002 PGP Corporation
        All rights reserved.

        Low-level keyring packet handling routines.

        $Id: pgpRngPkt.c,v 1.12 2002/08/06 20:11:00 dallen Exp $
____________________________________________________________________________*/
#include "pgpConfig.h"

#include <stdio.h>
#include <string.h>	/* For memset() and memcmp() */

#include "pgpDebug.h"
#include "pgpPktByte.h"
#include "pgpKeyPriv.h"
#include "pgpErrors.h"
#include "pgpUsuals.h"
#include "pgpFile.h"
#include "pgpMem.h"

#ifndef NULL
#define NULL 0
#endif


/*
 * Return the number of bytes taken up by the packet header
 */
	PGPSize
pgpPktBufferHeaderLen( PGPByte const *buf )
{
	PGPSize len;
	PGPByte pktbyte = buf[0];

	if (IS_OLD_PKTBYTE(pktbyte)) {
		switch(PKTBYTE_LLEN(pktbyte)) {
		  case 3:
			  return 1;
		  case 2:
			  return 5;
		  case 1:
			  return 3;
		  case 0:
			  return 2;
		}
	}
	pgpAssert (IS_NEW_PKTBYTE(pktbyte));
	len = buf[1];
	if (len < 0xc0) {
		return 2;
	} else if (len < 0xff) {
		return 3;
	}
	pgpAssert( len == 0xff );
	return 6;
}


/*
 * Helper function for pktByteGet; read new-style length, returning
 * length and also length of first subpacket.  If no subpackets are used
 * the second length will be the same as the first.
 */
static int
pktLengthNew(PGPFile *f, PGPSize *lenp, PGPSize *len1p)
{
	PGPBoolean final = FALSE;
	PGPFileOffset fpos = 0;
	PGPByte c;				/* Length character we read */
	PGPByte arr4[4];		/* For reading four byte lengths */
	PGPSize len = 0;		/* Length we return */
	PGPSize len0 = 0;		/* Length of subpacket */
	PGPSize lenfirst = 0;	/* Length of first subpacket, if more than 1 */
	PGPError err = kPGPError_NoErr;

	do {
		if (pgpFileRead(&c, 1, f) != 1)
			goto error;
		len0 = c;
		if (len0 < 0xc0) {
			/* len0 is the length */
			len += len0;
			final = TRUE;
		} else if ((len0 & 0xe0) == 0xc0) {
			len0 &= 0x3f;
			if (pgpFileRead(&c, 1, f) != 1)
				goto error;
			len += (len0 << 8) + (PGPSize)c + 192;
			final = TRUE;
		} else if (len0 == 0xff) {
			if (pgpFileRead(arr4, 4, f) != 4)
				goto error;
			len += (((((arr4[0]<<8)|arr4[1])<<8)|arr4[2])<<8)|arr4[3];
			final = TRUE;
		} else {
			/* Indeterminate length.  Count partial size and add up to total */
			len0 = 1 << (len0 & 0x1f);
			len += len0;
			/* Remember first packet position and size */
			if (lenfirst == 0) {
				pgpAssert (len0 != 0);
				fpos = pgpFileTell(f);
				lenfirst = len0;
			}
			err = pgpFileSeek( f, len0, SEEK_CUR );
			if( IsPGPError( err ) ) {
				pgpFileSeek( f, fpos, SEEK_SET );
				return err;
			}
			/* Loop for next subpacket */
		}
	} while (!final);

	if (lenfirst != 0) {
		err = pgpFileSeek( f, fpos, SEEK_SET );
		if( IsPGPError( err ) )
			return err;
		*len1p = lenfirst;
	} else {
		*len1p = len;
	}
	*lenp = len;
	return kPGPError_NoErr;

error:
	if (!pgpFileError(f))
		return kPGPError_EOF;
	pgpFileClearError(f);
	return kPGPError_ReadFailed;
}

/*
 * Returns packet byte, 0 on normal EOF, or error code < 0.
 * Returns length of whole packet, plus length of first sub-packet for
 * case of indefinite-length packets.
 */
	PGPSize
pgpPktByteGet(PGPFile *f, PGPSize *lenp, PGPSize *len1p, PGPFileOffset *posp)
{
	PGPByte pktbyte;
	PGPByte buf4[4];
	PGPSize len = 0;

	if (posp) {
		*posp = pgpFileTell(f);
		if (*posp == (PGPFileOffset)-1)
			return kPGPError_FileOpFailed;
	}

	if (pgpFileRead(&pktbyte, 1, f) != 1)
		return pgpFileError(f) ? kPGPError_ReadFailed : 0;

	if (IS_OLD_PKTBYTE(pktbyte)) {
		switch(PKTBYTE_LLEN(pktbyte)) {
		  case 3:
			/* Indeterminate length, can't handle that */
			return kPGPError_BadPacket;
		  case 2:
			if (pgpFileRead(buf4, 4, f) != 4)
				goto error;
			len = (PGPSize)buf4[0]<<24 | (PGPSize)buf4[1]<<16 |
						 (PGPSize)buf4[2]<<8 | (PGPSize)buf4[3];
			break;
		  case 1:
			if (pgpFileRead(buf4, 2, f) != 2)
				goto error;
			len = (PGPSize)buf4[0]<<8 | (PGPSize)buf4[1];
			break;
		  case 0:
			if (pgpFileRead(buf4, 1, f) != 1)
				goto error;
			len = (PGPSize)buf4[0];
			break;
		}
	} else if (IS_NEW_PKTBYTE(pktbyte)) {
		PGPError err = pktLengthNew( f, lenp, len1p );
		if( IsPGPError( err ) )
			return err;
		return (int)pktbyte;
	} else
		return kPGPError_BadPacket;

	*lenp = *len1p = len;
	return (int)pktbyte;

error:
	if (!pgpFileError(f))
		return kPGPError_EOF;
	pgpFileClearError(f);
	return kPGPError_ReadFailed;
}


/*
 * Read the body of a keyring packet.  Len is the length of the whole packet,
 * and len1 is the length of the first subpacket.  If these are equal we
 * just read raw data.  Else we read len1 bytes and then deal with the
 * additional subpackets.  We return the number of bytes read.
 */
	PGPSize
pgpPktBodyRead(void *ptr, PGPSize len, PGPSize len1, PGPFile *f)
{
	PGPBoolean final;
	PGPSize nread = 0;
	PGPSize n;
	PGPByte c;
	PGPByte arr4[4];

	if (len == len1) {
		return pgpFileRead (ptr, len, f);
	}

	/* Must read multiple subpackets */
	final = FALSE;
	for ( ; ; ) {
		n = pgpFileRead (ptr, len1, f);
		if (n != len1)
			break;
		nread += len1;
		if (final)
			break;
		ptr = (PGPByte *)ptr + len1;
		if (pgpFileRead(&c, 1, f) != 1)
			break;
		len1 = c;
		if (len1 < 0xc0) {
			/* One byte length, final packet */
			final = TRUE;
		} else if ((len1 & 0xe0) == 0xc0) {
			/* Two byte length, final packet */
			len1 &= 0x3f;
			if (pgpFileRead(&c, 1, f) != 1)
				break;
			len1 = (len1 << 8) + (PGPSize)c + 192;
			final = TRUE;
		} else if (len1 == 0xff) {
			/* Four byte length, final packet */
			if (pgpFileRead(arr4, 4, f) != 4)
				break;
			len1 = (((((arr4[0]<<8)|arr4[1])<<8)|arr4[2])<<8)|arr4[3];
			final = TRUE;
		} else {
			/* Indeterminate length, non-final packet */
			len1 = 1 << (len1 & 0x1f);
		}
	}

	return nread;
}


/*
 * Returns the number of bytes which will be needed by packet header
 * (packet type byte plus length).
 */
	PGPUInt32
pgpPktHeaderLen (PGPByte pktbyte, PGPSize len)
{
	if (IS_OLD_PKTBYTE(pktbyte)) {
		/* "Promote" packet byte llen field */
		/* if necessary to accomodate length */
		if (len > 0xffff) {
			if (!(pktbyte & 2))
				pktbyte = (pktbyte & ~3) | 2;
		} else if (len > 0xff) {
			if ((pktbyte & 3) == 0)
				pktbyte |= 1;
		}
		switch(pktbyte & 3) {
		  case 2:
			  return 5;
		  case 1:
			  return 3;
		  case 0:
			  return 2;
		}
	} else {
		pgpAssert(IS_NEW_PKTBYTE(pktbyte));
		if (PKTLEN_ONE_BYTE(len)) {
			return 2;
		} else if (PKTLEN_TWO_BYTES(len)) {
			return 3;
		} else {
			return 6;
		}
	}
	
	/* Avoid warning */
	pgpAssert(0);
	return 0;
}

/*
 * Output a packet header for a keyring packet.
 * Returns the packet byte actually written, whose llen field may be greater
 * than the one passed in, but will not be less, or error code < 0.
 */
	PGPByte
pgpPktHeaderPut( PGPByte *buf, PGPByte pktbyte, PGPSize len )
{
	if (IS_OLD_PKTBYTE(pktbyte)) {
		/* "Promote" packet byte llen field */
		/* if necessary to accomodate length */
		if (len > 0xffff) {
			if (!(pktbyte & 2))
				pktbyte = (pktbyte & ~3) | 2;
		} else if (len > 0xff) {
			if ((pktbyte & 3) == 0)
				pktbyte |= 1;
		}

		*buf++ = pktbyte;

		switch(pktbyte & 3) {
		  case 2:
			*buf++ = (PGPByte)(len >> 24);
			*buf++ = (PGPByte)(len >> 16);
			*buf++ = (PGPByte)(len >>  8);
			*buf++ = (PGPByte)(len      );
			break;
		  case 1:
			*buf++ = (PGPByte)(len >>  8);
			*buf++ = (PGPByte)(len      );
			break;
		  case 0:
			*buf++ = (PGPByte)len;
			break;
		}
	} else {
		pgpAssert(IS_NEW_PKTBYTE(pktbyte));
		*buf++ = (PGPByte)pktbyte;
		if (PKTLEN_TWO_BYTES(len)) {
			if (PKTLEN_ONE_BYTE(len)) {
				*buf++ = PKTLEN_1BYTE(len);
			} else {
				*buf++ = PKTLEN_BYTE0(len);
				*buf++ = PKTLEN_BYTE1(len);
			}
		} else {
			/* Use four byte mode */
			*buf++ = 0xff;
			*buf++ = (PGPByte)(len >> 24);
			*buf++ = (PGPByte)(len >> 16);
			*buf++ = (PGPByte)(len >>  8);
			*buf++ = (PGPByte)(len >>  0);
		}
	}
	return pktbyte;
}




/*
 * Local Variables:
 * tab-width: 4
 * End:
 * vi: ts=4 sw=4
 * vim: si
 */

⌨️ 快捷键说明

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