📄 pgpber.c
字号:
/*____________________________________________________________________________
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 + -