| 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | |
| 5 | /* |
| 6 | * Support for encoding/decoding of ASN.1 using BER/DER (Basic/Distinguished |
| 7 | * Encoding Rules). The routines are found in and used extensively by the |
| 8 | * security library, but exported for other use. |
| 9 | */ |
| 10 | |
| 11 | #ifndef _SECASN1_H_ |
| 12 | #define _SECASN1_H_ |
| 13 | |
| 14 | #include "utilrename.h" |
| 15 | #include "plarena.h" |
| 16 | |
| 17 | #include "seccomon.h" |
| 18 | #include "secasn1t.h" |
| 19 | |
| 20 | /************************************************************************/ |
| 21 | SEC_BEGIN_PROTOS |
| 22 | |
| 23 | /* |
| 24 | * XXX These function prototypes need full, explanatory comments. |
| 25 | */ |
| 26 | |
| 27 | /* |
| 28 | ** Decoding. |
| 29 | */ |
| 30 | |
| 31 | extern SEC_ASN1DecoderContext *SEC_ASN1DecoderStart(PLArenaPool *pool, |
| 32 | void *dest, |
| 33 | const SEC_ASN1Template *t); |
| 34 | |
| 35 | /* XXX char or unsigned char? */ |
| 36 | extern SECStatus SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx, |
| 37 | const char *buf, |
| 38 | unsigned long len); |
| 39 | |
| 40 | extern SECStatus SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx); |
| 41 | |
| 42 | /* Higher level code detected an error, abort the rest of the processing */ |
| 43 | extern void SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error); |
| 44 | |
| 45 | extern void SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx, |
| 46 | SEC_ASN1WriteProc fn, |
| 47 | void *arg, PRBool no_store); |
| 48 | |
| 49 | extern void SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx); |
| 50 | |
| 51 | extern void SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx, |
| 52 | SEC_ASN1NotifyProc fn, |
| 53 | void *arg); |
| 54 | |
| 55 | extern void SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx); |
| 56 | |
| 57 | /* Sets the maximum size that should be allocated for a single ASN.1 |
| 58 | * element. Set to 0 to indicate there is no limit. |
| 59 | * |
| 60 | * Note: This does not set the maximum size overall that may be allocated |
| 61 | * while parsing, nor does it guarantee that the decoder won't allocate |
| 62 | * more than |max_size| while parsing an individual element; rather, it |
| 63 | * merely guarantees that any individual allocation for returned data |
| 64 | * should not exceed |max_size|. |
| 65 | */ |
| 66 | extern void SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx, |
| 67 | unsigned long max_size); |
| 68 | |
| 69 | extern SECStatus SEC_ASN1Decode(PLArenaPool *pool, void *dest, |
| 70 | const SEC_ASN1Template *t, |
| 71 | const char *buf, long len); |
| 72 | |
| 73 | /* Both classic ASN.1 and QuickDER have a feature that removes leading zeroes |
| 74 | out of SEC_ASN1_INTEGER if the caller sets siUnsignedInteger in the type |
| 75 | field of the target SECItem prior to calling the decoder. Otherwise, the |
| 76 | type field is ignored and untouched. For SECItem that are dynamically |
| 77 | allocated (from POINTER, SET OF, SEQUENCE OF) the decoder sets the type |
| 78 | field to siBuffer. */ |
| 79 | |
| 80 | extern SECStatus SEC_ASN1DecodeItem(PLArenaPool *pool, void *dest, |
| 81 | const SEC_ASN1Template *t, |
| 82 | const SECItem *src); |
| 83 | |
| 84 | extern SECStatus SEC_QuickDERDecodeItem(PLArenaPool *arena, void *dest, |
| 85 | const SEC_ASN1Template *templateEntry, |
| 86 | const SECItem *src); |
| 87 | |
| 88 | /* |
| 89 | ** Encoding. |
| 90 | */ |
| 91 | |
| 92 | extern SEC_ASN1EncoderContext *SEC_ASN1EncoderStart(const void *src, |
| 93 | const SEC_ASN1Template *t, |
| 94 | SEC_ASN1WriteProc fn, |
| 95 | void *output_arg); |
| 96 | |
| 97 | /* XXX char or unsigned char? */ |
| 98 | extern SECStatus SEC_ASN1EncoderUpdate(SEC_ASN1EncoderContext *cx, |
| 99 | const char *buf, |
| 100 | unsigned long len); |
| 101 | |
| 102 | extern void SEC_ASN1EncoderFinish(SEC_ASN1EncoderContext *cx); |
| 103 | |
| 104 | /* Higher level code detected an error, abort the rest of the processing */ |
| 105 | extern void SEC_ASN1EncoderAbort(SEC_ASN1EncoderContext *cx, int error); |
| 106 | |
| 107 | extern void SEC_ASN1EncoderSetNotifyProc(SEC_ASN1EncoderContext *cx, |
| 108 | SEC_ASN1NotifyProc fn, |
| 109 | void *arg); |
| 110 | |
| 111 | extern void SEC_ASN1EncoderClearNotifyProc(SEC_ASN1EncoderContext *cx); |
| 112 | |
| 113 | extern void SEC_ASN1EncoderSetStreaming(SEC_ASN1EncoderContext *cx); |
| 114 | |
| 115 | extern void SEC_ASN1EncoderClearStreaming(SEC_ASN1EncoderContext *cx); |
| 116 | |
| 117 | extern void sec_ASN1EncoderSetDER(SEC_ASN1EncoderContext *cx); |
| 118 | |
| 119 | extern void sec_ASN1EncoderClearDER(SEC_ASN1EncoderContext *cx); |
| 120 | |
| 121 | extern void SEC_ASN1EncoderSetTakeFromBuf(SEC_ASN1EncoderContext *cx); |
| 122 | |
| 123 | extern void SEC_ASN1EncoderClearTakeFromBuf(SEC_ASN1EncoderContext *cx); |
| 124 | |
| 125 | extern SECStatus SEC_ASN1Encode(const void *src, const SEC_ASN1Template *t, |
| 126 | SEC_ASN1WriteProc output_proc, |
| 127 | void *output_arg); |
| 128 | |
| 129 | /* |
| 130 | * If both pool and dest are NULL, the caller should free the returned SECItem |
| 131 | * with a SECITEM_FreeItem(..., PR_TRUE) call. If pool is NULL but dest is |
| 132 | * not NULL, the caller should free the data buffer pointed to by dest with a |
| 133 | * SECITEM_FreeItem(dest, PR_FALSE) or PORT_Free(dest->data) call. |
| 134 | */ |
| 135 | extern SECItem *SEC_ASN1EncodeItem(PLArenaPool *pool, SECItem *dest, |
| 136 | const void *src, const SEC_ASN1Template *t); |
| 137 | |
| 138 | extern SECItem *SEC_ASN1EncodeInteger(PLArenaPool *pool, |
| 139 | SECItem *dest, long value); |
| 140 | |
| 141 | extern SECItem *SEC_ASN1EncodeUnsignedInteger(PLArenaPool *pool, |
| 142 | SECItem *dest, |
| 143 | unsigned long value); |
| 144 | |
| 145 | extern SECStatus SEC_ASN1DecodeInteger(SECItem *src, |
| 146 | unsigned long *value); |
| 147 | |
| 148 | /* |
| 149 | ** Utilities. |
| 150 | */ |
| 151 | |
| 152 | /* |
| 153 | * We have a length that needs to be encoded; how many bytes will the |
| 154 | * encoding take? |
| 155 | */ |
| 156 | extern int SEC_ASN1LengthLength(unsigned long len); |
| 157 | |
| 158 | /* encode the length and return the number of bytes we encoded. Buffer |
| 159 | * must be pre allocated */ |
| 160 | extern int SEC_ASN1EncodeLength(unsigned char *buf, int value); |
| 161 | |
| 162 | /* |
| 163 | * Find the appropriate subtemplate for the given template. |
| 164 | * This may involve calling a "chooser" function, or it may just |
| 165 | * be right there. In either case, it is expected to *have* a |
| 166 | * subtemplate; this is asserted in debug builds (in non-debug |
| 167 | * builds, NULL will be returned). |
| 168 | * |
| 169 | * "thing" is a pointer to the structure being encoded/decoded |
| 170 | * "encoding", when true, means that we are in the process of encoding |
| 171 | * (as opposed to in the process of decoding) |
| 172 | */ |
| 173 | extern const SEC_ASN1Template * |
| 174 | SEC_ASN1GetSubtemplate(const SEC_ASN1Template *inTemplate, void *thing, |
| 175 | PRBool encoding); |
| 176 | |
| 177 | /* whether the template is for a primitive type or a choice of |
| 178 | * primitive types |
| 179 | */ |
| 180 | extern PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate); |
| 181 | |
| 182 | /************************************************************************/ |
| 183 | |
| 184 | /* |
| 185 | * Generic Templates |
| 186 | * One for each of the simple types, plus a special one for ANY, plus: |
| 187 | * - a pointer to each one of those |
| 188 | * - a set of each one of those |
| 189 | * - a sequence of each one of those |
| 190 | * |
| 191 | * Note that these are alphabetical (case insensitive); please add new |
| 192 | * ones in the appropriate place. |
| 193 | */ |
| 194 | |
| 195 | extern const SEC_ASN1Template SEC_AnyTemplate[]; |
| 196 | extern const SEC_ASN1Template SEC_BitStringTemplate[]; |
| 197 | extern const SEC_ASN1Template SEC_BMPStringTemplate[]; |
| 198 | extern const SEC_ASN1Template SEC_BooleanTemplate[]; |
| 199 | extern const SEC_ASN1Template SEC_EnumeratedTemplate[]; |
| 200 | extern const SEC_ASN1Template SEC_GeneralizedTimeTemplate[]; |
| 201 | extern const SEC_ASN1Template SEC_IA5StringTemplate[]; |
| 202 | extern const SEC_ASN1Template SEC_IntegerTemplate[]; |
| 203 | extern const SEC_ASN1Template SEC_NullTemplate[]; |
| 204 | extern const SEC_ASN1Template SEC_ObjectIDTemplate[]; |
| 205 | extern const SEC_ASN1Template SEC_OctetStringTemplate[]; |
| 206 | extern const SEC_ASN1Template SEC_PrintableStringTemplate[]; |
| 207 | extern const SEC_ASN1Template SEC_T61StringTemplate[]; |
| 208 | extern const SEC_ASN1Template SEC_UniversalStringTemplate[]; |
| 209 | extern const SEC_ASN1Template SEC_UTCTimeTemplate[]; |
| 210 | extern const SEC_ASN1Template SEC_UTF8StringTemplate[]; |
| 211 | extern const SEC_ASN1Template SEC_VisibleStringTemplate[]; |
| 212 | |
| 213 | extern const SEC_ASN1Template SEC_PointerToAnyTemplate[]; |
| 214 | extern const SEC_ASN1Template SEC_PointerToBitStringTemplate[]; |
| 215 | extern const SEC_ASN1Template SEC_PointerToBMPStringTemplate[]; |
| 216 | extern const SEC_ASN1Template SEC_PointerToBooleanTemplate[]; |
| 217 | extern const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[]; |
| 218 | extern const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[]; |
| 219 | extern const SEC_ASN1Template SEC_PointerToIA5StringTemplate[]; |
| 220 | extern const SEC_ASN1Template SEC_PointerToIntegerTemplate[]; |
| 221 | extern const SEC_ASN1Template SEC_PointerToNullTemplate[]; |
| 222 | extern const SEC_ASN1Template SEC_PointerToObjectIDTemplate[]; |
| 223 | extern const SEC_ASN1Template SEC_PointerToOctetStringTemplate[]; |
| 224 | extern const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[]; |
| 225 | extern const SEC_ASN1Template SEC_PointerToT61StringTemplate[]; |
| 226 | extern const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[]; |
| 227 | extern const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[]; |
| 228 | extern const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[]; |
| 229 | extern const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[]; |
| 230 | |
| 231 | extern const SEC_ASN1Template SEC_SequenceOfAnyTemplate[]; |
| 232 | extern const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[]; |
| 233 | extern const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[]; |
| 234 | extern const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[]; |
| 235 | extern const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[]; |
| 236 | extern const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[]; |
| 237 | extern const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[]; |
| 238 | extern const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[]; |
| 239 | extern const SEC_ASN1Template SEC_SequenceOfNullTemplate[]; |
| 240 | extern const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[]; |
| 241 | extern const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[]; |
| 242 | extern const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[]; |
| 243 | extern const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[]; |
| 244 | extern const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[]; |
| 245 | extern const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[]; |
| 246 | extern const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[]; |
| 247 | extern const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[]; |
| 248 | |
| 249 | extern const SEC_ASN1Template SEC_SetOfAnyTemplate[]; |
| 250 | extern const SEC_ASN1Template SEC_SetOfBitStringTemplate[]; |
| 251 | extern const SEC_ASN1Template SEC_SetOfBMPStringTemplate[]; |
| 252 | extern const SEC_ASN1Template SEC_SetOfBooleanTemplate[]; |
| 253 | extern const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[]; |
| 254 | extern const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[]; |
| 255 | extern const SEC_ASN1Template SEC_SetOfIA5StringTemplate[]; |
| 256 | extern const SEC_ASN1Template SEC_SetOfIntegerTemplate[]; |
| 257 | extern const SEC_ASN1Template SEC_SetOfNullTemplate[]; |
| 258 | extern const SEC_ASN1Template SEC_SetOfObjectIDTemplate[]; |
| 259 | extern const SEC_ASN1Template SEC_SetOfOctetStringTemplate[]; |
| 260 | extern const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[]; |
| 261 | extern const SEC_ASN1Template SEC_SetOfT61StringTemplate[]; |
| 262 | extern const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[]; |
| 263 | extern const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[]; |
| 264 | extern const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[]; |
| 265 | extern const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[]; |
| 266 | |
| 267 | /* |
| 268 | * Template for skipping a subitem; this only makes sense when decoding. |
| 269 | */ |
| 270 | extern const SEC_ASN1Template SEC_SkipTemplate[]; |
| 271 | |
| 272 | /* These functions simply return the address of the above-declared templates. |
| 273 | ** This is necessary for Windows DLLs. Sigh. |
| 274 | */ |
| 275 | SEC_ASN1_CHOOSER_DECLARE(SEC_AnyTemplate) |
| 276 | SEC_ASN1_CHOOSER_DECLARE(SEC_BMPStringTemplate) |
| 277 | SEC_ASN1_CHOOSER_DECLARE(SEC_BooleanTemplate) |
| 278 | SEC_ASN1_CHOOSER_DECLARE(SEC_BitStringTemplate) |
| 279 | SEC_ASN1_CHOOSER_DECLARE(SEC_GeneralizedTimeTemplate) |
| 280 | SEC_ASN1_CHOOSER_DECLARE(SEC_IA5StringTemplate) |
| 281 | SEC_ASN1_CHOOSER_DECLARE(SEC_IntegerTemplate) |
| 282 | SEC_ASN1_CHOOSER_DECLARE(SEC_NullTemplate) |
| 283 | SEC_ASN1_CHOOSER_DECLARE(SEC_ObjectIDTemplate) |
| 284 | SEC_ASN1_CHOOSER_DECLARE(SEC_OctetStringTemplate) |
| 285 | SEC_ASN1_CHOOSER_DECLARE(SEC_UTCTimeTemplate) |
| 286 | SEC_ASN1_CHOOSER_DECLARE(SEC_UTF8StringTemplate) |
| 287 | |
| 288 | SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToAnyTemplate) |
| 289 | SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToOctetStringTemplate) |
| 290 | |
| 291 | SEC_ASN1_CHOOSER_DECLARE(SEC_SetOfAnyTemplate) |
| 292 | |
| 293 | SEC_ASN1_CHOOSER_DECLARE(SEC_EnumeratedTemplate) |
| 294 | SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToEnumeratedTemplate) |
| 295 | SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfAnyTemplate) |
| 296 | SEC_ASN1_CHOOSER_DECLARE(SEC_SequenceOfObjectIDTemplate) |
| 297 | SEC_ASN1_CHOOSER_DECLARE(SEC_SkipTemplate) |
| 298 | SEC_ASN1_CHOOSER_DECLARE(SEC_UniversalStringTemplate) |
| 299 | SEC_ASN1_CHOOSER_DECLARE(SEC_PrintableStringTemplate) |
| 300 | SEC_ASN1_CHOOSER_DECLARE(SEC_T61StringTemplate) |
| 301 | SEC_ASN1_CHOOSER_DECLARE(SEC_PointerToGeneralizedTimeTemplate) |
| 302 | SEC_END_PROTOS |
| 303 | #endif /* _SECASN1_H_ */ |
| 304 | |