michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * Types for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished michael@0: * Encoding Rules). michael@0: */ michael@0: michael@0: #ifndef _SECASN1T_H_ michael@0: #define _SECASN1T_H_ michael@0: michael@0: #include "utilrename.h" michael@0: michael@0: /* michael@0: ** An array of these structures defines a BER/DER encoding for an object. michael@0: ** michael@0: ** The array usually starts with a dummy entry whose kind is SEC_ASN1_SEQUENCE; michael@0: ** such an array is terminated with an entry where kind == 0. (An array michael@0: ** which consists of a single component does not require a second dummy michael@0: ** entry -- the array is only searched as long as previous component(s) michael@0: ** instruct it.) michael@0: */ michael@0: typedef struct sec_ASN1Template_struct { michael@0: /* michael@0: ** Kind of item being decoded/encoded, including tags and modifiers. michael@0: */ michael@0: unsigned long kind; michael@0: michael@0: /* michael@0: ** The value is the offset from the base of the structure to the michael@0: ** field that holds the value being decoded/encoded. michael@0: */ michael@0: unsigned long offset; michael@0: michael@0: /* michael@0: ** When kind suggests it (SEC_ASN1_POINTER, SEC_ASN1_GROUP, SEC_ASN1_INLINE, michael@0: ** or a component that is *not* a SEC_ASN1_UNIVERSAL), this points to michael@0: ** a sub-template for nested encoding/decoding, michael@0: ** OR, iff SEC_ASN1_DYNAMIC is set, then this is a pointer to a pointer michael@0: ** to a function which will return the appropriate template when called michael@0: ** at runtime. NOTE! that explicit level of indirection, which is michael@0: ** necessary because ANSI does not allow you to store a function michael@0: ** pointer directly as a "void *" so we must store it separately and michael@0: ** dereference it to get at the function pointer itself. michael@0: */ michael@0: const void *sub; michael@0: michael@0: /* michael@0: ** In the first element of a template array, the value is the size michael@0: ** of the structure to allocate when this template is being referenced michael@0: ** by another template via SEC_ASN1_POINTER or SEC_ASN1_GROUP. michael@0: ** In all other cases, the value is ignored. michael@0: */ michael@0: unsigned int size; michael@0: } SEC_ASN1Template; michael@0: michael@0: michael@0: /* default size used for allocation of encoding/decoding stuff */ michael@0: /* XXX what is the best value here? */ michael@0: #define SEC_ASN1_DEFAULT_ARENA_SIZE (2048) michael@0: michael@0: /* michael@0: ** BER/DER values for ASN.1 identifier octets. michael@0: */ michael@0: #define SEC_ASN1_TAG_MASK 0xff michael@0: michael@0: /* michael@0: * BER/DER universal type tag numbers. michael@0: * The values are defined by the X.208 standard; do not change them! michael@0: * NOTE: if you add anything to this list, you must add code to secasn1d.c michael@0: * to accept the tag, and probably also to secasn1e.c to encode it. michael@0: * XXX It appears some have been added recently without being added to michael@0: * the code; so need to go through the list now and double-check them all. michael@0: * (Look especially at those added in revision 1.10.) michael@0: */ michael@0: #define SEC_ASN1_TAGNUM_MASK 0x1f michael@0: #define SEC_ASN1_BOOLEAN 0x01 michael@0: #define SEC_ASN1_INTEGER 0x02 michael@0: #define SEC_ASN1_BIT_STRING 0x03 michael@0: #define SEC_ASN1_OCTET_STRING 0x04 michael@0: #define SEC_ASN1_NULL 0x05 michael@0: #define SEC_ASN1_OBJECT_ID 0x06 michael@0: #define SEC_ASN1_OBJECT_DESCRIPTOR 0x07 michael@0: /* External type and instance-of type 0x08 */ michael@0: #define SEC_ASN1_REAL 0x09 michael@0: #define SEC_ASN1_ENUMERATED 0x0a michael@0: #define SEC_ASN1_EMBEDDED_PDV 0x0b michael@0: #define SEC_ASN1_UTF8_STRING 0x0c michael@0: /* 0x0d */ michael@0: /* 0x0e */ michael@0: /* 0x0f */ michael@0: #define SEC_ASN1_SEQUENCE 0x10 michael@0: #define SEC_ASN1_SET 0x11 michael@0: #define SEC_ASN1_NUMERIC_STRING 0x12 michael@0: #define SEC_ASN1_PRINTABLE_STRING 0x13 michael@0: #define SEC_ASN1_T61_STRING 0x14 michael@0: #define SEC_ASN1_VIDEOTEX_STRING 0x15 michael@0: #define SEC_ASN1_IA5_STRING 0x16 michael@0: #define SEC_ASN1_UTC_TIME 0x17 michael@0: #define SEC_ASN1_GENERALIZED_TIME 0x18 michael@0: #define SEC_ASN1_GRAPHIC_STRING 0x19 michael@0: #define SEC_ASN1_VISIBLE_STRING 0x1a michael@0: #define SEC_ASN1_GENERAL_STRING 0x1b michael@0: #define SEC_ASN1_UNIVERSAL_STRING 0x1c michael@0: /* 0x1d */ michael@0: #define SEC_ASN1_BMP_STRING 0x1e michael@0: #define SEC_ASN1_HIGH_TAG_NUMBER 0x1f michael@0: #define SEC_ASN1_TELETEX_STRING SEC_ASN1_T61_STRING michael@0: michael@0: /* michael@0: ** Modifiers to type tags. These are also specified by a/the michael@0: ** standard, and must not be changed. michael@0: */ michael@0: michael@0: #define SEC_ASN1_METHOD_MASK 0x20 michael@0: #define SEC_ASN1_PRIMITIVE 0x00 michael@0: #define SEC_ASN1_CONSTRUCTED 0x20 michael@0: michael@0: #define SEC_ASN1_CLASS_MASK 0xc0 michael@0: #define SEC_ASN1_UNIVERSAL 0x00 michael@0: #define SEC_ASN1_APPLICATION 0x40 michael@0: #define SEC_ASN1_CONTEXT_SPECIFIC 0x80 michael@0: #define SEC_ASN1_PRIVATE 0xc0 michael@0: michael@0: /* michael@0: ** Our additions, used for templates. michael@0: ** These are not defined by any standard; the values are used internally only. michael@0: ** Just be careful to keep them out of the low 8 bits. michael@0: ** XXX finish comments michael@0: */ michael@0: #define SEC_ASN1_OPTIONAL 0x00100 michael@0: #define SEC_ASN1_EXPLICIT 0x00200 michael@0: #define SEC_ASN1_ANY 0x00400 michael@0: #define SEC_ASN1_INLINE 0x00800 michael@0: #define SEC_ASN1_POINTER 0x01000 michael@0: #define SEC_ASN1_GROUP 0x02000 /* with SET or SEQUENCE means michael@0: * SET OF or SEQUENCE OF */ michael@0: #define SEC_ASN1_DYNAMIC 0x04000 /* subtemplate is found by calling michael@0: * a function at runtime */ michael@0: #define SEC_ASN1_SKIP 0x08000 /* skip a field; only for decoding */ michael@0: #define SEC_ASN1_INNER 0x10000 /* with ANY means capture the michael@0: * contents only (not the id, len, michael@0: * or eoc); only for decoding */ michael@0: #define SEC_ASN1_SAVE 0x20000 /* stash away the encoded bytes first; michael@0: * only for decoding */ michael@0: #define SEC_ASN1_MAY_STREAM 0x40000 /* field or one of its sub-fields may michael@0: * stream in and so should encode as michael@0: * indefinite-length when streaming michael@0: * has been indicated; only for michael@0: * encoding */ michael@0: #define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; michael@0: only for decoding */ michael@0: #define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */ michael@0: #define SEC_ASN1_NO_STREAM 0X200000 /* This entry will not stream michael@0: even if the sub-template says michael@0: streaming is possible. Helps michael@0: to solve ambiguities with potential michael@0: streaming entries that are michael@0: optional */ michael@0: #define SEC_ASN1_DEBUG_BREAK 0X400000 /* put this in your template and the michael@0: decoder will assert when it michael@0: processes it. Only for use with michael@0: SEC_QuickDERDecodeItem */ michael@0: michael@0: michael@0: michael@0: /* Shorthand/Aliases */ michael@0: #define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE) michael@0: #define SEC_ASN1_SET_OF (SEC_ASN1_GROUP | SEC_ASN1_SET) michael@0: #define SEC_ASN1_ANY_CONTENTS (SEC_ASN1_ANY | SEC_ASN1_INNER) michael@0: michael@0: /* Maximum depth of nested SEQUENCEs and SETs */ michael@0: #define SEC_ASN1D_MAX_DEPTH 32 michael@0: michael@0: /* michael@0: ** Function used for SEC_ASN1_DYNAMIC. michael@0: ** "arg" is a pointer to the structure being encoded/decoded michael@0: ** "enc", when true, means that we are encoding (false means decoding) michael@0: */ michael@0: typedef const SEC_ASN1Template * SEC_ASN1TemplateChooser(void *arg, PRBool enc); michael@0: typedef SEC_ASN1TemplateChooser * SEC_ASN1TemplateChooserPtr; michael@0: michael@0: #if defined(_WIN32) || defined(ANDROID) michael@0: #define SEC_ASN1_GET(x) NSS_Get_##x(NULL, PR_FALSE) michael@0: #define SEC_ASN1_SUB(x) &p_NSS_Get_##x michael@0: #define SEC_ASN1_XTRN SEC_ASN1_DYNAMIC michael@0: #define SEC_ASN1_MKSUB(x) \ michael@0: static const SEC_ASN1TemplateChooserPtr p_NSS_Get_##x = &NSS_Get_##x; michael@0: #else michael@0: #define SEC_ASN1_GET(x) x michael@0: #define SEC_ASN1_SUB(x) x michael@0: #define SEC_ASN1_XTRN 0 michael@0: #define SEC_ASN1_MKSUB(x) michael@0: #endif michael@0: michael@0: #define SEC_ASN1_CHOOSER_DECLARE(x) \ michael@0: extern const SEC_ASN1Template * NSS_Get_##x (void *arg, PRBool enc); michael@0: michael@0: #define SEC_ASN1_CHOOSER_IMPLEMENT(x) \ michael@0: const SEC_ASN1Template * NSS_Get_##x(void * arg, PRBool enc) \ michael@0: { return x; } michael@0: michael@0: /* michael@0: ** Opaque object used by the decoder to store state. michael@0: */ michael@0: typedef struct sec_DecoderContext_struct SEC_ASN1DecoderContext; michael@0: michael@0: /* michael@0: ** Opaque object used by the encoder to store state. michael@0: */ michael@0: typedef struct sec_EncoderContext_struct SEC_ASN1EncoderContext; michael@0: michael@0: /* michael@0: * This is used to describe to a filter function the bytes that are michael@0: * being passed to it. This is only useful when the filter is an "outer" michael@0: * one, meaning it expects to get *all* of the bytes not just the michael@0: * contents octets. michael@0: */ michael@0: typedef enum { michael@0: SEC_ASN1_Identifier = 0, michael@0: SEC_ASN1_Length = 1, michael@0: SEC_ASN1_Contents = 2, michael@0: SEC_ASN1_EndOfContents = 3 michael@0: } SEC_ASN1EncodingPart; michael@0: michael@0: /* michael@0: * Type of the function pointer used either for decoding or encoding, michael@0: * when doing anything "funny" (e.g. manipulating the data stream) michael@0: */ michael@0: typedef void (* SEC_ASN1NotifyProc)(void *arg, PRBool before, michael@0: void *dest, int real_depth); michael@0: michael@0: /* michael@0: * Type of the function pointer used for grabbing encoded bytes. michael@0: * This can be used during either encoding or decoding, as follows... michael@0: * michael@0: * When decoding, this can be used to filter the encoded bytes as they michael@0: * are parsed. This is what you would do if you wanted to process the data michael@0: * along the way (like to decrypt it, or to perform a hash on it in order michael@0: * to do a signature check later). See SEC_ASN1DecoderSetFilterProc(). michael@0: * When processing only part of the encoded bytes is desired, you "watch" michael@0: * for the field(s) you are interested in with a "notify proc" (see michael@0: * SEC_ASN1DecoderSetNotifyProc()) and for even finer granularity (e.g. to michael@0: * ignore all by the contents bytes) you pay attention to the "data_kind" michael@0: * parameter. michael@0: * michael@0: * When encoding, this is the specification for the output function which michael@0: * will receive the bytes as they are encoded. The output function can michael@0: * perform any postprocessing necessary (like hashing (some of) the data michael@0: * to create a digest that gets included at the end) as well as shoving michael@0: * the data off wherever it needs to go. (In order to "tune" any processing, michael@0: * you can set a "notify proc" as described above in the decoding case.) michael@0: * michael@0: * The parameters: michael@0: * - "arg" is an opaque pointer that you provided at the same time you michael@0: * specified a function of this type michael@0: * - "data" is a buffer of length "len", containing the encoded bytes michael@0: * - "depth" is how deep in a nested encoding we are (it is not usually michael@0: * valuable, but can be useful sometimes so I included it) michael@0: * - "data_kind" tells you if these bytes are part of the ASN.1 encoded michael@0: * octets for identifier, length, contents, or end-of-contents michael@0: */ michael@0: typedef void (* SEC_ASN1WriteProc)(void *arg, michael@0: const char *data, unsigned long len, michael@0: int depth, SEC_ASN1EncodingPart data_kind); michael@0: michael@0: #endif /* _SECASN1T_H_ */