📄 asn1.h
字号:
/****************************************************************************
* *
* ASN.1 Constants and Structures *
* Copyright Peter Gutmann 1992-2007 *
* *
****************************************************************************/
#ifndef _ASN1_DEFINED
#define _ASN1_DEFINED
#include <time.h>
#if defined( INC_ALL )
#include "stream.h"
#else
#include "io/stream.h"
#endif /* Compiler-specific includes */
/****************************************************************************
* *
* BER/DER Constants and Macros *
* *
****************************************************************************/
/* Definitions for the ISO 8825:1990 Basic Encoding Rules */
/* Tag class */
#define BER_UNIVERSAL 0x00
#define BER_APPLICATION 0x40
#define BER_CONTEXT_SPECIFIC 0x80
#define BER_PRIVATE 0xC0
/* Whether the encoding is constructed or primitive */
#define BER_CONSTRUCTED 0x20
#define BER_PRIMITIVE 0x00
/* The ID's for universal tag numbers 0-31. Tag number 0 is reserved for
encoding the end-of-contents value when an indefinite-length encoding
is used */
enum { BER_ID_RESERVED, BER_ID_BOOLEAN, BER_ID_INTEGER, BER_ID_BITSTRING,
BER_ID_OCTETSTRING, BER_ID_NULL, BER_ID_OBJECT_IDENTIFIER,
BER_ID_OBJECT_DESCRIPTOR, BER_ID_EXTERNAL, BER_ID_REAL,
BER_ID_ENUMERATED, BER_ID_EMBEDDED_PDV, BER_ID_STRING_UTF8, BER_ID_13,
BER_ID_14, BER_ID_15, BER_ID_SEQUENCE, BER_ID_SET,
BER_ID_STRING_NUMERIC, BER_ID_STRING_PRINTABLE, BER_ID_STRING_T61,
BER_ID_STRING_VIDEOTEX, BER_ID_STRING_IA5, BER_ID_TIME_UTC,
BER_ID_TIME_GENERALIZED, BER_ID_STRING_GRAPHIC, BER_ID_STRING_ISO646,
BER_ID_STRING_GENERAL, BER_ID_STRING_UNIVERSAL, BER_ID_29,
BER_ID_STRING_BMP, BER_ID_LAST };
/* The encodings for the universal types */
#define BER_EOC 0 /* Pseudo-type for first EOC octet */
#define BER_RESERVED ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_RESERVED )
#define BER_BOOLEAN ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BOOLEAN )
#define BER_INTEGER ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_INTEGER )
#define BER_BITSTRING ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BITSTRING )
#define BER_OCTETSTRING ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OCTETSTRING )
#define BER_NULL ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_NULL )
#define BER_OBJECT_IDENTIFIER ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_IDENTIFIER )
#define BER_OBJECT_DESCRIPTOR ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_DESCRIPTOR )
#define BER_EXTERNAL ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EXTERNAL )
#define BER_REAL ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_REAL )
#define BER_ENUMERATED ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_ENUMERATED )
#define BER_EMBEDDED_PDV ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EMBEDDED_PDV )
#define BER_STRING_UTF8 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UTF8 )
#define BER_13 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_13 )
#define BER_14 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_14 )
#define BER_15 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_15 )
#define BER_SEQUENCE ( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SEQUENCE )
#define BER_SET ( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SET )
#define BER_STRING_NUMERIC ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_NUMERIC )
#define BER_STRING_PRINTABLE ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_PRINTABLE )
#define BER_STRING_T61 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_T61 )
#define BER_STRING_VIDEOTEX ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_VIDEOTEX )
#define BER_STRING_IA5 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_IA5 )
#define BER_TIME_UTC ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_UTC )
#define BER_TIME_GENERALIZED ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_GENERALIZED )
#define BER_STRING_GRAPHIC ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GRAPHIC )
#define BER_STRING_ISO646 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_ISO646 )
#define BER_STRING_GENERAL ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GENERAL )
#define BER_STRING_UNIVERSAL ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UNIVERSAL )
#define BER_29 ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BER29 )
#define BER_STRING_BMP ( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_BMP )
/* The encodings for constructed, indefinite-length tags and lengths */
#define BER_OCTETSTRING_INDEF ( ( BYTE * ) "\x24\x80" )
#define BER_SEQUENCE_INDEF ( ( BYTE * ) "\x30\x80" )
#define BER_SET_INDEF ( ( BYTE * ) "\x31\x80" )
#define BER_CTAG0_INDEF ( ( BYTE * ) "\xA0\x80" )
#define BER_END_INDEF ( ( BYTE * ) "\x00\x00" )
/* Masks to extract information from a tag number */
#define BER_CLASS_MASK 0xC0
#define BER_CONSTRUCTED_MASK 0x20
#define BER_SHORT_ID_MASK 0x1F
/* The maximum size for the short tag number encoding, and the magic value
which indicates that a long encoding of the number is being used */
#define MAX_SHORT_BER_ID 0x1E
#define LONG_BER_ID 0x1F
/* Turn an identifier into a context-specific tag, and extract the value from
a tag. Normally these are constructed, but in a few special cases they
are primitive */
#define MAKE_CTAG( identifier ) \
( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | ( identifier ) )
#define MAKE_CTAG_PRIMITIVE( identifier ) \
( BER_CONTEXT_SPECIFIC | ( identifier ) )
#define EXTRACT_CTAG( tag ) \
( ( tag ) & ~( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED ) )
/****************************************************************************
* *
* ASN.1 Constants and Macros *
* *
****************************************************************************/
/* Special-case tags. If DEFAULT_TAG is given the basic type (e.g. INTEGER,
ENUMERATED) is used, otherwise the value is used as a context-specific
tag. If NO_TAG is given, processing of the tag is skipped. If ANY_TAG
is given, the tag is ignored */
#define DEFAULT_TAG -1
#define NO_TAG -2
#define ANY_TAG -3
/* The highest encoded tag value */
#define MAX_TAG ( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | \
MAX_SHORT_BER_ID )
/* The highest allowed raw tag value before encoding as a primitive or
constructed tag or before encoding as a content-specific tag. In
addition to the standard MAX_TAG_VALUE we also have a value for universal
tags whose basic form is constructed (SETs and SEQUENCES), which would
fall outside the normal MAX_TAG_VALUE range.
Due to CMP's braindamaged use of tag values to communicate message type
information we have to be fairly permissive with the context-specific
tag range because CMP burns up tag values up to the mid-20s, however we
can restrict the range if CMP isn't being used */
#define MAX_TAG_VALUE MAX_SHORT_BER_ID
#define MAX_CONSTR_TAG_VALUE BER_SET
#ifdef USE_CMP
#define MAX_CTAG_VALUE 30
#else
#define MAX_CTAG_VALUE 10
#endif /* USE_CMP */
/* The minimum and maximum allowed size for an (encoded) object identifier */
#define MIN_OID_SIZE 5
#define MAX_OID_SIZE 32
/* When reading an OID selection with readOID(), we sometimes need to handle
a catch-all default value that's used when nothing else matches. This is
typically used for type-and-value data where we want to ignore anything
that we don't recognise. The following value is used as a match-all
wildcard. It's longer than any normal OID to make it possible to do a
quick-reject match based only on the length. The second byte is set to
0x0E (= 14) to make the standard sizeofOID() macro work, since this
examines the length field of the encoded OID */
#define WILDCARD_OID ( const BYTE * ) \
"\xFF\x0E\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00"
#define WILDCARD_OID_SZE 16
/* A macro to make make declaring OIDs simpler */
#define MKOID( value ) ( ( const BYTE * ) value )
/* Macros and functions to work with indefinite-length tags. The only ones
used are SEQUENCE and [0] (for the outer encapsulation) and OCTET STRING
(for the data itself) */
#define writeOctetStringIndef( stream ) swrite( stream, BER_OCTETSTRING_INDEF, 2 )
#define writeSequenceIndef( stream ) swrite( stream, BER_SEQUENCE_INDEF, 2 )
#define writeSetIndef( stream ) swrite( stream, BER_SET_INDEF, 2 )
#define writeCtag0Indef( stream ) swrite( stream, BER_CTAG0_INDEF, 2 )
#define writeEndIndef( stream ) swrite( stream, BER_END_INDEF, 2 )
RETVAL_RANGE( MAX_ERROR, TRUE ) STDC_NONNULL_ARG( ( 1 ) ) \
int checkEOC( STREAM *stream );
/****************************************************************************
* *
* ASN.1 Function Prototypes *
* *
****************************************************************************/
/* Read/peek at a tag and make sure that it's (approximately) valid, and
write a tag. The latter translates directly to sputc(), but we use a
macro to make explicit what's going on */
RETVAL_RANGE( MAX_ERROR, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \
int readTag( INOUT STREAM *stream );
RETVAL_RANGE( MAX_ERROR, 0xFF ) STDC_NONNULL_ARG( ( 1 ) ) \
int peekTag( INOUT STREAM *stream );
#define writeTag( stream, tag ) sputc( stream, tag )
/* Determine the size of an object once it's wrapped up with a tag and
length */
RETVAL_RANGE( MAX_ERROR, MAX_INTLENGTH ) \
long sizeofObject( IN_LENGTH const long length );
/* Generalized ASN.1 type manipulation routines. readRawObject() reads a
complete object (including tag and length data) while readUniversal()
just skips it. Since readRawObject() always requires a tag, we don't
have the xxx/xxxData() variants that exist for other functions */
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int readUniversalData( INOUT STREAM *stream );
RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
int readUniversal( INOUT STREAM *stream );
CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int readRawObject( INOUT STREAM *stream,
OUT_BUFFER( bufferMaxLength, bufferLength ) \
BYTE *buffer,
IN_LENGTH_SHORT_MIN( 3 ) const int bufferMaxLength,
OUT_LENGTH_SHORT_Z int *bufferLength,
IN_TAG_ENCODED const int tag );
#define writeRawObject( stream, object, size ) \
swrite( stream, object, size )
/* Routines for handling OBJECT IDENTIFIERS. The sizeof() macro determines
the length of an encoded object identifier as tag + length + value.
Write OID routines equivalent to the ones for other ASN.1 types don't
exist since OIDs are always read and written as a blob with sread()/
swrite(). OIDs are never tagged so we don't need any special-case
handling for tags.
When there's a choice of possible OIDs, the list of OID values and
corresponding selection IDs is provided in an OID_INFO structure (we also
provide a shortcut readFixedOID() function when there's only a single OID
that's valid at that point). The read OID value is checked against each
OID in the OID_INFO list, if a match is found the selectionID is returned.
The OID_INFO includes a pointer to further user-supplied information
related to this OID that may be used by the user, set when the OID list
is initialised. For example it could point to OID-specific handlers for
the data. When the caller needs to work with the extraInfo field, it's
necessary to return the complete OID_INFO entry rather than just the
selection ID, which is done by the ..Ex() form of the function */
typedef struct {
const BYTE FAR_BSS *oid;/* OID */
const int selectionID; /* Value to return for this OID */
const void *extraInfo; /* Additional info for this selection */
} OID_INFO;
#define sizeofOID( oid ) ( 1 + 1 + ( int ) oid[ 1 ] )
RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int readOID( INOUT STREAM *stream,
IN_ARRAY( noOidSelectionEntries ) \
const OID_INFO *oidSelection,
IN_RANGE( 1, 50 ) const int noOidSelectionEntries,
OUT_RANGE( CRYPT_ERROR, noOidSelectionEntries ) \
int *selectionID );
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readOIDEx( INOUT STREAM *stream,
IN_ARRAY( noOidSelectionEntries ) \
const OID_INFO *oidSelection,
IN_RANGE( 1, 50 ) const int noOidSelectionEntries,
OUT_OPT_PTR const OID_INFO **oidSelectionValue );
RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
int readFixedOID( INOUT STREAM *stream,
IN_BUFFER( oidLength ) \
const BYTE *oid, IN_LENGTH_OID const int oidLength );
RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
int readEncodedOID( INOUT STREAM *stream,
OUT_BUFFER( oidMaxLength, *oidLength ) \
BYTE *oid,
IN_LENGTH_SHORT_MIN( 5 ) const int oidMaxLength,
OUT_LENGTH_SHORT_Z int *oidLength,
IN_TAG_EXT const int tag );
#define writeOID( stream, oid ) \
swrite( ( stream ), ( oid ), sizeofOID( oid ) )
/* Routines for handling large integers. When we're writing these we can't
use sizeofObject() directly because the internal representation is
unsigned whereas the encoded form is signed. The following macro performs
the appropriate conversion on the data length before passing it on to
sizeofObject() */
#define sizeofInteger( value, valueLength ) \
( int ) sizeofObject( ( valueLength ) + \
( ( *( BYTE * )( value ) & 0x80 ) ? 1 : 0 ) )
RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
int readIntegerTag( INOUT STREAM *stream,
OUT_BUFFER_OPT( integerMaxLength, *integerLength ) \
BYTE *integer,
IN_LENGTH_SHORT const int integerMaxLength,
OUT_LENGTH_SHORT_Z int *integerLength,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -