📄 asn1_wr.c
字号:
return( writeNumeric( stream, ( long ) enumerated ) );
}
/* Write a null value */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeNull( INOUT STREAM *stream, IN_TAG const int tag )
{
BYTE buffer[ 8 + 8 ];
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
buffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \
BER_NULL : MAKE_CTAG_PRIMITIVE( tag );
buffer[ 1 ] = 0;
return( swrite( stream, buffer, 2 ) );
}
/* Write a boolean value */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeBoolean( INOUT STREAM *stream, const BOOLEAN boolean,
IN_TAG const int tag )
{
BYTE buffer[ 8 + 8 ];
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
buffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \
BER_BOOLEAN : MAKE_CTAG_PRIMITIVE( tag );
buffer[ 1 ] = 1;
buffer[ 2 ] = boolean ? 0xFF : 0;
return( swrite( stream, buffer, 3 ) );
}
/* Write an octet string */
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeOctetString( INOUT STREAM *stream,
IN_BUFFER( length ) const BYTE *string,
IN_LENGTH_SHORT const int length,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( string, length ) );
REQUIRES_S( length > 0 && length < MAX_INTLENGTH_SHORT );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
writeTag( stream, ( tag == DEFAULT_TAG ) ? \
BER_OCTETSTRING : MAKE_CTAG_PRIMITIVE( tag ) );
writeLength( stream, length );
return( swrite( stream, string, length ) );
}
/* Write a character string. This handles any of the myriad ASN.1 character
string types. The handling of the tag works somewhat differently here to
the usual manner in that since the function is polymorphic, the tag
defines the character string type and is always used (there's no
DEFAULT_TAG like the other functions use) */
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int writeCharacterString( INOUT STREAM *stream,
IN_BUFFER( bufSize ) const BYTE *string,
IN_LENGTH_SHORT const int length,
IN_TAG_ENCODED const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
assert( isReadPtr( string, length ) );
REQUIRES_S( length > 0 && length < MAX_INTLENGTH_SHORT );
REQUIRES_S( ( tag >= BER_STRING_UTF8 && tag <= BER_STRING_BMP ) || \
( tag >= MAKE_CTAG_PRIMITIVE( 0 ) && \
tag <= MAKE_CTAG_PRIMITIVE( MAX_CTAG_VALUE ) ) );
writeTag( stream, tag );
writeLength( stream, length );
return( swrite( stream, string, length ) );
}
/* Write a bit string */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeBitString( INOUT STREAM *stream, IN_INT const int bitString,
IN_TAG const int tag )
{
BYTE buffer[ 16 + 8 ];
unsigned int value = 0;
int data = bitString, noBits = 0, i;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( bitString >= 0 && bitString < INT_MAX );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
/* ASN.1 bitstrings start at bit 0, so we need to reverse the order of
the bits before we write them out */
for( i = 0; i < ( sizeof( int ) > 2 ? 32 : 16 ); i++ )
{
/* Update the number of significant bits */
if( data > 0 )
noBits++;
/* Reverse the bits */
value <<= 1;
if( data & 1 )
value |= 1;
data >>= 1;
}
/* Write the data as an ASN.1 BITSTRING. This has the potential to lose
some bits on 16-bit systems, but the only place where bit strings
longer than one or two bytes are used is with CMP's bizarre encoding
of error subcodes that just provide further information above and
beyond the main error code and text message, and it's unlikely that
too many people will be running a CMP server on a DOS box */
buffer[ 0 ] = ( tag == DEFAULT_TAG ) ? \
BER_BITSTRING : MAKE_CTAG_PRIMITIVE( tag );
buffer[ 1 ] = 1 + ( ( noBits + 7 ) >> 3 );
buffer[ 2 ] = ~( ( noBits - 1 ) & 7 ) & 7;
#if UINT_MAX > 0xFFFF
buffer[ 3 ] = ( value >> 24 ) & 0xFF;
buffer[ 4 ] = ( value >> 16 ) & 0xFF;
buffer[ 5 ] = ( value >> 8 ) & 0xFF;
buffer[ 6 ] = value & 0xFF;
#else
buffer[ 3 ] = ( value >> 8 ) & 0xFF;
buffer[ 4 ] = value & 0xFF;
#endif /* 16 vs.32-bit systems */
return( swrite( stream, buffer, 3 + ( ( noBits + 7 ) >> 3 ) ) );
}
/* Write a canonical UTCTime and GeneralizedTime value */
CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
static int writeTime( INOUT STREAM *stream, const time_t timeVal,
IN_TAG const int tag, const BOOLEAN isUTCTime )
{
struct tm timeInfo, *timeInfoPtr = &timeInfo;
char buffer[ 20 + 8 ];
const int length = isUTCTime ? 13 : 15;
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
timeInfoPtr = gmTime_s( &timeVal, timeInfoPtr );
ENSURES_S( timeInfoPtr != NULL && timeInfoPtr->tm_year > 90 );
buffer[ 0 ] = ( tag != DEFAULT_TAG ) ? MAKE_CTAG_PRIMITIVE( tag ) : \
isUTCTime ? BER_TIME_UTC : BER_TIME_GENERALIZED;
buffer[ 1 ] = length;
if( isUTCTime )
{
sprintf_s( buffer + 2, 16, "%02d%02d%02d%02d%02d%02dZ",
timeInfoPtr->tm_year % 100, timeInfoPtr->tm_mon + 1,
timeInfoPtr->tm_mday, timeInfoPtr->tm_hour,
timeInfoPtr->tm_min, timeInfoPtr->tm_sec );
}
else
{
sprintf_s( buffer + 2, 16, "%04d%02d%02d%02d%02d%02dZ",
timeInfoPtr->tm_year + 1900, timeInfoPtr->tm_mon + 1,
timeInfoPtr->tm_mday, timeInfoPtr->tm_hour,
timeInfoPtr->tm_min, timeInfoPtr->tm_sec );
}
return( swrite( stream, buffer, length + 2 ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeUTCTime( INOUT STREAM *stream, const time_t timeVal,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
return( writeTime( stream, timeVal, tag, TRUE ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeGeneralizedTime( INOUT STREAM *stream, const time_t timeVal,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( timeVal >= MIN_STORED_TIME_VALUE );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
return( writeTime( stream, timeVal, tag, FALSE) );
}
/****************************************************************************
* *
* Write Routines for Constructed Objects *
* *
****************************************************************************/
/* Write the start of an encapsulating SEQUENCE, SET, or generic tagged
constructed object. The difference between writeOctet/BitStringHole() and
writeGenericHole() is that the octet/bit-string versions create a normal
or context-specific-tagged primitive string while the generic version
creates a pure hole with no processing of tags */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeSequence( INOUT STREAM *stream, IN_LENGTH_Z const int length )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
writeTag( stream, BER_SEQUENCE );
return( writeLength( stream, length ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeSet( INOUT STREAM *stream, IN_LENGTH_Z const int length )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
writeTag( stream, BER_SET );
return( writeLength( stream, length ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeConstructed( INOUT STREAM *stream, IN_LENGTH_Z const int length,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
writeTag( stream, ( tag == DEFAULT_TAG ) ? \
BER_SEQUENCE : MAKE_CTAG( tag ) );
return( writeLength( stream, length ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeOctetStringHole( INOUT STREAM *stream,
IN_LENGTH_Z const int length,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
writeTag( stream, ( tag == DEFAULT_TAG ) ? \
BER_OCTETSTRING : MAKE_CTAG_PRIMITIVE( tag ) );
return( writeLength( stream, length ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeBitStringHole( INOUT STREAM *stream, IN_LENGTH_Z const int length,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
writeTag( stream, ( tag == DEFAULT_TAG ) ? \
BER_BITSTRING : MAKE_CTAG_PRIMITIVE( tag ) );
writeLength( stream, length + 1 ); /* +1 for bit count */
return( sputc( stream, 0 ) );
}
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int writeGenericHole( INOUT STREAM *stream, IN_LENGTH_Z const int length,
IN_TAG const int tag )
{
assert( isWritePtr( stream, sizeof( STREAM ) ) );
REQUIRES_S( length >= 0 && length < MAX_INTLENGTH );
REQUIRES_S( tag == DEFAULT_TAG || ( tag >= 0 && tag < MAX_TAG_VALUE ) );
writeTag( stream, tag );
return( writeLength( stream, length ) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -