1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/util/secasn1d.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3236 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished 1.10 + * Encoding Rules). 1.11 + */ 1.12 + 1.13 +/* #define DEBUG_ASN1D_STATES 1 */ 1.14 + 1.15 +#ifdef DEBUG_ASN1D_STATES 1.16 +#include <stdio.h> 1.17 +#define PR_Assert sec_asn1d_Assert 1.18 +#endif 1.19 + 1.20 +#include "secasn1.h" 1.21 +#include "secerr.h" 1.22 + 1.23 +typedef enum { 1.24 + beforeIdentifier, 1.25 + duringIdentifier, 1.26 + afterIdentifier, 1.27 + beforeLength, 1.28 + duringLength, 1.29 + afterLength, 1.30 + beforeBitString, 1.31 + duringBitString, 1.32 + duringConstructedString, 1.33 + duringGroup, 1.34 + duringLeaf, 1.35 + duringSaveEncoding, 1.36 + duringSequence, 1.37 + afterConstructedString, 1.38 + afterGroup, 1.39 + afterExplicit, 1.40 + afterImplicit, 1.41 + afterInline, 1.42 + afterPointer, 1.43 + afterSaveEncoding, 1.44 + beforeEndOfContents, 1.45 + duringEndOfContents, 1.46 + afterEndOfContents, 1.47 + beforeChoice, 1.48 + duringChoice, 1.49 + afterChoice, 1.50 + notInUse 1.51 +} sec_asn1d_parse_place; 1.52 + 1.53 +#ifdef DEBUG_ASN1D_STATES 1.54 +static const char * const place_names[] = { 1.55 + "beforeIdentifier", 1.56 + "duringIdentifier", 1.57 + "afterIdentifier", 1.58 + "beforeLength", 1.59 + "duringLength", 1.60 + "afterLength", 1.61 + "beforeBitString", 1.62 + "duringBitString", 1.63 + "duringConstructedString", 1.64 + "duringGroup", 1.65 + "duringLeaf", 1.66 + "duringSaveEncoding", 1.67 + "duringSequence", 1.68 + "afterConstructedString", 1.69 + "afterGroup", 1.70 + "afterExplicit", 1.71 + "afterImplicit", 1.72 + "afterInline", 1.73 + "afterPointer", 1.74 + "afterSaveEncoding", 1.75 + "beforeEndOfContents", 1.76 + "duringEndOfContents", 1.77 + "afterEndOfContents", 1.78 + "beforeChoice", 1.79 + "duringChoice", 1.80 + "afterChoice", 1.81 + "notInUse" 1.82 +}; 1.83 + 1.84 +static const char * const class_names[] = { 1.85 + "UNIVERSAL", 1.86 + "APPLICATION", 1.87 + "CONTEXT_SPECIFIC", 1.88 + "PRIVATE" 1.89 +}; 1.90 + 1.91 +static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" }; 1.92 + 1.93 +static const char * const type_names[] = { 1.94 + "END_OF_CONTENTS", 1.95 + "BOOLEAN", 1.96 + "INTEGER", 1.97 + "BIT_STRING", 1.98 + "OCTET_STRING", 1.99 + "NULL", 1.100 + "OBJECT_ID", 1.101 + "OBJECT_DESCRIPTOR", 1.102 + "(type 08)", 1.103 + "REAL", 1.104 + "ENUMERATED", 1.105 + "EMBEDDED", 1.106 + "UTF8_STRING", 1.107 + "(type 0d)", 1.108 + "(type 0e)", 1.109 + "(type 0f)", 1.110 + "SEQUENCE", 1.111 + "SET", 1.112 + "NUMERIC_STRING", 1.113 + "PRINTABLE_STRING", 1.114 + "T61_STRING", 1.115 + "VIDEOTEXT_STRING", 1.116 + "IA5_STRING", 1.117 + "UTC_TIME", 1.118 + "GENERALIZED_TIME", 1.119 + "GRAPHIC_STRING", 1.120 + "VISIBLE_STRING", 1.121 + "GENERAL_STRING", 1.122 + "UNIVERSAL_STRING", 1.123 + "(type 1d)", 1.124 + "BMP_STRING", 1.125 + "HIGH_TAG_VALUE" 1.126 +}; 1.127 + 1.128 +static const char * const flag_names[] = { /* flags, right to left */ 1.129 + "OPTIONAL", 1.130 + "EXPLICIT", 1.131 + "ANY", 1.132 + "INLINE", 1.133 + "POINTER", 1.134 + "GROUP", 1.135 + "DYNAMIC", 1.136 + "SKIP", 1.137 + "INNER", 1.138 + "SAVE", 1.139 + "", /* decoder ignores "MAY_STREAM", */ 1.140 + "SKIP_REST", 1.141 + "CHOICE", 1.142 + "NO_STREAM", 1.143 + "DEBUG_BREAK", 1.144 + "unknown 08", 1.145 + "unknown 10", 1.146 + "unknown 20", 1.147 + "unknown 40", 1.148 + "unknown 80" 1.149 +}; 1.150 + 1.151 +static int /* bool */ 1.152 +formatKind(unsigned long kind, char * buf) 1.153 +{ 1.154 + int i; 1.155 + unsigned long k = kind & SEC_ASN1_TAGNUM_MASK; 1.156 + unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER | 1.157 + SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE); 1.158 + 1.159 + buf[0] = 0; 1.160 + if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) { 1.161 + sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] ); 1.162 + buf += strlen(buf); 1.163 + } 1.164 + if (kind & SEC_ASN1_METHOD_MASK) { 1.165 + sprintf(buf, " %s", method_names[1]); 1.166 + buf += strlen(buf); 1.167 + } 1.168 + if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) { 1.169 + if (k || !notag) { 1.170 + sprintf(buf, " %s", type_names[k] ); 1.171 + if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) && 1.172 + (kind & SEC_ASN1_GROUP)) { 1.173 + buf += strlen(buf); 1.174 + sprintf(buf, "_OF"); 1.175 + } 1.176 + } 1.177 + } else { 1.178 + sprintf(buf, " [%d]", k); 1.179 + } 1.180 + buf += strlen(buf); 1.181 + 1.182 + for (k = kind >> 8, i = 0; k; k >>= 1, ++i) { 1.183 + if (k & 1) { 1.184 + sprintf(buf, " %s", flag_names[i]); 1.185 + buf += strlen(buf); 1.186 + } 1.187 + } 1.188 + return notag != 0; 1.189 +} 1.190 + 1.191 +#endif /* DEBUG_ASN1D_STATES */ 1.192 + 1.193 +typedef enum { 1.194 + allDone, 1.195 + decodeError, 1.196 + keepGoing, 1.197 + needBytes 1.198 +} sec_asn1d_parse_status; 1.199 + 1.200 +struct subitem { 1.201 + const void *data; 1.202 + unsigned long len; /* only used for substrings */ 1.203 + struct subitem *next; 1.204 +}; 1.205 + 1.206 +typedef struct sec_asn1d_state_struct { 1.207 + SEC_ASN1DecoderContext *top; 1.208 + const SEC_ASN1Template *theTemplate; 1.209 + void *dest; 1.210 + 1.211 + void *our_mark; /* free on completion */ 1.212 + 1.213 + struct sec_asn1d_state_struct *parent; /* aka prev */ 1.214 + struct sec_asn1d_state_struct *child; /* aka next */ 1.215 + 1.216 + sec_asn1d_parse_place place; 1.217 + 1.218 + /* 1.219 + * XXX explain the next fields as clearly as possible... 1.220 + */ 1.221 + unsigned char found_tag_modifiers; 1.222 + unsigned char expect_tag_modifiers; 1.223 + unsigned long check_tag_mask; 1.224 + unsigned long found_tag_number; 1.225 + unsigned long expect_tag_number; 1.226 + unsigned long underlying_kind; 1.227 + 1.228 + unsigned long contents_length; 1.229 + unsigned long pending; 1.230 + unsigned long consumed; 1.231 + 1.232 + int depth; 1.233 + 1.234 + /* 1.235 + * Bit strings have their length adjusted -- the first octet of the 1.236 + * contents contains a value between 0 and 7 which says how many bits 1.237 + * at the end of the octets are not actually part of the bit string; 1.238 + * when parsing bit strings we put that value here because we need it 1.239 + * later, for adjustment of the length (when the whole string is done). 1.240 + */ 1.241 + unsigned int bit_string_unused_bits; 1.242 + 1.243 + /* 1.244 + * The following are used for indefinite-length constructed strings. 1.245 + */ 1.246 + struct subitem *subitems_head; 1.247 + struct subitem *subitems_tail; 1.248 + 1.249 + PRPackedBool 1.250 + allocate, /* when true, need to allocate the destination */ 1.251 + endofcontents, /* this state ended up parsing end-of-contents octets */ 1.252 + explicit, /* we are handling an explicit header */ 1.253 + indefinite, /* the current item has indefinite-length encoding */ 1.254 + missing, /* an optional field that was not present */ 1.255 + optional, /* the template says this field may be omitted */ 1.256 + substring; /* this is a substring of a constructed string */ 1.257 + 1.258 +} sec_asn1d_state; 1.259 + 1.260 +#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER) 1.261 +#define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0) 1.262 +#define TAG_NUMBER_BITS 7 1.263 +#define TAG_NUMBER_MASK 0x7f 1.264 + 1.265 +#define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0) 1.266 +#define LONG_FORM_LENGTH(b) ((b) & 0x7f) 1.267 + 1.268 +#define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt))) 1.269 + 1.270 + 1.271 +/* 1.272 + * An "outsider" will have an opaque pointer to this, created by calling 1.273 + * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent 1.274 + * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to 1.275 + * SEC_ASN1DecoderFinish(). 1.276 + */ 1.277 +struct sec_DecoderContext_struct { 1.278 + PLArenaPool *our_pool; /* for our internal allocs */ 1.279 + PLArenaPool *their_pool; /* for destination structure allocs */ 1.280 +#ifdef SEC_ASN1D_FREE_ON_ERROR /* 1.281 + * XXX see comment below (by same 1.282 + * ifdef) that explains why this 1.283 + * does not work (need more smarts 1.284 + * in order to free back to mark) 1.285 + */ 1.286 + /* 1.287 + * XXX how to make their_mark work in the case where they do NOT 1.288 + * give us a pool pointer? 1.289 + */ 1.290 + void *their_mark; /* free on error */ 1.291 +#endif 1.292 + 1.293 + sec_asn1d_state *current; 1.294 + sec_asn1d_parse_status status; 1.295 + 1.296 + SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */ 1.297 + void *notify_arg; /* argument to notify_proc */ 1.298 + PRBool during_notify; /* true during call to notify_proc */ 1.299 + 1.300 + SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */ 1.301 + void *filter_arg; /* argument to that function */ 1.302 + PRBool filter_only; /* do not allocate/store fields */ 1.303 +}; 1.304 + 1.305 + 1.306 +/* 1.307 + * XXX this is a fairly generic function that may belong elsewhere 1.308 + */ 1.309 +static void * 1.310 +sec_asn1d_alloc (PLArenaPool *poolp, unsigned long len) 1.311 +{ 1.312 + void *thing; 1.313 + 1.314 + if (poolp != NULL) { 1.315 + /* 1.316 + * Allocate from the pool. 1.317 + */ 1.318 + thing = PORT_ArenaAlloc (poolp, len); 1.319 + } else { 1.320 + /* 1.321 + * Allocate generically. 1.322 + */ 1.323 + thing = PORT_Alloc (len); 1.324 + } 1.325 + 1.326 + return thing; 1.327 +} 1.328 + 1.329 + 1.330 +/* 1.331 + * XXX this is a fairly generic function that may belong elsewhere 1.332 + */ 1.333 +static void * 1.334 +sec_asn1d_zalloc (PLArenaPool *poolp, unsigned long len) 1.335 +{ 1.336 + void *thing; 1.337 + 1.338 + thing = sec_asn1d_alloc (poolp, len); 1.339 + if (thing != NULL) 1.340 + PORT_Memset (thing, 0, len); 1.341 + return thing; 1.342 +} 1.343 + 1.344 + 1.345 +static sec_asn1d_state * 1.346 +sec_asn1d_push_state (SEC_ASN1DecoderContext *cx, 1.347 + const SEC_ASN1Template *theTemplate, 1.348 + void *dest, PRBool new_depth) 1.349 +{ 1.350 + sec_asn1d_state *state, *new_state; 1.351 + 1.352 + state = cx->current; 1.353 + 1.354 + PORT_Assert (state == NULL || state->child == NULL); 1.355 + 1.356 + if (state != NULL) { 1.357 + PORT_Assert (state->our_mark == NULL); 1.358 + state->our_mark = PORT_ArenaMark (cx->our_pool); 1.359 + } 1.360 + 1.361 + new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool, 1.362 + sizeof(*new_state)); 1.363 + if (new_state == NULL) { 1.364 + goto loser; 1.365 + } 1.366 + 1.367 + new_state->top = cx; 1.368 + new_state->parent = state; 1.369 + new_state->theTemplate = theTemplate; 1.370 + new_state->place = notInUse; 1.371 + if (dest != NULL) 1.372 + new_state->dest = (char *)dest + theTemplate->offset; 1.373 + 1.374 + if (state != NULL) { 1.375 + new_state->depth = state->depth; 1.376 + if (new_depth) { 1.377 + if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) { 1.378 + PORT_SetError (SEC_ERROR_BAD_DER); 1.379 + goto loser; 1.380 + } 1.381 + } 1.382 + state->child = new_state; 1.383 + } 1.384 + 1.385 + cx->current = new_state; 1.386 + return new_state; 1.387 + 1.388 +loser: 1.389 + cx->status = decodeError; 1.390 + if (state != NULL) { 1.391 + PORT_ArenaRelease(cx->our_pool, state->our_mark); 1.392 + state->our_mark = NULL; 1.393 + } 1.394 + return NULL; 1.395 +} 1.396 + 1.397 + 1.398 +static void 1.399 +sec_asn1d_scrub_state (sec_asn1d_state *state) 1.400 +{ 1.401 + /* 1.402 + * Some default "scrubbing". 1.403 + * XXX right set of initializations? 1.404 + */ 1.405 + state->place = beforeIdentifier; 1.406 + state->endofcontents = PR_FALSE; 1.407 + state->indefinite = PR_FALSE; 1.408 + state->missing = PR_FALSE; 1.409 + PORT_Assert (state->consumed == 0); 1.410 +} 1.411 + 1.412 + 1.413 +static void 1.414 +sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth) 1.415 +{ 1.416 + if (cx->notify_proc == NULL) 1.417 + return; 1.418 + 1.419 + cx->during_notify = PR_TRUE; 1.420 + (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth); 1.421 + cx->during_notify = PR_FALSE; 1.422 +} 1.423 + 1.424 + 1.425 +static void 1.426 +sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth) 1.427 +{ 1.428 + if (cx->notify_proc == NULL) 1.429 + return; 1.430 + 1.431 + cx->during_notify = PR_TRUE; 1.432 + (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth); 1.433 + cx->during_notify = PR_FALSE; 1.434 +} 1.435 + 1.436 + 1.437 +static sec_asn1d_state * 1.438 +sec_asn1d_init_state_based_on_template (sec_asn1d_state *state) 1.439 +{ 1.440 + PRBool explicit, optional, universal; 1.441 + unsigned char expect_tag_modifiers; 1.442 + unsigned long encode_kind, under_kind; 1.443 + unsigned long check_tag_mask, expect_tag_number; 1.444 + 1.445 + 1.446 + /* XXX Check that both of these tests are really needed/appropriate. */ 1.447 + if (state == NULL || state->top->status == decodeError) 1.448 + return state; 1.449 + 1.450 + encode_kind = state->theTemplate->kind; 1.451 + 1.452 + if (encode_kind & SEC_ASN1_SAVE) { 1.453 + /* 1.454 + * This is a "magic" field that saves away all bytes, allowing 1.455 + * the immediately following field to still be decoded from this 1.456 + * same spot -- sort of a fork. 1.457 + */ 1.458 + /* check that there are no extraneous bits */ 1.459 + PORT_Assert (encode_kind == SEC_ASN1_SAVE); 1.460 + if (state->top->filter_only) { 1.461 + /* 1.462 + * If we are not storing, then we do not do the SAVE field 1.463 + * at all. Just move ahead to the "real" field instead, 1.464 + * doing the appropriate notify calls before and after. 1.465 + */ 1.466 + sec_asn1d_notify_after (state->top, state->dest, state->depth); 1.467 + /* 1.468 + * Since we are not storing, allow for our current dest value 1.469 + * to be NULL. (This might not actually occur, but right now I 1.470 + * cannot convince myself one way or the other.) If it is NULL, 1.471 + * assume that our parent dest can help us out. 1.472 + */ 1.473 + if (state->dest == NULL) 1.474 + state->dest = state->parent->dest; 1.475 + else 1.476 + state->dest = (char *)state->dest - state->theTemplate->offset; 1.477 + state->theTemplate++; 1.478 + if (state->dest != NULL) 1.479 + state->dest = (char *)state->dest + state->theTemplate->offset; 1.480 + sec_asn1d_notify_before (state->top, state->dest, state->depth); 1.481 + encode_kind = state->theTemplate->kind; 1.482 + PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0); 1.483 + } else { 1.484 + sec_asn1d_scrub_state (state); 1.485 + state->place = duringSaveEncoding; 1.486 + state = sec_asn1d_push_state (state->top, SEC_AnyTemplate, 1.487 + state->dest, PR_FALSE); 1.488 + if (state != NULL) 1.489 + state = sec_asn1d_init_state_based_on_template (state); 1.490 + return state; 1.491 + } 1.492 + } 1.493 + 1.494 + 1.495 + universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) 1.496 + ? PR_TRUE : PR_FALSE; 1.497 + 1.498 + explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; 1.499 + encode_kind &= ~SEC_ASN1_EXPLICIT; 1.500 + 1.501 + optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; 1.502 + encode_kind &= ~SEC_ASN1_OPTIONAL; 1.503 + 1.504 + PORT_Assert (!(explicit && universal)); /* bad templates */ 1.505 + 1.506 + encode_kind &= ~SEC_ASN1_DYNAMIC; 1.507 + encode_kind &= ~SEC_ASN1_MAY_STREAM; 1.508 + 1.509 + if (encode_kind & SEC_ASN1_CHOICE) { 1.510 +#if 0 /* XXX remove? */ 1.511 + sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE); 1.512 + if ((sec_asn1d_state *)NULL == child) { 1.513 + return (sec_asn1d_state *)NULL; 1.514 + } 1.515 + 1.516 + child->allocate = state->allocate; 1.517 + child->place = beforeChoice; 1.518 + return child; 1.519 +#else 1.520 + state->place = beforeChoice; 1.521 + return state; 1.522 +#endif 1.523 + } 1.524 + 1.525 + if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal 1.526 + && !explicit)) { 1.527 + const SEC_ASN1Template *subt; 1.528 + void *dest; 1.529 + PRBool child_allocate; 1.530 + 1.531 + PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); 1.532 + 1.533 + sec_asn1d_scrub_state (state); 1.534 + child_allocate = PR_FALSE; 1.535 + 1.536 + if (encode_kind & SEC_ASN1_POINTER) { 1.537 + /* 1.538 + * A POINTER means we need to allocate the destination for 1.539 + * this field. But, since it may also be an optional field, 1.540 + * we defer the allocation until later; we just record that 1.541 + * it needs to be done. 1.542 + * 1.543 + * There are two possible scenarios here -- one is just a 1.544 + * plain POINTER (kind of like INLINE, except with allocation) 1.545 + * and the other is an implicitly-tagged POINTER. We don't 1.546 + * need to do anything special here for the two cases, but 1.547 + * since the template definition can be tricky, we do check 1.548 + * that there are no extraneous bits set in encode_kind. 1.549 + * 1.550 + * XXX The same conditions which assert should set an error. 1.551 + */ 1.552 + if (universal) { 1.553 + /* 1.554 + * "universal" means this entry is a standalone POINTER; 1.555 + * there should be no other bits set in encode_kind. 1.556 + */ 1.557 + PORT_Assert (encode_kind == SEC_ASN1_POINTER); 1.558 + } else { 1.559 + /* 1.560 + * If we get here we have an implicitly-tagged field 1.561 + * that needs to be put into a POINTER. The subtemplate 1.562 + * will determine how to decode the field, but encode_kind 1.563 + * describes the (implicit) tag we are looking for. 1.564 + * The non-tag bits of encode_kind will be ignored by 1.565 + * the code below; none of them should be set, however, 1.566 + * except for the POINTER bit itself -- so check that. 1.567 + */ 1.568 + PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK) 1.569 + == SEC_ASN1_POINTER); 1.570 + } 1.571 + if (!state->top->filter_only) 1.572 + child_allocate = PR_TRUE; 1.573 + dest = NULL; 1.574 + state->place = afterPointer; 1.575 + } else { 1.576 + dest = state->dest; 1.577 + if (encode_kind & SEC_ASN1_INLINE) { 1.578 + /* check that there are no extraneous bits */ 1.579 + PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); 1.580 + state->place = afterInline; 1.581 + } else { 1.582 + state->place = afterImplicit; 1.583 + } 1.584 + } 1.585 + 1.586 + state->optional = optional; 1.587 + subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE); 1.588 + state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE); 1.589 + if (state == NULL) 1.590 + return NULL; 1.591 + 1.592 + state->allocate = child_allocate; 1.593 + 1.594 + if (universal) { 1.595 + state = sec_asn1d_init_state_based_on_template (state); 1.596 + if (state != NULL) { 1.597 + /* 1.598 + * If this field is optional, we need to record that on 1.599 + * the pushed child so it won't fail if the field isn't 1.600 + * found. I can't think of a way that this new state 1.601 + * could already have optional set (which we would wipe 1.602 + * out below if our local optional is not set) -- but 1.603 + * just to be sure, assert that it isn't set. 1.604 + */ 1.605 + PORT_Assert (!state->optional); 1.606 + state->optional = optional; 1.607 + } 1.608 + return state; 1.609 + } 1.610 + 1.611 + under_kind = state->theTemplate->kind; 1.612 + under_kind &= ~SEC_ASN1_MAY_STREAM; 1.613 + } else if (explicit) { 1.614 + /* 1.615 + * For explicit, we only need to match the encoding tag next, 1.616 + * then we will push another state to handle the entire inner 1.617 + * part. In this case, there is no underlying kind which plays 1.618 + * any part in the determination of the outer, explicit tag. 1.619 + * So we just set under_kind to 0, which is not a valid tag, 1.620 + * and the rest of the tag matching stuff should be okay. 1.621 + */ 1.622 + under_kind = 0; 1.623 + } else { 1.624 + /* 1.625 + * Nothing special; the underlying kind and the given encoding 1.626 + * information are the same. 1.627 + */ 1.628 + under_kind = encode_kind; 1.629 + } 1.630 + 1.631 + /* XXX is this the right set of bits to test here? */ 1.632 + PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL 1.633 + | SEC_ASN1_MAY_STREAM 1.634 + | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); 1.635 + 1.636 + if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) { 1.637 + PORT_Assert (encode_kind == under_kind); 1.638 + if (encode_kind & SEC_ASN1_SKIP) { 1.639 + PORT_Assert (!optional); 1.640 + PORT_Assert (encode_kind == SEC_ASN1_SKIP); 1.641 + state->dest = NULL; 1.642 + } 1.643 + check_tag_mask = 0; 1.644 + expect_tag_modifiers = 0; 1.645 + expect_tag_number = 0; 1.646 + } else { 1.647 + check_tag_mask = SEC_ASN1_TAG_MASK; 1.648 + expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK 1.649 + & ~SEC_ASN1_TAGNUM_MASK; 1.650 + /* 1.651 + * XXX This assumes only single-octet identifiers. To handle 1.652 + * the HIGH TAG form we would need to do some more work, especially 1.653 + * in how to specify them in the template, because right now we 1.654 + * do not provide a way to specify more *tag* bits in encode_kind. 1.655 + */ 1.656 + expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; 1.657 + 1.658 + switch (under_kind & SEC_ASN1_TAGNUM_MASK) { 1.659 + case SEC_ASN1_SET: 1.660 + /* 1.661 + * XXX A plain old SET (as opposed to a SET OF) is not implemented. 1.662 + * If it ever is, remove this assert... 1.663 + */ 1.664 + PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0); 1.665 + /* fallthru */ 1.666 + case SEC_ASN1_SEQUENCE: 1.667 + expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED; 1.668 + break; 1.669 + case SEC_ASN1_BIT_STRING: 1.670 + case SEC_ASN1_BMP_STRING: 1.671 + case SEC_ASN1_GENERALIZED_TIME: 1.672 + case SEC_ASN1_IA5_STRING: 1.673 + case SEC_ASN1_OCTET_STRING: 1.674 + case SEC_ASN1_PRINTABLE_STRING: 1.675 + case SEC_ASN1_T61_STRING: 1.676 + case SEC_ASN1_UNIVERSAL_STRING: 1.677 + case SEC_ASN1_UTC_TIME: 1.678 + case SEC_ASN1_UTF8_STRING: 1.679 + case SEC_ASN1_VISIBLE_STRING: 1.680 + check_tag_mask &= ~SEC_ASN1_CONSTRUCTED; 1.681 + break; 1.682 + } 1.683 + } 1.684 + 1.685 + state->check_tag_mask = check_tag_mask; 1.686 + state->expect_tag_modifiers = expect_tag_modifiers; 1.687 + state->expect_tag_number = expect_tag_number; 1.688 + state->underlying_kind = under_kind; 1.689 + state->explicit = explicit; 1.690 + state->optional = optional; 1.691 + 1.692 + sec_asn1d_scrub_state (state); 1.693 + 1.694 + return state; 1.695 +} 1.696 + 1.697 +static sec_asn1d_state * 1.698 +sec_asn1d_get_enclosing_construct(sec_asn1d_state *state) 1.699 +{ 1.700 + for (state = state->parent; state; state = state->parent) { 1.701 + sec_asn1d_parse_place place = state->place; 1.702 + if (place != afterImplicit && 1.703 + place != afterPointer && 1.704 + place != afterInline && 1.705 + place != afterSaveEncoding && 1.706 + place != duringSaveEncoding && 1.707 + place != duringChoice) { 1.708 + 1.709 + /* we've walked up the stack to a state that represents 1.710 + ** the enclosing construct. 1.711 + */ 1.712 + break; 1.713 + } 1.714 + } 1.715 + return state; 1.716 +} 1.717 + 1.718 +static PRBool 1.719 +sec_asn1d_parent_allows_EOC(sec_asn1d_state *state) 1.720 +{ 1.721 + /* get state of enclosing construct. */ 1.722 + state = sec_asn1d_get_enclosing_construct(state); 1.723 + if (state) { 1.724 + sec_asn1d_parse_place place = state->place; 1.725 + /* Is it one of the types that permits an unexpected EOC? */ 1.726 + int eoc_permitted = 1.727 + (place == duringGroup || 1.728 + place == duringConstructedString || 1.729 + state->child->optional); 1.730 + return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE; 1.731 + } 1.732 + return PR_FALSE; 1.733 +} 1.734 + 1.735 +static unsigned long 1.736 +sec_asn1d_parse_identifier (sec_asn1d_state *state, 1.737 + const char *buf, unsigned long len) 1.738 +{ 1.739 + unsigned char byte; 1.740 + unsigned char tag_number; 1.741 + 1.742 + PORT_Assert (state->place == beforeIdentifier); 1.743 + 1.744 + if (len == 0) { 1.745 + state->top->status = needBytes; 1.746 + return 0; 1.747 + } 1.748 + 1.749 + byte = (unsigned char) *buf; 1.750 +#ifdef DEBUG_ASN1D_STATES 1.751 + { 1.752 + char kindBuf[256]; 1.753 + formatKind(byte, kindBuf); 1.754 + printf("Found tag %02x %s\n", byte, kindBuf); 1.755 + } 1.756 +#endif 1.757 + tag_number = byte & SEC_ASN1_TAGNUM_MASK; 1.758 + 1.759 + if (IS_HIGH_TAG_NUMBER (tag_number)) { 1.760 + state->place = duringIdentifier; 1.761 + state->found_tag_number = 0; 1.762 + /* 1.763 + * Actually, we have no idea how many bytes are pending, but we 1.764 + * do know that it is at least 1. That is all we know; we have 1.765 + * to look at each byte to know if there is another, etc. 1.766 + */ 1.767 + state->pending = 1; 1.768 + } else { 1.769 + if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) { 1.770 + /* 1.771 + * Our parent has indefinite-length encoding, and the 1.772 + * entire tag found is 0, so it seems that we have hit the 1.773 + * end-of-contents octets. To handle this, we just change 1.774 + * our state to that which expects to get the bytes of the 1.775 + * end-of-contents octets and let that code re-read this byte 1.776 + * so that our categorization of field types is correct. 1.777 + * After that, our parent will then deal with everything else. 1.778 + */ 1.779 + state->place = duringEndOfContents; 1.780 + state->pending = 2; 1.781 + state->found_tag_number = 0; 1.782 + state->found_tag_modifiers = 0; 1.783 + /* 1.784 + * We might be an optional field that is, as we now find out, 1.785 + * missing. Give our parent a clue that this happened. 1.786 + */ 1.787 + if (state->optional) 1.788 + state->missing = PR_TRUE; 1.789 + return 0; 1.790 + } 1.791 + state->place = afterIdentifier; 1.792 + state->found_tag_number = tag_number; 1.793 + } 1.794 + state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK; 1.795 + 1.796 + return 1; 1.797 +} 1.798 + 1.799 + 1.800 +static unsigned long 1.801 +sec_asn1d_parse_more_identifier (sec_asn1d_state *state, 1.802 + const char *buf, unsigned long len) 1.803 +{ 1.804 + unsigned char byte; 1.805 + int count; 1.806 + 1.807 + PORT_Assert (state->pending == 1); 1.808 + PORT_Assert (state->place == duringIdentifier); 1.809 + 1.810 + if (len == 0) { 1.811 + state->top->status = needBytes; 1.812 + return 0; 1.813 + } 1.814 + 1.815 + count = 0; 1.816 + 1.817 + while (len && state->pending) { 1.818 + if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) { 1.819 + /* 1.820 + * The given high tag number overflows our container; 1.821 + * just give up. This is not likely to *ever* happen. 1.822 + */ 1.823 + PORT_SetError (SEC_ERROR_BAD_DER); 1.824 + state->top->status = decodeError; 1.825 + return 0; 1.826 + } 1.827 + 1.828 + state->found_tag_number <<= TAG_NUMBER_BITS; 1.829 + 1.830 + byte = (unsigned char) buf[count++]; 1.831 + state->found_tag_number |= (byte & TAG_NUMBER_MASK); 1.832 + 1.833 + len--; 1.834 + if (LAST_TAG_NUMBER_BYTE (byte)) 1.835 + state->pending = 0; 1.836 + } 1.837 + 1.838 + if (state->pending == 0) 1.839 + state->place = afterIdentifier; 1.840 + 1.841 + return count; 1.842 +} 1.843 + 1.844 + 1.845 +static void 1.846 +sec_asn1d_confirm_identifier (sec_asn1d_state *state) 1.847 +{ 1.848 + PRBool match; 1.849 + 1.850 + PORT_Assert (state->place == afterIdentifier); 1.851 + 1.852 + match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) 1.853 + == state->expect_tag_modifiers) 1.854 + && ((state->found_tag_number & state->check_tag_mask) 1.855 + == state->expect_tag_number)); 1.856 + if (match) { 1.857 + state->place = beforeLength; 1.858 + } else { 1.859 + if (state->optional) { 1.860 + state->missing = PR_TRUE; 1.861 + state->place = afterEndOfContents; 1.862 + } else { 1.863 + PORT_SetError (SEC_ERROR_BAD_DER); 1.864 + state->top->status = decodeError; 1.865 + } 1.866 + } 1.867 +} 1.868 + 1.869 + 1.870 +static unsigned long 1.871 +sec_asn1d_parse_length (sec_asn1d_state *state, 1.872 + const char *buf, unsigned long len) 1.873 +{ 1.874 + unsigned char byte; 1.875 + 1.876 + PORT_Assert (state->place == beforeLength); 1.877 + 1.878 + if (len == 0) { 1.879 + state->top->status = needBytes; 1.880 + return 0; 1.881 + } 1.882 + 1.883 + /* 1.884 + * The default/likely outcome. It may get adjusted below. 1.885 + */ 1.886 + state->place = afterLength; 1.887 + 1.888 + byte = (unsigned char) *buf; 1.889 + 1.890 + if (LENGTH_IS_SHORT_FORM (byte)) { 1.891 + state->contents_length = byte; 1.892 + } else { 1.893 + state->contents_length = 0; 1.894 + state->pending = LONG_FORM_LENGTH (byte); 1.895 + if (state->pending == 0) { 1.896 + state->indefinite = PR_TRUE; 1.897 + } else { 1.898 + state->place = duringLength; 1.899 + } 1.900 + } 1.901 + 1.902 + /* If we're parsing an ANY, SKIP, or SAVE template, and 1.903 + ** the object being saved is definite length encoded and constructed, 1.904 + ** there's no point in decoding that construct's members. 1.905 + ** So, just forget it's constructed and treat it as primitive. 1.906 + ** (SAVE appears as an ANY at this point) 1.907 + */ 1.908 + if (!state->indefinite && 1.909 + (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) { 1.910 + state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED; 1.911 + } 1.912 + 1.913 + return 1; 1.914 +} 1.915 + 1.916 + 1.917 +static unsigned long 1.918 +sec_asn1d_parse_more_length (sec_asn1d_state *state, 1.919 + const char *buf, unsigned long len) 1.920 +{ 1.921 + int count; 1.922 + 1.923 + PORT_Assert (state->pending > 0); 1.924 + PORT_Assert (state->place == duringLength); 1.925 + 1.926 + if (len == 0) { 1.927 + state->top->status = needBytes; 1.928 + return 0; 1.929 + } 1.930 + 1.931 + count = 0; 1.932 + 1.933 + while (len && state->pending) { 1.934 + if (HIGH_BITS (state->contents_length, 9) != 0) { 1.935 + /* 1.936 + * The given full content length overflows our container; 1.937 + * just give up. 1.938 + */ 1.939 + PORT_SetError (SEC_ERROR_BAD_DER); 1.940 + state->top->status = decodeError; 1.941 + return 0; 1.942 + } 1.943 + 1.944 + state->contents_length <<= 8; 1.945 + state->contents_length |= (unsigned char) buf[count++]; 1.946 + 1.947 + len--; 1.948 + state->pending--; 1.949 + } 1.950 + 1.951 + if (state->pending == 0) 1.952 + state->place = afterLength; 1.953 + 1.954 + return count; 1.955 +} 1.956 + 1.957 + 1.958 +static void 1.959 +sec_asn1d_prepare_for_contents (sec_asn1d_state *state) 1.960 +{ 1.961 + SECItem *item; 1.962 + PLArenaPool *poolp; 1.963 + unsigned long alloc_len; 1.964 + 1.965 +#ifdef DEBUG_ASN1D_STATES 1.966 + { 1.967 + printf("Found Length %d %s\n", state->contents_length, 1.968 + state->indefinite ? "indefinite" : ""); 1.969 + } 1.970 +#endif 1.971 + 1.972 + /* 1.973 + * XXX I cannot decide if this allocation should exclude the case 1.974 + * where state->endofcontents is true -- figure it out! 1.975 + */ 1.976 + if (state->allocate) { 1.977 + void *dest; 1.978 + 1.979 + PORT_Assert (state->dest == NULL); 1.980 + /* 1.981 + * We are handling a POINTER or a member of a GROUP, and need to 1.982 + * allocate for the data structure. 1.983 + */ 1.984 + dest = sec_asn1d_zalloc (state->top->their_pool, 1.985 + state->theTemplate->size); 1.986 + if (dest == NULL) { 1.987 + state->top->status = decodeError; 1.988 + return; 1.989 + } 1.990 + state->dest = (char *)dest + state->theTemplate->offset; 1.991 + 1.992 + /* 1.993 + * For a member of a GROUP, our parent will later put the 1.994 + * pointer wherever it belongs. But for a POINTER, we need 1.995 + * to record the destination now, in case notify or filter 1.996 + * procs need access to it -- they cannot find it otherwise, 1.997 + * until it is too late (for one-pass processing). 1.998 + */ 1.999 + if (state->parent->place == afterPointer) { 1.1000 + void **placep; 1.1001 + 1.1002 + placep = state->parent->dest; 1.1003 + *placep = dest; 1.1004 + } 1.1005 + } 1.1006 + 1.1007 + /* 1.1008 + * Remember, length may be indefinite here! In that case, 1.1009 + * both contents_length and pending will be zero. 1.1010 + */ 1.1011 + state->pending = state->contents_length; 1.1012 + 1.1013 + /* If this item has definite length encoding, and 1.1014 + ** is enclosed by a definite length constructed type, 1.1015 + ** make sure it isn't longer than the remaining space in that 1.1016 + ** constructed type. 1.1017 + */ 1.1018 + if (state->contents_length > 0) { 1.1019 + sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state); 1.1020 + if (parent && !parent->indefinite && 1.1021 + state->consumed + state->contents_length > parent->pending) { 1.1022 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1023 + state->top->status = decodeError; 1.1024 + return; 1.1025 + } 1.1026 + } 1.1027 + 1.1028 + /* 1.1029 + * An EXPLICIT is nothing but an outer header, which we have 1.1030 + * already parsed and accepted. Now we need to do the inner 1.1031 + * header and its contents. 1.1032 + */ 1.1033 + if (state->explicit) { 1.1034 + state->place = afterExplicit; 1.1035 + state = sec_asn1d_push_state (state->top, 1.1036 + SEC_ASN1GetSubtemplate(state->theTemplate, 1.1037 + state->dest, 1.1038 + PR_FALSE), 1.1039 + state->dest, PR_TRUE); 1.1040 + if (state != NULL) 1.1041 + state = sec_asn1d_init_state_based_on_template (state); 1.1042 + return; 1.1043 + } 1.1044 + 1.1045 + /* 1.1046 + * For GROUP (SET OF, SEQUENCE OF), even if we know the length here 1.1047 + * we cannot tell how many items we will end up with ... so push a 1.1048 + * state that can keep track of "children" (the individual members 1.1049 + * of the group; we will allocate as we go and put them all together 1.1050 + * at the end. 1.1051 + */ 1.1052 + if (state->underlying_kind & SEC_ASN1_GROUP) { 1.1053 + /* XXX If this assertion holds (should be able to confirm it via 1.1054 + * inspection, too) then move this code into the switch statement 1.1055 + * below under cases SET_OF and SEQUENCE_OF; it will be cleaner. 1.1056 + */ 1.1057 + PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF 1.1058 + || state->underlying_kind == SEC_ASN1_SEQUENCE_OF 1.1059 + || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC) 1.1060 + || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC) 1.1061 + ); 1.1062 + if (state->contents_length != 0 || state->indefinite) { 1.1063 + const SEC_ASN1Template *subt; 1.1064 + 1.1065 + state->place = duringGroup; 1.1066 + subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, 1.1067 + PR_FALSE); 1.1068 + state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE); 1.1069 + if (state != NULL) { 1.1070 + if (!state->top->filter_only) 1.1071 + state->allocate = PR_TRUE; /* XXX propogate this? */ 1.1072 + /* 1.1073 + * Do the "before" field notification for next in group. 1.1074 + */ 1.1075 + sec_asn1d_notify_before (state->top, state->dest, state->depth); 1.1076 + state = sec_asn1d_init_state_based_on_template (state); 1.1077 + } 1.1078 + } else { 1.1079 + /* 1.1080 + * A group of zero; we are done. 1.1081 + * Set state to afterGroup and let that code plant the NULL. 1.1082 + */ 1.1083 + state->place = afterGroup; 1.1084 + } 1.1085 + return; 1.1086 + } 1.1087 + 1.1088 + switch (state->underlying_kind) { 1.1089 + case SEC_ASN1_SEQUENCE: 1.1090 + /* 1.1091 + * We need to push a child to handle the individual fields. 1.1092 + */ 1.1093 + state->place = duringSequence; 1.1094 + state = sec_asn1d_push_state (state->top, state->theTemplate + 1, 1.1095 + state->dest, PR_TRUE); 1.1096 + if (state != NULL) { 1.1097 + /* 1.1098 + * Do the "before" field notification. 1.1099 + */ 1.1100 + sec_asn1d_notify_before (state->top, state->dest, state->depth); 1.1101 + state = sec_asn1d_init_state_based_on_template (state); 1.1102 + } 1.1103 + break; 1.1104 + 1.1105 + case SEC_ASN1_SET: /* XXX SET is not really implemented */ 1.1106 + /* 1.1107 + * XXX A plain SET requires special handling; scanning of a 1.1108 + * template to see where a field should go (because by definition, 1.1109 + * they are not in any particular order, and you have to look at 1.1110 + * each tag to disambiguate what the field is). We may never 1.1111 + * implement this because in practice, it seems to be unused. 1.1112 + */ 1.1113 + PORT_Assert(0); 1.1114 + PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */ 1.1115 + state->top->status = decodeError; 1.1116 + break; 1.1117 + 1.1118 + case SEC_ASN1_NULL: 1.1119 + /* 1.1120 + * The NULL type, by definition, is "nothing", content length of zero. 1.1121 + * An indefinite-length encoding is not alloweed. 1.1122 + */ 1.1123 + if (state->contents_length || state->indefinite) { 1.1124 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1125 + state->top->status = decodeError; 1.1126 + break; 1.1127 + } 1.1128 + if (state->dest != NULL) { 1.1129 + item = (SECItem *)(state->dest); 1.1130 + item->data = NULL; 1.1131 + item->len = 0; 1.1132 + } 1.1133 + state->place = afterEndOfContents; 1.1134 + break; 1.1135 + 1.1136 + case SEC_ASN1_BMP_STRING: 1.1137 + /* Error if length is not divisable by 2 */ 1.1138 + if (state->contents_length % 2) { 1.1139 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1140 + state->top->status = decodeError; 1.1141 + break; 1.1142 + } 1.1143 + /* otherwise, handle as other string types */ 1.1144 + goto regular_string_type; 1.1145 + 1.1146 + case SEC_ASN1_UNIVERSAL_STRING: 1.1147 + /* Error if length is not divisable by 4 */ 1.1148 + if (state->contents_length % 4) { 1.1149 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1150 + state->top->status = decodeError; 1.1151 + break; 1.1152 + } 1.1153 + /* otherwise, handle as other string types */ 1.1154 + goto regular_string_type; 1.1155 + 1.1156 + case SEC_ASN1_SKIP: 1.1157 + case SEC_ASN1_ANY: 1.1158 + case SEC_ASN1_ANY_CONTENTS: 1.1159 + /* 1.1160 + * These are not (necessarily) strings, but they need nearly 1.1161 + * identical handling (especially when we need to deal with 1.1162 + * constructed sub-pieces), so we pretend they are. 1.1163 + */ 1.1164 + /* fallthru */ 1.1165 +regular_string_type: 1.1166 + case SEC_ASN1_BIT_STRING: 1.1167 + case SEC_ASN1_IA5_STRING: 1.1168 + case SEC_ASN1_OCTET_STRING: 1.1169 + case SEC_ASN1_PRINTABLE_STRING: 1.1170 + case SEC_ASN1_T61_STRING: 1.1171 + case SEC_ASN1_UTC_TIME: 1.1172 + case SEC_ASN1_UTF8_STRING: 1.1173 + case SEC_ASN1_VISIBLE_STRING: 1.1174 + /* 1.1175 + * We are allocating for a primitive or a constructed string. 1.1176 + * If it is a constructed string, it may also be indefinite-length. 1.1177 + * If it is primitive, the length can (legally) be zero. 1.1178 + * Our first order of business is to allocate the memory for 1.1179 + * the string, if we can (if we know the length). 1.1180 + */ 1.1181 + item = (SECItem *)(state->dest); 1.1182 + 1.1183 + /* 1.1184 + * If the item is a definite-length constructed string, then 1.1185 + * the contents_length is actually larger than what we need 1.1186 + * (because it also counts each intermediate header which we 1.1187 + * will be throwing away as we go), but it is a perfectly good 1.1188 + * upper bound that we just allocate anyway, and then concat 1.1189 + * as we go; we end up wasting a few extra bytes but save a 1.1190 + * whole other copy. 1.1191 + */ 1.1192 + alloc_len = state->contents_length; 1.1193 + poolp = NULL; /* quiet compiler warnings about unused... */ 1.1194 + 1.1195 + if (item == NULL || state->top->filter_only) { 1.1196 + if (item != NULL) { 1.1197 + item->data = NULL; 1.1198 + item->len = 0; 1.1199 + } 1.1200 + alloc_len = 0; 1.1201 + } else if (state->substring) { 1.1202 + /* 1.1203 + * If we are a substring of a constructed string, then we may 1.1204 + * not have to allocate anything (because our parent, the 1.1205 + * actual constructed string, did it for us). If we are a 1.1206 + * substring and we *do* have to allocate, that means our 1.1207 + * parent is an indefinite-length, so we allocate from our pool; 1.1208 + * later our parent will copy our string into the aggregated 1.1209 + * whole and free our pool allocation. 1.1210 + */ 1.1211 + if (item->data == NULL) { 1.1212 + PORT_Assert (item->len == 0); 1.1213 + poolp = state->top->our_pool; 1.1214 + } else { 1.1215 + alloc_len = 0; 1.1216 + } 1.1217 + } else { 1.1218 + item->len = 0; 1.1219 + item->data = NULL; 1.1220 + poolp = state->top->their_pool; 1.1221 + } 1.1222 + 1.1223 + if (alloc_len || ((! state->indefinite) 1.1224 + && (state->subitems_head != NULL))) { 1.1225 + struct subitem *subitem; 1.1226 + int len; 1.1227 + 1.1228 + PORT_Assert (item); 1.1229 + if (!item) { 1.1230 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1231 + state->top->status = decodeError; 1.1232 + return; 1.1233 + } 1.1234 + PORT_Assert (item->len == 0 && item->data == NULL); 1.1235 + /* 1.1236 + * Check for and handle an ANY which has stashed aside the 1.1237 + * header (identifier and length) bytes for us to include 1.1238 + * in the saved contents. 1.1239 + */ 1.1240 + if (state->subitems_head != NULL) { 1.1241 + PORT_Assert (state->underlying_kind == SEC_ASN1_ANY); 1.1242 + for (subitem = state->subitems_head; 1.1243 + subitem != NULL; subitem = subitem->next) 1.1244 + alloc_len += subitem->len; 1.1245 + } 1.1246 + 1.1247 + item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len); 1.1248 + if (item->data == NULL) { 1.1249 + state->top->status = decodeError; 1.1250 + break; 1.1251 + } 1.1252 + 1.1253 + len = 0; 1.1254 + for (subitem = state->subitems_head; 1.1255 + subitem != NULL; subitem = subitem->next) { 1.1256 + PORT_Memcpy (item->data + len, subitem->data, subitem->len); 1.1257 + len += subitem->len; 1.1258 + } 1.1259 + item->len = len; 1.1260 + 1.1261 + /* 1.1262 + * Because we use arenas and have a mark set, we later free 1.1263 + * everything we have allocated, so this does *not* present 1.1264 + * a memory leak (it is just temporarily left dangling). 1.1265 + */ 1.1266 + state->subitems_head = state->subitems_tail = NULL; 1.1267 + } 1.1268 + 1.1269 + if (state->contents_length == 0 && (! state->indefinite)) { 1.1270 + /* 1.1271 + * A zero-length simple or constructed string; we are done. 1.1272 + */ 1.1273 + state->place = afterEndOfContents; 1.1274 + } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) { 1.1275 + const SEC_ASN1Template *sub; 1.1276 + 1.1277 + switch (state->underlying_kind) { 1.1278 + case SEC_ASN1_ANY: 1.1279 + case SEC_ASN1_ANY_CONTENTS: 1.1280 + sub = SEC_AnyTemplate; 1.1281 + break; 1.1282 + case SEC_ASN1_BIT_STRING: 1.1283 + sub = SEC_BitStringTemplate; 1.1284 + break; 1.1285 + case SEC_ASN1_BMP_STRING: 1.1286 + sub = SEC_BMPStringTemplate; 1.1287 + break; 1.1288 + case SEC_ASN1_GENERALIZED_TIME: 1.1289 + sub = SEC_GeneralizedTimeTemplate; 1.1290 + break; 1.1291 + case SEC_ASN1_IA5_STRING: 1.1292 + sub = SEC_IA5StringTemplate; 1.1293 + break; 1.1294 + case SEC_ASN1_OCTET_STRING: 1.1295 + sub = SEC_OctetStringTemplate; 1.1296 + break; 1.1297 + case SEC_ASN1_PRINTABLE_STRING: 1.1298 + sub = SEC_PrintableStringTemplate; 1.1299 + break; 1.1300 + case SEC_ASN1_T61_STRING: 1.1301 + sub = SEC_T61StringTemplate; 1.1302 + break; 1.1303 + case SEC_ASN1_UNIVERSAL_STRING: 1.1304 + sub = SEC_UniversalStringTemplate; 1.1305 + break; 1.1306 + case SEC_ASN1_UTC_TIME: 1.1307 + sub = SEC_UTCTimeTemplate; 1.1308 + break; 1.1309 + case SEC_ASN1_UTF8_STRING: 1.1310 + sub = SEC_UTF8StringTemplate; 1.1311 + break; 1.1312 + case SEC_ASN1_VISIBLE_STRING: 1.1313 + sub = SEC_VisibleStringTemplate; 1.1314 + break; 1.1315 + case SEC_ASN1_SKIP: 1.1316 + sub = SEC_SkipTemplate; 1.1317 + break; 1.1318 + default: /* redundant given outer switch cases, but */ 1.1319 + PORT_Assert(0); /* the compiler does not seem to know that, */ 1.1320 + sub = NULL; /* so just do enough to quiet it. */ 1.1321 + break; 1.1322 + } 1.1323 + 1.1324 + state->place = duringConstructedString; 1.1325 + state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE); 1.1326 + if (state != NULL) { 1.1327 + state->substring = PR_TRUE; /* XXX propogate? */ 1.1328 + state = sec_asn1d_init_state_based_on_template (state); 1.1329 + } 1.1330 + } else if (state->indefinite) { 1.1331 + /* 1.1332 + * An indefinite-length string *must* be constructed! 1.1333 + */ 1.1334 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1335 + state->top->status = decodeError; 1.1336 + } else { 1.1337 + /* 1.1338 + * A non-zero-length simple string. 1.1339 + */ 1.1340 + if (state->underlying_kind == SEC_ASN1_BIT_STRING) 1.1341 + state->place = beforeBitString; 1.1342 + else 1.1343 + state->place = duringLeaf; 1.1344 + } 1.1345 + break; 1.1346 + 1.1347 + default: 1.1348 + /* 1.1349 + * We are allocating for a simple leaf item. 1.1350 + */ 1.1351 + if (state->contents_length) { 1.1352 + if (state->dest != NULL) { 1.1353 + item = (SECItem *)(state->dest); 1.1354 + item->len = 0; 1.1355 + if (state->top->filter_only) { 1.1356 + item->data = NULL; 1.1357 + } else { 1.1358 + item->data = (unsigned char*) 1.1359 + sec_asn1d_zalloc (state->top->their_pool, 1.1360 + state->contents_length); 1.1361 + if (item->data == NULL) { 1.1362 + state->top->status = decodeError; 1.1363 + return; 1.1364 + } 1.1365 + } 1.1366 + } 1.1367 + state->place = duringLeaf; 1.1368 + } else { 1.1369 + /* 1.1370 + * An indefinite-length or zero-length item is not allowed. 1.1371 + * (All legal cases of such were handled above.) 1.1372 + */ 1.1373 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1374 + state->top->status = decodeError; 1.1375 + } 1.1376 + } 1.1377 +} 1.1378 + 1.1379 + 1.1380 +static void 1.1381 +sec_asn1d_free_child (sec_asn1d_state *state, PRBool error) 1.1382 +{ 1.1383 + if (state->child != NULL) { 1.1384 + PORT_Assert (error || state->child->consumed == 0); 1.1385 + PORT_Assert (state->our_mark != NULL); 1.1386 + PORT_ArenaZRelease (state->top->our_pool, state->our_mark); 1.1387 + if (error && state->top->their_pool == NULL) { 1.1388 + /* 1.1389 + * XXX We need to free anything allocated. 1.1390 + * At this point, we failed in the middle of decoding. But we 1.1391 + * can't free the data we previously allocated with PR_Malloc 1.1392 + * unless we keep track of every pointer. So instead we have a 1.1393 + * memory leak when decoding fails half-way, unless an arena is 1.1394 + * used. See bug 95311 . 1.1395 + */ 1.1396 + } 1.1397 + state->child = NULL; 1.1398 + state->our_mark = NULL; 1.1399 + } else { 1.1400 + /* 1.1401 + * It is important that we do not leave a mark unreleased/unmarked. 1.1402 + * But I do not think we should ever have one set in this case, only 1.1403 + * if we had a child (handled above). So check for that. If this 1.1404 + * assertion should ever get hit, then we probably need to add code 1.1405 + * here to release back to our_mark (and then set our_mark to NULL). 1.1406 + */ 1.1407 + PORT_Assert (state->our_mark == NULL); 1.1408 + } 1.1409 + state->place = beforeEndOfContents; 1.1410 +} 1.1411 + 1.1412 +/* We have just saved an entire encoded ASN.1 object (type) for a SAVE 1.1413 +** template, and now in the next template, we are going to decode that 1.1414 +** saved data by calling SEC_ASN1DecoderUpdate recursively. 1.1415 +** If that recursive call fails with needBytes, it is a fatal error, 1.1416 +** because the encoded object should have been complete. 1.1417 +** If that recursive call fails with decodeError, it will have already 1.1418 +** cleaned up the state stack, so we must bail out quickly. 1.1419 +** 1.1420 +** These checks of the status returned by the recursive call are now 1.1421 +** done in the caller of this function, immediately after it returns. 1.1422 +*/ 1.1423 +static void 1.1424 +sec_asn1d_reuse_encoding (sec_asn1d_state *state) 1.1425 +{ 1.1426 + sec_asn1d_state *child; 1.1427 + unsigned long consumed; 1.1428 + SECItem *item; 1.1429 + void *dest; 1.1430 + 1.1431 + 1.1432 + child = state->child; 1.1433 + PORT_Assert (child != NULL); 1.1434 + 1.1435 + consumed = child->consumed; 1.1436 + child->consumed = 0; 1.1437 + 1.1438 + item = (SECItem *)(state->dest); 1.1439 + PORT_Assert (item != NULL); 1.1440 + 1.1441 + PORT_Assert (item->len == consumed); 1.1442 + 1.1443 + /* 1.1444 + * Free any grandchild. 1.1445 + */ 1.1446 + sec_asn1d_free_child (child, PR_FALSE); 1.1447 + 1.1448 + /* 1.1449 + * Notify after the SAVE field. 1.1450 + */ 1.1451 + sec_asn1d_notify_after (state->top, state->dest, state->depth); 1.1452 + 1.1453 + /* 1.1454 + * Adjust to get new dest and move forward. 1.1455 + */ 1.1456 + dest = (char *)state->dest - state->theTemplate->offset; 1.1457 + state->theTemplate++; 1.1458 + child->dest = (char *)dest + state->theTemplate->offset; 1.1459 + child->theTemplate = state->theTemplate; 1.1460 + 1.1461 + /* 1.1462 + * Notify before the "real" field. 1.1463 + */ 1.1464 + PORT_Assert (state->depth == child->depth); 1.1465 + sec_asn1d_notify_before (state->top, child->dest, child->depth); 1.1466 + 1.1467 + /* 1.1468 + * This will tell DecoderUpdate to return when it is done. 1.1469 + */ 1.1470 + state->place = afterSaveEncoding; 1.1471 + 1.1472 + /* 1.1473 + * We already have a child; "push" it by making it current. 1.1474 + */ 1.1475 + state->top->current = child; 1.1476 + 1.1477 + /* 1.1478 + * And initialize it so it is ready to parse. 1.1479 + */ 1.1480 + (void) sec_asn1d_init_state_based_on_template(child); 1.1481 + 1.1482 + /* 1.1483 + * Now parse that out of our data. 1.1484 + */ 1.1485 + if (SEC_ASN1DecoderUpdate (state->top, 1.1486 + (char *) item->data, item->len) != SECSuccess) 1.1487 + return; 1.1488 + if (state->top->status == needBytes) { 1.1489 + return; 1.1490 + } 1.1491 + 1.1492 + PORT_Assert (state->top->current == state); 1.1493 + PORT_Assert (state->child == child); 1.1494 + 1.1495 + /* 1.1496 + * That should have consumed what we consumed before. 1.1497 + */ 1.1498 + PORT_Assert (consumed == child->consumed); 1.1499 + child->consumed = 0; 1.1500 + 1.1501 + /* 1.1502 + * Done. 1.1503 + */ 1.1504 + state->consumed += consumed; 1.1505 + child->place = notInUse; 1.1506 + state->place = afterEndOfContents; 1.1507 +} 1.1508 + 1.1509 + 1.1510 +static unsigned long 1.1511 +sec_asn1d_parse_leaf (sec_asn1d_state *state, 1.1512 + const char *buf, unsigned long len) 1.1513 +{ 1.1514 + SECItem *item; 1.1515 + unsigned long bufLen; 1.1516 + 1.1517 + if (len == 0) { 1.1518 + state->top->status = needBytes; 1.1519 + return 0; 1.1520 + } 1.1521 + 1.1522 + if (state->pending < len) 1.1523 + len = state->pending; 1.1524 + 1.1525 + bufLen = len; 1.1526 + 1.1527 + item = (SECItem *)(state->dest); 1.1528 + if (item != NULL && item->data != NULL) { 1.1529 + /* Strip leading zeroes when target is unsigned integer */ 1.1530 + if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */ 1.1531 + item->len == 0 && /* MSB */ 1.1532 + item->type == siUnsignedInteger) /* unsigned */ 1.1533 + { 1.1534 + while (len > 1 && buf[0] == 0) { /* leading 0 */ 1.1535 + buf++; 1.1536 + len--; 1.1537 + } 1.1538 + } 1.1539 + PORT_Memcpy (item->data + item->len, buf, len); 1.1540 + item->len += len; 1.1541 + } 1.1542 + state->pending -= bufLen; 1.1543 + if (state->pending == 0) 1.1544 + state->place = beforeEndOfContents; 1.1545 + 1.1546 + return bufLen; 1.1547 +} 1.1548 + 1.1549 + 1.1550 +static unsigned long 1.1551 +sec_asn1d_parse_bit_string (sec_asn1d_state *state, 1.1552 + const char *buf, unsigned long len) 1.1553 +{ 1.1554 + unsigned char byte; 1.1555 + 1.1556 + /*PORT_Assert (state->pending > 0); */ 1.1557 + PORT_Assert (state->place == beforeBitString); 1.1558 + 1.1559 + if (state->pending == 0) { 1.1560 + if (state->dest != NULL) { 1.1561 + SECItem *item = (SECItem *)(state->dest); 1.1562 + item->data = NULL; 1.1563 + item->len = 0; 1.1564 + state->place = beforeEndOfContents; 1.1565 + return 0; 1.1566 + } 1.1567 + } 1.1568 + 1.1569 + if (len == 0) { 1.1570 + state->top->status = needBytes; 1.1571 + return 0; 1.1572 + } 1.1573 + 1.1574 + byte = (unsigned char) *buf; 1.1575 + if (byte > 7) { 1.1576 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1577 + state->top->status = decodeError; 1.1578 + return 0; 1.1579 + } 1.1580 + 1.1581 + state->bit_string_unused_bits = byte; 1.1582 + state->place = duringBitString; 1.1583 + state->pending -= 1; 1.1584 + 1.1585 + return 1; 1.1586 +} 1.1587 + 1.1588 + 1.1589 +static unsigned long 1.1590 +sec_asn1d_parse_more_bit_string (sec_asn1d_state *state, 1.1591 + const char *buf, unsigned long len) 1.1592 +{ 1.1593 + PORT_Assert (state->place == duringBitString); 1.1594 + if (state->pending == 0) { 1.1595 + /* An empty bit string with some unused bits is invalid. */ 1.1596 + if (state->bit_string_unused_bits) { 1.1597 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1598 + state->top->status = decodeError; 1.1599 + } else { 1.1600 + /* An empty bit string with no unused bits is OK. */ 1.1601 + state->place = beforeEndOfContents; 1.1602 + } 1.1603 + return 0; 1.1604 + } 1.1605 + 1.1606 + len = sec_asn1d_parse_leaf (state, buf, len); 1.1607 + if (state->place == beforeEndOfContents && state->dest != NULL) { 1.1608 + SECItem *item; 1.1609 + 1.1610 + item = (SECItem *)(state->dest); 1.1611 + if (item->len) 1.1612 + item->len = (item->len << 3) - state->bit_string_unused_bits; 1.1613 + } 1.1614 + 1.1615 + return len; 1.1616 +} 1.1617 + 1.1618 + 1.1619 +/* 1.1620 + * XXX All callers should be looking at return value to detect 1.1621 + * out-of-memory errors (and stop!). 1.1622 + */ 1.1623 +static struct subitem * 1.1624 +sec_asn1d_add_to_subitems (sec_asn1d_state *state, 1.1625 + const void *data, unsigned long len, 1.1626 + PRBool copy_data) 1.1627 +{ 1.1628 + struct subitem *thing; 1.1629 + 1.1630 + thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool, 1.1631 + sizeof (struct subitem)); 1.1632 + if (thing == NULL) { 1.1633 + state->top->status = decodeError; 1.1634 + return NULL; 1.1635 + } 1.1636 + 1.1637 + if (copy_data) { 1.1638 + void *copy; 1.1639 + copy = sec_asn1d_alloc (state->top->our_pool, len); 1.1640 + if (copy == NULL) { 1.1641 + state->top->status = decodeError; 1.1642 + if (!state->top->our_pool) 1.1643 + PORT_Free(thing); 1.1644 + return NULL; 1.1645 + } 1.1646 + PORT_Memcpy (copy, data, len); 1.1647 + thing->data = copy; 1.1648 + } else { 1.1649 + thing->data = data; 1.1650 + } 1.1651 + thing->len = len; 1.1652 + thing->next = NULL; 1.1653 + 1.1654 + if (state->subitems_head == NULL) { 1.1655 + PORT_Assert (state->subitems_tail == NULL); 1.1656 + state->subitems_head = state->subitems_tail = thing; 1.1657 + } else { 1.1658 + state->subitems_tail->next = thing; 1.1659 + state->subitems_tail = thing; 1.1660 + } 1.1661 + 1.1662 + return thing; 1.1663 +} 1.1664 + 1.1665 + 1.1666 +static void 1.1667 +sec_asn1d_record_any_header (sec_asn1d_state *state, 1.1668 + const char *buf, 1.1669 + unsigned long len) 1.1670 +{ 1.1671 + SECItem *item; 1.1672 + 1.1673 + item = (SECItem *)(state->dest); 1.1674 + if (item != NULL && item->data != NULL) { 1.1675 + PORT_Assert (state->substring); 1.1676 + PORT_Memcpy (item->data + item->len, buf, len); 1.1677 + item->len += len; 1.1678 + } else { 1.1679 + sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE); 1.1680 + } 1.1681 +} 1.1682 + 1.1683 + 1.1684 +/* 1.1685 + * We are moving along through the substrings of a constructed string, 1.1686 + * and have just finished parsing one -- we need to save our child data 1.1687 + * (if the child was not already writing directly into the destination) 1.1688 + * and then move forward by one. 1.1689 + * 1.1690 + * We also have to detect when we are done: 1.1691 + * - a definite-length encoding stops when our pending value hits 0 1.1692 + * - an indefinite-length encoding stops when our child is empty 1.1693 + * (which means it was the end-of-contents octets) 1.1694 + */ 1.1695 +static void 1.1696 +sec_asn1d_next_substring (sec_asn1d_state *state) 1.1697 +{ 1.1698 + sec_asn1d_state *child; 1.1699 + SECItem *item; 1.1700 + unsigned long child_consumed; 1.1701 + PRBool done; 1.1702 + 1.1703 + PORT_Assert (state->place == duringConstructedString); 1.1704 + PORT_Assert (state->child != NULL); 1.1705 + 1.1706 + child = state->child; 1.1707 + 1.1708 + child_consumed = child->consumed; 1.1709 + child->consumed = 0; 1.1710 + state->consumed += child_consumed; 1.1711 + 1.1712 + done = PR_FALSE; 1.1713 + 1.1714 + if (state->pending) { 1.1715 + PORT_Assert (!state->indefinite); 1.1716 + if (child_consumed > state->pending) { 1.1717 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1718 + state->top->status = decodeError; 1.1719 + return; 1.1720 + } 1.1721 + 1.1722 + state->pending -= child_consumed; 1.1723 + if (state->pending == 0) 1.1724 + done = PR_TRUE; 1.1725 + } else { 1.1726 + PORT_Assert (state->indefinite); 1.1727 + 1.1728 + item = (SECItem *)(child->dest); 1.1729 + if (item != NULL && item->data != NULL) { 1.1730 + /* 1.1731 + * Save the string away for later concatenation. 1.1732 + */ 1.1733 + PORT_Assert (item->data != NULL); 1.1734 + sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE); 1.1735 + /* 1.1736 + * Clear the child item for the next round. 1.1737 + */ 1.1738 + item->data = NULL; 1.1739 + item->len = 0; 1.1740 + } 1.1741 + 1.1742 + /* 1.1743 + * If our child was just our end-of-contents octets, we are done. 1.1744 + */ 1.1745 + if (child->endofcontents) 1.1746 + done = PR_TRUE; 1.1747 + } 1.1748 + 1.1749 + /* 1.1750 + * Stop or do the next one. 1.1751 + */ 1.1752 + if (done) { 1.1753 + child->place = notInUse; 1.1754 + state->place = afterConstructedString; 1.1755 + } else { 1.1756 + sec_asn1d_scrub_state (child); 1.1757 + state->top->current = child; 1.1758 + } 1.1759 +} 1.1760 + 1.1761 + 1.1762 +/* 1.1763 + * We are doing a SET OF or SEQUENCE OF, and have just finished an item. 1.1764 + */ 1.1765 +static void 1.1766 +sec_asn1d_next_in_group (sec_asn1d_state *state) 1.1767 +{ 1.1768 + sec_asn1d_state *child; 1.1769 + unsigned long child_consumed; 1.1770 + 1.1771 + PORT_Assert (state->place == duringGroup); 1.1772 + PORT_Assert (state->child != NULL); 1.1773 + 1.1774 + child = state->child; 1.1775 + 1.1776 + child_consumed = child->consumed; 1.1777 + child->consumed = 0; 1.1778 + state->consumed += child_consumed; 1.1779 + 1.1780 + /* 1.1781 + * If our child was just our end-of-contents octets, we are done. 1.1782 + */ 1.1783 + if (child->endofcontents) { 1.1784 + /* XXX I removed the PORT_Assert (child->dest == NULL) because there 1.1785 + * was a bug in that a template that was a sequence of which also had 1.1786 + * a child of a sequence of, in an indefinite group was not working 1.1787 + * properly. This fix seems to work, (added the if statement below), 1.1788 + * and nothing appears broken, but I am putting this note here just 1.1789 + * in case. */ 1.1790 + /* 1.1791 + * XXX No matter how many times I read that comment, 1.1792 + * I cannot figure out what case he was fixing. I believe what he 1.1793 + * did was deliberate, so I am loathe to touch it. I need to 1.1794 + * understand how it could ever be that child->dest != NULL but 1.1795 + * child->endofcontents is true, and why it is important to check 1.1796 + * that state->subitems_head is NULL. This really needs to be 1.1797 + * figured out, as I am not sure if the following code should be 1.1798 + * compensating for "offset", as is done a little farther below 1.1799 + * in the more normal case. 1.1800 + */ 1.1801 + PORT_Assert (state->indefinite); 1.1802 + PORT_Assert (state->pending == 0); 1.1803 + if(child->dest && !state->subitems_head) { 1.1804 + sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE); 1.1805 + child->dest = NULL; 1.1806 + } 1.1807 + 1.1808 + child->place = notInUse; 1.1809 + state->place = afterGroup; 1.1810 + return; 1.1811 + } 1.1812 + 1.1813 + /* 1.1814 + * Do the "after" field notification for next in group. 1.1815 + */ 1.1816 + sec_asn1d_notify_after (state->top, child->dest, child->depth); 1.1817 + 1.1818 + /* 1.1819 + * Save it away (unless we are not storing). 1.1820 + */ 1.1821 + if (child->dest != NULL) { 1.1822 + void *dest; 1.1823 + 1.1824 + dest = child->dest; 1.1825 + dest = (char *)dest - child->theTemplate->offset; 1.1826 + sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE); 1.1827 + child->dest = NULL; 1.1828 + } 1.1829 + 1.1830 + /* 1.1831 + * Account for those bytes; see if we are done. 1.1832 + */ 1.1833 + if (state->pending) { 1.1834 + PORT_Assert (!state->indefinite); 1.1835 + if (child_consumed > state->pending) { 1.1836 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1837 + state->top->status = decodeError; 1.1838 + return; 1.1839 + } 1.1840 + 1.1841 + state->pending -= child_consumed; 1.1842 + if (state->pending == 0) { 1.1843 + child->place = notInUse; 1.1844 + state->place = afterGroup; 1.1845 + return; 1.1846 + } 1.1847 + } 1.1848 + 1.1849 + /* 1.1850 + * Do the "before" field notification for next item in group. 1.1851 + */ 1.1852 + sec_asn1d_notify_before (state->top, child->dest, child->depth); 1.1853 + 1.1854 + /* 1.1855 + * Now we do the next one. 1.1856 + */ 1.1857 + sec_asn1d_scrub_state (child); 1.1858 + 1.1859 + /* Initialize child state from the template */ 1.1860 + sec_asn1d_init_state_based_on_template(child); 1.1861 + 1.1862 + state->top->current = child; 1.1863 +} 1.1864 + 1.1865 + 1.1866 +/* 1.1867 + * We are moving along through a sequence; move forward by one, 1.1868 + * (detecting end-of-sequence when it happens). 1.1869 + * XXX The handling of "missing" is ugly. Fix it. 1.1870 + */ 1.1871 +static void 1.1872 +sec_asn1d_next_in_sequence (sec_asn1d_state *state) 1.1873 +{ 1.1874 + sec_asn1d_state *child; 1.1875 + unsigned long child_consumed; 1.1876 + PRBool child_missing; 1.1877 + 1.1878 + PORT_Assert (state->place == duringSequence); 1.1879 + PORT_Assert (state->child != NULL); 1.1880 + 1.1881 + child = state->child; 1.1882 + 1.1883 + /* 1.1884 + * Do the "after" field notification. 1.1885 + */ 1.1886 + sec_asn1d_notify_after (state->top, child->dest, child->depth); 1.1887 + 1.1888 + child_missing = (PRBool) child->missing; 1.1889 + child_consumed = child->consumed; 1.1890 + child->consumed = 0; 1.1891 + 1.1892 + /* 1.1893 + * Take care of accounting. 1.1894 + */ 1.1895 + if (child_missing) { 1.1896 + PORT_Assert (child->optional); 1.1897 + } else { 1.1898 + state->consumed += child_consumed; 1.1899 + /* 1.1900 + * Free any grandchild. 1.1901 + */ 1.1902 + sec_asn1d_free_child (child, PR_FALSE); 1.1903 + if (state->pending) { 1.1904 + PORT_Assert (!state->indefinite); 1.1905 + if (child_consumed > state->pending) { 1.1906 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1907 + state->top->status = decodeError; 1.1908 + return; 1.1909 + } 1.1910 + state->pending -= child_consumed; 1.1911 + if (state->pending == 0) { 1.1912 + child->theTemplate++; 1.1913 + while (child->theTemplate->kind != 0) { 1.1914 + if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) { 1.1915 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1916 + state->top->status = decodeError; 1.1917 + return; 1.1918 + } 1.1919 + child->theTemplate++; 1.1920 + } 1.1921 + child->place = notInUse; 1.1922 + state->place = afterEndOfContents; 1.1923 + return; 1.1924 + } 1.1925 + } 1.1926 + } 1.1927 + 1.1928 + /* 1.1929 + * Move forward. 1.1930 + */ 1.1931 + child->theTemplate++; 1.1932 + if (child->theTemplate->kind == 0) { 1.1933 + /* 1.1934 + * We are done with this sequence. 1.1935 + */ 1.1936 + child->place = notInUse; 1.1937 + if (state->pending) { 1.1938 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1939 + state->top->status = decodeError; 1.1940 + } else if (child_missing) { 1.1941 + /* 1.1942 + * We got to the end, but have a child that started parsing 1.1943 + * and ended up "missing". The only legitimate reason for 1.1944 + * this is that we had one or more optional fields at the 1.1945 + * end of our sequence, and we were encoded indefinite-length, 1.1946 + * so when we went looking for those optional fields we 1.1947 + * found our end-of-contents octets instead. 1.1948 + * (Yes, this is ugly; dunno a better way to handle it.) 1.1949 + * So, first confirm the situation, and then mark that we 1.1950 + * are done. 1.1951 + */ 1.1952 + if (state->indefinite && child->endofcontents) { 1.1953 + PORT_Assert (child_consumed == 2); 1.1954 + if (child_consumed != 2) { 1.1955 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1956 + state->top->status = decodeError; 1.1957 + } else { 1.1958 + state->consumed += child_consumed; 1.1959 + state->place = afterEndOfContents; 1.1960 + } 1.1961 + } else { 1.1962 + PORT_SetError (SEC_ERROR_BAD_DER); 1.1963 + state->top->status = decodeError; 1.1964 + } 1.1965 + } else { 1.1966 + /* 1.1967 + * We have to finish out, maybe reading end-of-contents octets; 1.1968 + * let the normal logic do the right thing. 1.1969 + */ 1.1970 + state->place = beforeEndOfContents; 1.1971 + } 1.1972 + } else { 1.1973 + unsigned char child_found_tag_modifiers = 0; 1.1974 + unsigned long child_found_tag_number = 0; 1.1975 + 1.1976 + /* 1.1977 + * Reset state and push. 1.1978 + */ 1.1979 + if (state->dest != NULL) 1.1980 + child->dest = (char *)state->dest + child->theTemplate->offset; 1.1981 + 1.1982 + /* 1.1983 + * Do the "before" field notification. 1.1984 + */ 1.1985 + sec_asn1d_notify_before (state->top, child->dest, child->depth); 1.1986 + 1.1987 + if (child_missing) { /* if previous child was missing, copy the tag data we already have */ 1.1988 + child_found_tag_modifiers = child->found_tag_modifiers; 1.1989 + child_found_tag_number = child->found_tag_number; 1.1990 + } 1.1991 + state->top->current = child; 1.1992 + child = sec_asn1d_init_state_based_on_template (child); 1.1993 + if (child_missing && child) { 1.1994 + child->place = afterIdentifier; 1.1995 + child->found_tag_modifiers = child_found_tag_modifiers; 1.1996 + child->found_tag_number = child_found_tag_number; 1.1997 + child->consumed = child_consumed; 1.1998 + if (child->underlying_kind == SEC_ASN1_ANY 1.1999 + && !child->top->filter_only) { 1.2000 + /* 1.2001 + * If the new field is an ANY, and we are storing, then 1.2002 + * we need to save the tag out. We would have done this 1.2003 + * already in the normal case, but since we were looking 1.2004 + * for an optional field, and we did not find it, we only 1.2005 + * now realize we need to save the tag. 1.2006 + */ 1.2007 + unsigned char identifier; 1.2008 + 1.2009 + /* 1.2010 + * Check that we did not end up with a high tag; for that 1.2011 + * we need to re-encode the tag into multiple bytes in order 1.2012 + * to store it back to look like what we parsed originally. 1.2013 + * In practice this does not happen, but for completeness 1.2014 + * sake it should probably be made to work at some point. 1.2015 + */ 1.2016 + PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER); 1.2017 + identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number); 1.2018 + sec_asn1d_record_any_header (child, (char *) &identifier, 1); 1.2019 + } 1.2020 + } 1.2021 + } 1.2022 +} 1.2023 + 1.2024 + 1.2025 +static void 1.2026 +sec_asn1d_concat_substrings (sec_asn1d_state *state) 1.2027 +{ 1.2028 + PORT_Assert (state->place == afterConstructedString); 1.2029 + 1.2030 + if (state->subitems_head != NULL) { 1.2031 + struct subitem *substring; 1.2032 + unsigned long alloc_len, item_len; 1.2033 + unsigned char *where; 1.2034 + SECItem *item; 1.2035 + PRBool is_bit_string; 1.2036 + 1.2037 + item_len = 0; 1.2038 + is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING) 1.2039 + ? PR_TRUE : PR_FALSE; 1.2040 + 1.2041 + substring = state->subitems_head; 1.2042 + while (substring != NULL) { 1.2043 + /* 1.2044 + * All bit-string substrings except the last one should be 1.2045 + * a clean multiple of 8 bits. 1.2046 + */ 1.2047 + if (is_bit_string && (substring->next == NULL) 1.2048 + && (substring->len & 0x7)) { 1.2049 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2050 + state->top->status = decodeError; 1.2051 + return; 1.2052 + } 1.2053 + item_len += substring->len; 1.2054 + substring = substring->next; 1.2055 + } 1.2056 + 1.2057 + if (is_bit_string) { 1.2058 + alloc_len = ((item_len + 7) >> 3); 1.2059 + } else { 1.2060 + /* 1.2061 + * Add 2 for the end-of-contents octets of an indefinite-length 1.2062 + * ANY that is *not* also an INNER. Because we zero-allocate 1.2063 + * below, all we need to do is increase the length here. 1.2064 + */ 1.2065 + if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite) 1.2066 + item_len += 2; 1.2067 + alloc_len = item_len; 1.2068 + } 1.2069 + 1.2070 + item = (SECItem *)(state->dest); 1.2071 + PORT_Assert (item != NULL); 1.2072 + PORT_Assert (item->data == NULL); 1.2073 + item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool, 1.2074 + alloc_len); 1.2075 + if (item->data == NULL) { 1.2076 + state->top->status = decodeError; 1.2077 + return; 1.2078 + } 1.2079 + item->len = item_len; 1.2080 + 1.2081 + where = item->data; 1.2082 + substring = state->subitems_head; 1.2083 + while (substring != NULL) { 1.2084 + if (is_bit_string) 1.2085 + item_len = (substring->len + 7) >> 3; 1.2086 + else 1.2087 + item_len = substring->len; 1.2088 + PORT_Memcpy (where, substring->data, item_len); 1.2089 + where += item_len; 1.2090 + substring = substring->next; 1.2091 + } 1.2092 + 1.2093 + /* 1.2094 + * Because we use arenas and have a mark set, we later free 1.2095 + * everything we have allocated, so this does *not* present 1.2096 + * a memory leak (it is just temporarily left dangling). 1.2097 + */ 1.2098 + state->subitems_head = state->subitems_tail = NULL; 1.2099 + } 1.2100 + 1.2101 + state->place = afterEndOfContents; 1.2102 +} 1.2103 + 1.2104 + 1.2105 +static void 1.2106 +sec_asn1d_concat_group (sec_asn1d_state *state) 1.2107 +{ 1.2108 + const void ***placep; 1.2109 + 1.2110 + PORT_Assert (state->place == afterGroup); 1.2111 + 1.2112 + placep = (const void***)state->dest; 1.2113 + PORT_Assert(state->subitems_head == NULL || placep != NULL); 1.2114 + if (placep != NULL) { 1.2115 + struct subitem *item; 1.2116 + const void **group; 1.2117 + int count; 1.2118 + 1.2119 + count = 0; 1.2120 + item = state->subitems_head; 1.2121 + while (item != NULL) { 1.2122 + PORT_Assert (item->next != NULL || item == state->subitems_tail); 1.2123 + count++; 1.2124 + item = item->next; 1.2125 + } 1.2126 + 1.2127 + group = (const void**)sec_asn1d_zalloc (state->top->their_pool, 1.2128 + (count + 1) * (sizeof(void *))); 1.2129 + if (group == NULL) { 1.2130 + state->top->status = decodeError; 1.2131 + return; 1.2132 + } 1.2133 + 1.2134 + *placep = group; 1.2135 + 1.2136 + item = state->subitems_head; 1.2137 + while (item != NULL) { 1.2138 + *group++ = item->data; 1.2139 + item = item->next; 1.2140 + } 1.2141 + *group = NULL; 1.2142 + 1.2143 + /* 1.2144 + * Because we use arenas and have a mark set, we later free 1.2145 + * everything we have allocated, so this does *not* present 1.2146 + * a memory leak (it is just temporarily left dangling). 1.2147 + */ 1.2148 + state->subitems_head = state->subitems_tail = NULL; 1.2149 + } 1.2150 + 1.2151 + state->place = afterEndOfContents; 1.2152 +} 1.2153 + 1.2154 + 1.2155 +/* 1.2156 + * For those states that push a child to handle a subtemplate, 1.2157 + * "absorb" that child (transfer necessary information). 1.2158 + */ 1.2159 +static void 1.2160 +sec_asn1d_absorb_child (sec_asn1d_state *state) 1.2161 +{ 1.2162 + /* 1.2163 + * There is absolutely supposed to be a child there. 1.2164 + */ 1.2165 + PORT_Assert (state->child != NULL); 1.2166 + 1.2167 + /* 1.2168 + * Inherit the missing status of our child, and do the ugly 1.2169 + * backing-up if necessary. 1.2170 + */ 1.2171 + state->missing = state->child->missing; 1.2172 + if (state->missing) { 1.2173 + state->found_tag_number = state->child->found_tag_number; 1.2174 + state->found_tag_modifiers = state->child->found_tag_modifiers; 1.2175 + state->endofcontents = state->child->endofcontents; 1.2176 + } 1.2177 + 1.2178 + /* 1.2179 + * Add in number of bytes consumed by child. 1.2180 + * (Only EXPLICIT should have already consumed bytes itself.) 1.2181 + */ 1.2182 + PORT_Assert (state->place == afterExplicit || state->consumed == 0); 1.2183 + state->consumed += state->child->consumed; 1.2184 + 1.2185 + /* 1.2186 + * Subtract from bytes pending; this only applies to a definite-length 1.2187 + * EXPLICIT field. 1.2188 + */ 1.2189 + if (state->pending) { 1.2190 + PORT_Assert (!state->indefinite); 1.2191 + PORT_Assert (state->place == afterExplicit); 1.2192 + 1.2193 + /* 1.2194 + * If we had a definite-length explicit, then what the child 1.2195 + * consumed should be what was left pending. 1.2196 + */ 1.2197 + if (state->pending != state->child->consumed) { 1.2198 + if (state->pending < state->child->consumed) { 1.2199 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2200 + state->top->status = decodeError; 1.2201 + return; 1.2202 + } 1.2203 + /* 1.2204 + * Okay, this is a hack. It *should* be an error whether 1.2205 + * pending is too big or too small, but it turns out that 1.2206 + * we had a bug in our *old* DER encoder that ended up 1.2207 + * counting an explicit header twice in the case where 1.2208 + * the underlying type was an ANY. So, because we cannot 1.2209 + * prevent receiving these (our own certificate server can 1.2210 + * send them to us), we need to be lenient and accept them. 1.2211 + * To do so, we need to pretend as if we read all of the 1.2212 + * bytes that the header said we would find, even though 1.2213 + * we actually came up short. 1.2214 + */ 1.2215 + state->consumed += (state->pending - state->child->consumed); 1.2216 + } 1.2217 + state->pending = 0; 1.2218 + } 1.2219 + 1.2220 + /* 1.2221 + * Indicate that we are done with child. 1.2222 + */ 1.2223 + state->child->consumed = 0; 1.2224 + 1.2225 + /* 1.2226 + * And move on to final state. 1.2227 + * (Technically everybody could move to afterEndOfContents except 1.2228 + * for an indefinite-length EXPLICIT; for simplicity though we assert 1.2229 + * that but let the end-of-contents code do the real determination.) 1.2230 + */ 1.2231 + PORT_Assert (state->place == afterExplicit || (! state->indefinite)); 1.2232 + state->place = beforeEndOfContents; 1.2233 +} 1.2234 + 1.2235 + 1.2236 +static void 1.2237 +sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state) 1.2238 +{ 1.2239 + PORT_Assert (state->place == beforeEndOfContents); 1.2240 + 1.2241 + if (state->indefinite) { 1.2242 + state->place = duringEndOfContents; 1.2243 + state->pending = 2; 1.2244 + } else { 1.2245 + state->place = afterEndOfContents; 1.2246 + } 1.2247 +} 1.2248 + 1.2249 + 1.2250 +static unsigned long 1.2251 +sec_asn1d_parse_end_of_contents (sec_asn1d_state *state, 1.2252 + const char *buf, unsigned long len) 1.2253 +{ 1.2254 + unsigned int i; 1.2255 + 1.2256 + PORT_Assert (state->pending <= 2); 1.2257 + PORT_Assert (state->place == duringEndOfContents); 1.2258 + 1.2259 + if (len == 0) { 1.2260 + state->top->status = needBytes; 1.2261 + return 0; 1.2262 + } 1.2263 + 1.2264 + if (state->pending < len) 1.2265 + len = state->pending; 1.2266 + 1.2267 + for (i = 0; i < len; i++) { 1.2268 + if (buf[i] != 0) { 1.2269 + /* 1.2270 + * We expect to find only zeros; if not, just give up. 1.2271 + */ 1.2272 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2273 + state->top->status = decodeError; 1.2274 + return 0; 1.2275 + } 1.2276 + } 1.2277 + 1.2278 + state->pending -= len; 1.2279 + 1.2280 + if (state->pending == 0) { 1.2281 + state->place = afterEndOfContents; 1.2282 + state->endofcontents = PR_TRUE; 1.2283 + } 1.2284 + 1.2285 + return len; 1.2286 +} 1.2287 + 1.2288 + 1.2289 +static void 1.2290 +sec_asn1d_pop_state (sec_asn1d_state *state) 1.2291 +{ 1.2292 +#if 0 /* XXX I think this should always be handled explicitly by parent? */ 1.2293 + /* 1.2294 + * Account for our child. 1.2295 + */ 1.2296 + if (state->child != NULL) { 1.2297 + state->consumed += state->child->consumed; 1.2298 + if (state->pending) { 1.2299 + PORT_Assert (!state->indefinite); 1.2300 + if (state->child->consumed > state->pending) { 1.2301 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2302 + state->top->status = decodeError; 1.2303 + } else { 1.2304 + state->pending -= state->child->consumed; 1.2305 + } 1.2306 + } 1.2307 + state->child->consumed = 0; 1.2308 + } 1.2309 +#endif /* XXX */ 1.2310 + 1.2311 + /* 1.2312 + * Free our child. 1.2313 + */ 1.2314 + sec_asn1d_free_child (state, PR_FALSE); 1.2315 + 1.2316 + /* 1.2317 + * Just make my parent be the current state. It will then clean 1.2318 + * up after me and free me (or reuse me). 1.2319 + */ 1.2320 + state->top->current = state->parent; 1.2321 +} 1.2322 + 1.2323 +static sec_asn1d_state * 1.2324 +sec_asn1d_before_choice (sec_asn1d_state *state) 1.2325 +{ 1.2326 + sec_asn1d_state *child; 1.2327 + 1.2328 + if (state->allocate) { 1.2329 + void *dest; 1.2330 + 1.2331 + dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size); 1.2332 + if ((void *)NULL == dest) { 1.2333 + state->top->status = decodeError; 1.2334 + return (sec_asn1d_state *)NULL; 1.2335 + } 1.2336 + 1.2337 + state->dest = (char *)dest + state->theTemplate->offset; 1.2338 + } 1.2339 + 1.2340 + child = sec_asn1d_push_state(state->top, state->theTemplate + 1, 1.2341 + (char *)state->dest - state->theTemplate->offset, 1.2342 + PR_FALSE); 1.2343 + if ((sec_asn1d_state *)NULL == child) { 1.2344 + return (sec_asn1d_state *)NULL; 1.2345 + } 1.2346 + 1.2347 + sec_asn1d_scrub_state(child); 1.2348 + child = sec_asn1d_init_state_based_on_template(child); 1.2349 + if ((sec_asn1d_state *)NULL == child) { 1.2350 + return (sec_asn1d_state *)NULL; 1.2351 + } 1.2352 + 1.2353 + child->optional = PR_TRUE; 1.2354 + 1.2355 + state->place = duringChoice; 1.2356 + 1.2357 + return child; 1.2358 +} 1.2359 + 1.2360 +static sec_asn1d_state * 1.2361 +sec_asn1d_during_choice (sec_asn1d_state *state) 1.2362 +{ 1.2363 + sec_asn1d_state *child = state->child; 1.2364 + 1.2365 + PORT_Assert((sec_asn1d_state *)NULL != child); 1.2366 + 1.2367 + if (child->missing) { 1.2368 + unsigned char child_found_tag_modifiers = 0; 1.2369 + unsigned long child_found_tag_number = 0; 1.2370 + void * dest; 1.2371 + 1.2372 + state->consumed += child->consumed; 1.2373 + 1.2374 + if (child->endofcontents) { 1.2375 + /* This choice is probably the first item in a GROUP 1.2376 + ** (e.g. SET_OF) that was indefinite-length encoded. 1.2377 + ** We're actually at the end of that GROUP. 1.2378 + ** We look up the stack to be sure that we find 1.2379 + ** a state with indefinite length encoding before we 1.2380 + ** find a state (like a SEQUENCE) that is definite. 1.2381 + */ 1.2382 + child->place = notInUse; 1.2383 + state->place = afterChoice; 1.2384 + state->endofcontents = PR_TRUE; /* propagate this up */ 1.2385 + if (sec_asn1d_parent_allows_EOC(state)) 1.2386 + return state; 1.2387 + PORT_SetError(SEC_ERROR_BAD_DER); 1.2388 + state->top->status = decodeError; 1.2389 + return NULL; 1.2390 + } 1.2391 + 1.2392 + dest = (char *)child->dest - child->theTemplate->offset; 1.2393 + child->theTemplate++; 1.2394 + 1.2395 + if (0 == child->theTemplate->kind) { 1.2396 + /* Ran out of choices */ 1.2397 + PORT_SetError(SEC_ERROR_BAD_DER); 1.2398 + state->top->status = decodeError; 1.2399 + return (sec_asn1d_state *)NULL; 1.2400 + } 1.2401 + child->dest = (char *)dest + child->theTemplate->offset; 1.2402 + 1.2403 + /* cargo'd from next_in_sequence innards */ 1.2404 + if (state->pending) { 1.2405 + PORT_Assert(!state->indefinite); 1.2406 + if (child->consumed > state->pending) { 1.2407 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2408 + state->top->status = decodeError; 1.2409 + return NULL; 1.2410 + } 1.2411 + state->pending -= child->consumed; 1.2412 + if (0 == state->pending) { 1.2413 + /* XXX uh.. not sure if I should have stopped this 1.2414 + * from happening before. */ 1.2415 + PORT_Assert(0); 1.2416 + PORT_SetError(SEC_ERROR_BAD_DER); 1.2417 + state->top->status = decodeError; 1.2418 + return (sec_asn1d_state *)NULL; 1.2419 + } 1.2420 + } 1.2421 + 1.2422 + child->consumed = 0; 1.2423 + sec_asn1d_scrub_state(child); 1.2424 + 1.2425 + /* move it on top again */ 1.2426 + state->top->current = child; 1.2427 + 1.2428 + child_found_tag_modifiers = child->found_tag_modifiers; 1.2429 + child_found_tag_number = child->found_tag_number; 1.2430 + 1.2431 + child = sec_asn1d_init_state_based_on_template(child); 1.2432 + if ((sec_asn1d_state *)NULL == child) { 1.2433 + return (sec_asn1d_state *)NULL; 1.2434 + } 1.2435 + 1.2436 + /* copy our findings to the new top */ 1.2437 + child->found_tag_modifiers = child_found_tag_modifiers; 1.2438 + child->found_tag_number = child_found_tag_number; 1.2439 + 1.2440 + child->optional = PR_TRUE; 1.2441 + child->place = afterIdentifier; 1.2442 + 1.2443 + return child; 1.2444 + } 1.2445 + if ((void *)NULL != state->dest) { 1.2446 + /* Store the enum */ 1.2447 + int *which = (int *)state->dest; 1.2448 + *which = (int)child->theTemplate->size; 1.2449 + } 1.2450 + 1.2451 + child->place = notInUse; 1.2452 + 1.2453 + state->place = afterChoice; 1.2454 + return state; 1.2455 +} 1.2456 + 1.2457 +static void 1.2458 +sec_asn1d_after_choice (sec_asn1d_state *state) 1.2459 +{ 1.2460 + state->consumed += state->child->consumed; 1.2461 + state->child->consumed = 0; 1.2462 + state->place = afterEndOfContents; 1.2463 + sec_asn1d_pop_state(state); 1.2464 +} 1.2465 + 1.2466 +unsigned long 1.2467 +sec_asn1d_uinteger(SECItem *src) 1.2468 +{ 1.2469 + unsigned long value; 1.2470 + int len; 1.2471 + 1.2472 + if (src->len > 5 || (src->len > 4 && src->data[0] == 0)) 1.2473 + return 0; 1.2474 + 1.2475 + value = 0; 1.2476 + len = src->len; 1.2477 + while (len) { 1.2478 + value <<= 8; 1.2479 + value |= src->data[--len]; 1.2480 + } 1.2481 + return value; 1.2482 +} 1.2483 + 1.2484 +SECStatus 1.2485 +SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value) 1.2486 +{ 1.2487 + unsigned long v; 1.2488 + unsigned int i; 1.2489 + 1.2490 + if (src == NULL) { 1.2491 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2492 + return SECFailure; 1.2493 + } 1.2494 + 1.2495 + if (src->len > sizeof(unsigned long)) { 1.2496 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2497 + return SECFailure; 1.2498 + } 1.2499 + 1.2500 + if (src->data == NULL) { 1.2501 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2502 + return SECFailure; 1.2503 + } 1.2504 + 1.2505 + if (src->data[0] & 0x80) 1.2506 + v = -1; /* signed and negative - start with all 1's */ 1.2507 + else 1.2508 + v = 0; 1.2509 + 1.2510 + for (i= 0; i < src->len; i++) { 1.2511 + /* shift in next byte */ 1.2512 + v <<= 8; 1.2513 + v |= src->data[i]; 1.2514 + } 1.2515 + *value = v; 1.2516 + return SECSuccess; 1.2517 +} 1.2518 + 1.2519 +#ifdef DEBUG_ASN1D_STATES 1.2520 +static void 1.2521 +dump_states(SEC_ASN1DecoderContext *cx) 1.2522 +{ 1.2523 + sec_asn1d_state *state; 1.2524 + char kindBuf[256]; 1.2525 + 1.2526 + for (state = cx->current; state->parent; state = state->parent) { 1.2527 + ; 1.2528 + } 1.2529 + 1.2530 + for (; state; state = state->child) { 1.2531 + int i; 1.2532 + for (i = 0; i < state->depth; i++) { 1.2533 + printf(" "); 1.2534 + } 1.2535 + 1.2536 + i = formatKind(state->theTemplate->kind, kindBuf); 1.2537 + printf("%s: tmpl %08x, kind%s", 1.2538 + (state == cx->current) ? "STATE" : "State", 1.2539 + state->theTemplate, 1.2540 + kindBuf); 1.2541 + printf(" %s", (state->place >= 0 && state->place <= notInUse) 1.2542 + ? place_names[ state->place ] 1.2543 + : "(undefined)"); 1.2544 + if (!i) 1.2545 + printf(", expect 0x%02x", 1.2546 + state->expect_tag_number | state->expect_tag_modifiers); 1.2547 + 1.2548 + printf("%s%s%s %d\n", 1.2549 + state->indefinite ? ", indef" : "", 1.2550 + state->missing ? ", miss" : "", 1.2551 + state->endofcontents ? ", EOC" : "", 1.2552 + state->pending 1.2553 + ); 1.2554 + } 1.2555 + 1.2556 + return; 1.2557 +} 1.2558 +#endif /* DEBUG_ASN1D_STATES */ 1.2559 + 1.2560 +SECStatus 1.2561 +SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx, 1.2562 + const char *buf, unsigned long len) 1.2563 +{ 1.2564 + sec_asn1d_state *state = NULL; 1.2565 + unsigned long consumed; 1.2566 + SEC_ASN1EncodingPart what; 1.2567 + sec_asn1d_state *stateEnd = cx->current; 1.2568 + 1.2569 + if (cx->status == needBytes) 1.2570 + cx->status = keepGoing; 1.2571 + 1.2572 + while (cx->status == keepGoing) { 1.2573 + state = cx->current; 1.2574 + what = SEC_ASN1_Contents; 1.2575 + consumed = 0; 1.2576 +#ifdef DEBUG_ASN1D_STATES 1.2577 + printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n", 1.2578 + (state->place >= 0 && state->place <= notInUse) ? 1.2579 + place_names[ state->place ] : "(undefined)", 1.2580 + (unsigned int)((unsigned char *)buf)[ consumed ], 1.2581 + buf, consumed); 1.2582 + dump_states(cx); 1.2583 +#endif /* DEBUG_ASN1D_STATES */ 1.2584 + switch (state->place) { 1.2585 + case beforeIdentifier: 1.2586 + consumed = sec_asn1d_parse_identifier (state, buf, len); 1.2587 + what = SEC_ASN1_Identifier; 1.2588 + break; 1.2589 + case duringIdentifier: 1.2590 + consumed = sec_asn1d_parse_more_identifier (state, buf, len); 1.2591 + what = SEC_ASN1_Identifier; 1.2592 + break; 1.2593 + case afterIdentifier: 1.2594 + sec_asn1d_confirm_identifier (state); 1.2595 + break; 1.2596 + case beforeLength: 1.2597 + consumed = sec_asn1d_parse_length (state, buf, len); 1.2598 + what = SEC_ASN1_Length; 1.2599 + break; 1.2600 + case duringLength: 1.2601 + consumed = sec_asn1d_parse_more_length (state, buf, len); 1.2602 + what = SEC_ASN1_Length; 1.2603 + break; 1.2604 + case afterLength: 1.2605 + sec_asn1d_prepare_for_contents (state); 1.2606 + break; 1.2607 + case beforeBitString: 1.2608 + consumed = sec_asn1d_parse_bit_string (state, buf, len); 1.2609 + break; 1.2610 + case duringBitString: 1.2611 + consumed = sec_asn1d_parse_more_bit_string (state, buf, len); 1.2612 + break; 1.2613 + case duringConstructedString: 1.2614 + sec_asn1d_next_substring (state); 1.2615 + break; 1.2616 + case duringGroup: 1.2617 + sec_asn1d_next_in_group (state); 1.2618 + break; 1.2619 + case duringLeaf: 1.2620 + consumed = sec_asn1d_parse_leaf (state, buf, len); 1.2621 + break; 1.2622 + case duringSaveEncoding: 1.2623 + sec_asn1d_reuse_encoding (state); 1.2624 + if (cx->status == decodeError) { 1.2625 + /* recursive call has already popped all states from stack. 1.2626 + ** Bail out quickly. 1.2627 + */ 1.2628 + return SECFailure; 1.2629 + } 1.2630 + if (cx->status == needBytes) { 1.2631 + /* recursive call wanted more data. Fatal. Clean up below. */ 1.2632 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2633 + cx->status = decodeError; 1.2634 + } 1.2635 + break; 1.2636 + case duringSequence: 1.2637 + sec_asn1d_next_in_sequence (state); 1.2638 + break; 1.2639 + case afterConstructedString: 1.2640 + sec_asn1d_concat_substrings (state); 1.2641 + break; 1.2642 + case afterExplicit: 1.2643 + case afterImplicit: 1.2644 + case afterInline: 1.2645 + case afterPointer: 1.2646 + sec_asn1d_absorb_child (state); 1.2647 + break; 1.2648 + case afterGroup: 1.2649 + sec_asn1d_concat_group (state); 1.2650 + break; 1.2651 + case afterSaveEncoding: 1.2652 + /* SEC_ASN1DecoderUpdate has called itself recursively to 1.2653 + ** decode SAVEd encoded data, and now is done decoding that. 1.2654 + ** Return to the calling copy of SEC_ASN1DecoderUpdate. 1.2655 + */ 1.2656 + return SECSuccess; 1.2657 + case beforeEndOfContents: 1.2658 + sec_asn1d_prepare_for_end_of_contents (state); 1.2659 + break; 1.2660 + case duringEndOfContents: 1.2661 + consumed = sec_asn1d_parse_end_of_contents (state, buf, len); 1.2662 + what = SEC_ASN1_EndOfContents; 1.2663 + break; 1.2664 + case afterEndOfContents: 1.2665 + sec_asn1d_pop_state (state); 1.2666 + break; 1.2667 + case beforeChoice: 1.2668 + state = sec_asn1d_before_choice(state); 1.2669 + break; 1.2670 + case duringChoice: 1.2671 + state = sec_asn1d_during_choice(state); 1.2672 + break; 1.2673 + case afterChoice: 1.2674 + sec_asn1d_after_choice(state); 1.2675 + break; 1.2676 + case notInUse: 1.2677 + default: 1.2678 + /* This is not an error, but rather a plain old BUG! */ 1.2679 + PORT_Assert (0); 1.2680 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2681 + cx->status = decodeError; 1.2682 + break; 1.2683 + } 1.2684 + 1.2685 + if (cx->status == decodeError) 1.2686 + break; 1.2687 + 1.2688 + /* We should not consume more than we have. */ 1.2689 + PORT_Assert (consumed <= len); 1.2690 + if (consumed > len) { 1.2691 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2692 + cx->status = decodeError; 1.2693 + break; 1.2694 + } 1.2695 + 1.2696 + /* It might have changed, so we have to update our local copy. */ 1.2697 + state = cx->current; 1.2698 + 1.2699 + /* If it is NULL, we have popped all the way to the top. */ 1.2700 + if (state == NULL) { 1.2701 + PORT_Assert (consumed == 0); 1.2702 +#if 0 /* XXX I want this here, but it seems that we have situations (like 1.2703 + * downloading a pkcs7 cert chain from some issuers) that give us a 1.2704 + * length which is greater than the entire encoding. So, we cannot 1.2705 + * have this be an error. 1.2706 + */ 1.2707 + if (len > 0) { 1.2708 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2709 + cx->status = decodeError; 1.2710 + } else 1.2711 +#endif 1.2712 + cx->status = allDone; 1.2713 + break; 1.2714 + } 1.2715 + else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) { 1.2716 + cx->status = allDone; 1.2717 + break; 1.2718 + } 1.2719 + 1.2720 + if (consumed == 0) 1.2721 + continue; 1.2722 + 1.2723 + /* 1.2724 + * The following check is specifically looking for an ANY 1.2725 + * that is *not* also an INNER, because we need to save aside 1.2726 + * all bytes in that case -- the contents parts will get 1.2727 + * handled like all other contents, and the end-of-contents 1.2728 + * bytes are added by the concat code, but the outer header 1.2729 + * bytes need to get saved too, so we do them explicitly here. 1.2730 + */ 1.2731 + if (state->underlying_kind == SEC_ASN1_ANY 1.2732 + && !cx->filter_only && (what == SEC_ASN1_Identifier 1.2733 + || what == SEC_ASN1_Length)) { 1.2734 + sec_asn1d_record_any_header (state, buf, consumed); 1.2735 + } 1.2736 + 1.2737 + /* 1.2738 + * We had some number of good, accepted bytes. If the caller 1.2739 + * has registered to see them, pass them along. 1.2740 + */ 1.2741 + if (state->top->filter_proc != NULL) { 1.2742 + int depth; 1.2743 + 1.2744 + depth = state->depth; 1.2745 + if (what == SEC_ASN1_EndOfContents && !state->indefinite) { 1.2746 + PORT_Assert (state->parent != NULL 1.2747 + && state->parent->indefinite); 1.2748 + depth--; 1.2749 + PORT_Assert (depth == state->parent->depth); 1.2750 + } 1.2751 + (* state->top->filter_proc) (state->top->filter_arg, 1.2752 + buf, consumed, depth, what); 1.2753 + } 1.2754 + 1.2755 + state->consumed += consumed; 1.2756 + buf += consumed; 1.2757 + len -= consumed; 1.2758 + } 1.2759 + 1.2760 + if (cx->status == decodeError) { 1.2761 + while (state != NULL && stateEnd->parent!=state) { 1.2762 + sec_asn1d_free_child (state, PR_TRUE); 1.2763 + state = state->parent; 1.2764 + } 1.2765 +#ifdef SEC_ASN1D_FREE_ON_ERROR /* 1.2766 + * XXX This does not work because we can 1.2767 + * end up leaving behind dangling pointers 1.2768 + * to stuff that was allocated. In order 1.2769 + * to make this really work (which would 1.2770 + * be a good thing, I think), we need to 1.2771 + * keep track of every place/pointer that 1.2772 + * was allocated and make sure to NULL it 1.2773 + * out before we then free back to the mark. 1.2774 + */ 1.2775 + if (cx->their_pool != NULL) { 1.2776 + PORT_Assert (cx->their_mark != NULL); 1.2777 + PORT_ArenaRelease (cx->their_pool, cx->their_mark); 1.2778 + cx->their_mark = NULL; 1.2779 + } 1.2780 +#endif 1.2781 + return SECFailure; 1.2782 + } 1.2783 + 1.2784 +#if 0 /* XXX This is what I want, but cannot have because it seems we 1.2785 + * have situations (like when downloading a pkcs7 cert chain from 1.2786 + * some issuers) that give us a total length which is greater than 1.2787 + * the entire encoding. So, we have to allow allDone to have a 1.2788 + * remaining length greater than zero. I wanted to catch internal 1.2789 + * bugs with this, noticing when we do not have the right length. 1.2790 + * Oh well. 1.2791 + */ 1.2792 + PORT_Assert (len == 0 1.2793 + && (cx->status == needBytes || cx->status == allDone)); 1.2794 +#else 1.2795 + PORT_Assert ((len == 0 && cx->status == needBytes) 1.2796 + || cx->status == allDone); 1.2797 +#endif 1.2798 + return SECSuccess; 1.2799 +} 1.2800 + 1.2801 + 1.2802 +SECStatus 1.2803 +SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx) 1.2804 +{ 1.2805 + SECStatus rv; 1.2806 + 1.2807 + if (cx->status == needBytes) { 1.2808 + PORT_SetError (SEC_ERROR_BAD_DER); 1.2809 + rv = SECFailure; 1.2810 + } else { 1.2811 + rv = SECSuccess; 1.2812 + } 1.2813 + 1.2814 + /* 1.2815 + * XXX anything else that needs to be finished? 1.2816 + */ 1.2817 + 1.2818 + PORT_FreeArena (cx->our_pool, PR_TRUE); 1.2819 + 1.2820 + return rv; 1.2821 +} 1.2822 + 1.2823 + 1.2824 +SEC_ASN1DecoderContext * 1.2825 +SEC_ASN1DecoderStart (PLArenaPool *their_pool, void *dest, 1.2826 + const SEC_ASN1Template *theTemplate) 1.2827 +{ 1.2828 + PLArenaPool *our_pool; 1.2829 + SEC_ASN1DecoderContext *cx; 1.2830 + 1.2831 + our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); 1.2832 + if (our_pool == NULL) 1.2833 + return NULL; 1.2834 + 1.2835 + cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); 1.2836 + if (cx == NULL) { 1.2837 + PORT_FreeArena (our_pool, PR_FALSE); 1.2838 + return NULL; 1.2839 + } 1.2840 + 1.2841 + cx->our_pool = our_pool; 1.2842 + if (their_pool != NULL) { 1.2843 + cx->their_pool = their_pool; 1.2844 +#ifdef SEC_ASN1D_FREE_ON_ERROR 1.2845 + cx->their_mark = PORT_ArenaMark (their_pool); 1.2846 +#endif 1.2847 + } 1.2848 + 1.2849 + cx->status = needBytes; 1.2850 + 1.2851 + if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL 1.2852 + || sec_asn1d_init_state_based_on_template (cx->current) == NULL) { 1.2853 + /* 1.2854 + * Trouble initializing (probably due to failed allocations) 1.2855 + * requires that we just give up. 1.2856 + */ 1.2857 + PORT_FreeArena (our_pool, PR_FALSE); 1.2858 + return NULL; 1.2859 + } 1.2860 + 1.2861 + return cx; 1.2862 +} 1.2863 + 1.2864 + 1.2865 +void 1.2866 +SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx, 1.2867 + SEC_ASN1WriteProc fn, void *arg, 1.2868 + PRBool only) 1.2869 +{ 1.2870 + /* check that we are "between" fields here */ 1.2871 + PORT_Assert (cx->during_notify); 1.2872 + 1.2873 + cx->filter_proc = fn; 1.2874 + cx->filter_arg = arg; 1.2875 + cx->filter_only = only; 1.2876 +} 1.2877 + 1.2878 + 1.2879 +void 1.2880 +SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx) 1.2881 +{ 1.2882 + /* check that we are "between" fields here */ 1.2883 + PORT_Assert (cx->during_notify); 1.2884 + 1.2885 + cx->filter_proc = NULL; 1.2886 + cx->filter_arg = NULL; 1.2887 + cx->filter_only = PR_FALSE; 1.2888 +} 1.2889 + 1.2890 + 1.2891 +void 1.2892 +SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx, 1.2893 + SEC_ASN1NotifyProc fn, void *arg) 1.2894 +{ 1.2895 + cx->notify_proc = fn; 1.2896 + cx->notify_arg = arg; 1.2897 +} 1.2898 + 1.2899 + 1.2900 +void 1.2901 +SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx) 1.2902 +{ 1.2903 + cx->notify_proc = NULL; 1.2904 + cx->notify_arg = NULL; /* not necessary; just being clean */ 1.2905 +} 1.2906 + 1.2907 +void 1.2908 +SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error) 1.2909 +{ 1.2910 + PORT_Assert(cx); 1.2911 + PORT_SetError(error); 1.2912 + cx->status = decodeError; 1.2913 +} 1.2914 + 1.2915 + 1.2916 +SECStatus 1.2917 +SEC_ASN1Decode (PLArenaPool *poolp, void *dest, 1.2918 + const SEC_ASN1Template *theTemplate, 1.2919 + const char *buf, long len) 1.2920 +{ 1.2921 + SEC_ASN1DecoderContext *dcx; 1.2922 + SECStatus urv, frv; 1.2923 + 1.2924 + dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate); 1.2925 + if (dcx == NULL) 1.2926 + return SECFailure; 1.2927 + 1.2928 + urv = SEC_ASN1DecoderUpdate (dcx, buf, len); 1.2929 + frv = SEC_ASN1DecoderFinish (dcx); 1.2930 + 1.2931 + if (urv != SECSuccess) 1.2932 + return urv; 1.2933 + 1.2934 + return frv; 1.2935 +} 1.2936 + 1.2937 + 1.2938 +SECStatus 1.2939 +SEC_ASN1DecodeItem (PLArenaPool *poolp, void *dest, 1.2940 + const SEC_ASN1Template *theTemplate, 1.2941 + const SECItem *src) 1.2942 +{ 1.2943 + return SEC_ASN1Decode (poolp, dest, theTemplate, 1.2944 + (const char *)src->data, src->len); 1.2945 +} 1.2946 + 1.2947 +#ifdef DEBUG_ASN1D_STATES 1.2948 +void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln) 1.2949 +{ 1.2950 + printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln); 1.2951 + fflush(stdout); 1.2952 +} 1.2953 +#endif 1.2954 + 1.2955 +/* 1.2956 + * Generic templates for individual/simple items and pointers to 1.2957 + * and sets of same. 1.2958 + * 1.2959 + * If you need to add a new one, please note the following: 1.2960 + * - For each new basic type you should add *four* templates: 1.2961 + * one plain, one PointerTo, one SequenceOf and one SetOf. 1.2962 + * - If the new type can be constructed (meaning, it is a 1.2963 + * *string* type according to BER/DER rules), then you should 1.2964 + * or-in SEC_ASN1_MAY_STREAM to the type in the basic template. 1.2965 + * See the definition of the OctetString template for an example. 1.2966 + * - It may not be obvious, but these are in *alphabetical* 1.2967 + * order based on the SEC_ASN1_XXX name; so put new ones in 1.2968 + * the appropriate place. 1.2969 + */ 1.2970 + 1.2971 +const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = { 1.2972 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate } 1.2973 +}; 1.2974 + 1.2975 +#if 0 1.2976 + 1.2977 +const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = { 1.2978 + { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate } 1.2979 +}; 1.2980 + 1.2981 +const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = { 1.2982 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate } 1.2983 +}; 1.2984 + 1.2985 +const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = { 1.2986 + { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate } 1.2987 +}; 1.2988 + 1.2989 +const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = { 1.2990 + { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate } 1.2991 +}; 1.2992 + 1.2993 +const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = { 1.2994 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate } 1.2995 +}; 1.2996 + 1.2997 +const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = { 1.2998 + { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate } 1.2999 +}; 1.3000 + 1.3001 +const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = { 1.3002 + { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate } 1.3003 +}; 1.3004 + 1.3005 +const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = { 1.3006 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate } 1.3007 +}; 1.3008 + 1.3009 +const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = { 1.3010 + { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate } 1.3011 +}; 1.3012 + 1.3013 +#endif 1.3014 + 1.3015 +const SEC_ASN1Template SEC_EnumeratedTemplate[] = { 1.3016 + { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) } 1.3017 +}; 1.3018 + 1.3019 +const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = { 1.3020 + { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate } 1.3021 +}; 1.3022 + 1.3023 +#if 0 1.3024 + 1.3025 +const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = { 1.3026 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate } 1.3027 +}; 1.3028 + 1.3029 +#endif 1.3030 + 1.3031 +const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = { 1.3032 + { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate } 1.3033 +}; 1.3034 + 1.3035 +const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = { 1.3036 + { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate } 1.3037 +}; 1.3038 + 1.3039 +#if 0 1.3040 + 1.3041 +const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = { 1.3042 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate } 1.3043 +}; 1.3044 + 1.3045 +const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = { 1.3046 + { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate } 1.3047 +}; 1.3048 + 1.3049 +const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = { 1.3050 + { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate } 1.3051 +}; 1.3052 + 1.3053 +const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = { 1.3054 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate } 1.3055 +}; 1.3056 + 1.3057 +const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = { 1.3058 + { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate } 1.3059 +}; 1.3060 + 1.3061 +const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = { 1.3062 + { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate } 1.3063 +}; 1.3064 + 1.3065 +const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = { 1.3066 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate } 1.3067 +}; 1.3068 + 1.3069 +const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = { 1.3070 + { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate } 1.3071 +}; 1.3072 + 1.3073 +const SEC_ASN1Template SEC_PointerToNullTemplate[] = { 1.3074 + { SEC_ASN1_POINTER, 0, SEC_NullTemplate } 1.3075 +}; 1.3076 + 1.3077 +const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = { 1.3078 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate } 1.3079 +}; 1.3080 + 1.3081 +const SEC_ASN1Template SEC_SetOfNullTemplate[] = { 1.3082 + { SEC_ASN1_SET_OF, 0, SEC_NullTemplate } 1.3083 +}; 1.3084 + 1.3085 +const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = { 1.3086 + { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate } 1.3087 +}; 1.3088 + 1.3089 +#endif 1.3090 + 1.3091 +const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = { 1.3092 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate } 1.3093 +}; 1.3094 + 1.3095 +#if 0 1.3096 + 1.3097 +const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = { 1.3098 + { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate } 1.3099 +}; 1.3100 + 1.3101 +const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = { 1.3102 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate } 1.3103 +}; 1.3104 + 1.3105 +const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = { 1.3106 + { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate } 1.3107 +}; 1.3108 + 1.3109 +#endif 1.3110 + 1.3111 +const SEC_ASN1Template SEC_PrintableStringTemplate[] = { 1.3112 + { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} 1.3113 +}; 1.3114 + 1.3115 +#if 0 1.3116 + 1.3117 +const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = { 1.3118 + { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate } 1.3119 +}; 1.3120 + 1.3121 +const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = { 1.3122 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate } 1.3123 +}; 1.3124 + 1.3125 +const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = { 1.3126 + { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate } 1.3127 +}; 1.3128 + 1.3129 +#endif 1.3130 + 1.3131 +const SEC_ASN1Template SEC_T61StringTemplate[] = { 1.3132 + { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } 1.3133 +}; 1.3134 + 1.3135 +#if 0 1.3136 + 1.3137 +const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = { 1.3138 + { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate } 1.3139 +}; 1.3140 + 1.3141 +const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = { 1.3142 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate } 1.3143 +}; 1.3144 + 1.3145 +const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = { 1.3146 + { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate } 1.3147 +}; 1.3148 + 1.3149 +#endif 1.3150 + 1.3151 +const SEC_ASN1Template SEC_UniversalStringTemplate[] = { 1.3152 + { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)} 1.3153 +}; 1.3154 + 1.3155 +#if 0 1.3156 + 1.3157 +const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = { 1.3158 + { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate } 1.3159 +}; 1.3160 + 1.3161 +const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = { 1.3162 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate } 1.3163 +}; 1.3164 + 1.3165 +const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = { 1.3166 + { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate } 1.3167 +}; 1.3168 + 1.3169 +const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = { 1.3170 + { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate } 1.3171 +}; 1.3172 + 1.3173 +const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = { 1.3174 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate } 1.3175 +}; 1.3176 + 1.3177 +const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = { 1.3178 + { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate } 1.3179 +}; 1.3180 + 1.3181 +const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = { 1.3182 + { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate } 1.3183 +}; 1.3184 + 1.3185 +const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = { 1.3186 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate } 1.3187 +}; 1.3188 + 1.3189 +const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = { 1.3190 + { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate } 1.3191 +}; 1.3192 + 1.3193 +#endif 1.3194 + 1.3195 +const SEC_ASN1Template SEC_VisibleStringTemplate[] = { 1.3196 + { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) } 1.3197 +}; 1.3198 + 1.3199 +#if 0 1.3200 + 1.3201 +const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = { 1.3202 + { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate } 1.3203 +}; 1.3204 + 1.3205 +const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = { 1.3206 + { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate } 1.3207 +}; 1.3208 + 1.3209 +const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = { 1.3210 + { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate } 1.3211 +}; 1.3212 + 1.3213 +#endif 1.3214 + 1.3215 +/* 1.3216 + * Template for skipping a subitem. 1.3217 + * 1.3218 + * Note that it only makes sense to use this for decoding (when you want 1.3219 + * to decode something where you are only interested in one or two of 1.3220 + * the fields); you cannot encode a SKIP! 1.3221 + */ 1.3222 +const SEC_ASN1Template SEC_SkipTemplate[] = { 1.3223 + { SEC_ASN1_SKIP } 1.3224 +}; 1.3225 + 1.3226 + 1.3227 +/* These functions simply return the address of the above-declared templates. 1.3228 +** This is necessary for Windows DLLs. Sigh. 1.3229 +*/ 1.3230 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_EnumeratedTemplate) 1.3231 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToEnumeratedTemplate) 1.3232 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfAnyTemplate) 1.3233 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfObjectIDTemplate) 1.3234 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SkipTemplate) 1.3235 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate) 1.3236 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate) 1.3237 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate) 1.3238 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate) 1.3239 +