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

📄 pgpber.c

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

	$Id: pgpBER.c,v 1.37 2002/08/06 20:11:12 dallen Exp $
____________________________________________________________________________*/
#include <string.h>

#include "pgpMem.h"
#include "pgpContext.h"
#include "pgpPFLPriv.h"
#include "pgpBERPriv.h"
#include "pgpLDAP.h"
#include "pgpEndianConversion.h"

	PGPError
pgpNewBERElement(
	PGPMemoryMgrRef		memMgr,
	PGPberElementRef *	ber )
{
	PGPError		err 	= kPGPError_NoErr;

	PGPValidateMemoryMgr( memMgr );
	PGPValidatePtr( ber );

	*ber = PGPNewData(
				memMgr, 
				sizeof( PGPberElement ), 
				kPGPMemoryMgrFlags_Clear );
	if( IsNull( *ber ) )
		return kPGPError_OutOfMemory;

	(*ber)->encoding = NULL;
	(*ber)->length = 0;
	(*ber)->nextInsertIndex = 0;
	(*ber)->nextReadIndex = 0;
	(*ber)->tag = 0;

	(*ber)->next.nextSeq = NULL;
	(*ber)->prev.prevSeq = NULL;

	(*ber)->memMgr = memMgr;

	return err;
}

	PGPError
PGPNewBERElement(
	PGPContextRef		context,
	PGPberElementRef *	ber )
{
	PGPError			err 	= kPGPError_NoErr;
	PGPberElementRef	newBer	= kInvalidPGPberElementRef;
	PGPMemoryMgrRef		memMgr	= kInvalidPGPMemoryMgrRef;

	PGPValidateContext( context );
	PGPValidatePtr( ber );

	memMgr = PGPPeekContextMemoryMgr( context );

	err = pgpNewBERElement( memMgr, &newBer ); CKERR;

	*ber = newBer;

error:
	return err;
}

/*
 * This frees the current PGPberElement and any sequences/sets/PGPberElements
 * pointed to by the current one.
 */
	PGPError
PGPFreeBERElement(
	PGPberElementRef	ber )
{
	PGPValidateBERElementRef( ber );

	if( ber->next.nextSeq )
		PGPFreeBERElement( ber->next.nextSeq->nextBER );
	if( ber->prev.prevSeq )
		ber->prev.prevSeq->nextBER = NULL;
	
	if( IsntNull( ber->encoding ) )
		(void) PGPFreeData( ber->encoding );

	if( IsntNull( ber->next.nextSeq ) )
		(void) PGPFreeData( ber->next.nextSeq );

	(void) PGPFreeData( ber );

    return kPGPError_NoErr;
}

/****************************************************************************
 * BER encoding routines													*
 ****************************************************************************/

	PGPError 
pgpBERGetTagEncoding(
	PGPUInt32	tag,
	PGPByte *	s, 
	PGPSize *	length)
{
	PGPUInt32		i			= 0;
	PGPUInt32		mask		= 0;
	PGPUInt32		netTag		= 0;

	PGPValidatePtr( length );
	PGPValidatePtr( s );

	for( i = sizeof( PGPUInt32 ) - 1; i > 0; i-- )
	{
		mask = 0xFF << ( i * 8 );
		if( tag & mask )
			break;
	}

	*length = i + 1;

	netTag = PGPHostToNetLong( tag );

	pgpCopyMemory( ( (PGPByte *) &netTag ) + sizeof( PGPUInt32 ) - *length, s, *length );

	return kPGPError_NoErr;
}

	PGPError
pgpBERGetLengthEncoding(
	PGPSize 	length,
	PGPByte *	s,
	PGPSize *	lengthOfLength )
{
	PGPValidatePtr( lengthOfLength );
	PGPValidatePtr( s );

	/* Use short form if length <= 127 */
	if( length <= 0x7F )
		*lengthOfLength = 1;

	/* else use long encoding */
	else if( length <= 0xFFFF )
		*lengthOfLength = 2;
	else if( length <= 0xFFFFFF )
		*lengthOfLength = 3;
	else /* if( length <= 0xFFFFFFFF ) */
		*lengthOfLength = 4;

	if( *lengthOfLength == 1 )
		s[0] = ( length & 0xFF );
	else
	{
		PGPByte		netLength[sizeof(PGPUInt32)];
		
		s[0] = ( *lengthOfLength & 0xFF ) | kPGPberMask_BigLength;
		PGPUInt32ToEndian( length, kPGPBigEndian, &netLength[0] );
		pgpCopyMemory( &netLength[sizeof(PGPUInt32) - *lengthOfLength], &s[1],
			*lengthOfLength );

		/* We need to encode the length of the length, too */
		(*lengthOfLength)++;
	}

	return kPGPError_NoErr;
}

	PGPError
pgpBERStrAppend(
	PGPberElementRef	ber,
	PGPByte *			src, 
	PGPUInt32			tag, 
	PGPSize 			srcLength )
{
	PGPByte 	*s					= NULL;
	PGPSize 	length				= 0;
	PGPSize 	lengthLength		= 0;
	PGPByte 	lengthEncoding[8];
	PGPSize 	tagLength			= 0;
	PGPByte 	tagEncoding[4];
	PGPError	err 				= kPGPError_NoErr;

	PGPValidatePtr( src );
	PGPValidateBERElementRef( ber );

	err = pgpBERGetLengthEncoding( srcLength, lengthEncoding, &lengthLength ); CKERR;

	err = pgpBERGetTagEncoding( tag, tagEncoding, &tagLength ); CKERR;

	length = ber->length + srcLength + tagLength + lengthLength;

	s = PGPNewData( ber->memMgr, length, kPGPMemoryMgrFlags_Clear );
	if( IsNull( s ) )
		return kPGPError_OutOfMemory;

	if( ber->length != 0 )
		pgpCopyMemory( ber->encoding, s, ber->length );
	
	pgpCopyMemory( tagEncoding, s + ber->length, tagLength );
	ber->length += tagLength;

	pgpCopyMemory( lengthEncoding, s + ber->length, lengthLength );
	ber->length += lengthLength;

	pgpCopyMemory( src, s + ber->length, srcLength );
	ber->length += srcLength;

	if( IsntNull( ber->encoding ) )
	{
		err = PGPFreeData( ber->encoding );	CKERR;
		ber->encoding = NULL;
	}

	ber->encoding = s;

error:
	return kPGPError_NoErr;
}

	PGPError
pgpSeekLastBERElement(
	PGPberElementRef 	ber, 
	PGPberElementRef *	lastBER )
{
	PGPberElementRef 	berPtr = NULL;
	PGPberSequence *	seqPtr = NULL;

	PGPValidateBERElementRef( ber );
	PGPValidatePtr( lastBER );

	/*
	 * Seek to the last PGPberElement in our chain of PGPberElements and
	 * PGPberSequences/PGPberSets.
	 */

	berPtr = ber;
	for( seqPtr = berPtr->next.nextSeq; seqPtr != NULL; seqPtr = berPtr->next.nextSeq )
	{
		berPtr = seqPtr->nextBER;

		/* berPtr should never be NULL */
		PGPValidatePtr( berPtr );
	}

	*lastBER = berPtr;

	return kPGPError_NoErr;
}


	PGPError
pgpBERBeginSequence(
	PGPberElementRef	ber,
	PGPUInt32			tag )
{
	PGPberSequence *	seq 	= NULL;
	PGPError			err 	= kPGPError_NoErr;
	PGPberElementRef 	lastBER = NULL;
	PGPberElementRef 	newBER	= NULL;

	PGPValidateBERElementRef( ber );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	/* Make new PGPberSequence */
	seq = PGPNewData( ber->memMgr, 
			  sizeof( PGPberSequence ), 
			  kPGPMemoryMgrFlags_Clear );
	if( IsNull( seq ) )
		return kPGPError_OutOfMemory;

	/* Make new PGPberElement */
	err = pgpNewBERElement( ber->memMgr, &newBER ); CKERR;

	newBER->tag = tag;

	/* Set pointers 
	 *
	 * This is how the pointer chain should look:
	 *
	 * [lastBER] -> [seq] -> [newBER]
	 */
	lastBER->next.nextSeq = seq;
	seq->prevBER = lastBER;

	seq->nextBER = newBER;
	newBER->prev.prevSeq = seq;

	goto done;
error:
	if( IsntNull( seq ) )
		(void) PGPFreeData( seq );

	if( !PGPberElementRefIsValid( newBER ) )
		(void) PGPFreeBERElement( newBER );

done:
	
	return err;
}

	PGPError
pgpBEREndSequence(
	PGPberElementRef	ber )
{
	PGPberElementRef	lastBER		= kInvalidPGPberElementRef;
	PGPberElementRef	newLastBER	= kInvalidPGPberElementRef;
	PGPberSequence *	seq			= NULL;
	PGPError			err 		= kPGPError_NoErr;

	PGPValidateBERElementRef( ber );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	seq = lastBER->prev.prevSeq;
	newLastBER = seq->prevBER;

	err = pgpBERStrAppend( 
			newLastBER, 
			(IsNull( lastBER->encoding ) ? (PGPByte *) "": lastBER->encoding ), 
			lastBER->tag, 
			lastBER->length ); CKERR;

	/*
	 * We just ended a sequence... Now we need to free the last PGPberElement
	 * and fix the end of the pointer chain to indicate it's gone.
	 */
	(void) PGPFreeData( newLastBER->next.nextSeq );
	newLastBER->next.nextSeq = NULL;
	lastBER->prev.prevSeq = NULL;

	(void) PGPFreeBERElement( lastBER );

error:
	return err;
}

	PGPError
pgpBERBeginSet(
	PGPberElementRef	ber,
	PGPUInt32			tag )
{
	/*
	 * The only real difference between a sequence and a set is the tag, but
	 * this difference has already been accounted for, so we can just call
	 * pgpBERBeginSequence with a set tag.
	 */
	return pgpBERBeginSequence( ber, tag );
}

	PGPError
pgpBEREndSet(
	PGPberElementRef	ber )
{
	return pgpBEREndSequence( ber );
}

	PGPError
pgpBERInsertInt(
	PGPberElementRef	ber, 
	PGPInt32			value, 
	PGPUInt32			tag )
{
	PGPError			err 			= kPGPError_NoErr;
	PGPByte 			intString[16];
	PGPSize				intStringLength	= 0;
	PGPBoolean			sign			= FALSE;
	PGPInt32			i				= 0;
	PGPInt32			mask			= 0;
	PGPberElementRef	lastBER			= NULL;

	PGPValidateBERElementRef( ber );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	sign = (value < 0);

	/* Find the first byte that's not all ones or all zeros */
	for( i = sizeof( PGPInt32 ) - 1; i > 0; i-- )
	{
		mask = 0xFF << ( i * 8 );

		/* 
		 * if high bit is set, look for first non-all-one byte
		 * if high bit is not set, look for first non-all-zero byte
		 */
		if( sign )
		{
			if( ( value & mask ) != mask )	/* not all ones */
				break;
		}
		else
		{
			if( value & mask )		/* not all zeros */
				break;
		}
	}

	/*
	 * i now points to the first byte we encode.  If the high bit of
	 * this byte is not the same as the sign bit, when this is decoded,
	 * it will sign extend the wrong bit, so we need to tack an extra
	 * byte on to this to make sure it is sign extended correctly.
	 */
	mask = value & ( 0x80 << ( i * 8 ) );
	if( ( mask && !sign ) || ( !mask && sign ) )
		i++;

	/* Need to convert value to network byte order */
	PGPUInt32ToEndian( value, kPGPBigEndian, (PGPByte *) &value );

	intStringLength = i + 1;

	pgpCopyMemory( (char *) &value + sizeof( PGPInt32 ) - intStringLength, intString, intStringLength );

	err = pgpBERStrAppend( lastBER, intString, tag, intStringLength ); CKERR;

error:

	return err;
}

	PGPError
pgpBERInsertString(
	PGPberElementRef	ber,
	char *				string,
	PGPUInt32			tag )
{
	PGPError			err		= kPGPError_NoErr;
	PGPSize				length	= 0;
	PGPberElementRef	lastBER	= NULL;

	PGPValidateBERElementRef( ber );
	PGPValidatePtr( string );

	length = strlen( string );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	err = pgpBERStrAppend( lastBER, (PGPByte *) string, tag, length ); CKERR;

error:

	return err;
}

	PGPError
pgpBERInsertOctetstring(
	PGPberElementRef	ber,
	PGPByte *			string,
	PGPSize				length,
	PGPUInt32			tag )
{
	PGPError			err		= kPGPError_NoErr;
	PGPberElementRef	lastBER	= NULL;

	PGPValidateBERElementRef( ber );
	PGPValidatePtr( string );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	err = pgpBERStrAppend( lastBER, string, tag, length ); CKERR;

error:

	return err;
}

	PGPError
pgpBERInsertNULL(
	PGPberElementRef	ber,
	PGPUInt32			tag )
{
	PGPError			err		= kPGPError_NoErr;
	PGPberElementRef	lastBER	= kInvalidPGPberElementRef;

	PGPValidateBERElementRef( ber );

	err = pgpSeekLastBERElement( ber, &lastBER ); CKERR;

	err = pgpBERStrAppend( lastBER, (PGPByte *)"", tag, 0 ); CKERR;

error:

	return err;
}

	PGPError 
PGPberAppend(
	PGPberElementRef	ber, 
	const char *		fmt, 
	... )
{
	va_list 	argList;
	PGPUInt32	i					= 0;
	PGPUInt32	j					= 0;
	PGPError	err 				= kPGPError_NoErr;
	PGPUInt32	tag 				= kPGPberType_None;
	PGPBoolean	clearTag			= TRUE;

	char *			stringArg		= NULL;
	PGPByte *		octetStringArg	= NULL;
	char **			stringVectorArg	= NULL;
	PGPberValue **	berVectorArg	= NULL;
	PGPBoolean		boolArg			= FALSE;
	PGPInt32		intArg			= 0;

	PGPValidateBERElementRef( ber );
	PGPValidatePtr( fmt );

	va_start( argList, fmt );

⌨️ 快捷键说明

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