williamr@2: /* asn1t.h */ williamr@2: /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL williamr@2: * project 2000. williamr@2: */ williamr@2: /* ==================================================================== williamr@2: * Copyright (c) 2000 The OpenSSL Project. All rights reserved. williamr@2: * williamr@2: * Redistribution and use in source and binary forms, with or without williamr@2: * modification, are permitted provided that the following conditions williamr@2: * are met: williamr@2: * williamr@2: * 1. Redistributions of source code must retain the above copyright williamr@2: * notice, this list of conditions and the following disclaimer. williamr@2: * williamr@2: * 2. Redistributions in binary form must reproduce the above copyright williamr@2: * notice, this list of conditions and the following disclaimer in williamr@2: * the documentation and/or other materials provided with the williamr@2: * distribution. williamr@2: * williamr@2: * 3. All advertising materials mentioning features or use of this williamr@2: * software must display the following acknowledgment: williamr@2: * "This product includes software developed by the OpenSSL Project williamr@2: * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" williamr@2: * williamr@2: * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to williamr@2: * endorse or promote products derived from this software without williamr@2: * prior written permission. For written permission, please contact williamr@2: * licensing@OpenSSL.org. williamr@2: * williamr@2: * 5. Products derived from this software may not be called "OpenSSL" williamr@2: * nor may "OpenSSL" appear in their names without prior written williamr@2: * permission of the OpenSSL Project. williamr@2: * williamr@2: * 6. Redistributions of any form whatsoever must retain the following williamr@2: * acknowledgment: williamr@2: * "This product includes software developed by the OpenSSL Project williamr@2: * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" williamr@2: * williamr@2: * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY williamr@2: * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE williamr@2: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR williamr@2: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR williamr@2: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, williamr@2: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT williamr@2: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; williamr@2: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) williamr@2: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, williamr@2: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) williamr@2: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED williamr@2: * OF THE POSSIBILITY OF SUCH DAMAGE. williamr@2: * ==================================================================== williamr@2: * williamr@2: * This product includes cryptographic software written by Eric Young williamr@2: * (eay@cryptsoft.com). This product includes software written by Tim williamr@2: * Hudson (tjh@cryptsoft.com). williamr@2: * williamr@2: */ williamr@2: #ifndef HEADER_ASN1T_H williamr@2: #define HEADER_ASN1T_H williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #ifdef OPENSSL_BUILD_SHLIBCRYPTO williamr@2: # undef OPENSSL_EXTERN williamr@2: # define OPENSSL_EXTERN OPENSSL_EXPORT williamr@2: #endif williamr@2: williamr@2: /* ASN1 template defines, structures and functions */ williamr@2: williamr@2: #ifdef __cplusplus williamr@2: extern "C" { williamr@2: #endif williamr@2: williamr@2: williamr@2: #ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION williamr@2: williamr@2: /* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ williamr@2: #define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr)) williamr@2: williamr@2: williamr@2: /* Macros for start and end of ASN1_ITEM definition */ williamr@2: williamr@2: #define ASN1_ITEM_start(itname) \ williamr@2: OPENSSL_GLOBAL const ASN1_ITEM itname##_it = { williamr@2: williamr@2: #define ASN1_ITEM_end(itname) \ williamr@2: }; williamr@2: williamr@2: #else williamr@2: williamr@2: /* Macro to obtain ASN1_ADB pointer from a type (only used internally) */ williamr@2: #define ASN1_ADB_ptr(iptr) ((const ASN1_ADB *)(iptr())) williamr@2: williamr@2: williamr@2: /* Macros for start and end of ASN1_ITEM definition */ williamr@2: williamr@2: #define ASN1_ITEM_start(itname) \ williamr@2: EXPORT_C const ASN1_ITEM * itname##_it(void) \ williamr@2: { \ williamr@2: static const ASN1_ITEM local_it = { williamr@2: williamr@2: #define ASN1_ITEM_end(itname) \ williamr@2: }; \ williamr@2: return &local_it; \ williamr@2: } williamr@2: williamr@2: #endif williamr@2: williamr@2: williamr@2: /* Macros to aid ASN1 template writing */ williamr@2: williamr@2: #define ASN1_ITEM_TEMPLATE(tname) \ williamr@2: static const ASN1_TEMPLATE tname##_item_tt williamr@2: williamr@2: #define ASN1_ITEM_TEMPLATE_END(tname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_PRIMITIVE,\ williamr@2: -1,\ williamr@2: &tname##_item_tt,\ williamr@2: 0,\ williamr@2: NULL,\ williamr@2: 0,\ williamr@2: #tname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: williamr@2: /* This is a ASN1 type which just embeds a template */ williamr@2: williamr@2: /* This pair helps declare a SEQUENCE. We can do: williamr@2: * williamr@2: * ASN1_SEQUENCE(stname) = { williamr@2: * ... SEQUENCE components ... williamr@2: * } ASN1_SEQUENCE_END(stname) williamr@2: * williamr@2: * This will produce an ASN1_ITEM called stname_it williamr@2: * for a structure called stname. williamr@2: * williamr@2: * If you want the same structure but a different williamr@2: * name then use: williamr@2: * williamr@2: * ASN1_SEQUENCE(itname) = { williamr@2: * ... SEQUENCE components ... williamr@2: * } ASN1_SEQUENCE_END_name(stname, itname) williamr@2: * williamr@2: * This will create an item called itname_it using williamr@2: * a structure called stname. williamr@2: */ williamr@2: williamr@2: #define ASN1_SEQUENCE(tname) \ williamr@2: static const ASN1_TEMPLATE tname##_seq_tt[] williamr@2: williamr@2: #define ASN1_SEQUENCE_END(stname) ASN1_SEQUENCE_END_name(stname, stname) williamr@2: williamr@2: #define ASN1_SEQUENCE_END_name(stname, tname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_SEQUENCE,\ williamr@2: V_ASN1_SEQUENCE,\ williamr@2: tname##_seq_tt,\ williamr@2: sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ williamr@2: NULL,\ williamr@2: sizeof(stname),\ williamr@2: #stname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: #define ASN1_NDEF_SEQUENCE(tname) \ williamr@2: ASN1_SEQUENCE(tname) williamr@2: williamr@2: #define ASN1_SEQUENCE_cb(tname, cb) \ williamr@2: static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ williamr@2: ASN1_SEQUENCE(tname) williamr@2: williamr@2: #define ASN1_BROKEN_SEQUENCE(tname) \ williamr@2: static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_BROKEN, 0, 0, 0, 0}; \ williamr@2: ASN1_SEQUENCE(tname) williamr@2: williamr@2: #define ASN1_SEQUENCE_ref(tname, cb, lck) \ williamr@2: static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_REFCOUNT, offsetof(tname, references), lck, cb, 0}; \ williamr@2: ASN1_SEQUENCE(tname) williamr@2: williamr@2: #define ASN1_SEQUENCE_enc(tname, enc, cb) \ williamr@2: static const ASN1_AUX tname##_aux = {NULL, ASN1_AFLG_ENCODING, 0, 0, cb, offsetof(tname, enc)}; \ williamr@2: ASN1_SEQUENCE(tname) williamr@2: williamr@2: #define ASN1_NDEF_SEQUENCE_END(tname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_NDEF_SEQUENCE,\ williamr@2: V_ASN1_SEQUENCE,\ williamr@2: tname##_seq_tt,\ williamr@2: sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ williamr@2: NULL,\ williamr@2: sizeof(tname),\ williamr@2: #tname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: #define ASN1_BROKEN_SEQUENCE_END(stname) ASN1_SEQUENCE_END_ref(stname, stname) williamr@2: williamr@2: #define ASN1_SEQUENCE_END_enc(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) williamr@2: williamr@2: #define ASN1_SEQUENCE_END_cb(stname, tname) ASN1_SEQUENCE_END_ref(stname, tname) williamr@2: williamr@2: #define ASN1_SEQUENCE_END_ref(stname, tname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_SEQUENCE,\ williamr@2: V_ASN1_SEQUENCE,\ williamr@2: tname##_seq_tt,\ williamr@2: sizeof(tname##_seq_tt) / sizeof(ASN1_TEMPLATE),\ williamr@2: &tname##_aux,\ williamr@2: sizeof(stname),\ williamr@2: #stname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: williamr@2: /* This pair helps declare a CHOICE type. We can do: williamr@2: * williamr@2: * ASN1_CHOICE(chname) = { williamr@2: * ... CHOICE options ... williamr@2: * ASN1_CHOICE_END(chname) williamr@2: * williamr@2: * This will produce an ASN1_ITEM called chname_it williamr@2: * for a structure called chname. The structure williamr@2: * definition must look like this: williamr@2: * typedef struct { williamr@2: * int type; williamr@2: * union { williamr@2: * ASN1_SOMETHING *opt1; williamr@2: * ASN1_SOMEOTHER *opt2; williamr@2: * } value; williamr@2: * } chname; williamr@2: * williamr@2: * the name of the selector must be 'type'. williamr@2: * to use an alternative selector name use the williamr@2: * ASN1_CHOICE_END_selector() version. williamr@2: */ williamr@2: williamr@2: #define ASN1_CHOICE(tname) \ williamr@2: static const ASN1_TEMPLATE tname##_ch_tt[] williamr@2: williamr@2: #define ASN1_CHOICE_cb(tname, cb) \ williamr@2: static const ASN1_AUX tname##_aux = {NULL, 0, 0, 0, cb, 0}; \ williamr@2: ASN1_CHOICE(tname) williamr@2: williamr@2: #define ASN1_CHOICE_END(stname) ASN1_CHOICE_END_name(stname, stname) williamr@2: williamr@2: #define ASN1_CHOICE_END_name(stname, tname) ASN1_CHOICE_END_selector(stname, tname, type) williamr@2: williamr@2: #define ASN1_CHOICE_END_selector(stname, tname, selname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_CHOICE,\ williamr@2: offsetof(stname,selname) ,\ williamr@2: tname##_ch_tt,\ williamr@2: sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ williamr@2: NULL,\ williamr@2: sizeof(stname),\ williamr@2: #stname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: #define ASN1_CHOICE_END_cb(stname, tname, selname) \ williamr@2: ;\ williamr@2: ASN1_ITEM_start(tname) \ williamr@2: ASN1_ITYPE_CHOICE,\ williamr@2: offsetof(stname,selname) ,\ williamr@2: tname##_ch_tt,\ williamr@2: sizeof(tname##_ch_tt) / sizeof(ASN1_TEMPLATE),\ williamr@2: &tname##_aux,\ williamr@2: sizeof(stname),\ williamr@2: #stname \ williamr@2: ASN1_ITEM_end(tname) williamr@2: williamr@2: /* This helps with the template wrapper form of ASN1_ITEM */ williamr@2: williamr@2: #define ASN1_EX_TEMPLATE_TYPE(flags, tag, name, type) { \ williamr@2: (flags), (tag), 0,\ williamr@2: #name, ASN1_ITEM_ref(type) } williamr@2: williamr@2: /* These help with SEQUENCE or CHOICE components */ williamr@2: williamr@2: /* used to declare other types */ williamr@2: williamr@2: #define ASN1_EX_TYPE(flags, tag, stname, field, type) { \ williamr@2: (flags), (tag), offsetof(stname, field),\ williamr@2: #field, ASN1_ITEM_ref(type) } williamr@2: williamr@2: /* used when the structure is combined with the parent */ williamr@2: williamr@2: #define ASN1_EX_COMBINE(flags, tag, type) { \ williamr@2: (flags)|ASN1_TFLG_COMBINE, (tag), 0, NULL, ASN1_ITEM_ref(type) } williamr@2: williamr@2: /* implicit and explicit helper macros */ williamr@2: williamr@2: #define ASN1_IMP_EX(stname, field, type, tag, ex) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_IMPLICIT | ex, tag, stname, field, type) williamr@2: williamr@2: #define ASN1_EXP_EX(stname, field, type, tag, ex) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_EXPLICIT | ex, tag, stname, field, type) williamr@2: williamr@2: /* Any defined by macros: the field used is in the table itself */ williamr@2: williamr@2: #ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION williamr@2: #define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } williamr@2: #define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, (const ASN1_ITEM *)&(tblname##_adb) } williamr@2: #else williamr@2: #define ASN1_ADB_OBJECT(tblname) { ASN1_TFLG_ADB_OID, -1, 0, #tblname, tblname##_adb } williamr@2: #define ASN1_ADB_INTEGER(tblname) { ASN1_TFLG_ADB_INT, -1, 0, #tblname, tblname##_adb } williamr@2: #endif williamr@2: /* Plain simple type */ williamr@2: #define ASN1_SIMPLE(stname, field, type) ASN1_EX_TYPE(0,0, stname, field, type) williamr@2: williamr@2: /* OPTIONAL simple type */ williamr@2: #define ASN1_OPT(stname, field, type) ASN1_EX_TYPE(ASN1_TFLG_OPTIONAL, 0, stname, field, type) williamr@2: williamr@2: /* IMPLICIT tagged simple type */ williamr@2: #define ASN1_IMP(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, 0) williamr@2: williamr@2: /* IMPLICIT tagged OPTIONAL simple type */ williamr@2: #define ASN1_IMP_OPT(stname, field, type, tag) ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: /* Same as above but EXPLICIT */ williamr@2: williamr@2: #define ASN1_EXP(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, 0) williamr@2: #define ASN1_EXP_OPT(stname, field, type, tag) ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: /* SEQUENCE OF type */ williamr@2: #define ASN1_SEQUENCE_OF(stname, field, type) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, stname, field, type) williamr@2: williamr@2: /* OPTIONAL SEQUENCE OF */ williamr@2: #define ASN1_SEQUENCE_OF_OPT(stname, field, type) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) williamr@2: williamr@2: /* Same as above but for SET OF */ williamr@2: williamr@2: #define ASN1_SET_OF(stname, field, type) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_SET_OF, 0, stname, field, type) williamr@2: williamr@2: #define ASN1_SET_OF_OPT(stname, field, type) \ williamr@2: ASN1_EX_TYPE(ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL, 0, stname, field, type) williamr@2: williamr@2: /* Finally compound types of SEQUENCE, SET, IMPLICIT, EXPLICIT and OPTIONAL */ williamr@2: williamr@2: #define ASN1_IMP_SET_OF(stname, field, type, tag) \ williamr@2: ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) williamr@2: williamr@2: #define ASN1_EXP_SET_OF(stname, field, type, tag) \ williamr@2: ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF) williamr@2: williamr@2: #define ASN1_IMP_SET_OF_OPT(stname, field, type, tag) \ williamr@2: ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: #define ASN1_EXP_SET_OF_OPT(stname, field, type, tag) \ williamr@2: ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SET_OF|ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: #define ASN1_IMP_SEQUENCE_OF(stname, field, type, tag) \ williamr@2: ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) williamr@2: williamr@2: #define ASN1_IMP_SEQUENCE_OF_OPT(stname, field, type, tag) \ williamr@2: ASN1_IMP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: #define ASN1_EXP_SEQUENCE_OF(stname, field, type, tag) \ williamr@2: ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF) williamr@2: williamr@2: #define ASN1_EXP_SEQUENCE_OF_OPT(stname, field, type, tag) \ williamr@2: ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_SEQUENCE_OF|ASN1_TFLG_OPTIONAL) williamr@2: williamr@2: /* EXPLICIT OPTIONAL using indefinite length constructed form */ williamr@2: #define ASN1_NDEF_EXP_OPT(stname, field, type, tag) \ williamr@2: ASN1_EXP_EX(stname, field, type, tag, ASN1_TFLG_OPTIONAL|ASN1_TFLG_NDEF) williamr@2: williamr@2: /* Macros for the ASN1_ADB structure */ williamr@2: williamr@2: #define ASN1_ADB(name) \ williamr@2: static const ASN1_ADB_TABLE name##_adbtbl[] williamr@2: williamr@2: #ifndef OPENSSL_EXPORT_VAR_AS_FUNCTION williamr@2: williamr@2: #define ASN1_ADB_END(name, flags, field, app_table, def, none) \ williamr@2: ;\ williamr@2: static const ASN1_ADB name##_adb = {\ williamr@2: flags,\ williamr@2: offsetof(name, field),\ williamr@2: app_table,\ williamr@2: name##_adbtbl,\ williamr@2: sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ williamr@2: def,\ williamr@2: none\ williamr@2: } williamr@2: williamr@2: #else williamr@2: williamr@2: #define ASN1_ADB_END(name, flags, field, app_table, def, none) \ williamr@2: ;\ williamr@2: EXPORT_C static const ASN1_ITEM *name##_adb(void) \ williamr@2: { \ williamr@2: static const ASN1_ADB internal_adb = \ williamr@2: {\ williamr@2: flags,\ williamr@2: offsetof(name, field),\ williamr@2: app_table,\ williamr@2: name##_adbtbl,\ williamr@2: sizeof(name##_adbtbl) / sizeof(ASN1_ADB_TABLE),\ williamr@2: def,\ williamr@2: none\ williamr@2: }; \ williamr@2: return (const ASN1_ITEM *) &internal_adb; \ williamr@2: } \ williamr@2: void dummy_function(void) williamr@2: williamr@2: #endif williamr@2: williamr@2: #define ADB_ENTRY(val, template) {val, template} williamr@2: williamr@2: #define ASN1_ADB_TEMPLATE(name) \ williamr@2: static const ASN1_TEMPLATE name##_tt williamr@2: williamr@2: /* This is the ASN1 template structure that defines williamr@2: * a wrapper round the actual type. It determines the williamr@2: * actual position of the field in the value structure, williamr@2: * various flags such as OPTIONAL and the field name. williamr@2: */ williamr@2: williamr@2: struct ASN1_TEMPLATE_st { williamr@2: unsigned long flags; /* Various flags */ williamr@2: long tag; /* tag, not used if no tagging */ williamr@2: unsigned long offset; /* Offset of this field in structure */ williamr@2: #ifndef NO_ASN1_FIELD_NAMES williamr@2: const char *field_name; /* Field name */ williamr@2: #endif williamr@2: ASN1_ITEM_EXP *item; /* Relevant ASN1_ITEM or ASN1_ADB */ williamr@2: }; williamr@2: williamr@2: /* Macro to extract ASN1_ITEM and ASN1_ADB pointer from ASN1_TEMPLATE */ williamr@2: williamr@2: #define ASN1_TEMPLATE_item(t) (t->item_ptr) williamr@2: #define ASN1_TEMPLATE_adb(t) (t->item_ptr) williamr@2: williamr@2: typedef struct ASN1_ADB_TABLE_st ASN1_ADB_TABLE; williamr@2: typedef struct ASN1_ADB_st ASN1_ADB; williamr@2: williamr@2: struct ASN1_ADB_st { williamr@2: unsigned long flags; /* Various flags */ williamr@2: unsigned long offset; /* Offset of selector field */ williamr@2: STACK_OF(ASN1_ADB_TABLE) **app_items; /* Application defined items */ williamr@2: const ASN1_ADB_TABLE *tbl; /* Table of possible types */ williamr@2: long tblcount; /* Number of entries in tbl */ williamr@2: const ASN1_TEMPLATE *default_tt; /* Type to use if no match */ williamr@2: const ASN1_TEMPLATE *null_tt; /* Type to use if selector is NULL */ williamr@2: }; williamr@2: williamr@2: struct ASN1_ADB_TABLE_st { williamr@2: long value; /* NID for an object or value for an int */ williamr@2: const ASN1_TEMPLATE tt; /* item for this value */ williamr@2: }; williamr@2: williamr@2: /* template flags */ williamr@2: williamr@2: /* Field is optional */ williamr@2: #define ASN1_TFLG_OPTIONAL (0x1) williamr@2: williamr@2: /* Field is a SET OF */ williamr@2: #define ASN1_TFLG_SET_OF (0x1 << 1) williamr@2: williamr@2: /* Field is a SEQUENCE OF */ williamr@2: #define ASN1_TFLG_SEQUENCE_OF (0x2 << 1) williamr@2: williamr@2: /* Special case: this refers to a SET OF that williamr@2: * will be sorted into DER order when encoded *and* williamr@2: * the corresponding STACK will be modified to match williamr@2: * the new order. williamr@2: */ williamr@2: #define ASN1_TFLG_SET_ORDER (0x3 << 1) williamr@2: williamr@2: /* Mask for SET OF or SEQUENCE OF */ williamr@2: #define ASN1_TFLG_SK_MASK (0x3 << 1) williamr@2: williamr@2: /* These flags mean the tag should be taken from the williamr@2: * tag field. If EXPLICIT then the underlying type williamr@2: * is used for the inner tag. williamr@2: */ williamr@2: williamr@2: /* IMPLICIT tagging */ williamr@2: #define ASN1_TFLG_IMPTAG (0x1 << 3) williamr@2: williamr@2: williamr@2: /* EXPLICIT tagging, inner tag from underlying type */ williamr@2: #define ASN1_TFLG_EXPTAG (0x2 << 3) williamr@2: williamr@2: #define ASN1_TFLG_TAG_MASK (0x3 << 3) williamr@2: williamr@2: /* context specific IMPLICIT */ williamr@2: #define ASN1_TFLG_IMPLICIT ASN1_TFLG_IMPTAG|ASN1_TFLG_CONTEXT williamr@2: williamr@2: /* context specific EXPLICIT */ williamr@2: #define ASN1_TFLG_EXPLICIT ASN1_TFLG_EXPTAG|ASN1_TFLG_CONTEXT williamr@2: williamr@2: /* If tagging is in force these determine the williamr@2: * type of tag to use. Otherwise the tag is williamr@2: * determined by the underlying type. These williamr@2: * values reflect the actual octet format. williamr@2: */ williamr@2: williamr@2: /* Universal tag */ williamr@2: #define ASN1_TFLG_UNIVERSAL (0x0<<6) williamr@2: /* Application tag */ williamr@2: #define ASN1_TFLG_APPLICATION (0x1<<6) williamr@2: /* Context specific tag */ williamr@2: #define ASN1_TFLG_CONTEXT (0x2<<6) williamr@2: /* Private tag */ williamr@2: #define ASN1_TFLG_PRIVATE (0x3<<6) williamr@2: williamr@2: #define ASN1_TFLG_TAG_CLASS (0x3<<6) williamr@2: williamr@2: /* These are for ANY DEFINED BY type. In this case williamr@2: * the 'item' field points to an ASN1_ADB structure williamr@2: * which contains a table of values to decode the williamr@2: * relevant type williamr@2: */ williamr@2: williamr@2: #define ASN1_TFLG_ADB_MASK (0x3<<8) williamr@2: williamr@2: #define ASN1_TFLG_ADB_OID (0x1<<8) williamr@2: williamr@2: #define ASN1_TFLG_ADB_INT (0x1<<9) williamr@2: williamr@2: /* This flag means a parent structure is passed williamr@2: * instead of the field: this is useful is a williamr@2: * SEQUENCE is being combined with a CHOICE for williamr@2: * example. Since this means the structure and williamr@2: * item name will differ we need to use the williamr@2: * ASN1_CHOICE_END_name() macro for example. williamr@2: */ williamr@2: williamr@2: #define ASN1_TFLG_COMBINE (0x1<<10) williamr@2: williamr@2: /* This flag when present in a SEQUENCE OF, SET OF williamr@2: * or EXPLICIT causes indefinite length constructed williamr@2: * encoding to be used if required. williamr@2: */ williamr@2: williamr@2: #define ASN1_TFLG_NDEF (0x1<<11) williamr@2: williamr@2: /* This is the actual ASN1 item itself */ williamr@2: williamr@2: struct ASN1_ITEM_st { williamr@2: char itype; /* The item type, primitive, SEQUENCE, CHOICE or extern */ williamr@2: long utype; /* underlying type */ williamr@2: const ASN1_TEMPLATE *templates; /* If SEQUENCE or CHOICE this contains the contents */ williamr@2: long tcount; /* Number of templates if SEQUENCE or CHOICE */ williamr@2: const void *funcs; /* functions that handle this type */ williamr@2: long size; /* Structure size (usually)*/ williamr@2: #ifndef NO_ASN1_FIELD_NAMES williamr@2: const char *sname; /* Structure name */ williamr@2: #endif williamr@2: }; williamr@2: williamr@2: /* These are values for the itype field and williamr@2: * determine how the type is interpreted. williamr@2: * williamr@2: * For PRIMITIVE types the underlying type williamr@2: * determines the behaviour if items is NULL. williamr@2: * williamr@2: * Otherwise templates must contain a single williamr@2: * template and the type is treated in the williamr@2: * same way as the type specified in the template. williamr@2: * williamr@2: * For SEQUENCE types the templates field points williamr@2: * to the members, the size field is the williamr@2: * structure size. williamr@2: * williamr@2: * For CHOICE types the templates field points williamr@2: * to each possible member (typically a union) williamr@2: * and the 'size' field is the offset of the williamr@2: * selector. williamr@2: * williamr@2: * The 'funcs' field is used for application williamr@2: * specific functions. williamr@2: * williamr@2: * For COMPAT types the funcs field gives a williamr@2: * set of functions that handle this type, this williamr@2: * supports the old d2i, i2d convention. williamr@2: * williamr@2: * The EXTERN type uses a new style d2i/i2d. williamr@2: * The new style should be used where possible williamr@2: * because it avoids things like the d2i IMPLICIT williamr@2: * hack. williamr@2: * williamr@2: * MSTRING is a multiple string type, it is used williamr@2: * for a CHOICE of character strings where the williamr@2: * actual strings all occupy an ASN1_STRING williamr@2: * structure. In this case the 'utype' field williamr@2: * has a special meaning, it is used as a mask williamr@2: * of acceptable types using the B_ASN1 constants. williamr@2: * williamr@2: * NDEF_SEQUENCE is the same as SEQUENCE except williamr@2: * that it will use indefinite length constructed williamr@2: * encoding if requested. williamr@2: * williamr@2: */ williamr@2: williamr@2: #define ASN1_ITYPE_PRIMITIVE 0x0 williamr@2: williamr@2: #define ASN1_ITYPE_SEQUENCE 0x1 williamr@2: williamr@2: #define ASN1_ITYPE_CHOICE 0x2 williamr@2: williamr@2: #define ASN1_ITYPE_COMPAT 0x3 williamr@2: williamr@2: #define ASN1_ITYPE_EXTERN 0x4 williamr@2: williamr@2: #define ASN1_ITYPE_MSTRING 0x5 williamr@2: williamr@2: #define ASN1_ITYPE_NDEF_SEQUENCE 0x6 williamr@2: williamr@2: /* Cache for ASN1 tag and length, so we williamr@2: * don't keep re-reading it for things williamr@2: * like CHOICE williamr@2: */ williamr@2: williamr@2: struct ASN1_TLC_st{ williamr@2: char valid; /* Values below are valid */ williamr@2: int ret; /* return value */ williamr@2: long plen; /* length */ williamr@2: int ptag; /* class value */ williamr@2: int pclass; /* class value */ williamr@2: int hdrlen; /* header length */ williamr@2: }; williamr@2: williamr@2: /* Typedefs for ASN1 function pointers */ williamr@2: williamr@2: typedef ASN1_VALUE * ASN1_new_func(void); williamr@2: typedef void ASN1_free_func(ASN1_VALUE *a); williamr@2: typedef ASN1_VALUE * ASN1_d2i_func(ASN1_VALUE **a, const unsigned char ** in, long length); williamr@2: typedef int ASN1_i2d_func(ASN1_VALUE * a, unsigned char **in); williamr@2: williamr@2: typedef int ASN1_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, williamr@2: int tag, int aclass, char opt, ASN1_TLC *ctx); williamr@2: williamr@2: typedef int ASN1_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); williamr@2: typedef int ASN1_ex_new_func(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: typedef void ASN1_ex_free_func(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: williamr@2: typedef int ASN1_primitive_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); williamr@2: typedef int ASN1_primitive_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); williamr@2: williamr@2: typedef struct ASN1_COMPAT_FUNCS_st { williamr@2: ASN1_new_func *asn1_new; williamr@2: ASN1_free_func *asn1_free; williamr@2: ASN1_d2i_func *asn1_d2i; williamr@2: ASN1_i2d_func *asn1_i2d; williamr@2: } ASN1_COMPAT_FUNCS; williamr@2: williamr@2: typedef struct ASN1_EXTERN_FUNCS_st { williamr@2: void *app_data; williamr@2: ASN1_ex_new_func *asn1_ex_new; williamr@2: ASN1_ex_free_func *asn1_ex_free; williamr@2: ASN1_ex_free_func *asn1_ex_clear; williamr@2: ASN1_ex_d2i *asn1_ex_d2i; williamr@2: ASN1_ex_i2d *asn1_ex_i2d; williamr@2: } ASN1_EXTERN_FUNCS; williamr@2: williamr@2: typedef struct ASN1_PRIMITIVE_FUNCS_st { williamr@2: void *app_data; williamr@2: unsigned long flags; williamr@2: ASN1_ex_new_func *prim_new; williamr@2: ASN1_ex_free_func *prim_free; williamr@2: ASN1_ex_free_func *prim_clear; williamr@2: ASN1_primitive_c2i *prim_c2i; williamr@2: ASN1_primitive_i2c *prim_i2c; williamr@2: } ASN1_PRIMITIVE_FUNCS; williamr@2: williamr@2: /* This is the ASN1_AUX structure: it handles various williamr@2: * miscellaneous requirements. For example the use of williamr@2: * reference counts and an informational callback. williamr@2: * williamr@2: * The "informational callback" is called at various williamr@2: * points during the ASN1 encoding and decoding. It can williamr@2: * be used to provide minor customisation of the structures williamr@2: * used. This is most useful where the supplied routines williamr@2: * *almost* do the right thing but need some extra help williamr@2: * at a few points. If the callback returns zero then williamr@2: * it is assumed a fatal error has occurred and the williamr@2: * main operation should be abandoned. williamr@2: * williamr@2: * If major changes in the default behaviour are required williamr@2: * then an external type is more appropriate. williamr@2: */ williamr@2: williamr@2: typedef int ASN1_aux_cb(int operation, ASN1_VALUE **in, const ASN1_ITEM *it); williamr@2: williamr@2: typedef struct ASN1_AUX_st { williamr@2: void *app_data; williamr@2: int flags; williamr@2: int ref_offset; /* Offset of reference value */ williamr@2: int ref_lock; /* Lock type to use */ williamr@2: ASN1_aux_cb *asn1_cb; williamr@2: int enc_offset; /* Offset of ASN1_ENCODING structure */ williamr@2: } ASN1_AUX; williamr@2: williamr@2: /* Flags in ASN1_AUX */ williamr@2: williamr@2: /* Use a reference count */ williamr@2: #define ASN1_AFLG_REFCOUNT 1 williamr@2: /* Save the encoding of structure (useful for signatures) */ williamr@2: #define ASN1_AFLG_ENCODING 2 williamr@2: /* The Sequence length is invalid */ williamr@2: #define ASN1_AFLG_BROKEN 4 williamr@2: williamr@2: /* operation values for asn1_cb */ williamr@2: williamr@2: #define ASN1_OP_NEW_PRE 0 williamr@2: #define ASN1_OP_NEW_POST 1 williamr@2: #define ASN1_OP_FREE_PRE 2 williamr@2: #define ASN1_OP_FREE_POST 3 williamr@2: #define ASN1_OP_D2I_PRE 4 williamr@2: #define ASN1_OP_D2I_POST 5 williamr@2: #define ASN1_OP_I2D_PRE 6 williamr@2: #define ASN1_OP_I2D_POST 7 williamr@2: williamr@2: /* Macro to implement a primitive type */ williamr@2: #define IMPLEMENT_ASN1_TYPE(stname) IMPLEMENT_ASN1_TYPE_ex(stname, stname, 0) williamr@2: #define IMPLEMENT_ASN1_TYPE_ex(itname, vname, ex) \ williamr@2: ASN1_ITEM_start(itname) \ williamr@2: ASN1_ITYPE_PRIMITIVE, V_##vname, NULL, 0, NULL, ex, #itname \ williamr@2: ASN1_ITEM_end(itname) williamr@2: williamr@2: /* Macro to implement a multi string type */ williamr@2: #define IMPLEMENT_ASN1_MSTRING(itname, mask) \ williamr@2: ASN1_ITEM_start(itname) \ williamr@2: ASN1_ITYPE_MSTRING, mask, NULL, 0, NULL, sizeof(ASN1_STRING), #itname \ williamr@2: ASN1_ITEM_end(itname) williamr@2: williamr@2: /* Macro to implement an ASN1_ITEM in terms of old style funcs */ williamr@2: williamr@2: #define IMPLEMENT_COMPAT_ASN1(sname) IMPLEMENT_COMPAT_ASN1_type(sname, V_ASN1_SEQUENCE) williamr@2: williamr@2: #define IMPLEMENT_COMPAT_ASN1_type(sname, tag) \ williamr@2: static const ASN1_COMPAT_FUNCS sname##_ff = { \ williamr@2: (ASN1_new_func *)sname##_new, \ williamr@2: (ASN1_free_func *)sname##_free, \ williamr@2: (ASN1_d2i_func *)d2i_##sname, \ williamr@2: (ASN1_i2d_func *)i2d_##sname, \ williamr@2: }; \ williamr@2: ASN1_ITEM_start(sname) \ williamr@2: ASN1_ITYPE_COMPAT, \ williamr@2: tag, \ williamr@2: NULL, \ williamr@2: 0, \ williamr@2: &sname##_ff, \ williamr@2: 0, \ williamr@2: #sname \ williamr@2: ASN1_ITEM_end(sname) williamr@2: williamr@2: #define IMPLEMENT_EXTERN_ASN1(sname, tag, fptrs) \ williamr@2: ASN1_ITEM_start(sname) \ williamr@2: ASN1_ITYPE_EXTERN, \ williamr@2: tag, \ williamr@2: NULL, \ williamr@2: 0, \ williamr@2: &fptrs, \ williamr@2: 0, \ williamr@2: #sname \ williamr@2: ASN1_ITEM_end(sname) williamr@2: williamr@2: /* Macro to implement standard functions in terms of ASN1_ITEM structures */ williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS(stname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, stname, stname) williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS_name(stname, itname) IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, itname) williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS_ENCODE_name(stname, itname) \ williamr@2: IMPLEMENT_ASN1_FUNCTIONS_ENCODE_fname(stname, itname, itname) williamr@2: williamr@2: #define IMPLEMENT_ASN1_ALLOC_FUNCTIONS(stname) \ williamr@2: IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, stname, stname) williamr@2: williamr@2: #define IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) \ williamr@2: EXPORT_C stname *fname##_new(void) \ williamr@2: { \ williamr@2: return (stname *)ASN1_item_new(ASN1_ITEM_rptr(itname)); \ williamr@2: } \ williamr@2: EXPORT_C void fname##_free(stname *a) \ williamr@2: { \ williamr@2: ASN1_item_free((ASN1_VALUE *)a, ASN1_ITEM_rptr(itname)); \ williamr@2: } williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS_fname(stname, itname, fname) \ williamr@2: IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ williamr@2: IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) williamr@2: williamr@2: #define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(stname, itname, fname) \ williamr@2: EXPORT_C stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ williamr@2: { \ williamr@2: return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ williamr@2: } \ williamr@2: EXPORT_C int i2d_##fname(stname *a, unsigned char **out) \ williamr@2: { \ williamr@2: return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ williamr@2: } williamr@2: williamr@2: #define IMPLEMENT_ASN1_NDEF_FUNCTION(stname) \ williamr@2: EXPORT_C int i2d_##stname##_NDEF(stname *a, unsigned char **out) \ williamr@2: { \ williamr@2: return ASN1_item_ndef_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(stname));\ williamr@2: } williamr@2: williamr@2: /* This includes evil casts to remove const: they will go away when full williamr@2: * ASN1 constification is done. williamr@2: */ williamr@2: #define IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ williamr@2: EXPORT_C stname *d2i_##fname(stname **a, const unsigned char **in, long len) \ williamr@2: { \ williamr@2: return (stname *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, ASN1_ITEM_rptr(itname));\ williamr@2: } \ williamr@2: EXPORT_C int i2d_##fname(const stname *a, unsigned char **out) \ williamr@2: { \ williamr@2: return ASN1_item_i2d((ASN1_VALUE *)a, out, ASN1_ITEM_rptr(itname));\ williamr@2: } williamr@2: williamr@2: #define IMPLEMENT_ASN1_DUP_FUNCTION(stname) \ williamr@2: EXPORT_C stname * stname##_dup(stname *x) \ williamr@2: { \ williamr@2: return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \ williamr@2: } williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS_const(name) \ williamr@2: IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name) williamr@2: williamr@2: #define IMPLEMENT_ASN1_FUNCTIONS_const_fname(stname, itname, fname) \ williamr@2: IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(stname, itname, fname) \ williamr@2: IMPLEMENT_ASN1_ALLOC_FUNCTIONS_fname(stname, itname, fname) williamr@2: williamr@2: /* external definitions for primitive types */ williamr@2: williamr@2: DECLARE_ASN1_ITEM(ASN1_BOOLEAN) williamr@2: DECLARE_ASN1_ITEM(ASN1_TBOOLEAN) williamr@2: DECLARE_ASN1_ITEM(ASN1_FBOOLEAN) williamr@2: DECLARE_ASN1_ITEM(ASN1_SEQUENCE) williamr@2: DECLARE_ASN1_ITEM(CBIGNUM) williamr@2: DECLARE_ASN1_ITEM(BIGNUM) williamr@2: DECLARE_ASN1_ITEM(LONG) williamr@2: DECLARE_ASN1_ITEM(ZLONG) williamr@2: williamr@2: DECLARE_STACK_OF(ASN1_VALUE) williamr@2: williamr@2: /* Functions used internally by the ASN1 code */ williamr@2: williamr@2: IMPORT_C int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: IMPORT_C void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); williamr@2: int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: williamr@2: IMPORT_C void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); williamr@2: int ASN1_template_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_TEMPLATE *tt); williamr@2: IMPORT_C int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, const ASN1_ITEM *it, williamr@2: int tag, int aclass, char opt, ASN1_TLC *ctx); williamr@2: williamr@2: IMPORT_C int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass); williamr@2: int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt); williamr@2: IMPORT_C void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: williamr@2: int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it); williamr@2: int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it); williamr@2: williamr@2: IMPORT_C int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: IMPORT_C int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it); williamr@2: williamr@2: IMPORT_C ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); williamr@2: williamr@2: IMPORT_C const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, int nullerr); williamr@2: williamr@2: IMPORT_C int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); williamr@2: williamr@2: IMPORT_C void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: IMPORT_C void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: IMPORT_C int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, const ASN1_ITEM *it); williamr@2: IMPORT_C int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, const ASN1_ITEM *it); williamr@2: williamr@2: #ifdef __cplusplus williamr@2: } williamr@2: #endif williamr@2: #endif