comparison nss/lib/util/secasn1d.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
7 * Encoding Rules).
8 */
9
10 /* #define DEBUG_ASN1D_STATES 1 */
11
12 #ifdef DEBUG_ASN1D_STATES
13 #include <stdio.h>
14 #define PR_Assert sec_asn1d_Assert
15 #endif
16
17 #include "secasn1.h"
18 #include "secerr.h"
19
20 typedef enum {
21 beforeIdentifier,
22 duringIdentifier,
23 afterIdentifier,
24 beforeLength,
25 duringLength,
26 afterLength,
27 beforeBitString,
28 duringBitString,
29 duringConstructedString,
30 duringGroup,
31 duringLeaf,
32 duringSaveEncoding,
33 duringSequence,
34 afterConstructedString,
35 afterGroup,
36 afterExplicit,
37 afterImplicit,
38 afterInline,
39 afterPointer,
40 afterSaveEncoding,
41 beforeEndOfContents,
42 duringEndOfContents,
43 afterEndOfContents,
44 beforeChoice,
45 duringChoice,
46 afterChoice,
47 notInUse
48 } sec_asn1d_parse_place;
49
50 #ifdef DEBUG_ASN1D_STATES
51 static const char * const place_names[] = {
52 "beforeIdentifier",
53 "duringIdentifier",
54 "afterIdentifier",
55 "beforeLength",
56 "duringLength",
57 "afterLength",
58 "beforeBitString",
59 "duringBitString",
60 "duringConstructedString",
61 "duringGroup",
62 "duringLeaf",
63 "duringSaveEncoding",
64 "duringSequence",
65 "afterConstructedString",
66 "afterGroup",
67 "afterExplicit",
68 "afterImplicit",
69 "afterInline",
70 "afterPointer",
71 "afterSaveEncoding",
72 "beforeEndOfContents",
73 "duringEndOfContents",
74 "afterEndOfContents",
75 "beforeChoice",
76 "duringChoice",
77 "afterChoice",
78 "notInUse"
79 };
80
81 static const char * const class_names[] = {
82 "UNIVERSAL",
83 "APPLICATION",
84 "CONTEXT_SPECIFIC",
85 "PRIVATE"
86 };
87
88 static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
89
90 static const char * const type_names[] = {
91 "END_OF_CONTENTS",
92 "BOOLEAN",
93 "INTEGER",
94 "BIT_STRING",
95 "OCTET_STRING",
96 "NULL",
97 "OBJECT_ID",
98 "OBJECT_DESCRIPTOR",
99 "(type 08)",
100 "REAL",
101 "ENUMERATED",
102 "EMBEDDED",
103 "UTF8_STRING",
104 "(type 0d)",
105 "(type 0e)",
106 "(type 0f)",
107 "SEQUENCE",
108 "SET",
109 "NUMERIC_STRING",
110 "PRINTABLE_STRING",
111 "T61_STRING",
112 "VIDEOTEXT_STRING",
113 "IA5_STRING",
114 "UTC_TIME",
115 "GENERALIZED_TIME",
116 "GRAPHIC_STRING",
117 "VISIBLE_STRING",
118 "GENERAL_STRING",
119 "UNIVERSAL_STRING",
120 "(type 1d)",
121 "BMP_STRING",
122 "HIGH_TAG_VALUE"
123 };
124
125 static const char * const flag_names[] = { /* flags, right to left */
126 "OPTIONAL",
127 "EXPLICIT",
128 "ANY",
129 "INLINE",
130 "POINTER",
131 "GROUP",
132 "DYNAMIC",
133 "SKIP",
134 "INNER",
135 "SAVE",
136 "", /* decoder ignores "MAY_STREAM", */
137 "SKIP_REST",
138 "CHOICE",
139 "NO_STREAM",
140 "DEBUG_BREAK",
141 "unknown 08",
142 "unknown 10",
143 "unknown 20",
144 "unknown 40",
145 "unknown 80"
146 };
147
148 static int /* bool */
149 formatKind(unsigned long kind, char * buf)
150 {
151 int i;
152 unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
153 unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
154 SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
155
156 buf[0] = 0;
157 if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
158 sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] );
159 buf += strlen(buf);
160 }
161 if (kind & SEC_ASN1_METHOD_MASK) {
162 sprintf(buf, " %s", method_names[1]);
163 buf += strlen(buf);
164 }
165 if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
166 if (k || !notag) {
167 sprintf(buf, " %s", type_names[k] );
168 if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
169 (kind & SEC_ASN1_GROUP)) {
170 buf += strlen(buf);
171 sprintf(buf, "_OF");
172 }
173 }
174 } else {
175 sprintf(buf, " [%d]", k);
176 }
177 buf += strlen(buf);
178
179 for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
180 if (k & 1) {
181 sprintf(buf, " %s", flag_names[i]);
182 buf += strlen(buf);
183 }
184 }
185 return notag != 0;
186 }
187
188 #endif /* DEBUG_ASN1D_STATES */
189
190 typedef enum {
191 allDone,
192 decodeError,
193 keepGoing,
194 needBytes
195 } sec_asn1d_parse_status;
196
197 struct subitem {
198 const void *data;
199 unsigned long len; /* only used for substrings */
200 struct subitem *next;
201 };
202
203 typedef struct sec_asn1d_state_struct {
204 SEC_ASN1DecoderContext *top;
205 const SEC_ASN1Template *theTemplate;
206 void *dest;
207
208 void *our_mark; /* free on completion */
209
210 struct sec_asn1d_state_struct *parent; /* aka prev */
211 struct sec_asn1d_state_struct *child; /* aka next */
212
213 sec_asn1d_parse_place place;
214
215 /*
216 * XXX explain the next fields as clearly as possible...
217 */
218 unsigned char found_tag_modifiers;
219 unsigned char expect_tag_modifiers;
220 unsigned long check_tag_mask;
221 unsigned long found_tag_number;
222 unsigned long expect_tag_number;
223 unsigned long underlying_kind;
224
225 unsigned long contents_length;
226 unsigned long pending;
227 unsigned long consumed;
228
229 int depth;
230
231 /*
232 * Bit strings have their length adjusted -- the first octet of the
233 * contents contains a value between 0 and 7 which says how many bits
234 * at the end of the octets are not actually part of the bit string;
235 * when parsing bit strings we put that value here because we need it
236 * later, for adjustment of the length (when the whole string is done).
237 */
238 unsigned int bit_string_unused_bits;
239
240 /*
241 * The following are used for indefinite-length constructed strings.
242 */
243 struct subitem *subitems_head;
244 struct subitem *subitems_tail;
245
246 PRPackedBool
247 allocate, /* when true, need to allocate the destination */
248 endofcontents, /* this state ended up parsing end-of-contents octets */
249 explicit, /* we are handling an explicit header */
250 indefinite, /* the current item has indefinite-length encoding */
251 missing, /* an optional field that was not present */
252 optional, /* the template says this field may be omitted */
253 substring; /* this is a substring of a constructed string */
254
255 } sec_asn1d_state;
256
257 #define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
258 #define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0)
259 #define TAG_NUMBER_BITS 7
260 #define TAG_NUMBER_MASK 0x7f
261
262 #define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0)
263 #define LONG_FORM_LENGTH(b) ((b) & 0x7f)
264
265 #define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
266
267
268 /*
269 * An "outsider" will have an opaque pointer to this, created by calling
270 * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent
271 * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
272 * SEC_ASN1DecoderFinish().
273 */
274 struct sec_DecoderContext_struct {
275 PLArenaPool *our_pool; /* for our internal allocs */
276 PLArenaPool *their_pool; /* for destination structure allocs */
277 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
278 * XXX see comment below (by same
279 * ifdef) that explains why this
280 * does not work (need more smarts
281 * in order to free back to mark)
282 */
283 /*
284 * XXX how to make their_mark work in the case where they do NOT
285 * give us a pool pointer?
286 */
287 void *their_mark; /* free on error */
288 #endif
289
290 sec_asn1d_state *current;
291 sec_asn1d_parse_status status;
292
293 SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
294 void *notify_arg; /* argument to notify_proc */
295 PRBool during_notify; /* true during call to notify_proc */
296
297 SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */
298 void *filter_arg; /* argument to that function */
299 PRBool filter_only; /* do not allocate/store fields */
300 };
301
302
303 /*
304 * XXX this is a fairly generic function that may belong elsewhere
305 */
306 static void *
307 sec_asn1d_alloc (PLArenaPool *poolp, unsigned long len)
308 {
309 void *thing;
310
311 if (poolp != NULL) {
312 /*
313 * Allocate from the pool.
314 */
315 thing = PORT_ArenaAlloc (poolp, len);
316 } else {
317 /*
318 * Allocate generically.
319 */
320 thing = PORT_Alloc (len);
321 }
322
323 return thing;
324 }
325
326
327 /*
328 * XXX this is a fairly generic function that may belong elsewhere
329 */
330 static void *
331 sec_asn1d_zalloc (PLArenaPool *poolp, unsigned long len)
332 {
333 void *thing;
334
335 thing = sec_asn1d_alloc (poolp, len);
336 if (thing != NULL)
337 PORT_Memset (thing, 0, len);
338 return thing;
339 }
340
341
342 static sec_asn1d_state *
343 sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
344 const SEC_ASN1Template *theTemplate,
345 void *dest, PRBool new_depth)
346 {
347 sec_asn1d_state *state, *new_state;
348
349 state = cx->current;
350
351 PORT_Assert (state == NULL || state->child == NULL);
352
353 if (state != NULL) {
354 PORT_Assert (state->our_mark == NULL);
355 state->our_mark = PORT_ArenaMark (cx->our_pool);
356 }
357
358 new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool,
359 sizeof(*new_state));
360 if (new_state == NULL) {
361 goto loser;
362 }
363
364 new_state->top = cx;
365 new_state->parent = state;
366 new_state->theTemplate = theTemplate;
367 new_state->place = notInUse;
368 if (dest != NULL)
369 new_state->dest = (char *)dest + theTemplate->offset;
370
371 if (state != NULL) {
372 new_state->depth = state->depth;
373 if (new_depth) {
374 if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
375 PORT_SetError (SEC_ERROR_BAD_DER);
376 goto loser;
377 }
378 }
379 state->child = new_state;
380 }
381
382 cx->current = new_state;
383 return new_state;
384
385 loser:
386 cx->status = decodeError;
387 if (state != NULL) {
388 PORT_ArenaRelease(cx->our_pool, state->our_mark);
389 state->our_mark = NULL;
390 }
391 return NULL;
392 }
393
394
395 static void
396 sec_asn1d_scrub_state (sec_asn1d_state *state)
397 {
398 /*
399 * Some default "scrubbing".
400 * XXX right set of initializations?
401 */
402 state->place = beforeIdentifier;
403 state->endofcontents = PR_FALSE;
404 state->indefinite = PR_FALSE;
405 state->missing = PR_FALSE;
406 PORT_Assert (state->consumed == 0);
407 }
408
409
410 static void
411 sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth)
412 {
413 if (cx->notify_proc == NULL)
414 return;
415
416 cx->during_notify = PR_TRUE;
417 (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth);
418 cx->during_notify = PR_FALSE;
419 }
420
421
422 static void
423 sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth)
424 {
425 if (cx->notify_proc == NULL)
426 return;
427
428 cx->during_notify = PR_TRUE;
429 (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth);
430 cx->during_notify = PR_FALSE;
431 }
432
433
434 static sec_asn1d_state *
435 sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
436 {
437 PRBool explicit, optional, universal;
438 unsigned char expect_tag_modifiers;
439 unsigned long encode_kind, under_kind;
440 unsigned long check_tag_mask, expect_tag_number;
441
442
443 /* XXX Check that both of these tests are really needed/appropriate. */
444 if (state == NULL || state->top->status == decodeError)
445 return state;
446
447 encode_kind = state->theTemplate->kind;
448
449 if (encode_kind & SEC_ASN1_SAVE) {
450 /*
451 * This is a "magic" field that saves away all bytes, allowing
452 * the immediately following field to still be decoded from this
453 * same spot -- sort of a fork.
454 */
455 /* check that there are no extraneous bits */
456 PORT_Assert (encode_kind == SEC_ASN1_SAVE);
457 if (state->top->filter_only) {
458 /*
459 * If we are not storing, then we do not do the SAVE field
460 * at all. Just move ahead to the "real" field instead,
461 * doing the appropriate notify calls before and after.
462 */
463 sec_asn1d_notify_after (state->top, state->dest, state->depth);
464 /*
465 * Since we are not storing, allow for our current dest value
466 * to be NULL. (This might not actually occur, but right now I
467 * cannot convince myself one way or the other.) If it is NULL,
468 * assume that our parent dest can help us out.
469 */
470 if (state->dest == NULL)
471 state->dest = state->parent->dest;
472 else
473 state->dest = (char *)state->dest - state->theTemplate->offset;
474 state->theTemplate++;
475 if (state->dest != NULL)
476 state->dest = (char *)state->dest + state->theTemplate->offset;
477 sec_asn1d_notify_before (state->top, state->dest, state->depth);
478 encode_kind = state->theTemplate->kind;
479 PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0);
480 } else {
481 sec_asn1d_scrub_state (state);
482 state->place = duringSaveEncoding;
483 state = sec_asn1d_push_state (state->top, SEC_AnyTemplate,
484 state->dest, PR_FALSE);
485 if (state != NULL)
486 state = sec_asn1d_init_state_based_on_template (state);
487 return state;
488 }
489 }
490
491
492 universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
493 ? PR_TRUE : PR_FALSE;
494
495 explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
496 encode_kind &= ~SEC_ASN1_EXPLICIT;
497
498 optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
499 encode_kind &= ~SEC_ASN1_OPTIONAL;
500
501 PORT_Assert (!(explicit && universal)); /* bad templates */
502
503 encode_kind &= ~SEC_ASN1_DYNAMIC;
504 encode_kind &= ~SEC_ASN1_MAY_STREAM;
505
506 if (encode_kind & SEC_ASN1_CHOICE) {
507 #if 0 /* XXX remove? */
508 sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
509 if ((sec_asn1d_state *)NULL == child) {
510 return (sec_asn1d_state *)NULL;
511 }
512
513 child->allocate = state->allocate;
514 child->place = beforeChoice;
515 return child;
516 #else
517 state->place = beforeChoice;
518 return state;
519 #endif
520 }
521
522 if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal
523 && !explicit)) {
524 const SEC_ASN1Template *subt;
525 void *dest;
526 PRBool child_allocate;
527
528 PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
529
530 sec_asn1d_scrub_state (state);
531 child_allocate = PR_FALSE;
532
533 if (encode_kind & SEC_ASN1_POINTER) {
534 /*
535 * A POINTER means we need to allocate the destination for
536 * this field. But, since it may also be an optional field,
537 * we defer the allocation until later; we just record that
538 * it needs to be done.
539 *
540 * There are two possible scenarios here -- one is just a
541 * plain POINTER (kind of like INLINE, except with allocation)
542 * and the other is an implicitly-tagged POINTER. We don't
543 * need to do anything special here for the two cases, but
544 * since the template definition can be tricky, we do check
545 * that there are no extraneous bits set in encode_kind.
546 *
547 * XXX The same conditions which assert should set an error.
548 */
549 if (universal) {
550 /*
551 * "universal" means this entry is a standalone POINTER;
552 * there should be no other bits set in encode_kind.
553 */
554 PORT_Assert (encode_kind == SEC_ASN1_POINTER);
555 } else {
556 /*
557 * If we get here we have an implicitly-tagged field
558 * that needs to be put into a POINTER. The subtemplate
559 * will determine how to decode the field, but encode_kind
560 * describes the (implicit) tag we are looking for.
561 * The non-tag bits of encode_kind will be ignored by
562 * the code below; none of them should be set, however,
563 * except for the POINTER bit itself -- so check that.
564 */
565 PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK)
566 == SEC_ASN1_POINTER);
567 }
568 if (!state->top->filter_only)
569 child_allocate = PR_TRUE;
570 dest = NULL;
571 state->place = afterPointer;
572 } else {
573 dest = state->dest;
574 if (encode_kind & SEC_ASN1_INLINE) {
575 /* check that there are no extraneous bits */
576 PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);
577 state->place = afterInline;
578 } else {
579 state->place = afterImplicit;
580 }
581 }
582
583 state->optional = optional;
584 subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE);
585 state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE);
586 if (state == NULL)
587 return NULL;
588
589 state->allocate = child_allocate;
590
591 if (universal) {
592 state = sec_asn1d_init_state_based_on_template (state);
593 if (state != NULL) {
594 /*
595 * If this field is optional, we need to record that on
596 * the pushed child so it won't fail if the field isn't
597 * found. I can't think of a way that this new state
598 * could already have optional set (which we would wipe
599 * out below if our local optional is not set) -- but
600 * just to be sure, assert that it isn't set.
601 */
602 PORT_Assert (!state->optional);
603 state->optional = optional;
604 }
605 return state;
606 }
607
608 under_kind = state->theTemplate->kind;
609 under_kind &= ~SEC_ASN1_MAY_STREAM;
610 } else if (explicit) {
611 /*
612 * For explicit, we only need to match the encoding tag next,
613 * then we will push another state to handle the entire inner
614 * part. In this case, there is no underlying kind which plays
615 * any part in the determination of the outer, explicit tag.
616 * So we just set under_kind to 0, which is not a valid tag,
617 * and the rest of the tag matching stuff should be okay.
618 */
619 under_kind = 0;
620 } else {
621 /*
622 * Nothing special; the underlying kind and the given encoding
623 * information are the same.
624 */
625 under_kind = encode_kind;
626 }
627
628 /* XXX is this the right set of bits to test here? */
629 PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL
630 | SEC_ASN1_MAY_STREAM
631 | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
632
633 if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
634 PORT_Assert (encode_kind == under_kind);
635 if (encode_kind & SEC_ASN1_SKIP) {
636 PORT_Assert (!optional);
637 PORT_Assert (encode_kind == SEC_ASN1_SKIP);
638 state->dest = NULL;
639 }
640 check_tag_mask = 0;
641 expect_tag_modifiers = 0;
642 expect_tag_number = 0;
643 } else {
644 check_tag_mask = SEC_ASN1_TAG_MASK;
645 expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK
646 & ~SEC_ASN1_TAGNUM_MASK;
647 /*
648 * XXX This assumes only single-octet identifiers. To handle
649 * the HIGH TAG form we would need to do some more work, especially
650 * in how to specify them in the template, because right now we
651 * do not provide a way to specify more *tag* bits in encode_kind.
652 */
653 expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
654
655 switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
656 case SEC_ASN1_SET:
657 /*
658 * XXX A plain old SET (as opposed to a SET OF) is not implemented.
659 * If it ever is, remove this assert...
660 */
661 PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);
662 /* fallthru */
663 case SEC_ASN1_SEQUENCE:
664 expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
665 break;
666 case SEC_ASN1_BIT_STRING:
667 case SEC_ASN1_BMP_STRING:
668 case SEC_ASN1_GENERALIZED_TIME:
669 case SEC_ASN1_IA5_STRING:
670 case SEC_ASN1_OCTET_STRING:
671 case SEC_ASN1_PRINTABLE_STRING:
672 case SEC_ASN1_T61_STRING:
673 case SEC_ASN1_UNIVERSAL_STRING:
674 case SEC_ASN1_UTC_TIME:
675 case SEC_ASN1_UTF8_STRING:
676 case SEC_ASN1_VISIBLE_STRING:
677 check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
678 break;
679 }
680 }
681
682 state->check_tag_mask = check_tag_mask;
683 state->expect_tag_modifiers = expect_tag_modifiers;
684 state->expect_tag_number = expect_tag_number;
685 state->underlying_kind = under_kind;
686 state->explicit = explicit;
687 state->optional = optional;
688
689 sec_asn1d_scrub_state (state);
690
691 return state;
692 }
693
694 static sec_asn1d_state *
695 sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
696 {
697 for (state = state->parent; state; state = state->parent) {
698 sec_asn1d_parse_place place = state->place;
699 if (place != afterImplicit &&
700 place != afterPointer &&
701 place != afterInline &&
702 place != afterSaveEncoding &&
703 place != duringSaveEncoding &&
704 place != duringChoice) {
705
706 /* we've walked up the stack to a state that represents
707 ** the enclosing construct.
708 */
709 break;
710 }
711 }
712 return state;
713 }
714
715 static PRBool
716 sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
717 {
718 /* get state of enclosing construct. */
719 state = sec_asn1d_get_enclosing_construct(state);
720 if (state) {
721 sec_asn1d_parse_place place = state->place;
722 /* Is it one of the types that permits an unexpected EOC? */
723 int eoc_permitted =
724 (place == duringGroup ||
725 place == duringConstructedString ||
726 state->child->optional);
727 return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
728 }
729 return PR_FALSE;
730 }
731
732 static unsigned long
733 sec_asn1d_parse_identifier (sec_asn1d_state *state,
734 const char *buf, unsigned long len)
735 {
736 unsigned char byte;
737 unsigned char tag_number;
738
739 PORT_Assert (state->place == beforeIdentifier);
740
741 if (len == 0) {
742 state->top->status = needBytes;
743 return 0;
744 }
745
746 byte = (unsigned char) *buf;
747 #ifdef DEBUG_ASN1D_STATES
748 {
749 char kindBuf[256];
750 formatKind(byte, kindBuf);
751 printf("Found tag %02x %s\n", byte, kindBuf);
752 }
753 #endif
754 tag_number = byte & SEC_ASN1_TAGNUM_MASK;
755
756 if (IS_HIGH_TAG_NUMBER (tag_number)) {
757 state->place = duringIdentifier;
758 state->found_tag_number = 0;
759 /*
760 * Actually, we have no idea how many bytes are pending, but we
761 * do know that it is at least 1. That is all we know; we have
762 * to look at each byte to know if there is another, etc.
763 */
764 state->pending = 1;
765 } else {
766 if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
767 /*
768 * Our parent has indefinite-length encoding, and the
769 * entire tag found is 0, so it seems that we have hit the
770 * end-of-contents octets. To handle this, we just change
771 * our state to that which expects to get the bytes of the
772 * end-of-contents octets and let that code re-read this byte
773 * so that our categorization of field types is correct.
774 * After that, our parent will then deal with everything else.
775 */
776 state->place = duringEndOfContents;
777 state->pending = 2;
778 state->found_tag_number = 0;
779 state->found_tag_modifiers = 0;
780 /*
781 * We might be an optional field that is, as we now find out,
782 * missing. Give our parent a clue that this happened.
783 */
784 if (state->optional)
785 state->missing = PR_TRUE;
786 return 0;
787 }
788 state->place = afterIdentifier;
789 state->found_tag_number = tag_number;
790 }
791 state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
792
793 return 1;
794 }
795
796
797 static unsigned long
798 sec_asn1d_parse_more_identifier (sec_asn1d_state *state,
799 const char *buf, unsigned long len)
800 {
801 unsigned char byte;
802 int count;
803
804 PORT_Assert (state->pending == 1);
805 PORT_Assert (state->place == duringIdentifier);
806
807 if (len == 0) {
808 state->top->status = needBytes;
809 return 0;
810 }
811
812 count = 0;
813
814 while (len && state->pending) {
815 if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) {
816 /*
817 * The given high tag number overflows our container;
818 * just give up. This is not likely to *ever* happen.
819 */
820 PORT_SetError (SEC_ERROR_BAD_DER);
821 state->top->status = decodeError;
822 return 0;
823 }
824
825 state->found_tag_number <<= TAG_NUMBER_BITS;
826
827 byte = (unsigned char) buf[count++];
828 state->found_tag_number |= (byte & TAG_NUMBER_MASK);
829
830 len--;
831 if (LAST_TAG_NUMBER_BYTE (byte))
832 state->pending = 0;
833 }
834
835 if (state->pending == 0)
836 state->place = afterIdentifier;
837
838 return count;
839 }
840
841
842 static void
843 sec_asn1d_confirm_identifier (sec_asn1d_state *state)
844 {
845 PRBool match;
846
847 PORT_Assert (state->place == afterIdentifier);
848
849 match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask)
850 == state->expect_tag_modifiers)
851 && ((state->found_tag_number & state->check_tag_mask)
852 == state->expect_tag_number));
853 if (match) {
854 state->place = beforeLength;
855 } else {
856 if (state->optional) {
857 state->missing = PR_TRUE;
858 state->place = afterEndOfContents;
859 } else {
860 PORT_SetError (SEC_ERROR_BAD_DER);
861 state->top->status = decodeError;
862 }
863 }
864 }
865
866
867 static unsigned long
868 sec_asn1d_parse_length (sec_asn1d_state *state,
869 const char *buf, unsigned long len)
870 {
871 unsigned char byte;
872
873 PORT_Assert (state->place == beforeLength);
874
875 if (len == 0) {
876 state->top->status = needBytes;
877 return 0;
878 }
879
880 /*
881 * The default/likely outcome. It may get adjusted below.
882 */
883 state->place = afterLength;
884
885 byte = (unsigned char) *buf;
886
887 if (LENGTH_IS_SHORT_FORM (byte)) {
888 state->contents_length = byte;
889 } else {
890 state->contents_length = 0;
891 state->pending = LONG_FORM_LENGTH (byte);
892 if (state->pending == 0) {
893 state->indefinite = PR_TRUE;
894 } else {
895 state->place = duringLength;
896 }
897 }
898
899 /* If we're parsing an ANY, SKIP, or SAVE template, and
900 ** the object being saved is definite length encoded and constructed,
901 ** there's no point in decoding that construct's members.
902 ** So, just forget it's constructed and treat it as primitive.
903 ** (SAVE appears as an ANY at this point)
904 */
905 if (!state->indefinite &&
906 (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
907 state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
908 }
909
910 return 1;
911 }
912
913
914 static unsigned long
915 sec_asn1d_parse_more_length (sec_asn1d_state *state,
916 const char *buf, unsigned long len)
917 {
918 int count;
919
920 PORT_Assert (state->pending > 0);
921 PORT_Assert (state->place == duringLength);
922
923 if (len == 0) {
924 state->top->status = needBytes;
925 return 0;
926 }
927
928 count = 0;
929
930 while (len && state->pending) {
931 if (HIGH_BITS (state->contents_length, 9) != 0) {
932 /*
933 * The given full content length overflows our container;
934 * just give up.
935 */
936 PORT_SetError (SEC_ERROR_BAD_DER);
937 state->top->status = decodeError;
938 return 0;
939 }
940
941 state->contents_length <<= 8;
942 state->contents_length |= (unsigned char) buf[count++];
943
944 len--;
945 state->pending--;
946 }
947
948 if (state->pending == 0)
949 state->place = afterLength;
950
951 return count;
952 }
953
954
955 static void
956 sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
957 {
958 SECItem *item;
959 PLArenaPool *poolp;
960 unsigned long alloc_len;
961
962 #ifdef DEBUG_ASN1D_STATES
963 {
964 printf("Found Length %d %s\n", state->contents_length,
965 state->indefinite ? "indefinite" : "");
966 }
967 #endif
968
969 /*
970 * XXX I cannot decide if this allocation should exclude the case
971 * where state->endofcontents is true -- figure it out!
972 */
973 if (state->allocate) {
974 void *dest;
975
976 PORT_Assert (state->dest == NULL);
977 /*
978 * We are handling a POINTER or a member of a GROUP, and need to
979 * allocate for the data structure.
980 */
981 dest = sec_asn1d_zalloc (state->top->their_pool,
982 state->theTemplate->size);
983 if (dest == NULL) {
984 state->top->status = decodeError;
985 return;
986 }
987 state->dest = (char *)dest + state->theTemplate->offset;
988
989 /*
990 * For a member of a GROUP, our parent will later put the
991 * pointer wherever it belongs. But for a POINTER, we need
992 * to record the destination now, in case notify or filter
993 * procs need access to it -- they cannot find it otherwise,
994 * until it is too late (for one-pass processing).
995 */
996 if (state->parent->place == afterPointer) {
997 void **placep;
998
999 placep = state->parent->dest;
1000 *placep = dest;
1001 }
1002 }
1003
1004 /*
1005 * Remember, length may be indefinite here! In that case,
1006 * both contents_length and pending will be zero.
1007 */
1008 state->pending = state->contents_length;
1009
1010 /* If this item has definite length encoding, and
1011 ** is enclosed by a definite length constructed type,
1012 ** make sure it isn't longer than the remaining space in that
1013 ** constructed type.
1014 */
1015 if (state->contents_length > 0) {
1016 sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
1017 if (parent && !parent->indefinite &&
1018 state->consumed + state->contents_length > parent->pending) {
1019 PORT_SetError (SEC_ERROR_BAD_DER);
1020 state->top->status = decodeError;
1021 return;
1022 }
1023 }
1024
1025 /*
1026 * An EXPLICIT is nothing but an outer header, which we have
1027 * already parsed and accepted. Now we need to do the inner
1028 * header and its contents.
1029 */
1030 if (state->explicit) {
1031 state->place = afterExplicit;
1032 state = sec_asn1d_push_state (state->top,
1033 SEC_ASN1GetSubtemplate(state->theTemplate,
1034 state->dest,
1035 PR_FALSE),
1036 state->dest, PR_TRUE);
1037 if (state != NULL)
1038 state = sec_asn1d_init_state_based_on_template (state);
1039 return;
1040 }
1041
1042 /*
1043 * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
1044 * we cannot tell how many items we will end up with ... so push a
1045 * state that can keep track of "children" (the individual members
1046 * of the group; we will allocate as we go and put them all together
1047 * at the end.
1048 */
1049 if (state->underlying_kind & SEC_ASN1_GROUP) {
1050 /* XXX If this assertion holds (should be able to confirm it via
1051 * inspection, too) then move this code into the switch statement
1052 * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
1053 */
1054 PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF
1055 || state->underlying_kind == SEC_ASN1_SEQUENCE_OF
1056 || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
1057 || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
1058 );
1059 if (state->contents_length != 0 || state->indefinite) {
1060 const SEC_ASN1Template *subt;
1061
1062 state->place = duringGroup;
1063 subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest,
1064 PR_FALSE);
1065 state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE);
1066 if (state != NULL) {
1067 if (!state->top->filter_only)
1068 state->allocate = PR_TRUE; /* XXX propogate this? */
1069 /*
1070 * Do the "before" field notification for next in group.
1071 */
1072 sec_asn1d_notify_before (state->top, state->dest, state->depth);
1073 state = sec_asn1d_init_state_based_on_template (state);
1074 }
1075 } else {
1076 /*
1077 * A group of zero; we are done.
1078 * Set state to afterGroup and let that code plant the NULL.
1079 */
1080 state->place = afterGroup;
1081 }
1082 return;
1083 }
1084
1085 switch (state->underlying_kind) {
1086 case SEC_ASN1_SEQUENCE:
1087 /*
1088 * We need to push a child to handle the individual fields.
1089 */
1090 state->place = duringSequence;
1091 state = sec_asn1d_push_state (state->top, state->theTemplate + 1,
1092 state->dest, PR_TRUE);
1093 if (state != NULL) {
1094 /*
1095 * Do the "before" field notification.
1096 */
1097 sec_asn1d_notify_before (state->top, state->dest, state->depth);
1098 state = sec_asn1d_init_state_based_on_template (state);
1099 }
1100 break;
1101
1102 case SEC_ASN1_SET: /* XXX SET is not really implemented */
1103 /*
1104 * XXX A plain SET requires special handling; scanning of a
1105 * template to see where a field should go (because by definition,
1106 * they are not in any particular order, and you have to look at
1107 * each tag to disambiguate what the field is). We may never
1108 * implement this because in practice, it seems to be unused.
1109 */
1110 PORT_Assert(0);
1111 PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */
1112 state->top->status = decodeError;
1113 break;
1114
1115 case SEC_ASN1_NULL:
1116 /*
1117 * The NULL type, by definition, is "nothing", content length of zero.
1118 * An indefinite-length encoding is not alloweed.
1119 */
1120 if (state->contents_length || state->indefinite) {
1121 PORT_SetError (SEC_ERROR_BAD_DER);
1122 state->top->status = decodeError;
1123 break;
1124 }
1125 if (state->dest != NULL) {
1126 item = (SECItem *)(state->dest);
1127 item->data = NULL;
1128 item->len = 0;
1129 }
1130 state->place = afterEndOfContents;
1131 break;
1132
1133 case SEC_ASN1_BMP_STRING:
1134 /* Error if length is not divisable by 2 */
1135 if (state->contents_length % 2) {
1136 PORT_SetError (SEC_ERROR_BAD_DER);
1137 state->top->status = decodeError;
1138 break;
1139 }
1140 /* otherwise, handle as other string types */
1141 goto regular_string_type;
1142
1143 case SEC_ASN1_UNIVERSAL_STRING:
1144 /* Error if length is not divisable by 4 */
1145 if (state->contents_length % 4) {
1146 PORT_SetError (SEC_ERROR_BAD_DER);
1147 state->top->status = decodeError;
1148 break;
1149 }
1150 /* otherwise, handle as other string types */
1151 goto regular_string_type;
1152
1153 case SEC_ASN1_SKIP:
1154 case SEC_ASN1_ANY:
1155 case SEC_ASN1_ANY_CONTENTS:
1156 /*
1157 * These are not (necessarily) strings, but they need nearly
1158 * identical handling (especially when we need to deal with
1159 * constructed sub-pieces), so we pretend they are.
1160 */
1161 /* fallthru */
1162 regular_string_type:
1163 case SEC_ASN1_BIT_STRING:
1164 case SEC_ASN1_IA5_STRING:
1165 case SEC_ASN1_OCTET_STRING:
1166 case SEC_ASN1_PRINTABLE_STRING:
1167 case SEC_ASN1_T61_STRING:
1168 case SEC_ASN1_UTC_TIME:
1169 case SEC_ASN1_UTF8_STRING:
1170 case SEC_ASN1_VISIBLE_STRING:
1171 /*
1172 * We are allocating for a primitive or a constructed string.
1173 * If it is a constructed string, it may also be indefinite-length.
1174 * If it is primitive, the length can (legally) be zero.
1175 * Our first order of business is to allocate the memory for
1176 * the string, if we can (if we know the length).
1177 */
1178 item = (SECItem *)(state->dest);
1179
1180 /*
1181 * If the item is a definite-length constructed string, then
1182 * the contents_length is actually larger than what we need
1183 * (because it also counts each intermediate header which we
1184 * will be throwing away as we go), but it is a perfectly good
1185 * upper bound that we just allocate anyway, and then concat
1186 * as we go; we end up wasting a few extra bytes but save a
1187 * whole other copy.
1188 */
1189 alloc_len = state->contents_length;
1190 poolp = NULL; /* quiet compiler warnings about unused... */
1191
1192 if (item == NULL || state->top->filter_only) {
1193 if (item != NULL) {
1194 item->data = NULL;
1195 item->len = 0;
1196 }
1197 alloc_len = 0;
1198 } else if (state->substring) {
1199 /*
1200 * If we are a substring of a constructed string, then we may
1201 * not have to allocate anything (because our parent, the
1202 * actual constructed string, did it for us). If we are a
1203 * substring and we *do* have to allocate, that means our
1204 * parent is an indefinite-length, so we allocate from our pool;
1205 * later our parent will copy our string into the aggregated
1206 * whole and free our pool allocation.
1207 */
1208 if (item->data == NULL) {
1209 PORT_Assert (item->len == 0);
1210 poolp = state->top->our_pool;
1211 } else {
1212 alloc_len = 0;
1213 }
1214 } else {
1215 item->len = 0;
1216 item->data = NULL;
1217 poolp = state->top->their_pool;
1218 }
1219
1220 if (alloc_len || ((! state->indefinite)
1221 && (state->subitems_head != NULL))) {
1222 struct subitem *subitem;
1223 int len;
1224
1225 PORT_Assert (item);
1226 if (!item) {
1227 PORT_SetError (SEC_ERROR_BAD_DER);
1228 state->top->status = decodeError;
1229 return;
1230 }
1231 PORT_Assert (item->len == 0 && item->data == NULL);
1232 /*
1233 * Check for and handle an ANY which has stashed aside the
1234 * header (identifier and length) bytes for us to include
1235 * in the saved contents.
1236 */
1237 if (state->subitems_head != NULL) {
1238 PORT_Assert (state->underlying_kind == SEC_ASN1_ANY);
1239 for (subitem = state->subitems_head;
1240 subitem != NULL; subitem = subitem->next)
1241 alloc_len += subitem->len;
1242 }
1243
1244 item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len);
1245 if (item->data == NULL) {
1246 state->top->status = decodeError;
1247 break;
1248 }
1249
1250 len = 0;
1251 for (subitem = state->subitems_head;
1252 subitem != NULL; subitem = subitem->next) {
1253 PORT_Memcpy (item->data + len, subitem->data, subitem->len);
1254 len += subitem->len;
1255 }
1256 item->len = len;
1257
1258 /*
1259 * Because we use arenas and have a mark set, we later free
1260 * everything we have allocated, so this does *not* present
1261 * a memory leak (it is just temporarily left dangling).
1262 */
1263 state->subitems_head = state->subitems_tail = NULL;
1264 }
1265
1266 if (state->contents_length == 0 && (! state->indefinite)) {
1267 /*
1268 * A zero-length simple or constructed string; we are done.
1269 */
1270 state->place = afterEndOfContents;
1271 } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
1272 const SEC_ASN1Template *sub;
1273
1274 switch (state->underlying_kind) {
1275 case SEC_ASN1_ANY:
1276 case SEC_ASN1_ANY_CONTENTS:
1277 sub = SEC_AnyTemplate;
1278 break;
1279 case SEC_ASN1_BIT_STRING:
1280 sub = SEC_BitStringTemplate;
1281 break;
1282 case SEC_ASN1_BMP_STRING:
1283 sub = SEC_BMPStringTemplate;
1284 break;
1285 case SEC_ASN1_GENERALIZED_TIME:
1286 sub = SEC_GeneralizedTimeTemplate;
1287 break;
1288 case SEC_ASN1_IA5_STRING:
1289 sub = SEC_IA5StringTemplate;
1290 break;
1291 case SEC_ASN1_OCTET_STRING:
1292 sub = SEC_OctetStringTemplate;
1293 break;
1294 case SEC_ASN1_PRINTABLE_STRING:
1295 sub = SEC_PrintableStringTemplate;
1296 break;
1297 case SEC_ASN1_T61_STRING:
1298 sub = SEC_T61StringTemplate;
1299 break;
1300 case SEC_ASN1_UNIVERSAL_STRING:
1301 sub = SEC_UniversalStringTemplate;
1302 break;
1303 case SEC_ASN1_UTC_TIME:
1304 sub = SEC_UTCTimeTemplate;
1305 break;
1306 case SEC_ASN1_UTF8_STRING:
1307 sub = SEC_UTF8StringTemplate;
1308 break;
1309 case SEC_ASN1_VISIBLE_STRING:
1310 sub = SEC_VisibleStringTemplate;
1311 break;
1312 case SEC_ASN1_SKIP:
1313 sub = SEC_SkipTemplate;
1314 break;
1315 default: /* redundant given outer switch cases, but */
1316 PORT_Assert(0); /* the compiler does not seem to know that, */
1317 sub = NULL; /* so just do enough to quiet it. */
1318 break;
1319 }
1320
1321 state->place = duringConstructedString;
1322 state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE);
1323 if (state != NULL) {
1324 state->substring = PR_TRUE; /* XXX propogate? */
1325 state = sec_asn1d_init_state_based_on_template (state);
1326 }
1327 } else if (state->indefinite) {
1328 /*
1329 * An indefinite-length string *must* be constructed!
1330 */
1331 PORT_SetError (SEC_ERROR_BAD_DER);
1332 state->top->status = decodeError;
1333 } else {
1334 /*
1335 * A non-zero-length simple string.
1336 */
1337 if (state->underlying_kind == SEC_ASN1_BIT_STRING)
1338 state->place = beforeBitString;
1339 else
1340 state->place = duringLeaf;
1341 }
1342 break;
1343
1344 default:
1345 /*
1346 * We are allocating for a simple leaf item.
1347 */
1348 if (state->contents_length) {
1349 if (state->dest != NULL) {
1350 item = (SECItem *)(state->dest);
1351 item->len = 0;
1352 if (state->top->filter_only) {
1353 item->data = NULL;
1354 } else {
1355 item->data = (unsigned char*)
1356 sec_asn1d_zalloc (state->top->their_pool,
1357 state->contents_length);
1358 if (item->data == NULL) {
1359 state->top->status = decodeError;
1360 return;
1361 }
1362 }
1363 }
1364 state->place = duringLeaf;
1365 } else {
1366 /*
1367 * An indefinite-length or zero-length item is not allowed.
1368 * (All legal cases of such were handled above.)
1369 */
1370 PORT_SetError (SEC_ERROR_BAD_DER);
1371 state->top->status = decodeError;
1372 }
1373 }
1374 }
1375
1376
1377 static void
1378 sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
1379 {
1380 if (state->child != NULL) {
1381 PORT_Assert (error || state->child->consumed == 0);
1382 PORT_Assert (state->our_mark != NULL);
1383 PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
1384 if (error && state->top->their_pool == NULL) {
1385 /*
1386 * XXX We need to free anything allocated.
1387 * At this point, we failed in the middle of decoding. But we
1388 * can't free the data we previously allocated with PR_Malloc
1389 * unless we keep track of every pointer. So instead we have a
1390 * memory leak when decoding fails half-way, unless an arena is
1391 * used. See bug 95311 .
1392 */
1393 }
1394 state->child = NULL;
1395 state->our_mark = NULL;
1396 } else {
1397 /*
1398 * It is important that we do not leave a mark unreleased/unmarked.
1399 * But I do not think we should ever have one set in this case, only
1400 * if we had a child (handled above). So check for that. If this
1401 * assertion should ever get hit, then we probably need to add code
1402 * here to release back to our_mark (and then set our_mark to NULL).
1403 */
1404 PORT_Assert (state->our_mark == NULL);
1405 }
1406 state->place = beforeEndOfContents;
1407 }
1408
1409 /* We have just saved an entire encoded ASN.1 object (type) for a SAVE
1410 ** template, and now in the next template, we are going to decode that
1411 ** saved data by calling SEC_ASN1DecoderUpdate recursively.
1412 ** If that recursive call fails with needBytes, it is a fatal error,
1413 ** because the encoded object should have been complete.
1414 ** If that recursive call fails with decodeError, it will have already
1415 ** cleaned up the state stack, so we must bail out quickly.
1416 **
1417 ** These checks of the status returned by the recursive call are now
1418 ** done in the caller of this function, immediately after it returns.
1419 */
1420 static void
1421 sec_asn1d_reuse_encoding (sec_asn1d_state *state)
1422 {
1423 sec_asn1d_state *child;
1424 unsigned long consumed;
1425 SECItem *item;
1426 void *dest;
1427
1428
1429 child = state->child;
1430 PORT_Assert (child != NULL);
1431
1432 consumed = child->consumed;
1433 child->consumed = 0;
1434
1435 item = (SECItem *)(state->dest);
1436 PORT_Assert (item != NULL);
1437
1438 PORT_Assert (item->len == consumed);
1439
1440 /*
1441 * Free any grandchild.
1442 */
1443 sec_asn1d_free_child (child, PR_FALSE);
1444
1445 /*
1446 * Notify after the SAVE field.
1447 */
1448 sec_asn1d_notify_after (state->top, state->dest, state->depth);
1449
1450 /*
1451 * Adjust to get new dest and move forward.
1452 */
1453 dest = (char *)state->dest - state->theTemplate->offset;
1454 state->theTemplate++;
1455 child->dest = (char *)dest + state->theTemplate->offset;
1456 child->theTemplate = state->theTemplate;
1457
1458 /*
1459 * Notify before the "real" field.
1460 */
1461 PORT_Assert (state->depth == child->depth);
1462 sec_asn1d_notify_before (state->top, child->dest, child->depth);
1463
1464 /*
1465 * This will tell DecoderUpdate to return when it is done.
1466 */
1467 state->place = afterSaveEncoding;
1468
1469 /*
1470 * We already have a child; "push" it by making it current.
1471 */
1472 state->top->current = child;
1473
1474 /*
1475 * And initialize it so it is ready to parse.
1476 */
1477 (void) sec_asn1d_init_state_based_on_template(child);
1478
1479 /*
1480 * Now parse that out of our data.
1481 */
1482 if (SEC_ASN1DecoderUpdate (state->top,
1483 (char *) item->data, item->len) != SECSuccess)
1484 return;
1485 if (state->top->status == needBytes) {
1486 return;
1487 }
1488
1489 PORT_Assert (state->top->current == state);
1490 PORT_Assert (state->child == child);
1491
1492 /*
1493 * That should have consumed what we consumed before.
1494 */
1495 PORT_Assert (consumed == child->consumed);
1496 child->consumed = 0;
1497
1498 /*
1499 * Done.
1500 */
1501 state->consumed += consumed;
1502 child->place = notInUse;
1503 state->place = afterEndOfContents;
1504 }
1505
1506
1507 static unsigned long
1508 sec_asn1d_parse_leaf (sec_asn1d_state *state,
1509 const char *buf, unsigned long len)
1510 {
1511 SECItem *item;
1512 unsigned long bufLen;
1513
1514 if (len == 0) {
1515 state->top->status = needBytes;
1516 return 0;
1517 }
1518
1519 if (state->pending < len)
1520 len = state->pending;
1521
1522 bufLen = len;
1523
1524 item = (SECItem *)(state->dest);
1525 if (item != NULL && item->data != NULL) {
1526 /* Strip leading zeroes when target is unsigned integer */
1527 if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
1528 item->len == 0 && /* MSB */
1529 item->type == siUnsignedInteger) /* unsigned */
1530 {
1531 while (len > 1 && buf[0] == 0) { /* leading 0 */
1532 buf++;
1533 len--;
1534 }
1535 }
1536 PORT_Memcpy (item->data + item->len, buf, len);
1537 item->len += len;
1538 }
1539 state->pending -= bufLen;
1540 if (state->pending == 0)
1541 state->place = beforeEndOfContents;
1542
1543 return bufLen;
1544 }
1545
1546
1547 static unsigned long
1548 sec_asn1d_parse_bit_string (sec_asn1d_state *state,
1549 const char *buf, unsigned long len)
1550 {
1551 unsigned char byte;
1552
1553 /*PORT_Assert (state->pending > 0); */
1554 PORT_Assert (state->place == beforeBitString);
1555
1556 if (state->pending == 0) {
1557 if (state->dest != NULL) {
1558 SECItem *item = (SECItem *)(state->dest);
1559 item->data = NULL;
1560 item->len = 0;
1561 state->place = beforeEndOfContents;
1562 return 0;
1563 }
1564 }
1565
1566 if (len == 0) {
1567 state->top->status = needBytes;
1568 return 0;
1569 }
1570
1571 byte = (unsigned char) *buf;
1572 if (byte > 7) {
1573 PORT_SetError (SEC_ERROR_BAD_DER);
1574 state->top->status = decodeError;
1575 return 0;
1576 }
1577
1578 state->bit_string_unused_bits = byte;
1579 state->place = duringBitString;
1580 state->pending -= 1;
1581
1582 return 1;
1583 }
1584
1585
1586 static unsigned long
1587 sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
1588 const char *buf, unsigned long len)
1589 {
1590 PORT_Assert (state->place == duringBitString);
1591 if (state->pending == 0) {
1592 /* An empty bit string with some unused bits is invalid. */
1593 if (state->bit_string_unused_bits) {
1594 PORT_SetError (SEC_ERROR_BAD_DER);
1595 state->top->status = decodeError;
1596 } else {
1597 /* An empty bit string with no unused bits is OK. */
1598 state->place = beforeEndOfContents;
1599 }
1600 return 0;
1601 }
1602
1603 len = sec_asn1d_parse_leaf (state, buf, len);
1604 if (state->place == beforeEndOfContents && state->dest != NULL) {
1605 SECItem *item;
1606
1607 item = (SECItem *)(state->dest);
1608 if (item->len)
1609 item->len = (item->len << 3) - state->bit_string_unused_bits;
1610 }
1611
1612 return len;
1613 }
1614
1615
1616 /*
1617 * XXX All callers should be looking at return value to detect
1618 * out-of-memory errors (and stop!).
1619 */
1620 static struct subitem *
1621 sec_asn1d_add_to_subitems (sec_asn1d_state *state,
1622 const void *data, unsigned long len,
1623 PRBool copy_data)
1624 {
1625 struct subitem *thing;
1626
1627 thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool,
1628 sizeof (struct subitem));
1629 if (thing == NULL) {
1630 state->top->status = decodeError;
1631 return NULL;
1632 }
1633
1634 if (copy_data) {
1635 void *copy;
1636 copy = sec_asn1d_alloc (state->top->our_pool, len);
1637 if (copy == NULL) {
1638 state->top->status = decodeError;
1639 if (!state->top->our_pool)
1640 PORT_Free(thing);
1641 return NULL;
1642 }
1643 PORT_Memcpy (copy, data, len);
1644 thing->data = copy;
1645 } else {
1646 thing->data = data;
1647 }
1648 thing->len = len;
1649 thing->next = NULL;
1650
1651 if (state->subitems_head == NULL) {
1652 PORT_Assert (state->subitems_tail == NULL);
1653 state->subitems_head = state->subitems_tail = thing;
1654 } else {
1655 state->subitems_tail->next = thing;
1656 state->subitems_tail = thing;
1657 }
1658
1659 return thing;
1660 }
1661
1662
1663 static void
1664 sec_asn1d_record_any_header (sec_asn1d_state *state,
1665 const char *buf,
1666 unsigned long len)
1667 {
1668 SECItem *item;
1669
1670 item = (SECItem *)(state->dest);
1671 if (item != NULL && item->data != NULL) {
1672 PORT_Assert (state->substring);
1673 PORT_Memcpy (item->data + item->len, buf, len);
1674 item->len += len;
1675 } else {
1676 sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE);
1677 }
1678 }
1679
1680
1681 /*
1682 * We are moving along through the substrings of a constructed string,
1683 * and have just finished parsing one -- we need to save our child data
1684 * (if the child was not already writing directly into the destination)
1685 * and then move forward by one.
1686 *
1687 * We also have to detect when we are done:
1688 * - a definite-length encoding stops when our pending value hits 0
1689 * - an indefinite-length encoding stops when our child is empty
1690 * (which means it was the end-of-contents octets)
1691 */
1692 static void
1693 sec_asn1d_next_substring (sec_asn1d_state *state)
1694 {
1695 sec_asn1d_state *child;
1696 SECItem *item;
1697 unsigned long child_consumed;
1698 PRBool done;
1699
1700 PORT_Assert (state->place == duringConstructedString);
1701 PORT_Assert (state->child != NULL);
1702
1703 child = state->child;
1704
1705 child_consumed = child->consumed;
1706 child->consumed = 0;
1707 state->consumed += child_consumed;
1708
1709 done = PR_FALSE;
1710
1711 if (state->pending) {
1712 PORT_Assert (!state->indefinite);
1713 if (child_consumed > state->pending) {
1714 PORT_SetError (SEC_ERROR_BAD_DER);
1715 state->top->status = decodeError;
1716 return;
1717 }
1718
1719 state->pending -= child_consumed;
1720 if (state->pending == 0)
1721 done = PR_TRUE;
1722 } else {
1723 PORT_Assert (state->indefinite);
1724
1725 item = (SECItem *)(child->dest);
1726 if (item != NULL && item->data != NULL) {
1727 /*
1728 * Save the string away for later concatenation.
1729 */
1730 PORT_Assert (item->data != NULL);
1731 sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE);
1732 /*
1733 * Clear the child item for the next round.
1734 */
1735 item->data = NULL;
1736 item->len = 0;
1737 }
1738
1739 /*
1740 * If our child was just our end-of-contents octets, we are done.
1741 */
1742 if (child->endofcontents)
1743 done = PR_TRUE;
1744 }
1745
1746 /*
1747 * Stop or do the next one.
1748 */
1749 if (done) {
1750 child->place = notInUse;
1751 state->place = afterConstructedString;
1752 } else {
1753 sec_asn1d_scrub_state (child);
1754 state->top->current = child;
1755 }
1756 }
1757
1758
1759 /*
1760 * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
1761 */
1762 static void
1763 sec_asn1d_next_in_group (sec_asn1d_state *state)
1764 {
1765 sec_asn1d_state *child;
1766 unsigned long child_consumed;
1767
1768 PORT_Assert (state->place == duringGroup);
1769 PORT_Assert (state->child != NULL);
1770
1771 child = state->child;
1772
1773 child_consumed = child->consumed;
1774 child->consumed = 0;
1775 state->consumed += child_consumed;
1776
1777 /*
1778 * If our child was just our end-of-contents octets, we are done.
1779 */
1780 if (child->endofcontents) {
1781 /* XXX I removed the PORT_Assert (child->dest == NULL) because there
1782 * was a bug in that a template that was a sequence of which also had
1783 * a child of a sequence of, in an indefinite group was not working
1784 * properly. This fix seems to work, (added the if statement below),
1785 * and nothing appears broken, but I am putting this note here just
1786 * in case. */
1787 /*
1788 * XXX No matter how many times I read that comment,
1789 * I cannot figure out what case he was fixing. I believe what he
1790 * did was deliberate, so I am loathe to touch it. I need to
1791 * understand how it could ever be that child->dest != NULL but
1792 * child->endofcontents is true, and why it is important to check
1793 * that state->subitems_head is NULL. This really needs to be
1794 * figured out, as I am not sure if the following code should be
1795 * compensating for "offset", as is done a little farther below
1796 * in the more normal case.
1797 */
1798 PORT_Assert (state->indefinite);
1799 PORT_Assert (state->pending == 0);
1800 if(child->dest && !state->subitems_head) {
1801 sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE);
1802 child->dest = NULL;
1803 }
1804
1805 child->place = notInUse;
1806 state->place = afterGroup;
1807 return;
1808 }
1809
1810 /*
1811 * Do the "after" field notification for next in group.
1812 */
1813 sec_asn1d_notify_after (state->top, child->dest, child->depth);
1814
1815 /*
1816 * Save it away (unless we are not storing).
1817 */
1818 if (child->dest != NULL) {
1819 void *dest;
1820
1821 dest = child->dest;
1822 dest = (char *)dest - child->theTemplate->offset;
1823 sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE);
1824 child->dest = NULL;
1825 }
1826
1827 /*
1828 * Account for those bytes; see if we are done.
1829 */
1830 if (state->pending) {
1831 PORT_Assert (!state->indefinite);
1832 if (child_consumed > state->pending) {
1833 PORT_SetError (SEC_ERROR_BAD_DER);
1834 state->top->status = decodeError;
1835 return;
1836 }
1837
1838 state->pending -= child_consumed;
1839 if (state->pending == 0) {
1840 child->place = notInUse;
1841 state->place = afterGroup;
1842 return;
1843 }
1844 }
1845
1846 /*
1847 * Do the "before" field notification for next item in group.
1848 */
1849 sec_asn1d_notify_before (state->top, child->dest, child->depth);
1850
1851 /*
1852 * Now we do the next one.
1853 */
1854 sec_asn1d_scrub_state (child);
1855
1856 /* Initialize child state from the template */
1857 sec_asn1d_init_state_based_on_template(child);
1858
1859 state->top->current = child;
1860 }
1861
1862
1863 /*
1864 * We are moving along through a sequence; move forward by one,
1865 * (detecting end-of-sequence when it happens).
1866 * XXX The handling of "missing" is ugly. Fix it.
1867 */
1868 static void
1869 sec_asn1d_next_in_sequence (sec_asn1d_state *state)
1870 {
1871 sec_asn1d_state *child;
1872 unsigned long child_consumed;
1873 PRBool child_missing;
1874
1875 PORT_Assert (state->place == duringSequence);
1876 PORT_Assert (state->child != NULL);
1877
1878 child = state->child;
1879
1880 /*
1881 * Do the "after" field notification.
1882 */
1883 sec_asn1d_notify_after (state->top, child->dest, child->depth);
1884
1885 child_missing = (PRBool) child->missing;
1886 child_consumed = child->consumed;
1887 child->consumed = 0;
1888
1889 /*
1890 * Take care of accounting.
1891 */
1892 if (child_missing) {
1893 PORT_Assert (child->optional);
1894 } else {
1895 state->consumed += child_consumed;
1896 /*
1897 * Free any grandchild.
1898 */
1899 sec_asn1d_free_child (child, PR_FALSE);
1900 if (state->pending) {
1901 PORT_Assert (!state->indefinite);
1902 if (child_consumed > state->pending) {
1903 PORT_SetError (SEC_ERROR_BAD_DER);
1904 state->top->status = decodeError;
1905 return;
1906 }
1907 state->pending -= child_consumed;
1908 if (state->pending == 0) {
1909 child->theTemplate++;
1910 while (child->theTemplate->kind != 0) {
1911 if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
1912 PORT_SetError (SEC_ERROR_BAD_DER);
1913 state->top->status = decodeError;
1914 return;
1915 }
1916 child->theTemplate++;
1917 }
1918 child->place = notInUse;
1919 state->place = afterEndOfContents;
1920 return;
1921 }
1922 }
1923 }
1924
1925 /*
1926 * Move forward.
1927 */
1928 child->theTemplate++;
1929 if (child->theTemplate->kind == 0) {
1930 /*
1931 * We are done with this sequence.
1932 */
1933 child->place = notInUse;
1934 if (state->pending) {
1935 PORT_SetError (SEC_ERROR_BAD_DER);
1936 state->top->status = decodeError;
1937 } else if (child_missing) {
1938 /*
1939 * We got to the end, but have a child that started parsing
1940 * and ended up "missing". The only legitimate reason for
1941 * this is that we had one or more optional fields at the
1942 * end of our sequence, and we were encoded indefinite-length,
1943 * so when we went looking for those optional fields we
1944 * found our end-of-contents octets instead.
1945 * (Yes, this is ugly; dunno a better way to handle it.)
1946 * So, first confirm the situation, and then mark that we
1947 * are done.
1948 */
1949 if (state->indefinite && child->endofcontents) {
1950 PORT_Assert (child_consumed == 2);
1951 if (child_consumed != 2) {
1952 PORT_SetError (SEC_ERROR_BAD_DER);
1953 state->top->status = decodeError;
1954 } else {
1955 state->consumed += child_consumed;
1956 state->place = afterEndOfContents;
1957 }
1958 } else {
1959 PORT_SetError (SEC_ERROR_BAD_DER);
1960 state->top->status = decodeError;
1961 }
1962 } else {
1963 /*
1964 * We have to finish out, maybe reading end-of-contents octets;
1965 * let the normal logic do the right thing.
1966 */
1967 state->place = beforeEndOfContents;
1968 }
1969 } else {
1970 unsigned char child_found_tag_modifiers = 0;
1971 unsigned long child_found_tag_number = 0;
1972
1973 /*
1974 * Reset state and push.
1975 */
1976 if (state->dest != NULL)
1977 child->dest = (char *)state->dest + child->theTemplate->offset;
1978
1979 /*
1980 * Do the "before" field notification.
1981 */
1982 sec_asn1d_notify_before (state->top, child->dest, child->depth);
1983
1984 if (child_missing) { /* if previous child was missing, copy the tag data we already have */
1985 child_found_tag_modifiers = child->found_tag_modifiers;
1986 child_found_tag_number = child->found_tag_number;
1987 }
1988 state->top->current = child;
1989 child = sec_asn1d_init_state_based_on_template (child);
1990 if (child_missing && child) {
1991 child->place = afterIdentifier;
1992 child->found_tag_modifiers = child_found_tag_modifiers;
1993 child->found_tag_number = child_found_tag_number;
1994 child->consumed = child_consumed;
1995 if (child->underlying_kind == SEC_ASN1_ANY
1996 && !child->top->filter_only) {
1997 /*
1998 * If the new field is an ANY, and we are storing, then
1999 * we need to save the tag out. We would have done this
2000 * already in the normal case, but since we were looking
2001 * for an optional field, and we did not find it, we only
2002 * now realize we need to save the tag.
2003 */
2004 unsigned char identifier;
2005
2006 /*
2007 * Check that we did not end up with a high tag; for that
2008 * we need to re-encode the tag into multiple bytes in order
2009 * to store it back to look like what we parsed originally.
2010 * In practice this does not happen, but for completeness
2011 * sake it should probably be made to work at some point.
2012 */
2013 PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
2014 identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
2015 sec_asn1d_record_any_header (child, (char *) &identifier, 1);
2016 }
2017 }
2018 }
2019 }
2020
2021
2022 static void
2023 sec_asn1d_concat_substrings (sec_asn1d_state *state)
2024 {
2025 PORT_Assert (state->place == afterConstructedString);
2026
2027 if (state->subitems_head != NULL) {
2028 struct subitem *substring;
2029 unsigned long alloc_len, item_len;
2030 unsigned char *where;
2031 SECItem *item;
2032 PRBool is_bit_string;
2033
2034 item_len = 0;
2035 is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
2036 ? PR_TRUE : PR_FALSE;
2037
2038 substring = state->subitems_head;
2039 while (substring != NULL) {
2040 /*
2041 * All bit-string substrings except the last one should be
2042 * a clean multiple of 8 bits.
2043 */
2044 if (is_bit_string && (substring->next == NULL)
2045 && (substring->len & 0x7)) {
2046 PORT_SetError (SEC_ERROR_BAD_DER);
2047 state->top->status = decodeError;
2048 return;
2049 }
2050 item_len += substring->len;
2051 substring = substring->next;
2052 }
2053
2054 if (is_bit_string) {
2055 alloc_len = ((item_len + 7) >> 3);
2056 } else {
2057 /*
2058 * Add 2 for the end-of-contents octets of an indefinite-length
2059 * ANY that is *not* also an INNER. Because we zero-allocate
2060 * below, all we need to do is increase the length here.
2061 */
2062 if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
2063 item_len += 2;
2064 alloc_len = item_len;
2065 }
2066
2067 item = (SECItem *)(state->dest);
2068 PORT_Assert (item != NULL);
2069 PORT_Assert (item->data == NULL);
2070 item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool,
2071 alloc_len);
2072 if (item->data == NULL) {
2073 state->top->status = decodeError;
2074 return;
2075 }
2076 item->len = item_len;
2077
2078 where = item->data;
2079 substring = state->subitems_head;
2080 while (substring != NULL) {
2081 if (is_bit_string)
2082 item_len = (substring->len + 7) >> 3;
2083 else
2084 item_len = substring->len;
2085 PORT_Memcpy (where, substring->data, item_len);
2086 where += item_len;
2087 substring = substring->next;
2088 }
2089
2090 /*
2091 * Because we use arenas and have a mark set, we later free
2092 * everything we have allocated, so this does *not* present
2093 * a memory leak (it is just temporarily left dangling).
2094 */
2095 state->subitems_head = state->subitems_tail = NULL;
2096 }
2097
2098 state->place = afterEndOfContents;
2099 }
2100
2101
2102 static void
2103 sec_asn1d_concat_group (sec_asn1d_state *state)
2104 {
2105 const void ***placep;
2106
2107 PORT_Assert (state->place == afterGroup);
2108
2109 placep = (const void***)state->dest;
2110 PORT_Assert(state->subitems_head == NULL || placep != NULL);
2111 if (placep != NULL) {
2112 struct subitem *item;
2113 const void **group;
2114 int count;
2115
2116 count = 0;
2117 item = state->subitems_head;
2118 while (item != NULL) {
2119 PORT_Assert (item->next != NULL || item == state->subitems_tail);
2120 count++;
2121 item = item->next;
2122 }
2123
2124 group = (const void**)sec_asn1d_zalloc (state->top->their_pool,
2125 (count + 1) * (sizeof(void *)));
2126 if (group == NULL) {
2127 state->top->status = decodeError;
2128 return;
2129 }
2130
2131 *placep = group;
2132
2133 item = state->subitems_head;
2134 while (item != NULL) {
2135 *group++ = item->data;
2136 item = item->next;
2137 }
2138 *group = NULL;
2139
2140 /*
2141 * Because we use arenas and have a mark set, we later free
2142 * everything we have allocated, so this does *not* present
2143 * a memory leak (it is just temporarily left dangling).
2144 */
2145 state->subitems_head = state->subitems_tail = NULL;
2146 }
2147
2148 state->place = afterEndOfContents;
2149 }
2150
2151
2152 /*
2153 * For those states that push a child to handle a subtemplate,
2154 * "absorb" that child (transfer necessary information).
2155 */
2156 static void
2157 sec_asn1d_absorb_child (sec_asn1d_state *state)
2158 {
2159 /*
2160 * There is absolutely supposed to be a child there.
2161 */
2162 PORT_Assert (state->child != NULL);
2163
2164 /*
2165 * Inherit the missing status of our child, and do the ugly
2166 * backing-up if necessary.
2167 */
2168 state->missing = state->child->missing;
2169 if (state->missing) {
2170 state->found_tag_number = state->child->found_tag_number;
2171 state->found_tag_modifiers = state->child->found_tag_modifiers;
2172 state->endofcontents = state->child->endofcontents;
2173 }
2174
2175 /*
2176 * Add in number of bytes consumed by child.
2177 * (Only EXPLICIT should have already consumed bytes itself.)
2178 */
2179 PORT_Assert (state->place == afterExplicit || state->consumed == 0);
2180 state->consumed += state->child->consumed;
2181
2182 /*
2183 * Subtract from bytes pending; this only applies to a definite-length
2184 * EXPLICIT field.
2185 */
2186 if (state->pending) {
2187 PORT_Assert (!state->indefinite);
2188 PORT_Assert (state->place == afterExplicit);
2189
2190 /*
2191 * If we had a definite-length explicit, then what the child
2192 * consumed should be what was left pending.
2193 */
2194 if (state->pending != state->child->consumed) {
2195 if (state->pending < state->child->consumed) {
2196 PORT_SetError (SEC_ERROR_BAD_DER);
2197 state->top->status = decodeError;
2198 return;
2199 }
2200 /*
2201 * Okay, this is a hack. It *should* be an error whether
2202 * pending is too big or too small, but it turns out that
2203 * we had a bug in our *old* DER encoder that ended up
2204 * counting an explicit header twice in the case where
2205 * the underlying type was an ANY. So, because we cannot
2206 * prevent receiving these (our own certificate server can
2207 * send them to us), we need to be lenient and accept them.
2208 * To do so, we need to pretend as if we read all of the
2209 * bytes that the header said we would find, even though
2210 * we actually came up short.
2211 */
2212 state->consumed += (state->pending - state->child->consumed);
2213 }
2214 state->pending = 0;
2215 }
2216
2217 /*
2218 * Indicate that we are done with child.
2219 */
2220 state->child->consumed = 0;
2221
2222 /*
2223 * And move on to final state.
2224 * (Technically everybody could move to afterEndOfContents except
2225 * for an indefinite-length EXPLICIT; for simplicity though we assert
2226 * that but let the end-of-contents code do the real determination.)
2227 */
2228 PORT_Assert (state->place == afterExplicit || (! state->indefinite));
2229 state->place = beforeEndOfContents;
2230 }
2231
2232
2233 static void
2234 sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state)
2235 {
2236 PORT_Assert (state->place == beforeEndOfContents);
2237
2238 if (state->indefinite) {
2239 state->place = duringEndOfContents;
2240 state->pending = 2;
2241 } else {
2242 state->place = afterEndOfContents;
2243 }
2244 }
2245
2246
2247 static unsigned long
2248 sec_asn1d_parse_end_of_contents (sec_asn1d_state *state,
2249 const char *buf, unsigned long len)
2250 {
2251 unsigned int i;
2252
2253 PORT_Assert (state->pending <= 2);
2254 PORT_Assert (state->place == duringEndOfContents);
2255
2256 if (len == 0) {
2257 state->top->status = needBytes;
2258 return 0;
2259 }
2260
2261 if (state->pending < len)
2262 len = state->pending;
2263
2264 for (i = 0; i < len; i++) {
2265 if (buf[i] != 0) {
2266 /*
2267 * We expect to find only zeros; if not, just give up.
2268 */
2269 PORT_SetError (SEC_ERROR_BAD_DER);
2270 state->top->status = decodeError;
2271 return 0;
2272 }
2273 }
2274
2275 state->pending -= len;
2276
2277 if (state->pending == 0) {
2278 state->place = afterEndOfContents;
2279 state->endofcontents = PR_TRUE;
2280 }
2281
2282 return len;
2283 }
2284
2285
2286 static void
2287 sec_asn1d_pop_state (sec_asn1d_state *state)
2288 {
2289 #if 0 /* XXX I think this should always be handled explicitly by parent? */
2290 /*
2291 * Account for our child.
2292 */
2293 if (state->child != NULL) {
2294 state->consumed += state->child->consumed;
2295 if (state->pending) {
2296 PORT_Assert (!state->indefinite);
2297 if (state->child->consumed > state->pending) {
2298 PORT_SetError (SEC_ERROR_BAD_DER);
2299 state->top->status = decodeError;
2300 } else {
2301 state->pending -= state->child->consumed;
2302 }
2303 }
2304 state->child->consumed = 0;
2305 }
2306 #endif /* XXX */
2307
2308 /*
2309 * Free our child.
2310 */
2311 sec_asn1d_free_child (state, PR_FALSE);
2312
2313 /*
2314 * Just make my parent be the current state. It will then clean
2315 * up after me and free me (or reuse me).
2316 */
2317 state->top->current = state->parent;
2318 }
2319
2320 static sec_asn1d_state *
2321 sec_asn1d_before_choice (sec_asn1d_state *state)
2322 {
2323 sec_asn1d_state *child;
2324
2325 if (state->allocate) {
2326 void *dest;
2327
2328 dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
2329 if ((void *)NULL == dest) {
2330 state->top->status = decodeError;
2331 return (sec_asn1d_state *)NULL;
2332 }
2333
2334 state->dest = (char *)dest + state->theTemplate->offset;
2335 }
2336
2337 child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
2338 (char *)state->dest - state->theTemplate->offset,
2339 PR_FALSE);
2340 if ((sec_asn1d_state *)NULL == child) {
2341 return (sec_asn1d_state *)NULL;
2342 }
2343
2344 sec_asn1d_scrub_state(child);
2345 child = sec_asn1d_init_state_based_on_template(child);
2346 if ((sec_asn1d_state *)NULL == child) {
2347 return (sec_asn1d_state *)NULL;
2348 }
2349
2350 child->optional = PR_TRUE;
2351
2352 state->place = duringChoice;
2353
2354 return child;
2355 }
2356
2357 static sec_asn1d_state *
2358 sec_asn1d_during_choice (sec_asn1d_state *state)
2359 {
2360 sec_asn1d_state *child = state->child;
2361
2362 PORT_Assert((sec_asn1d_state *)NULL != child);
2363
2364 if (child->missing) {
2365 unsigned char child_found_tag_modifiers = 0;
2366 unsigned long child_found_tag_number = 0;
2367 void * dest;
2368
2369 state->consumed += child->consumed;
2370
2371 if (child->endofcontents) {
2372 /* This choice is probably the first item in a GROUP
2373 ** (e.g. SET_OF) that was indefinite-length encoded.
2374 ** We're actually at the end of that GROUP.
2375 ** We look up the stack to be sure that we find
2376 ** a state with indefinite length encoding before we
2377 ** find a state (like a SEQUENCE) that is definite.
2378 */
2379 child->place = notInUse;
2380 state->place = afterChoice;
2381 state->endofcontents = PR_TRUE; /* propagate this up */
2382 if (sec_asn1d_parent_allows_EOC(state))
2383 return state;
2384 PORT_SetError(SEC_ERROR_BAD_DER);
2385 state->top->status = decodeError;
2386 return NULL;
2387 }
2388
2389 dest = (char *)child->dest - child->theTemplate->offset;
2390 child->theTemplate++;
2391
2392 if (0 == child->theTemplate->kind) {
2393 /* Ran out of choices */
2394 PORT_SetError(SEC_ERROR_BAD_DER);
2395 state->top->status = decodeError;
2396 return (sec_asn1d_state *)NULL;
2397 }
2398 child->dest = (char *)dest + child->theTemplate->offset;
2399
2400 /* cargo'd from next_in_sequence innards */
2401 if (state->pending) {
2402 PORT_Assert(!state->indefinite);
2403 if (child->consumed > state->pending) {
2404 PORT_SetError (SEC_ERROR_BAD_DER);
2405 state->top->status = decodeError;
2406 return NULL;
2407 }
2408 state->pending -= child->consumed;
2409 if (0 == state->pending) {
2410 /* XXX uh.. not sure if I should have stopped this
2411 * from happening before. */
2412 PORT_Assert(0);
2413 PORT_SetError(SEC_ERROR_BAD_DER);
2414 state->top->status = decodeError;
2415 return (sec_asn1d_state *)NULL;
2416 }
2417 }
2418
2419 child->consumed = 0;
2420 sec_asn1d_scrub_state(child);
2421
2422 /* move it on top again */
2423 state->top->current = child;
2424
2425 child_found_tag_modifiers = child->found_tag_modifiers;
2426 child_found_tag_number = child->found_tag_number;
2427
2428 child = sec_asn1d_init_state_based_on_template(child);
2429 if ((sec_asn1d_state *)NULL == child) {
2430 return (sec_asn1d_state *)NULL;
2431 }
2432
2433 /* copy our findings to the new top */
2434 child->found_tag_modifiers = child_found_tag_modifiers;
2435 child->found_tag_number = child_found_tag_number;
2436
2437 child->optional = PR_TRUE;
2438 child->place = afterIdentifier;
2439
2440 return child;
2441 }
2442 if ((void *)NULL != state->dest) {
2443 /* Store the enum */
2444 int *which = (int *)state->dest;
2445 *which = (int)child->theTemplate->size;
2446 }
2447
2448 child->place = notInUse;
2449
2450 state->place = afterChoice;
2451 return state;
2452 }
2453
2454 static void
2455 sec_asn1d_after_choice (sec_asn1d_state *state)
2456 {
2457 state->consumed += state->child->consumed;
2458 state->child->consumed = 0;
2459 state->place = afterEndOfContents;
2460 sec_asn1d_pop_state(state);
2461 }
2462
2463 unsigned long
2464 sec_asn1d_uinteger(SECItem *src)
2465 {
2466 unsigned long value;
2467 int len;
2468
2469 if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
2470 return 0;
2471
2472 value = 0;
2473 len = src->len;
2474 while (len) {
2475 value <<= 8;
2476 value |= src->data[--len];
2477 }
2478 return value;
2479 }
2480
2481 SECStatus
2482 SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
2483 {
2484 unsigned long v;
2485 unsigned int i;
2486
2487 if (src == NULL) {
2488 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2489 return SECFailure;
2490 }
2491
2492 if (src->len > sizeof(unsigned long)) {
2493 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2494 return SECFailure;
2495 }
2496
2497 if (src->data == NULL) {
2498 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2499 return SECFailure;
2500 }
2501
2502 if (src->data[0] & 0x80)
2503 v = -1; /* signed and negative - start with all 1's */
2504 else
2505 v = 0;
2506
2507 for (i= 0; i < src->len; i++) {
2508 /* shift in next byte */
2509 v <<= 8;
2510 v |= src->data[i];
2511 }
2512 *value = v;
2513 return SECSuccess;
2514 }
2515
2516 #ifdef DEBUG_ASN1D_STATES
2517 static void
2518 dump_states(SEC_ASN1DecoderContext *cx)
2519 {
2520 sec_asn1d_state *state;
2521 char kindBuf[256];
2522
2523 for (state = cx->current; state->parent; state = state->parent) {
2524 ;
2525 }
2526
2527 for (; state; state = state->child) {
2528 int i;
2529 for (i = 0; i < state->depth; i++) {
2530 printf(" ");
2531 }
2532
2533 i = formatKind(state->theTemplate->kind, kindBuf);
2534 printf("%s: tmpl %08x, kind%s",
2535 (state == cx->current) ? "STATE" : "State",
2536 state->theTemplate,
2537 kindBuf);
2538 printf(" %s", (state->place >= 0 && state->place <= notInUse)
2539 ? place_names[ state->place ]
2540 : "(undefined)");
2541 if (!i)
2542 printf(", expect 0x%02x",
2543 state->expect_tag_number | state->expect_tag_modifiers);
2544
2545 printf("%s%s%s %d\n",
2546 state->indefinite ? ", indef" : "",
2547 state->missing ? ", miss" : "",
2548 state->endofcontents ? ", EOC" : "",
2549 state->pending
2550 );
2551 }
2552
2553 return;
2554 }
2555 #endif /* DEBUG_ASN1D_STATES */
2556
2557 SECStatus
2558 SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
2559 const char *buf, unsigned long len)
2560 {
2561 sec_asn1d_state *state = NULL;
2562 unsigned long consumed;
2563 SEC_ASN1EncodingPart what;
2564 sec_asn1d_state *stateEnd = cx->current;
2565
2566 if (cx->status == needBytes)
2567 cx->status = keepGoing;
2568
2569 while (cx->status == keepGoing) {
2570 state = cx->current;
2571 what = SEC_ASN1_Contents;
2572 consumed = 0;
2573 #ifdef DEBUG_ASN1D_STATES
2574 printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
2575 (state->place >= 0 && state->place <= notInUse) ?
2576 place_names[ state->place ] : "(undefined)",
2577 (unsigned int)((unsigned char *)buf)[ consumed ],
2578 buf, consumed);
2579 dump_states(cx);
2580 #endif /* DEBUG_ASN1D_STATES */
2581 switch (state->place) {
2582 case beforeIdentifier:
2583 consumed = sec_asn1d_parse_identifier (state, buf, len);
2584 what = SEC_ASN1_Identifier;
2585 break;
2586 case duringIdentifier:
2587 consumed = sec_asn1d_parse_more_identifier (state, buf, len);
2588 what = SEC_ASN1_Identifier;
2589 break;
2590 case afterIdentifier:
2591 sec_asn1d_confirm_identifier (state);
2592 break;
2593 case beforeLength:
2594 consumed = sec_asn1d_parse_length (state, buf, len);
2595 what = SEC_ASN1_Length;
2596 break;
2597 case duringLength:
2598 consumed = sec_asn1d_parse_more_length (state, buf, len);
2599 what = SEC_ASN1_Length;
2600 break;
2601 case afterLength:
2602 sec_asn1d_prepare_for_contents (state);
2603 break;
2604 case beforeBitString:
2605 consumed = sec_asn1d_parse_bit_string (state, buf, len);
2606 break;
2607 case duringBitString:
2608 consumed = sec_asn1d_parse_more_bit_string (state, buf, len);
2609 break;
2610 case duringConstructedString:
2611 sec_asn1d_next_substring (state);
2612 break;
2613 case duringGroup:
2614 sec_asn1d_next_in_group (state);
2615 break;
2616 case duringLeaf:
2617 consumed = sec_asn1d_parse_leaf (state, buf, len);
2618 break;
2619 case duringSaveEncoding:
2620 sec_asn1d_reuse_encoding (state);
2621 if (cx->status == decodeError) {
2622 /* recursive call has already popped all states from stack.
2623 ** Bail out quickly.
2624 */
2625 return SECFailure;
2626 }
2627 if (cx->status == needBytes) {
2628 /* recursive call wanted more data. Fatal. Clean up below. */
2629 PORT_SetError (SEC_ERROR_BAD_DER);
2630 cx->status = decodeError;
2631 }
2632 break;
2633 case duringSequence:
2634 sec_asn1d_next_in_sequence (state);
2635 break;
2636 case afterConstructedString:
2637 sec_asn1d_concat_substrings (state);
2638 break;
2639 case afterExplicit:
2640 case afterImplicit:
2641 case afterInline:
2642 case afterPointer:
2643 sec_asn1d_absorb_child (state);
2644 break;
2645 case afterGroup:
2646 sec_asn1d_concat_group (state);
2647 break;
2648 case afterSaveEncoding:
2649 /* SEC_ASN1DecoderUpdate has called itself recursively to
2650 ** decode SAVEd encoded data, and now is done decoding that.
2651 ** Return to the calling copy of SEC_ASN1DecoderUpdate.
2652 */
2653 return SECSuccess;
2654 case beforeEndOfContents:
2655 sec_asn1d_prepare_for_end_of_contents (state);
2656 break;
2657 case duringEndOfContents:
2658 consumed = sec_asn1d_parse_end_of_contents (state, buf, len);
2659 what = SEC_ASN1_EndOfContents;
2660 break;
2661 case afterEndOfContents:
2662 sec_asn1d_pop_state (state);
2663 break;
2664 case beforeChoice:
2665 state = sec_asn1d_before_choice(state);
2666 break;
2667 case duringChoice:
2668 state = sec_asn1d_during_choice(state);
2669 break;
2670 case afterChoice:
2671 sec_asn1d_after_choice(state);
2672 break;
2673 case notInUse:
2674 default:
2675 /* This is not an error, but rather a plain old BUG! */
2676 PORT_Assert (0);
2677 PORT_SetError (SEC_ERROR_BAD_DER);
2678 cx->status = decodeError;
2679 break;
2680 }
2681
2682 if (cx->status == decodeError)
2683 break;
2684
2685 /* We should not consume more than we have. */
2686 PORT_Assert (consumed <= len);
2687 if (consumed > len) {
2688 PORT_SetError (SEC_ERROR_BAD_DER);
2689 cx->status = decodeError;
2690 break;
2691 }
2692
2693 /* It might have changed, so we have to update our local copy. */
2694 state = cx->current;
2695
2696 /* If it is NULL, we have popped all the way to the top. */
2697 if (state == NULL) {
2698 PORT_Assert (consumed == 0);
2699 #if 0 /* XXX I want this here, but it seems that we have situations (like
2700 * downloading a pkcs7 cert chain from some issuers) that give us a
2701 * length which is greater than the entire encoding. So, we cannot
2702 * have this be an error.
2703 */
2704 if (len > 0) {
2705 PORT_SetError (SEC_ERROR_BAD_DER);
2706 cx->status = decodeError;
2707 } else
2708 #endif
2709 cx->status = allDone;
2710 break;
2711 }
2712 else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
2713 cx->status = allDone;
2714 break;
2715 }
2716
2717 if (consumed == 0)
2718 continue;
2719
2720 /*
2721 * The following check is specifically looking for an ANY
2722 * that is *not* also an INNER, because we need to save aside
2723 * all bytes in that case -- the contents parts will get
2724 * handled like all other contents, and the end-of-contents
2725 * bytes are added by the concat code, but the outer header
2726 * bytes need to get saved too, so we do them explicitly here.
2727 */
2728 if (state->underlying_kind == SEC_ASN1_ANY
2729 && !cx->filter_only && (what == SEC_ASN1_Identifier
2730 || what == SEC_ASN1_Length)) {
2731 sec_asn1d_record_any_header (state, buf, consumed);
2732 }
2733
2734 /*
2735 * We had some number of good, accepted bytes. If the caller
2736 * has registered to see them, pass them along.
2737 */
2738 if (state->top->filter_proc != NULL) {
2739 int depth;
2740
2741 depth = state->depth;
2742 if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
2743 PORT_Assert (state->parent != NULL
2744 && state->parent->indefinite);
2745 depth--;
2746 PORT_Assert (depth == state->parent->depth);
2747 }
2748 (* state->top->filter_proc) (state->top->filter_arg,
2749 buf, consumed, depth, what);
2750 }
2751
2752 state->consumed += consumed;
2753 buf += consumed;
2754 len -= consumed;
2755 }
2756
2757 if (cx->status == decodeError) {
2758 while (state != NULL && stateEnd->parent!=state) {
2759 sec_asn1d_free_child (state, PR_TRUE);
2760 state = state->parent;
2761 }
2762 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
2763 * XXX This does not work because we can
2764 * end up leaving behind dangling pointers
2765 * to stuff that was allocated. In order
2766 * to make this really work (which would
2767 * be a good thing, I think), we need to
2768 * keep track of every place/pointer that
2769 * was allocated and make sure to NULL it
2770 * out before we then free back to the mark.
2771 */
2772 if (cx->their_pool != NULL) {
2773 PORT_Assert (cx->their_mark != NULL);
2774 PORT_ArenaRelease (cx->their_pool, cx->their_mark);
2775 cx->their_mark = NULL;
2776 }
2777 #endif
2778 return SECFailure;
2779 }
2780
2781 #if 0 /* XXX This is what I want, but cannot have because it seems we
2782 * have situations (like when downloading a pkcs7 cert chain from
2783 * some issuers) that give us a total length which is greater than
2784 * the entire encoding. So, we have to allow allDone to have a
2785 * remaining length greater than zero. I wanted to catch internal
2786 * bugs with this, noticing when we do not have the right length.
2787 * Oh well.
2788 */
2789 PORT_Assert (len == 0
2790 && (cx->status == needBytes || cx->status == allDone));
2791 #else
2792 PORT_Assert ((len == 0 && cx->status == needBytes)
2793 || cx->status == allDone);
2794 #endif
2795 return SECSuccess;
2796 }
2797
2798
2799 SECStatus
2800 SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
2801 {
2802 SECStatus rv;
2803
2804 if (cx->status == needBytes) {
2805 PORT_SetError (SEC_ERROR_BAD_DER);
2806 rv = SECFailure;
2807 } else {
2808 rv = SECSuccess;
2809 }
2810
2811 /*
2812 * XXX anything else that needs to be finished?
2813 */
2814
2815 PORT_FreeArena (cx->our_pool, PR_TRUE);
2816
2817 return rv;
2818 }
2819
2820
2821 SEC_ASN1DecoderContext *
2822 SEC_ASN1DecoderStart (PLArenaPool *their_pool, void *dest,
2823 const SEC_ASN1Template *theTemplate)
2824 {
2825 PLArenaPool *our_pool;
2826 SEC_ASN1DecoderContext *cx;
2827
2828 our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
2829 if (our_pool == NULL)
2830 return NULL;
2831
2832 cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx));
2833 if (cx == NULL) {
2834 PORT_FreeArena (our_pool, PR_FALSE);
2835 return NULL;
2836 }
2837
2838 cx->our_pool = our_pool;
2839 if (their_pool != NULL) {
2840 cx->their_pool = their_pool;
2841 #ifdef SEC_ASN1D_FREE_ON_ERROR
2842 cx->their_mark = PORT_ArenaMark (their_pool);
2843 #endif
2844 }
2845
2846 cx->status = needBytes;
2847
2848 if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL
2849 || sec_asn1d_init_state_based_on_template (cx->current) == NULL) {
2850 /*
2851 * Trouble initializing (probably due to failed allocations)
2852 * requires that we just give up.
2853 */
2854 PORT_FreeArena (our_pool, PR_FALSE);
2855 return NULL;
2856 }
2857
2858 return cx;
2859 }
2860
2861
2862 void
2863 SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx,
2864 SEC_ASN1WriteProc fn, void *arg,
2865 PRBool only)
2866 {
2867 /* check that we are "between" fields here */
2868 PORT_Assert (cx->during_notify);
2869
2870 cx->filter_proc = fn;
2871 cx->filter_arg = arg;
2872 cx->filter_only = only;
2873 }
2874
2875
2876 void
2877 SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx)
2878 {
2879 /* check that we are "between" fields here */
2880 PORT_Assert (cx->during_notify);
2881
2882 cx->filter_proc = NULL;
2883 cx->filter_arg = NULL;
2884 cx->filter_only = PR_FALSE;
2885 }
2886
2887
2888 void
2889 SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx,
2890 SEC_ASN1NotifyProc fn, void *arg)
2891 {
2892 cx->notify_proc = fn;
2893 cx->notify_arg = arg;
2894 }
2895
2896
2897 void
2898 SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx)
2899 {
2900 cx->notify_proc = NULL;
2901 cx->notify_arg = NULL; /* not necessary; just being clean */
2902 }
2903
2904 void
2905 SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
2906 {
2907 PORT_Assert(cx);
2908 PORT_SetError(error);
2909 cx->status = decodeError;
2910 }
2911
2912
2913 SECStatus
2914 SEC_ASN1Decode (PLArenaPool *poolp, void *dest,
2915 const SEC_ASN1Template *theTemplate,
2916 const char *buf, long len)
2917 {
2918 SEC_ASN1DecoderContext *dcx;
2919 SECStatus urv, frv;
2920
2921 dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate);
2922 if (dcx == NULL)
2923 return SECFailure;
2924
2925 urv = SEC_ASN1DecoderUpdate (dcx, buf, len);
2926 frv = SEC_ASN1DecoderFinish (dcx);
2927
2928 if (urv != SECSuccess)
2929 return urv;
2930
2931 return frv;
2932 }
2933
2934
2935 SECStatus
2936 SEC_ASN1DecodeItem (PLArenaPool *poolp, void *dest,
2937 const SEC_ASN1Template *theTemplate,
2938 const SECItem *src)
2939 {
2940 return SEC_ASN1Decode (poolp, dest, theTemplate,
2941 (const char *)src->data, src->len);
2942 }
2943
2944 #ifdef DEBUG_ASN1D_STATES
2945 void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
2946 {
2947 printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
2948 fflush(stdout);
2949 }
2950 #endif
2951
2952 /*
2953 * Generic templates for individual/simple items and pointers to
2954 * and sets of same.
2955 *
2956 * If you need to add a new one, please note the following:
2957 * - For each new basic type you should add *four* templates:
2958 * one plain, one PointerTo, one SequenceOf and one SetOf.
2959 * - If the new type can be constructed (meaning, it is a
2960 * *string* type according to BER/DER rules), then you should
2961 * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
2962 * See the definition of the OctetString template for an example.
2963 * - It may not be obvious, but these are in *alphabetical*
2964 * order based on the SEC_ASN1_XXX name; so put new ones in
2965 * the appropriate place.
2966 */
2967
2968 const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
2969 { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
2970 };
2971
2972 #if 0
2973
2974 const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
2975 { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
2976 };
2977
2978 const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
2979 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
2980 };
2981
2982 const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
2983 { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
2984 };
2985
2986 const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
2987 { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
2988 };
2989
2990 const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
2991 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
2992 };
2993
2994 const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
2995 { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
2996 };
2997
2998 const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
2999 { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
3000 };
3001
3002 const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
3003 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
3004 };
3005
3006 const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
3007 { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
3008 };
3009
3010 #endif
3011
3012 const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
3013 { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
3014 };
3015
3016 const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
3017 { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
3018 };
3019
3020 #if 0
3021
3022 const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
3023 { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
3024 };
3025
3026 #endif
3027
3028 const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
3029 { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
3030 };
3031
3032 const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
3033 { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
3034 };
3035
3036 #if 0
3037
3038 const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
3039 { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
3040 };
3041
3042 const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
3043 { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
3044 };
3045
3046 const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
3047 { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
3048 };
3049
3050 const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
3051 { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
3052 };
3053
3054 const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
3055 { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
3056 };
3057
3058 const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
3059 { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
3060 };
3061
3062 const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
3063 { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
3064 };
3065
3066 const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
3067 { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
3068 };
3069
3070 const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
3071 { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
3072 };
3073
3074 const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
3075 { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
3076 };
3077
3078 const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
3079 { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
3080 };
3081
3082 const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
3083 { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
3084 };
3085
3086 #endif
3087
3088 const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
3089 { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
3090 };
3091
3092 #if 0
3093
3094 const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
3095 { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
3096 };
3097
3098 const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
3099 { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
3100 };
3101
3102 const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
3103 { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
3104 };
3105
3106 #endif
3107
3108 const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
3109 { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3110 };
3111
3112 #if 0
3113
3114 const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
3115 { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
3116 };
3117
3118 const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
3119 { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
3120 };
3121
3122 const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
3123 { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
3124 };
3125
3126 #endif
3127
3128 const SEC_ASN1Template SEC_T61StringTemplate[] = {
3129 { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3130 };
3131
3132 #if 0
3133
3134 const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
3135 { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
3136 };
3137
3138 const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
3139 { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
3140 };
3141
3142 const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
3143 { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
3144 };
3145
3146 #endif
3147
3148 const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
3149 { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3150 };
3151
3152 #if 0
3153
3154 const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
3155 { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
3156 };
3157
3158 const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
3159 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
3160 };
3161
3162 const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
3163 { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
3164 };
3165
3166 const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
3167 { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
3168 };
3169
3170 const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
3171 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
3172 };
3173
3174 const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
3175 { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
3176 };
3177
3178 const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
3179 { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
3180 };
3181
3182 const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
3183 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
3184 };
3185
3186 const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
3187 { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
3188 };
3189
3190 #endif
3191
3192 const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
3193 { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3194 };
3195
3196 #if 0
3197
3198 const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
3199 { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
3200 };
3201
3202 const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
3203 { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
3204 };
3205
3206 const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
3207 { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
3208 };
3209
3210 #endif
3211
3212 /*
3213 * Template for skipping a subitem.
3214 *
3215 * Note that it only makes sense to use this for decoding (when you want
3216 * to decode something where you are only interested in one or two of
3217 * the fields); you cannot encode a SKIP!
3218 */
3219 const SEC_ASN1Template SEC_SkipTemplate[] = {
3220 { SEC_ASN1_SKIP }
3221 };
3222
3223
3224 /* These functions simply return the address of the above-declared templates.
3225 ** This is necessary for Windows DLLs. Sigh.
3226 */
3227 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_EnumeratedTemplate)
3228 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToEnumeratedTemplate)
3229 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfAnyTemplate)
3230 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfObjectIDTemplate)
3231 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SkipTemplate)
3232 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate)
3233 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate)
3234 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate)
3235 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate)
3236
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)