1 /****************************************************************************
2 *																			*
3 *						  ASN.1 Constants and Structures					*
4 *						Copyright Peter Gutmann 1992-2015					*
5 *																			*
6 ****************************************************************************/
7 
8 #ifndef _ASN1_DEFINED
9 
10 #define _ASN1_DEFINED
11 
12 #include <time.h>
13 #if defined( INC_ALL )
14   #include "stream.h"
15 #else
16   #include "io/stream.h"
17 #endif /* Compiler-specific includes */
18 
19 #ifdef USE_INT_ASN1
20 
21 /****************************************************************************
22 *																			*
23 *						BER/DER Constants and Macros						*
24 *																			*
25 ****************************************************************************/
26 
27 /* Definitions for the ISO 8825:1990 Basic Encoding Rules */
28 
29 /* Tag class */
30 
31 #define BER_UNIVERSAL			0x00
32 #define BER_APPLICATION			0x40
33 #define BER_CONTEXT_SPECIFIC	0x80
34 #define BER_PRIVATE				0xC0
35 
36 /* Whether the encoding is constructed or primitive */
37 
38 #define BER_CONSTRUCTED			0x20
39 #define BER_PRIMITIVE			0x00
40 
41 /* The ID's for universal tag numbers 0-31.  Tag number 0 is reserved for
42    encoding the end-of-contents value when an indefinite-length encoding
43    is used */
44 
45 enum { BER_ID_RESERVED, BER_ID_BOOLEAN, BER_ID_INTEGER, BER_ID_BITSTRING,
46 	   BER_ID_OCTETSTRING, BER_ID_NULL, BER_ID_OBJECT_IDENTIFIER,
47 	   BER_ID_OBJECT_DESCRIPTOR, BER_ID_EXTERNAL, BER_ID_REAL,
48 	   BER_ID_ENUMERATED, BER_ID_EMBEDDED_PDV, BER_ID_STRING_UTF8, BER_ID_13,
49 	   BER_ID_14, BER_ID_15, BER_ID_SEQUENCE, BER_ID_SET,
50 	   BER_ID_STRING_NUMERIC, BER_ID_STRING_PRINTABLE, BER_ID_STRING_T61,
51 	   BER_ID_STRING_VIDEOTEX, BER_ID_STRING_IA5, BER_ID_TIME_UTC,
52 	   BER_ID_TIME_GENERALIZED, BER_ID_STRING_GRAPHIC, BER_ID_STRING_ISO646,
53 	   BER_ID_STRING_GENERAL, BER_ID_STRING_UNIVERSAL, BER_ID_29,
54 	   BER_ID_STRING_BMP, BER_ID_LAST };
55 
56 /* The encodings for the universal types */
57 
58 #define BER_EOC					0	/* Pseudo-type for first EOC octet */
59 #define BER_RESERVED			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_RESERVED )
60 #define BER_BOOLEAN				( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BOOLEAN )
61 #define BER_INTEGER				( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_INTEGER )
62 #define BER_BITSTRING			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BITSTRING )
63 #define BER_OCTETSTRING			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OCTETSTRING )
64 #define BER_NULL				( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_NULL )
65 #define BER_OBJECT_IDENTIFIER	( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_IDENTIFIER )
66 #define BER_OBJECT_DESCRIPTOR	( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_OBJECT_DESCRIPTOR )
67 #define BER_EXTERNAL			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EXTERNAL )
68 #define BER_REAL				( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_REAL )
69 #define BER_ENUMERATED			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_ENUMERATED )
70 #define BER_EMBEDDED_PDV		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_EMBEDDED_PDV )
71 #define BER_STRING_UTF8			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UTF8 )
72 #define BER_13					( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_13 )
73 #define BER_14					( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_14 )
74 #define BER_15					( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_15 )
75 #define BER_SEQUENCE			( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SEQUENCE )
76 #define BER_SET					( BER_UNIVERSAL | BER_CONSTRUCTED | BER_ID_SET )
77 #define BER_STRING_NUMERIC		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_NUMERIC )
78 #define BER_STRING_PRINTABLE	( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_PRINTABLE )
79 #define BER_STRING_T61			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_T61 )
80 #define BER_STRING_VIDEOTEX		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_VIDEOTEX )
81 #define BER_STRING_IA5			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_IA5 )
82 #define BER_TIME_UTC			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_UTC )
83 #define BER_TIME_GENERALIZED	( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_TIME_GENERALIZED )
84 #define BER_STRING_GRAPHIC		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GRAPHIC )
85 #define BER_STRING_ISO646		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_ISO646 )
86 #define BER_STRING_GENERAL		( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_GENERAL )
87 #define BER_STRING_UNIVERSAL	( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_UNIVERSAL )
88 #define BER_29					( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_BER29 )
89 #define BER_STRING_BMP			( BER_UNIVERSAL | BER_PRIMITIVE | BER_ID_STRING_BMP )
90 
91 /* The encodings for constructed, indefinite-length tags and lengths */
92 
93 #define BER_OCTETSTRING_INDEF	MKDATA( "\x24\x80" )
94 #define BER_SEQUENCE_INDEF		MKDATA( "\x30\x80" )
95 #define BER_SET_INDEF			MKDATA( "\x31\x80" )
96 #define BER_CTAG0_INDEF			MKDATA( "\xA0\x80" )
97 #define BER_END_INDEF			MKDATA( "\x00\x00" )
98 
99 /* Masks to extract information from a tag number */
100 
101 #define BER_CLASS_MASK			0xC0
102 #define BER_CONSTRUCTED_MASK	0x20
103 #define BER_SHORT_ID_MASK		0x1F
104 
105 /* The maximum value for the short tag encoding, and the magic value which
106    indicates that a long encoding of the number is being used */
107 
108 #define MAX_SHORT_BER_ID		( BER_STRING_BMP + 1 )
109 #define LONG_BER_ID				0x1F
110 
111 /* Turn an identifier into a context-specific tag, and extract the value from
112    a tag.  Normally these are constructed, but in a few special cases they
113    are primitive */
114 
115 #define MAKE_CTAG( identifier ) \
116 		( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | ( identifier ) )
117 #define MAKE_CTAG_PRIMITIVE( identifier ) \
118 		( BER_CONTEXT_SPECIFIC | ( identifier ) )
119 #define EXTRACT_CTAG( tag ) \
120 		( ( tag ) & ~( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED ) )
121 
122 /****************************************************************************
123 *																			*
124 *							ASN.1 Constants and Macros						*
125 *																			*
126 ****************************************************************************/
127 
128 /* Special-case tags.  If DEFAULT_TAG is given the basic type (e.g. INTEGER,
129    ENUMERATED) is used, otherwise the value is used as a context-specific
130    tag.  If NO_TAG is given, processing of the tag is skipped.  If ANY_TAG
131    is given, the tag is ignored.  The parentheses are to catch potential
132    erroneous use in an expression */
133 
134 #define DEFAULT_TAG			( -1 )
135 #define NO_TAG				( -2 )
136 #define ANY_TAG				( -3 )
137 
138 /* The highest encoded tag value */
139 
140 #define MAX_TAG				( BER_CONTEXT_SPECIFIC | BER_CONSTRUCTED | \
141 							  MAX_SHORT_BER_ID )
142 
143 /* The highest allowed raw tag value before encoding as a primitive or
144    constructed tag or before encoding as a content-specific tag.  In
145    addition to the standard MAX_TAG_VALUE we also have a value for universal
146    tags whose basic form is constructed (SETs and SEQUENCES), which would
147    fall outside the normal MAX_TAG_VALUE range.
148 
149    Due to CMP's braindamaged use of tag values to communicate message type
150    information we have to be fairly permissive with the context-specific
151    tag range because CMP burns up tag values up to the mid-20s, however we
152    can restrict the range if CMP isn't being used */
153 
154 #define MAX_TAG_VALUE		MAX_SHORT_BER_ID
155 #define MAX_CONSTR_TAG_VALUE BER_SET
156 #ifdef USE_CMP
157   #define MAX_CTAG_VALUE	30
158 #else
159   #define MAX_CTAG_VALUE	10
160 #endif /* USE_CMP */
161 
162 /* The minimum and maximum allowed size for an (encoded) object identifier */
163 
164 #define MIN_OID_SIZE		5
165 #define MAX_OID_SIZE		32
166 
167 /* When reading an OID selection with readOID() we sometimes need to allow
168    a catch-all default value that's used when nothing else matches.  This is
169    typically used for type-and-value data where we want to ignore anything
170    that we don't recognise.  The following value is used as a match-all
171    wildcard.  It's longer than any normal OID to make it possible to do a
172    quick-reject match based only on the length.  The second byte is set to
173    0x0E (= 14) to make the standard sizeofOID() macro work, since this
174    examines the length field of the encoded OID */
175 
176 #define WILDCARD_OID		( const BYTE * ) \
177 							"\xFF\x0E\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00\xFF\x00"
178 #define WILDCARD_OID_SIZE	16
179 
180 /* A macro to make make declaring OIDs simpler */
181 
182 #define MKOID( value )		( ( const BYTE * ) value )
183 
184 /* Macros and functions to work with indefinite-length tags.  The only ones
185    used are SEQUENCE and [0] (for the outer encapsulation) and OCTET STRING
186    (for the data itself) */
187 
188 #define writeOctetStringIndef( stream )	swrite( stream, BER_OCTETSTRING_INDEF, 2 )
189 #define writeSequenceIndef( stream )	swrite( stream, BER_SEQUENCE_INDEF, 2 )
190 #define writeSetIndef( stream )			swrite( stream, BER_SET_INDEF, 2 )
191 #define writeCtag0Indef( stream )		swrite( stream, BER_CTAG0_INDEF, 2 )
192 #define writeEndIndef( stream )			swrite( stream, BER_END_INDEF, 2 )
193 
194 #define sizeofEOC()						2
195 RETVAL_RANGE( FALSE, TRUE ) STDC_NONNULL_ARG( ( 1 ) ) \
196 int checkEOC( INOUT STREAM *stream );
197 
198 /****************************************************************************
199 *																			*
200 *							ASN.1 Function Prototypes						*
201 *																			*
202 ****************************************************************************/
203 
204 /* Read/peek at a tag and make sure that it's (approximately) valid, and
205    write a tag.  The latter translates directly to sputc(), but we use a
206    macro to make explicit what's going on */
207 
208 RETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \
209 int readTag( INOUT STREAM *stream );
210 RETVAL_RANGE( MAX_ERROR, MAX_TAG - 1 ) STDC_NONNULL_ARG( ( 1 ) ) \
211 int peekTag( INOUT STREAM *stream );
212 #define writeTag( stream, tag )	sputc( stream, tag )
213 
214 /* peekTag() is a somewhat awkward function because it can return an error
215    code alongside the tag, so code like:
216 
217 	if( peekTag() == tag1 )
218 		status = read1();
219 	if( peekTag() == tag2 )
220 		status = read2();
221 
222    to read a sequence of optional elements can conclude with an OK status
223    but an error on the stream if an earlier peekTag() returns an error (so
224    that all sunsequent peekTags() don't match the tag).  To deal with this
225    we define a macro that checks that the status from an earlier read
226    is OK, peeks at the next tag, and checks that the result isn't an error
227    status.  The resulting usage is:
228 
229 	status = read();
230 	if( checkStatusPeekTag( stream, status, tag ) && \
231 		tag == MAKE_CTAG( 0 ) )
232 		status = read(); */
233 
234 #define checkStatusPeekTag( stream, status, tag ) \
235 		( !cryptStatusError( status ) && \
236 		  ( ( status ) = ( tag ) = peekTag( stream ), !cryptStatusError( status ) ) )
237 
238 /* Alongside the standard checkStatusPeekTag() we also provide a version
239    that checks whether we should still be looking for new tags, for use
240    when we're reading a SEQUENCE OF/SET OF.
241 
242    Note that this sets status to a non-error/CRYPT_OK value, which means
243    that the status can't be checked using cryptStatusOK() but has to be
244    checked with !cryptStatusError() */
245 
246 #define checkStatusLimitsPeekTag( stream, status, tag, endPos ) \
247 		( !cryptStatusError( status ) && \
248 		  stell( stream ) < ( endPos ) && \
249 		  ( ( status ) = ( tag ) = peekTag( stream ), !cryptStatusError( status ) ) )
250 
251 /* Determine the size of an object once it's wrapped up with a tag and
252    length */
253 
254 RETVAL_LENGTH_NOERROR \
255 long sizeofObject( IN_LENGTH_Z const long length );
256 
257 /* Generalized ASN.1 type manipulation routines.  readRawObject() reads a
258    complete object (including tag and length data) while readUniversal()
259    just skips it.  Since readRawObject() always requires a tag, we don't
260    have the xxx/xxxData() variants that exist for other functions */
261 
262 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
263 int readUniversalData( INOUT STREAM *stream );
264 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
265 int readUniversal( INOUT STREAM *stream );
266 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
267 int readRawObject( INOUT STREAM *stream,
268 				   OUT_BUFFER( bufferMaxLength, *bufferLength ) BYTE *buffer,
269 				   IN_LENGTH_SHORT_MIN( 3 ) const int bufferMaxLength,
270 				   OUT_LENGTH_BOUNDED_Z( bufferMaxLength ) \
271 						int *bufferLength,
272 				   IN_TAG_ENCODED const int tag );
273 
274 #define writeRawObject( stream, object, size ) \
275 		swrite( stream, object, size )
276 
277 /* Routines for handling OBJECT IDENTIFIERS.  The sizeof() macro determines
278    the length of an encoded object identifier as tag + length + value.
279    Write OID routines equivalent to the ones for other ASN.1 types don't
280    exist since OIDs are always read and written as a blob with sread()/
281    swrite().  OIDs are never tagged so we don't need any special-case
282    handling for tags.
283 
284    When there's a choice of possible OIDs, the list of OID values and
285    corresponding selection IDs is provided in an OID_INFO structure (we also
286    provide a shortcut readFixedOID() function when there's only a single OID
287    that's valid at that point).  The read OID value is checked against each
288    OID in the OID_INFO list, if a match is found the selectionID is returned.
289 
290    The OID_INFO includes a pointer to further user-supplied information
291    related to this OID that may be used by the user, set when the OID list
292    is initialised.  For example it could point to OID-specific handlers for
293    the data.  When the caller needs to work with the extraInfo field, it's
294    necessary to return the complete OID_INFO entry rather than just the
295    selection ID, which is done by the ..Ex() form of the function */
296 
297 typedef struct {
298 	const BYTE FAR_BSS *oid;/* OID */
299 	const int selectionID;	/* Value to return for this OID */
300 	const void *extraInfo;	/* Additional info for this selection */
301 	} OID_INFO;
302 
303 #define sizeofOID( oid )	( 1 + 1 + ( int ) oid[ 1 ] )
304 RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
305 int readOID( INOUT STREAM *stream,
306 			 IN_ARRAY( noOidSelectionEntries ) \
307 			 const OID_INFO *oidSelection,
308 			 IN_RANGE( 1, 50 ) const int noOidSelectionEntries,
309 			 OUT_RANGE( CRYPT_ERROR, noOidSelectionEntries ) \
310 			 int *selectionID );
311 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
312 int readOIDEx( INOUT STREAM *stream,
313 			   IN_ARRAY( noOidSelectionEntries ) \
314 			   const OID_INFO *oidSelection,
315 			   IN_RANGE( 1, 50 ) const int noOidSelectionEntries,
316 			   OUT_OPT_PTR_COND const OID_INFO **oidSelectionValue );
317 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
318 int readFixedOID( INOUT STREAM *stream,
319 				  IN_BUFFER( oidLength ) \
320 				  const BYTE *oid, IN_LENGTH_OID const int oidLength );
321 RETVAL STDC_NONNULL_ARG( ( 1, 2, 4 ) ) \
322 int readEncodedOID( INOUT STREAM *stream,
323 					OUT_BUFFER( oidMaxLength, *oidLength ) BYTE *oid,
324 					IN_LENGTH_SHORT_MIN( 5 ) const int oidMaxLength,
325 					OUT_LENGTH_BOUNDED_Z( oidMaxLength ) int *oidLength,
326 					IN_TAG_ENCODED const int tag );
327 #define writeOID( stream, oid ) \
328 				  swrite( ( stream ), ( oid ), sizeofOID( oid ) )
329 
330 /* Routines for handling large integers.  When we're writing these we can't
331    use sizeofObject() directly because the internal representation is
332    unsigned whereas the encoded form is signed.  The following macro performs
333    the appropriate conversion on the data length before passing it on to
334    sizeofObject() */
335 
336 #define sizeofInteger( value, valueLength ) \
337 		( int ) sizeofObject( ( valueLength ) + \
338 							  ( ( *( BYTE * )( value ) & 0x80 ) ? 1 : 0 ) )
339 
340 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
341 int readIntegerTag( INOUT STREAM *stream,
342 					OUT_BUFFER_OPT( integerMaxLength, \
343 									*integerLength ) BYTE *integer,
344 					IN_LENGTH_SHORT const int integerMaxLength,
345 					OUT_OPT_LENGTH_SHORT_Z int *integerLength,
346 					IN_TAG_EXT const int tag );
347 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
348 int writeInteger( INOUT STREAM *stream,
349 				  IN_BUFFER( integerLength ) const BYTE *integer,
350 				  IN_LENGTH_SHORT const int integerLength,
351 				  IN_TAG const int tag );
352 
353 #define readIntegerData( stream, integer, integerLength, maxLength )	\
354 		readIntegerTag( stream, integer, integerLength, maxLength, NO_TAG )
355 #define readInteger( stream, integer, integerLength, maxLength )	\
356 		readIntegerTag( stream, integer, integerLength, maxLength, DEFAULT_TAG )
357 
358 /* Routines for handling bignums.  We use void * rather than BIGNUM * to save
359    having to include the bignum header everywhere where ASN.1 is used */
360 
361 #define sizeofBignum( bignum ) \
362 		( ( int ) sizeofObject( signedBignumSize( bignum ) ) )
363 
364 RETVAL_RANGE_NOERROR( 0, MAX_INTLENGTH_SHORT ) STDC_NONNULL_ARG( ( 1 ) ) \
365 int signedBignumSize( IN TYPECAST( BIGNUM * ) const void *bignum );
366 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
367 int readBignumTag( INOUT STREAM *stream, INOUT void *bignum,
368 				   IN_LENGTH_PKC const int minLength,
369 				   IN_LENGTH_PKC const int maxLength,
370 				   IN_OPT const void *maxRange,
371 				   IN_TAG_EXT const int tag );
372 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
373 int writeBignumTag( INOUT STREAM *stream,
374 					IN const void *bignum,
375 					IN_TAG const int tag );
376 
377 #define readBignum( stream, bignum, minLen, maxLen, maxRange ) \
378 		readBignumTag( stream, bignum, minLen, maxLen, maxRange, DEFAULT_TAG )
379 #define writeBignum( stream, bignum ) \
380 		writeBignumTag( stream, bignum, DEFAULT_TAG )
381 
382 /* Special-case bignum read routine that explicitly checks for a too-short
383    key and returns CRYPT_ERROR_NOSECURE rather than the CRYPT_ERROR_BADDATA
384    that'd otherwise be returned */
385 
386 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
387 int readBignumChecked( INOUT STREAM *stream,
388 					   INOUT TYPECAST( BIGNUM * ) void *bignum,
389 					   IN_LENGTH_PKC const int minLength,
390 					   IN_LENGTH_PKC const int maxLength,
391 					   IN_OPT const void *maxRange );
392 
393 /* Generally most integers will be non-bignum values, so we also define
394    routines to handle values that will fit into a machine word */
395 
396 #define sizeofShortInteger( value )	\
397 	( ( ( value ) < 0x80 ) ? 3 : \
398 	  ( ( ( long ) value ) < 0x8000L ) ? 4 : \
399 	  ( ( ( long ) value ) < 0x800000L ) ? 5 : \
400 	  ( ( ( long ) value ) < 0x80000000UL ) ? 6 : 7 )
401 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
402 int writeShortInteger( INOUT STREAM *stream,
403 					   IN_INT_Z const long integer,
404 					   IN_TAG const int tag );
405 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
406 int readShortIntegerTag( INOUT STREAM *stream,
407 						 OUT_OPT_INT_Z long *value,
408 						 IN_TAG_EXT const int tag );
409 
410 #define readShortIntegerData( stream, integer )	\
411 		readShortIntegerTag( stream, integer, NO_TAG )
412 #define readShortInteger( stream, integer )	\
413 		readShortIntegerTag( stream, integer, DEFAULT_TAG )
414 
415 /* Routines for handling enumerations */
416 
417 #define sizeofEnumerated( value )	( ( ( value ) < 128 ) ? 3 : 4 )
418 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
419 int writeEnumerated( INOUT STREAM *stream,
420 					 IN_RANGE( 0, 999 ) const int enumerated,
421 					 IN_TAG const int tag );
422 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
423 int readEnumeratedTag( INOUT STREAM *stream,
424 					   OUT_OPT_INT_Z int *enumeration,
425 					   IN_TAG_EXT const int tag );
426 
427 #define readEnumeratedData( stream, enumeration ) \
428 		readEnumeratedTag( stream, enumeration, NO_TAG )
429 #define readEnumerated( stream, enumeration ) \
430 		readEnumeratedTag( stream, enumeration, DEFAULT_TAG )
431 
432 /* Routines for handling booleans */
433 
434 #define sizeofBoolean()	( sizeof( BYTE ) + sizeof( BYTE ) + sizeof( BYTE ) )
435 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
436 int writeBoolean( INOUT STREAM *stream, const BOOLEAN boolean,
437 				  IN_TAG const int tag );
438 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
439 int readBooleanTag( INOUT STREAM *stream,
440 					OUT_OPT_BOOL BOOLEAN *boolean,
441 					IN_TAG_EXT const int tag );
442 
443 #define readBooleanData( stream, boolean ) \
444 		readBooleanTag( stream, boolean, NO_TAG )
445 #define readBoolean( stream, boolean ) \
446 		readBooleanTag( stream, boolean, DEFAULT_TAG )
447 
448 /* Routines for handling null values */
449 
450 #define sizeofNull()	( sizeof( BYTE ) + sizeof( BYTE ) )
451 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
452 int writeNull( INOUT STREAM *stream, IN_TAG const int tag );
453 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
454 int readNullTag( INOUT STREAM *stream, IN_TAG_EXT const int tag );
455 
456 #define readNullData( stream )	readNullTag( stream, NO_TAG )
457 #define readNull( stream )		readNullTag( stream, DEFAULT_TAG )
458 
459 /* Routines for handling octet strings */
460 
461 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
462 int writeOctetString( INOUT STREAM *stream,
463 					  IN_BUFFER( length ) \
464 					  const BYTE *string,
465 					  IN_LENGTH_SHORT const int length,
466 					  IN_TAG const int tag );
467 RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
468 int readOctetStringTag( INOUT STREAM *stream,
469 						OUT_BUFFER( maxLength, *stringLength ) \
470 							BYTE *string,
471 						OUT_LENGTH_BOUNDED_Z( maxLength ) \
472 							int *stringLength,
473 						IN_LENGTH_SHORT const int minLength,
474 						IN_LENGTH_SHORT const int maxLength,
475 						IN_TAG_EXT const int tag );
476 
477 #define readOctetStringData( stream, string, stringLength, minLength, maxLength ) \
478 		readOctetStringTag( stream, string, stringLength, minLength, maxLength, NO_TAG )
479 #define readOctetString( stream, string, stringLength, minLength, maxLength ) \
480 		readOctetStringTag( stream, string, stringLength, minLength, maxLength, DEFAULT_TAG )
481 
482 /* Routines for handling character strings.  There are a number of oddball
483    character string types that are all handled through the same functions -
484    it's not worth having a seperate function to handle each of the half-dozen
485    types */
486 
487 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
488 int writeCharacterString( INOUT STREAM *stream,
489 						  IN_BUFFER( length ) const void *string,
490 						  IN_LENGTH_SHORT const int length,
491 						  IN_TAG_ENCODED const int tag );
492 RETVAL STDC_NONNULL_ARG( ( 1, 4 ) ) \
493 int readCharacterString( INOUT STREAM *stream,
494 						 OUT_BUFFER_OPT( stringMaxLength, *stringLength ) \
495 							void *string,
496 						 IN_LENGTH_SHORT const int stringMaxLength,
497 						 OUT_LENGTH_BOUNDED_Z( stringMaxLength ) \
498 							int *stringLength,
499 						 IN_TAG_EXT const int tag );
500 
501 /* Routines for handling bit strings.  The sizeof() values are 3 bytes for
502    the tag, length, and surplus-bits value, and the data itself */
503 
504 #define sizeofBitString( value )	\
505 	( 3 + ( ( ( ( long ) value ) > 0xFFFFFFL ) ? 4 : \
506 			( ( ( long ) value ) > 0xFFFFL ) ? 3 : \
507 			( ( value ) > 0xFF ) ? 2 : ( value ) ? 1 : 0 ) )
508 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
509 int writeBitString( INOUT STREAM *stream,
510 					IN_INT_Z const int bitString,
511 					IN_TAG const int tag );
512 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
513 int readBitStringTag( INOUT STREAM *stream,
514 					  OUT_OPT_INT_Z int *bitString,
515 					  IN_TAG_EXT const int tag );
516 
517 #define readBitStringData( stream, bitString ) \
518 		readBitStringTag( stream, bitString, NO_TAG )
519 #define readBitString( stream, bitString ) \
520 		readBitStringTag( stream, bitString, DEFAULT_TAG )
521 
522 /* Routines for handling UTC and Generalized time */
523 
524 #define sizeofUTCTime()			( 1 + 1 + 13 )
525 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
526 int writeUTCTime( INOUT STREAM *stream, const time_t timeVal,
527 				  IN_TAG const int tag );
528 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
529 int readUTCTimeTag( INOUT STREAM *stream, OUT time_t *timeVal,
530 					IN_TAG_EXT const int tag );
531 
532 #define readUTCTimeData( stream, time )	readUTCTimeTag( stream, time, NO_TAG )
533 #define readUTCTime( stream, time )		readUTCTimeTag( stream, time, DEFAULT_TAG )
534 
535 #define sizeofGeneralizedTime()	( 1 + 1 + 15 )
536 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
537 int writeGeneralizedTime( INOUT STREAM *stream, const time_t timeVal,
538 						  IN_TAG const int tag );
539 RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
540 int readGeneralizedTimeTag( INOUT STREAM *stream, OUT time_t *timeVal,
541 							IN_TAG_EXT const int tag );
542 
543 #define readGeneralizedTimeData( stream, time )	\
544 		readGeneralizedTimeTag( stream, time, NO_TAG )
545 #define readGeneralizedTime( stream, time )	\
546 		readGeneralizedTimeTag( stream, time, DEFAULT_TAG )
547 
548 /* Utilitity routines for reading and writing constructed objects and
549    equivalent holes.  As with the other ASN.1-read routines we need
550    variants to check for different permitted conditions:
551 
552 	Length = 1 ... MAX, most cases.
553 	Length = 0 ... MAX, occasional cases where a zero-length SEQUENCE
554 						is permitted.
555 	Length = 1 ... MAX || INDEF.
556 
557    The difference between writeOctet/BitStringHole() and writeGenericHole()
558    is that the octet/bit-string versions create a normal or context-
559    specific-tagged string while the generic version creates a pure hole with
560    no processing of tags.
561 
562    Note that readGenericHole() takes a full encoded tag value, since we
563    don't know what form it has to be turned into when reading the tag.
564    In addition it has to be able to read zero-length values in order to
565    deal with broken encodings */
566 
567 typedef enum {
568 	LENGTH_CHECK_NONE,		/* No length check type */
569 	LENGTH_CHECK_ZERO,		/* 0 ... MAX */
570 	LENGTH_CHECK_NONZERO,	/* 1 ... MAX */
571 	LENGTH_CHECK_NONZERO_INDEF,	/* 1 ... MAX || INDEF */
572 	LENGTH_CHECK_LAST		/* Last possible length check type */
573 	} LENGTH_CHECK_TYPE;
574 
575 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
576 PARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \
577 PARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \
578 int readSequenceExt( INOUT STREAM *stream,
579 					 /* PARAMCHECK */ int *length,
580 					 IN_ENUM( LENGTH_CHECK ) \
581 						const LENGTH_CHECK_TYPE lengthCheckType );
582 #define readSequence( stream, length ) \
583 		readSequenceExt( stream, length, LENGTH_CHECK_NONZERO )
584 #define readSequenceZ( stream, length ) \
585 		readSequenceExt( stream, length, LENGTH_CHECK_ZERO )
586 #define readSequenceI( stream, length ) \
587 		readSequenceExt( stream, length, LENGTH_CHECK_NONZERO_INDEF )
588 
589 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
590 PARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \
591 PARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \
592 int readSetExt( INOUT STREAM *stream,
593 				/* PARAMCHECK */ int *length,
594 				IN_ENUM( LENGTH_CHECK ) \
595 					const LENGTH_CHECK_TYPE lengthCheckType );
596 #define readSet( stream, length ) \
597 		readSetExt( stream, length, LENGTH_CHECK_NONZERO )
598 #define readSetZ( stream, length ) \
599 		readSetExt( stream, length, LENGTH_CHECK_ZERO )
600 #define readSetI( stream, length ) \
601 		readSetExt( stream, length, LENGTH_CHECK_NONZERO_INDEF )
602 
603 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
604 PARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \
605 PARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT ) \
606 int readConstructedExt( INOUT STREAM *stream,
607 						/* PARAMCHECK */ int *length,
608 						IN_TAG const int tag,
609 						IN_ENUM( LENGTH_CHECK ) \
610 							const LENGTH_CHECK_TYPE lengthCheckType );
611 #define readConstructed( stream, length, tag ) \
612 		readConstructedExt( stream, length, tag, LENGTH_CHECK_NONZERO )
613 #define readConstructedZ( stream, length, tag ) \
614 		readConstructedExt( stream, length, tag, LENGTH_CHECK_ZERO )
615 #define readConstructedI( stream, length, tag ) \
616 		readConstructedExt( stream, length, tag, LENGTH_CHECK_NONZERO_INDEF )
617 
618 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
619 int readOctetStringHole( INOUT STREAM *stream,
620 						 OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,
621 						 IN_LENGTH_SHORT const int minLength,
622 						 IN_TAG const int tag );
623 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
624 int readBitStringHole( INOUT STREAM *stream,
625 					   OUT_OPT_LENGTH_SHORT_MIN( minLength ) int *length,
626 					   IN_LENGTH_SHORT const int minLength,
627 					   IN_TAG const int tag );
628 
629 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
630 PARAMCHECK( lengthCheckType == LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_SHORT_Z ) \
631 PARAMCHECK( lengthCheckType != LENGTH_CHECK_ZERO, length, OUT_OPT_LENGTH_MIN( minLength ) ) \
632 int readGenericHoleExt( INOUT STREAM *stream,
633 						/* PARAMCHECK */ int *length,
634 						IN_LENGTH_SHORT_Z const int minLength,
635 						IN_TAG_ENCODED const int tag,
636 						IN_ENUM( LENGTH_CHECK ) \
637 							const LENGTH_CHECK_TYPE lengthCheckType );
638 #define readGenericHole( stream, length, minLength, tag ) \
639 		readGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_NONZERO )
640 #define readGenericHoleZ( stream, length, minLength, tag ) \
641 		readGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_ZERO )
642 #define readGenericHoleI( stream, length, minLength, tag ) \
643 		readGenericHoleExt( stream, length, minLength, tag, LENGTH_CHECK_NONZERO_INDEF )
644 
645 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
646 int writeSequence( INOUT STREAM *stream,
647 				   IN_LENGTH_Z const int length );
648 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
649 int writeSet( INOUT STREAM *stream,
650 			  IN_LENGTH_SHORT_Z const int length );
651 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
652 int writeConstructed( INOUT STREAM *stream,
653 					  IN_LENGTH_Z const int length,
654 					  IN_TAG const int tag );
655 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
656 int writeOctetStringHole( INOUT STREAM *stream,
657 						  IN_LENGTH_Z const int length,
658 						  IN_TAG const int tag );
659 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
660 int writeBitStringHole( INOUT STREAM *stream,
661 						IN_LENGTH_SHORT_Z const int length,
662 						IN_TAG const int tag );
663 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
664 int writeGenericHole( INOUT STREAM *stream,
665 					  IN_LENGTH_Z const int length,
666 					  IN_TAG const int tag );
667 
668 /* Read a generic object header, used to find the length of an object being
669    read as a blob */
670 
671 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
672 int readGenericObjectHeader( INOUT STREAM *stream,
673 							 OUT_LENGTH_INDEF long *length,
674 							 const BOOLEAN isLongObject );
675 
676 /* Read an arbitrary-length constructed object's data into a memory buffer.
677    This is the arbitrary-length form of readRawObject() */
678 
679 #define OBJECT_HEADER_DATA_SIZE		16
680 
681 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2, 3 ) ) \
682 int readRawObjectAlloc( INOUT STREAM *stream,
683 						OUT_BUFFER_ALLOC_OPT( *objectLengthPtr ) \
684 							void **objectPtrPtr,
685 						OUT_LENGTH_BOUNDED_Z( maxLength ) \
686 							int *objectLengthPtr,
687 						IN_LENGTH_SHORT_MIN( OBJECT_HEADER_DATA_SIZE ) \
688 							const int minLength,
689 						IN_LENGTH_SHORT const int maxLength );
690 
691 /* Determine the length of an ASN.1-encoded object (this just reads the
692    outer length if present, but will burrow down into the object if necessary
693    if the length is indefinite) and check that an object has valid encoding */
694 
695 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
696 int getStreamObjectLength( INOUT STREAM *stream, OUT_DATALENGTH_Z int *length );
697 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
698 int getObjectLength( IN_BUFFER( objectLength ) \
699 					 const void *objectPtr,
700 					 IN_DATALENGTH const int objectLength,
701 					 OUT_DATALENGTH_Z int *length );
702 CHECK_RETVAL_LENGTH STDC_NONNULL_ARG( ( 1 ) ) \
703 int checkObjectEncoding( IN_BUFFER( objectLength ) const void *objectPtr,
704 						 IN_DATALENGTH const int objectLength );
705 
706 /* Full-length equivalents of length/encapsulating-object read routines.
707    These are used explicitly in the rare situations where long lengths are
708    valid, all other ASN.1 code only works with short lengths.  Because these
709    can be quite long, they allow definite or indefinite lengths.
710 
711    Note that readLongGenericHole() takes a full encoded tag value, since we
712    don't know what form it has to be turned into when reading the tag */
713 
714 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
715 int readLongSequence( INOUT STREAM *stream,
716 					  OUT_OPT_LENGTH_INDEF long *length );
717 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
718 int readLongSet( INOUT STREAM *stream, OUT_OPT_LENGTH_INDEF long *length );
719 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
720 int readLongConstructed( INOUT STREAM *stream,
721 						 OUT_OPT_LENGTH_INDEF long *length,
722 						 IN_TAG const int tag );
723 
724 RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
725 int readLongGenericHoleExt( INOUT STREAM *stream,
726 							OUT_OPT_LENGTH_INDEF long *length,
727 							IN_TAG_ENCODED const int tag,
728 							IN_ENUM( LENGTH_CHECK ) \
729 								const LENGTH_CHECK_TYPE lengthCheckType );
730 #define readLongGenericHole( stream, length, tag ) \
731 		readLongGenericHoleExt( stream, length, tag, LENGTH_CHECK_NONZERO )
732 #define readLongGenericHoleZ( stream, length, tag ) \
733 		readLongGenericHoleExt( stream, length, tag, LENGTH_CHECK_ZERO )
734 
735 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
736 int getLongStreamObjectLength( INOUT STREAM *stream,
737 							   OUT_DATALENGTH_Z long *length );
738 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
739 int getLongObjectLength( IN_BUFFER( objectLength ) const void *objectPtr,
740 						 IN_DATALENGTH const long objectLength,
741 						 OUT_DATALENGTH_Z long *length );
742 
743 #endif /* USE_INT_ASN1 */
744 #endif /* !_ASN1_DEFINED */
745