📄 pgprngpkt.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 + -