1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
41 * $Id: secasn1d.c,v 1.37 2007/01/03 12:57:41 nelson%bolyard.com Exp $
44 /* #define DEBUG_ASN1D_STATES 1 */
46 #ifdef DEBUG_ASN1D_STATES
48 #define PR_Assert sec_asn1d_Assert
63 duringConstructedString
,
68 afterConstructedString
,
82 } sec_asn1d_parse_place
;
84 #ifdef DEBUG_ASN1D_STATES
85 static const char * const place_names
[] = {
94 "duringConstructedString",
99 "afterConstructedString",
106 "beforeEndOfContents",
107 "duringEndOfContents",
108 "afterEndOfContents",
115 static const char * const class_names
[] = {
122 static const char * const method_names
[] = { "PRIMITIVE", "CONSTRUCTED" };
124 static const char * const type_names
[] = {
159 static const char * const flag_names
[] = { /* flags, right to left */
170 "", /* decoder ignores "MAY_STREAM", */
182 static int /* bool */
183 formatKind(unsigned long kind
, char * buf
)
186 unsigned long k
= kind
& SEC_ASN1_TAGNUM_MASK
;
187 unsigned long notag
= kind
& (SEC_ASN1_CHOICE
| SEC_ASN1_POINTER
|
188 SEC_ASN1_INLINE
| SEC_ASN1_ANY
| SEC_ASN1_SAVE
);
191 if ((kind
& SEC_ASN1_CLASS_MASK
) != SEC_ASN1_UNIVERSAL
) {
192 sprintf(buf
, " %s", class_names
[(kind
& SEC_ASN1_CLASS_MASK
) >> 6] );
195 if (kind
& SEC_ASN1_METHOD_MASK
) {
196 sprintf(buf
, " %s", method_names
[1]);
199 if ((kind
& SEC_ASN1_CLASS_MASK
) == SEC_ASN1_UNIVERSAL
) {
201 sprintf(buf
, " %s", type_names
[k
] );
202 if ((k
== SEC_ASN1_SET
|| k
== SEC_ASN1_SEQUENCE
) &&
203 (kind
& SEC_ASN1_GROUP
)) {
209 sprintf(buf
, " [%d]", k
);
213 for (k
= kind
>> 8, i
= 0; k
; k
>>= 1, ++i
) {
215 sprintf(buf
, " %s", flag_names
[i
]);
222 #endif /* DEBUG_ASN1D_STATES */
229 } sec_asn1d_parse_status
;
233 unsigned long len
; /* only used for substrings */
234 struct subitem
*next
;
237 typedef struct sec_asn1d_state_struct
{
238 SEC_ASN1DecoderContext
*top
;
239 const SEC_ASN1Template
*theTemplate
;
242 void *our_mark
; /* free on completion */
244 struct sec_asn1d_state_struct
*parent
; /* aka prev */
245 struct sec_asn1d_state_struct
*child
; /* aka next */
247 sec_asn1d_parse_place place
;
250 * XXX explain the next fields as clearly as possible...
252 unsigned char found_tag_modifiers
;
253 unsigned char expect_tag_modifiers
;
254 unsigned long check_tag_mask
;
255 unsigned long found_tag_number
;
256 unsigned long expect_tag_number
;
257 unsigned long underlying_kind
;
259 unsigned long contents_length
;
260 unsigned long pending
;
261 unsigned long consumed
;
266 * Bit strings have their length adjusted -- the first octet of the
267 * contents contains a value between 0 and 7 which says how many bits
268 * at the end of the octets are not actually part of the bit string;
269 * when parsing bit strings we put that value here because we need it
270 * later, for adjustment of the length (when the whole string is done).
272 unsigned int bit_string_unused_bits
;
275 * The following are used for indefinite-length constructed strings.
277 struct subitem
*subitems_head
;
278 struct subitem
*subitems_tail
;
281 allocate
, /* when true, need to allocate the destination */
282 endofcontents
, /* this state ended up parsing end-of-contents octets */
283 explicit, /* we are handling an explicit header */
284 indefinite
, /* the current item has indefinite-length encoding */
285 missing
, /* an optional field that was not present */
286 optional
, /* the template says this field may be omitted */
287 substring
; /* this is a substring of a constructed string */
291 #define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
292 #define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0)
293 #define TAG_NUMBER_BITS 7
294 #define TAG_NUMBER_MASK 0x7f
296 #define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0)
297 #define LONG_FORM_LENGTH(b) ((b) & 0x7f)
299 #define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
303 * An "outsider" will have an opaque pointer to this, created by calling
304 * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent
305 * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
306 * SEC_ASN1DecoderFinish().
308 struct sec_DecoderContext_struct
{
309 PRArenaPool
*our_pool
; /* for our internal allocs */
310 PRArenaPool
*their_pool
; /* for destination structure allocs */
311 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
312 * XXX see comment below (by same
313 * ifdef) that explains why this
314 * does not work (need more smarts
315 * in order to free back to mark)
318 * XXX how to make their_mark work in the case where they do NOT
319 * give us a pool pointer?
321 void *their_mark
; /* free on error */
324 sec_asn1d_state
*current
;
325 sec_asn1d_parse_status status
;
327 SEC_ASN1NotifyProc notify_proc
; /* call before/after handling field */
328 void *notify_arg
; /* argument to notify_proc */
329 PRBool during_notify
; /* true during call to notify_proc */
331 SEC_ASN1WriteProc filter_proc
; /* pass field bytes to this */
332 void *filter_arg
; /* argument to that function */
333 PRBool filter_only
; /* do not allocate/store fields */
338 * XXX this is a fairly generic function that may belong elsewhere
341 sec_asn1d_alloc (PRArenaPool
*poolp
, unsigned long len
)
347 * Allocate from the pool.
349 thing
= PORT_ArenaAlloc (poolp
, len
);
352 * Allocate generically.
354 thing
= PORT_Alloc (len
);
362 * XXX this is a fairly generic function that may belong elsewhere
365 sec_asn1d_zalloc (PRArenaPool
*poolp
, unsigned long len
)
369 thing
= sec_asn1d_alloc (poolp
, len
);
371 PORT_Memset (thing
, 0, len
);
376 static sec_asn1d_state
*
377 sec_asn1d_push_state (SEC_ASN1DecoderContext
*cx
,
378 const SEC_ASN1Template
*theTemplate
,
379 void *dest
, PRBool new_depth
)
381 sec_asn1d_state
*state
, *new_state
;
385 PORT_Assert (state
== NULL
|| state
->child
== NULL
);
388 PORT_Assert (state
->our_mark
== NULL
);
389 state
->our_mark
= PORT_ArenaMark (cx
->our_pool
);
392 new_state
= (sec_asn1d_state
*)sec_asn1d_zalloc (cx
->our_pool
,
394 if (new_state
== NULL
) {
399 new_state
->parent
= state
;
400 new_state
->theTemplate
= theTemplate
;
401 new_state
->place
= notInUse
;
403 new_state
->dest
= (char *)dest
+ theTemplate
->offset
;
406 new_state
->depth
= state
->depth
;
408 if (++new_state
->depth
> SEC_ASN1D_MAX_DEPTH
) {
409 PORT_SetError (SEC_ERROR_BAD_DER
);
413 state
->child
= new_state
;
416 cx
->current
= new_state
;
420 cx
->status
= decodeError
;
422 PORT_ArenaRelease(cx
->our_pool
, state
->our_mark
);
423 state
->our_mark
= NULL
;
430 sec_asn1d_scrub_state (sec_asn1d_state
*state
)
433 * Some default "scrubbing".
434 * XXX right set of initializations?
436 state
->place
= beforeIdentifier
;
437 state
->endofcontents
= PR_FALSE
;
438 state
->indefinite
= PR_FALSE
;
439 state
->missing
= PR_FALSE
;
440 PORT_Assert (state
->consumed
== 0);
445 sec_asn1d_notify_before (SEC_ASN1DecoderContext
*cx
, void *dest
, int depth
)
447 if (cx
->notify_proc
== NULL
)
450 cx
->during_notify
= PR_TRUE
;
451 (* cx
->notify_proc
) (cx
->notify_arg
, PR_TRUE
, dest
, depth
);
452 cx
->during_notify
= PR_FALSE
;
457 sec_asn1d_notify_after (SEC_ASN1DecoderContext
*cx
, void *dest
, int depth
)
459 if (cx
->notify_proc
== NULL
)
462 cx
->during_notify
= PR_TRUE
;
463 (* cx
->notify_proc
) (cx
->notify_arg
, PR_FALSE
, dest
, depth
);
464 cx
->during_notify
= PR_FALSE
;
468 static sec_asn1d_state
*
469 sec_asn1d_init_state_based_on_template (sec_asn1d_state
*state
)
471 PRBool
explicit, optional
, universal
;
472 unsigned char expect_tag_modifiers
;
473 unsigned long encode_kind
, under_kind
;
474 unsigned long check_tag_mask
, expect_tag_number
;
477 /* XXX Check that both of these tests are really needed/appropriate. */
478 if (state
== NULL
|| state
->top
->status
== decodeError
)
481 encode_kind
= state
->theTemplate
->kind
;
483 if (encode_kind
& SEC_ASN1_SAVE
) {
485 * This is a "magic" field that saves away all bytes, allowing
486 * the immediately following field to still be decoded from this
487 * same spot -- sort of a fork.
489 /* check that there are no extraneous bits */
490 PORT_Assert (encode_kind
== SEC_ASN1_SAVE
);
491 if (state
->top
->filter_only
) {
493 * If we are not storing, then we do not do the SAVE field
494 * at all. Just move ahead to the "real" field instead,
495 * doing the appropriate notify calls before and after.
497 sec_asn1d_notify_after (state
->top
, state
->dest
, state
->depth
);
499 * Since we are not storing, allow for our current dest value
500 * to be NULL. (This might not actually occur, but right now I
501 * cannot convince myself one way or the other.) If it is NULL,
502 * assume that our parent dest can help us out.
504 if (state
->dest
== NULL
)
505 state
->dest
= state
->parent
->dest
;
507 state
->dest
= (char *)state
->dest
- state
->theTemplate
->offset
;
508 state
->theTemplate
++;
509 if (state
->dest
!= NULL
)
510 state
->dest
= (char *)state
->dest
+ state
->theTemplate
->offset
;
511 sec_asn1d_notify_before (state
->top
, state
->dest
, state
->depth
);
512 encode_kind
= state
->theTemplate
->kind
;
513 PORT_Assert ((encode_kind
& SEC_ASN1_SAVE
) == 0);
515 sec_asn1d_scrub_state (state
);
516 state
->place
= duringSaveEncoding
;
517 state
= sec_asn1d_push_state (state
->top
, SEC_AnyTemplate
,
518 state
->dest
, PR_FALSE
);
520 state
= sec_asn1d_init_state_based_on_template (state
);
526 universal
= ((encode_kind
& SEC_ASN1_CLASS_MASK
) == SEC_ASN1_UNIVERSAL
)
527 ? PR_TRUE
: PR_FALSE
;
529 explicit = (encode_kind
& SEC_ASN1_EXPLICIT
) ? PR_TRUE
: PR_FALSE
;
530 encode_kind
&= ~SEC_ASN1_EXPLICIT
;
532 optional
= (encode_kind
& SEC_ASN1_OPTIONAL
) ? PR_TRUE
: PR_FALSE
;
533 encode_kind
&= ~SEC_ASN1_OPTIONAL
;
535 PORT_Assert (!(explicit && universal
)); /* bad templates */
537 encode_kind
&= ~SEC_ASN1_DYNAMIC
;
538 encode_kind
&= ~SEC_ASN1_MAY_STREAM
;
540 if (encode_kind
& SEC_ASN1_CHOICE
) {
541 #if 0 /* XXX remove? */
542 sec_asn1d_state
*child
= sec_asn1d_push_state(state
->top
, state
->theTemplate
, state
->dest
, PR_FALSE
);
543 if ((sec_asn1d_state
*)NULL
== child
) {
544 return (sec_asn1d_state
*)NULL
;
547 child
->allocate
= state
->allocate
;
548 child
->place
= beforeChoice
;
551 state
->place
= beforeChoice
;
556 if ((encode_kind
& (SEC_ASN1_POINTER
| SEC_ASN1_INLINE
)) || (!universal
558 const SEC_ASN1Template
*subt
;
560 PRBool child_allocate
;
562 PORT_Assert ((encode_kind
& (SEC_ASN1_ANY
| SEC_ASN1_SKIP
)) == 0);
564 sec_asn1d_scrub_state (state
);
565 child_allocate
= PR_FALSE
;
567 if (encode_kind
& SEC_ASN1_POINTER
) {
569 * A POINTER means we need to allocate the destination for
570 * this field. But, since it may also be an optional field,
571 * we defer the allocation until later; we just record that
572 * it needs to be done.
574 * There are two possible scenarios here -- one is just a
575 * plain POINTER (kind of like INLINE, except with allocation)
576 * and the other is an implicitly-tagged POINTER. We don't
577 * need to do anything special here for the two cases, but
578 * since the template definition can be tricky, we do check
579 * that there are no extraneous bits set in encode_kind.
581 * XXX The same conditions which assert should set an error.
585 * "universal" means this entry is a standalone POINTER;
586 * there should be no other bits set in encode_kind.
588 PORT_Assert (encode_kind
== SEC_ASN1_POINTER
);
591 * If we get here we have an implicitly-tagged field
592 * that needs to be put into a POINTER. The subtemplate
593 * will determine how to decode the field, but encode_kind
594 * describes the (implicit) tag we are looking for.
595 * The non-tag bits of encode_kind will be ignored by
596 * the code below; none of them should be set, however,
597 * except for the POINTER bit itself -- so check that.
599 PORT_Assert ((encode_kind
& ~SEC_ASN1_TAG_MASK
)
600 == SEC_ASN1_POINTER
);
602 if (!state
->top
->filter_only
)
603 child_allocate
= PR_TRUE
;
605 state
->place
= afterPointer
;
608 if (encode_kind
& SEC_ASN1_INLINE
) {
609 /* check that there are no extraneous bits */
610 PORT_Assert (encode_kind
== SEC_ASN1_INLINE
&& !optional
);
611 state
->place
= afterInline
;
613 state
->place
= afterImplicit
;
617 state
->optional
= optional
;
618 subt
= SEC_ASN1GetSubtemplate (state
->theTemplate
, state
->dest
, PR_FALSE
);
619 state
= sec_asn1d_push_state (state
->top
, subt
, dest
, PR_FALSE
);
623 state
->allocate
= child_allocate
;
626 state
= sec_asn1d_init_state_based_on_template (state
);
629 * If this field is optional, we need to record that on
630 * the pushed child so it won't fail if the field isn't
631 * found. I can't think of a way that this new state
632 * could already have optional set (which we would wipe
633 * out below if our local optional is not set) -- but
634 * just to be sure, assert that it isn't set.
636 PORT_Assert (!state
->optional
);
637 state
->optional
= optional
;
642 under_kind
= state
->theTemplate
->kind
;
643 under_kind
&= ~SEC_ASN1_MAY_STREAM
;
644 } else if (explicit) {
646 * For explicit, we only need to match the encoding tag next,
647 * then we will push another state to handle the entire inner
648 * part. In this case, there is no underlying kind which plays
649 * any part in the determination of the outer, explicit tag.
650 * So we just set under_kind to 0, which is not a valid tag,
651 * and the rest of the tag matching stuff should be okay.
656 * Nothing special; the underlying kind and the given encoding
657 * information are the same.
659 under_kind
= encode_kind
;
662 /* XXX is this the right set of bits to test here? */
663 PORT_Assert ((under_kind
& (SEC_ASN1_EXPLICIT
| SEC_ASN1_OPTIONAL
664 | SEC_ASN1_MAY_STREAM
665 | SEC_ASN1_INLINE
| SEC_ASN1_POINTER
)) == 0);
667 if (encode_kind
& (SEC_ASN1_ANY
| SEC_ASN1_SKIP
)) {
668 PORT_Assert (encode_kind
== under_kind
);
669 if (encode_kind
& SEC_ASN1_SKIP
) {
670 PORT_Assert (!optional
);
671 PORT_Assert (encode_kind
== SEC_ASN1_SKIP
);
675 expect_tag_modifiers
= 0;
676 expect_tag_number
= 0;
678 check_tag_mask
= SEC_ASN1_TAG_MASK
;
679 expect_tag_modifiers
= (unsigned char)encode_kind
& SEC_ASN1_TAG_MASK
680 & ~SEC_ASN1_TAGNUM_MASK
;
682 * XXX This assumes only single-octet identifiers. To handle
683 * the HIGH TAG form we would need to do some more work, especially
684 * in how to specify them in the template, because right now we
685 * do not provide a way to specify more *tag* bits in encode_kind.
687 expect_tag_number
= encode_kind
& SEC_ASN1_TAGNUM_MASK
;
689 switch (under_kind
& SEC_ASN1_TAGNUM_MASK
) {
692 * XXX A plain old SET (as opposed to a SET OF) is not implemented.
693 * If it ever is, remove this assert...
695 PORT_Assert ((under_kind
& SEC_ASN1_GROUP
) != 0);
697 case SEC_ASN1_SEQUENCE
:
698 expect_tag_modifiers
|= SEC_ASN1_CONSTRUCTED
;
700 case SEC_ASN1_BIT_STRING
:
701 case SEC_ASN1_BMP_STRING
:
702 case SEC_ASN1_GENERALIZED_TIME
:
703 case SEC_ASN1_IA5_STRING
:
704 case SEC_ASN1_OCTET_STRING
:
705 case SEC_ASN1_PRINTABLE_STRING
:
706 case SEC_ASN1_T61_STRING
:
707 case SEC_ASN1_UNIVERSAL_STRING
:
708 case SEC_ASN1_UTC_TIME
:
709 case SEC_ASN1_UTF8_STRING
:
710 case SEC_ASN1_VISIBLE_STRING
:
711 check_tag_mask
&= ~SEC_ASN1_CONSTRUCTED
;
716 state
->check_tag_mask
= check_tag_mask
;
717 state
->expect_tag_modifiers
= expect_tag_modifiers
;
718 state
->expect_tag_number
= expect_tag_number
;
719 state
->underlying_kind
= under_kind
;
720 state
->explicit = explicit;
721 state
->optional
= optional
;
723 sec_asn1d_scrub_state (state
);
728 static sec_asn1d_state
*
729 sec_asn1d_get_enclosing_construct(sec_asn1d_state
*state
)
731 for (state
= state
->parent
; state
; state
= state
->parent
) {
732 sec_asn1d_parse_place place
= state
->place
;
733 if (place
!= afterImplicit
&&
734 place
!= afterPointer
&&
735 place
!= afterInline
&&
736 place
!= afterSaveEncoding
&&
737 place
!= duringSaveEncoding
&&
738 place
!= duringChoice
) {
740 /* we've walked up the stack to a state that represents
741 ** the enclosing construct.
750 sec_asn1d_parent_allows_EOC(sec_asn1d_state
*state
)
752 /* get state of enclosing construct. */
753 state
= sec_asn1d_get_enclosing_construct(state
);
755 sec_asn1d_parse_place place
= state
->place
;
756 /* Is it one of the types that permits an unexpected EOC? */
758 (place
== duringGroup
||
759 place
== duringConstructedString
||
760 state
->child
->optional
);
761 return (state
->indefinite
&& eoc_permitted
) ? PR_TRUE
: PR_FALSE
;
767 sec_asn1d_parse_identifier (sec_asn1d_state
*state
,
768 const char *buf
, unsigned long len
)
771 unsigned char tag_number
;
773 PORT_Assert (state
->place
== beforeIdentifier
);
776 state
->top
->status
= needBytes
;
780 byte
= (unsigned char) *buf
;
781 #ifdef DEBUG_ASN1D_STATES
784 formatKind(byte
, kindBuf
);
785 printf("Found tag %02x %s\n", byte
, kindBuf
);
788 tag_number
= byte
& SEC_ASN1_TAGNUM_MASK
;
790 if (IS_HIGH_TAG_NUMBER (tag_number
)) {
791 state
->place
= duringIdentifier
;
792 state
->found_tag_number
= 0;
794 * Actually, we have no idea how many bytes are pending, but we
795 * do know that it is at least 1. That is all we know; we have
796 * to look at each byte to know if there is another, etc.
800 if (byte
== 0 && sec_asn1d_parent_allows_EOC(state
)) {
802 * Our parent has indefinite-length encoding, and the
803 * entire tag found is 0, so it seems that we have hit the
804 * end-of-contents octets. To handle this, we just change
805 * our state to that which expects to get the bytes of the
806 * end-of-contents octets and let that code re-read this byte
807 * so that our categorization of field types is correct.
808 * After that, our parent will then deal with everything else.
810 state
->place
= duringEndOfContents
;
812 state
->found_tag_number
= 0;
813 state
->found_tag_modifiers
= 0;
815 * We might be an optional field that is, as we now find out,
816 * missing. Give our parent a clue that this happened.
819 state
->missing
= PR_TRUE
;
822 state
->place
= afterIdentifier
;
823 state
->found_tag_number
= tag_number
;
825 state
->found_tag_modifiers
= byte
& ~SEC_ASN1_TAGNUM_MASK
;
832 sec_asn1d_parse_more_identifier (sec_asn1d_state
*state
,
833 const char *buf
, unsigned long len
)
838 PORT_Assert (state
->pending
== 1);
839 PORT_Assert (state
->place
== duringIdentifier
);
842 state
->top
->status
= needBytes
;
848 while (len
&& state
->pending
) {
849 if (HIGH_BITS (state
->found_tag_number
, TAG_NUMBER_BITS
) != 0) {
851 * The given high tag number overflows our container;
852 * just give up. This is not likely to *ever* happen.
854 PORT_SetError (SEC_ERROR_BAD_DER
);
855 state
->top
->status
= decodeError
;
859 state
->found_tag_number
<<= TAG_NUMBER_BITS
;
861 byte
= (unsigned char) buf
[count
++];
862 state
->found_tag_number
|= (byte
& TAG_NUMBER_MASK
);
865 if (LAST_TAG_NUMBER_BYTE (byte
))
869 if (state
->pending
== 0)
870 state
->place
= afterIdentifier
;
877 sec_asn1d_confirm_identifier (sec_asn1d_state
*state
)
881 PORT_Assert (state
->place
== afterIdentifier
);
883 match
= (PRBool
)(((state
->found_tag_modifiers
& state
->check_tag_mask
)
884 == state
->expect_tag_modifiers
)
885 && ((state
->found_tag_number
& state
->check_tag_mask
)
886 == state
->expect_tag_number
));
888 state
->place
= beforeLength
;
890 if (state
->optional
) {
891 state
->missing
= PR_TRUE
;
892 state
->place
= afterEndOfContents
;
894 PORT_SetError (SEC_ERROR_BAD_DER
);
895 state
->top
->status
= decodeError
;
902 sec_asn1d_parse_length (sec_asn1d_state
*state
,
903 const char *buf
, unsigned long len
)
907 PORT_Assert (state
->place
== beforeLength
);
910 state
->top
->status
= needBytes
;
915 * The default/likely outcome. It may get adjusted below.
917 state
->place
= afterLength
;
919 byte
= (unsigned char) *buf
;
921 if (LENGTH_IS_SHORT_FORM (byte
)) {
922 state
->contents_length
= byte
;
924 state
->contents_length
= 0;
925 state
->pending
= LONG_FORM_LENGTH (byte
);
926 if (state
->pending
== 0) {
927 state
->indefinite
= PR_TRUE
;
929 state
->place
= duringLength
;
933 /* If we're parsing an ANY, SKIP, or SAVE template, and
934 ** the object being saved is definite length encoded and constructed,
935 ** there's no point in decoding that construct's members.
936 ** So, just forget it's constructed and treat it as primitive.
937 ** (SAVE appears as an ANY at this point)
939 if (!state
->indefinite
&&
940 (state
->underlying_kind
& (SEC_ASN1_ANY
| SEC_ASN1_SKIP
))) {
941 state
->found_tag_modifiers
&= ~SEC_ASN1_CONSTRUCTED
;
949 sec_asn1d_parse_more_length (sec_asn1d_state
*state
,
950 const char *buf
, unsigned long len
)
954 PORT_Assert (state
->pending
> 0);
955 PORT_Assert (state
->place
== duringLength
);
958 state
->top
->status
= needBytes
;
964 while (len
&& state
->pending
) {
965 if (HIGH_BITS (state
->contents_length
, 9) != 0) {
967 * The given full content length overflows our container;
970 PORT_SetError (SEC_ERROR_BAD_DER
);
971 state
->top
->status
= decodeError
;
975 state
->contents_length
<<= 8;
976 state
->contents_length
|= (unsigned char) buf
[count
++];
982 if (state
->pending
== 0)
983 state
->place
= afterLength
;
990 sec_asn1d_prepare_for_contents (sec_asn1d_state
*state
)
994 unsigned long alloc_len
;
996 #ifdef DEBUG_ASN1D_STATES
998 printf("Found Length %d %s\n", state
->contents_length
,
999 state
->indefinite
? "indefinite" : "");
1004 * XXX I cannot decide if this allocation should exclude the case
1005 * where state->endofcontents is true -- figure it out!
1007 if (state
->allocate
) {
1010 PORT_Assert (state
->dest
== NULL
);
1012 * We are handling a POINTER or a member of a GROUP, and need to
1013 * allocate for the data structure.
1015 dest
= sec_asn1d_zalloc (state
->top
->their_pool
,
1016 state
->theTemplate
->size
);
1018 state
->top
->status
= decodeError
;
1021 state
->dest
= (char *)dest
+ state
->theTemplate
->offset
;
1024 * For a member of a GROUP, our parent will later put the
1025 * pointer wherever it belongs. But for a POINTER, we need
1026 * to record the destination now, in case notify or filter
1027 * procs need access to it -- they cannot find it otherwise,
1028 * until it is too late (for one-pass processing).
1030 if (state
->parent
->place
== afterPointer
) {
1033 placep
= state
->parent
->dest
;
1039 * Remember, length may be indefinite here! In that case,
1040 * both contents_length and pending will be zero.
1042 state
->pending
= state
->contents_length
;
1044 /* If this item has definite length encoding, and
1045 ** is enclosed by a definite length constructed type,
1046 ** make sure it isn't longer than the remaining space in that
1047 ** constructed type.
1049 if (state
->contents_length
> 0) {
1050 sec_asn1d_state
*parent
= sec_asn1d_get_enclosing_construct(state
);
1051 if (parent
&& !parent
->indefinite
&&
1052 state
->consumed
+ state
->contents_length
> parent
->pending
) {
1053 PORT_SetError (SEC_ERROR_BAD_DER
);
1054 state
->top
->status
= decodeError
;
1060 * An EXPLICIT is nothing but an outer header, which we have
1061 * already parsed and accepted. Now we need to do the inner
1062 * header and its contents.
1064 if (state
->explicit) {
1065 state
->place
= afterExplicit
;
1066 state
= sec_asn1d_push_state (state
->top
,
1067 SEC_ASN1GetSubtemplate(state
->theTemplate
,
1070 state
->dest
, PR_TRUE
);
1072 state
= sec_asn1d_init_state_based_on_template (state
);
1077 * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
1078 * we cannot tell how many items we will end up with ... so push a
1079 * state that can keep track of "children" (the individual members
1080 * of the group; we will allocate as we go and put them all together
1083 if (state
->underlying_kind
& SEC_ASN1_GROUP
) {
1084 /* XXX If this assertion holds (should be able to confirm it via
1085 * inspection, too) then move this code into the switch statement
1086 * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
1088 PORT_Assert (state
->underlying_kind
== SEC_ASN1_SET_OF
1089 || state
->underlying_kind
== SEC_ASN1_SEQUENCE_OF
1090 || state
->underlying_kind
== (SEC_ASN1_SEQUENCE_OF
|SEC_ASN1_DYNAMIC
)
1091 || state
->underlying_kind
== (SEC_ASN1_SEQUENCE_OF
|SEC_ASN1_DYNAMIC
)
1093 if (state
->contents_length
!= 0 || state
->indefinite
) {
1094 const SEC_ASN1Template
*subt
;
1096 state
->place
= duringGroup
;
1097 subt
= SEC_ASN1GetSubtemplate (state
->theTemplate
, state
->dest
,
1099 state
= sec_asn1d_push_state (state
->top
, subt
, NULL
, PR_TRUE
);
1100 if (state
!= NULL
) {
1101 if (!state
->top
->filter_only
)
1102 state
->allocate
= PR_TRUE
; /* XXX propogate this? */
1104 * Do the "before" field notification for next in group.
1106 sec_asn1d_notify_before (state
->top
, state
->dest
, state
->depth
);
1107 state
= sec_asn1d_init_state_based_on_template (state
);
1111 * A group of zero; we are done.
1112 * Set state to afterGroup and let that code plant the NULL.
1114 state
->place
= afterGroup
;
1119 switch (state
->underlying_kind
) {
1120 case SEC_ASN1_SEQUENCE
:
1122 * We need to push a child to handle the individual fields.
1124 state
->place
= duringSequence
;
1125 state
= sec_asn1d_push_state (state
->top
, state
->theTemplate
+ 1,
1126 state
->dest
, PR_TRUE
);
1127 if (state
!= NULL
) {
1129 * Do the "before" field notification.
1131 sec_asn1d_notify_before (state
->top
, state
->dest
, state
->depth
);
1132 state
= sec_asn1d_init_state_based_on_template (state
);
1136 case SEC_ASN1_SET
: /* XXX SET is not really implemented */
1138 * XXX A plain SET requires special handling; scanning of a
1139 * template to see where a field should go (because by definition,
1140 * they are not in any particular order, and you have to look at
1141 * each tag to disambiguate what the field is). We may never
1142 * implement this because in practice, it seems to be unused.
1145 PORT_SetError (SEC_ERROR_BAD_DER
); /* XXX */
1146 state
->top
->status
= decodeError
;
1151 * The NULL type, by definition, is "nothing", content length of zero.
1152 * An indefinite-length encoding is not alloweed.
1154 if (state
->contents_length
|| state
->indefinite
) {
1155 PORT_SetError (SEC_ERROR_BAD_DER
);
1156 state
->top
->status
= decodeError
;
1159 if (state
->dest
!= NULL
) {
1160 item
= (SECItem
*)(state
->dest
);
1164 state
->place
= afterEndOfContents
;
1167 case SEC_ASN1_BMP_STRING
:
1168 /* Error if length is not divisable by 2 */
1169 if (state
->contents_length
% 2) {
1170 PORT_SetError (SEC_ERROR_BAD_DER
);
1171 state
->top
->status
= decodeError
;
1174 /* otherwise, handle as other string types */
1175 goto regular_string_type
;
1177 case SEC_ASN1_UNIVERSAL_STRING
:
1178 /* Error if length is not divisable by 4 */
1179 if (state
->contents_length
% 4) {
1180 PORT_SetError (SEC_ERROR_BAD_DER
);
1181 state
->top
->status
= decodeError
;
1184 /* otherwise, handle as other string types */
1185 goto regular_string_type
;
1189 case SEC_ASN1_ANY_CONTENTS
:
1191 * These are not (necessarily) strings, but they need nearly
1192 * identical handling (especially when we need to deal with
1193 * constructed sub-pieces), so we pretend they are.
1196 regular_string_type
:
1197 case SEC_ASN1_BIT_STRING
:
1198 case SEC_ASN1_IA5_STRING
:
1199 case SEC_ASN1_OCTET_STRING
:
1200 case SEC_ASN1_PRINTABLE_STRING
:
1201 case SEC_ASN1_T61_STRING
:
1202 case SEC_ASN1_UTC_TIME
:
1203 case SEC_ASN1_UTF8_STRING
:
1204 case SEC_ASN1_VISIBLE_STRING
:
1206 * We are allocating for a primitive or a constructed string.
1207 * If it is a constructed string, it may also be indefinite-length.
1208 * If it is primitive, the length can (legally) be zero.
1209 * Our first order of business is to allocate the memory for
1210 * the string, if we can (if we know the length).
1212 item
= (SECItem
*)(state
->dest
);
1215 * If the item is a definite-length constructed string, then
1216 * the contents_length is actually larger than what we need
1217 * (because it also counts each intermediate header which we
1218 * will be throwing away as we go), but it is a perfectly good
1219 * upper bound that we just allocate anyway, and then concat
1220 * as we go; we end up wasting a few extra bytes but save a
1223 alloc_len
= state
->contents_length
;
1224 poolp
= NULL
; /* quiet compiler warnings about unused... */
1226 if (item
== NULL
|| state
->top
->filter_only
) {
1232 } else if (state
->substring
) {
1234 * If we are a substring of a constructed string, then we may
1235 * not have to allocate anything (because our parent, the
1236 * actual constructed string, did it for us). If we are a
1237 * substring and we *do* have to allocate, that means our
1238 * parent is an indefinite-length, so we allocate from our pool;
1239 * later our parent will copy our string into the aggregated
1240 * whole and free our pool allocation.
1242 if (item
->data
== NULL
) {
1243 PORT_Assert (item
->len
== 0);
1244 poolp
= state
->top
->our_pool
;
1251 poolp
= state
->top
->their_pool
;
1254 if (alloc_len
|| ((! state
->indefinite
)
1255 && (state
->subitems_head
!= NULL
))) {
1256 struct subitem
*subitem
;
1261 PORT_SetError (SEC_ERROR_BAD_DER
);
1262 state
->top
->status
= decodeError
;
1265 PORT_Assert (item
->len
== 0 && item
->data
== NULL
);
1267 * Check for and handle an ANY which has stashed aside the
1268 * header (identifier and length) bytes for us to include
1269 * in the saved contents.
1271 if (state
->subitems_head
!= NULL
) {
1272 PORT_Assert (state
->underlying_kind
== SEC_ASN1_ANY
);
1273 for (subitem
= state
->subitems_head
;
1274 subitem
!= NULL
; subitem
= subitem
->next
)
1275 alloc_len
+= subitem
->len
;
1278 item
->data
= (unsigned char*)sec_asn1d_zalloc (poolp
, alloc_len
);
1279 if (item
->data
== NULL
) {
1280 state
->top
->status
= decodeError
;
1285 for (subitem
= state
->subitems_head
;
1286 subitem
!= NULL
; subitem
= subitem
->next
) {
1287 PORT_Memcpy (item
->data
+ len
, subitem
->data
, subitem
->len
);
1288 len
+= subitem
->len
;
1293 * Because we use arenas and have a mark set, we later free
1294 * everything we have allocated, so this does *not* present
1295 * a memory leak (it is just temporarily left dangling).
1297 state
->subitems_head
= state
->subitems_tail
= NULL
;
1300 if (state
->contents_length
== 0 && (! state
->indefinite
)) {
1302 * A zero-length simple or constructed string; we are done.
1304 state
->place
= afterEndOfContents
;
1305 } else if (state
->found_tag_modifiers
& SEC_ASN1_CONSTRUCTED
) {
1306 const SEC_ASN1Template
*sub
;
1308 switch (state
->underlying_kind
) {
1310 case SEC_ASN1_ANY_CONTENTS
:
1311 sub
= SEC_AnyTemplate
;
1313 case SEC_ASN1_BIT_STRING
:
1314 sub
= SEC_BitStringTemplate
;
1316 case SEC_ASN1_BMP_STRING
:
1317 sub
= SEC_BMPStringTemplate
;
1319 case SEC_ASN1_GENERALIZED_TIME
:
1320 sub
= SEC_GeneralizedTimeTemplate
;
1322 case SEC_ASN1_IA5_STRING
:
1323 sub
= SEC_IA5StringTemplate
;
1325 case SEC_ASN1_OCTET_STRING
:
1326 sub
= SEC_OctetStringTemplate
;
1328 case SEC_ASN1_PRINTABLE_STRING
:
1329 sub
= SEC_PrintableStringTemplate
;
1331 case SEC_ASN1_T61_STRING
:
1332 sub
= SEC_T61StringTemplate
;
1334 case SEC_ASN1_UNIVERSAL_STRING
:
1335 sub
= SEC_UniversalStringTemplate
;
1337 case SEC_ASN1_UTC_TIME
:
1338 sub
= SEC_UTCTimeTemplate
;
1340 case SEC_ASN1_UTF8_STRING
:
1341 sub
= SEC_UTF8StringTemplate
;
1343 case SEC_ASN1_VISIBLE_STRING
:
1344 sub
= SEC_VisibleStringTemplate
;
1347 sub
= SEC_SkipTemplate
;
1349 default: /* redundant given outer switch cases, but */
1350 PORT_Assert(0); /* the compiler does not seem to know that, */
1351 sub
= NULL
; /* so just do enough to quiet it. */
1355 state
->place
= duringConstructedString
;
1356 state
= sec_asn1d_push_state (state
->top
, sub
, item
, PR_TRUE
);
1357 if (state
!= NULL
) {
1358 state
->substring
= PR_TRUE
; /* XXX propogate? */
1359 state
= sec_asn1d_init_state_based_on_template (state
);
1361 } else if (state
->indefinite
) {
1363 * An indefinite-length string *must* be constructed!
1365 PORT_SetError (SEC_ERROR_BAD_DER
);
1366 state
->top
->status
= decodeError
;
1369 * A non-zero-length simple string.
1371 if (state
->underlying_kind
== SEC_ASN1_BIT_STRING
)
1372 state
->place
= beforeBitString
;
1374 state
->place
= duringLeaf
;
1380 * We are allocating for a simple leaf item.
1382 if (state
->contents_length
) {
1383 if (state
->dest
!= NULL
) {
1384 item
= (SECItem
*)(state
->dest
);
1386 if (state
->top
->filter_only
) {
1389 item
->data
= (unsigned char*)
1390 sec_asn1d_zalloc (state
->top
->their_pool
,
1391 state
->contents_length
);
1392 if (item
->data
== NULL
) {
1393 state
->top
->status
= decodeError
;
1398 state
->place
= duringLeaf
;
1401 * An indefinite-length or zero-length item is not allowed.
1402 * (All legal cases of such were handled above.)
1404 PORT_SetError (SEC_ERROR_BAD_DER
);
1405 state
->top
->status
= decodeError
;
1412 sec_asn1d_free_child (sec_asn1d_state
*state
, PRBool error
)
1414 if (state
->child
!= NULL
) {
1415 PORT_Assert (error
|| state
->child
->consumed
== 0);
1416 PORT_Assert (state
->our_mark
!= NULL
);
1417 PORT_ArenaZRelease (state
->top
->our_pool
, state
->our_mark
);
1418 if (error
&& state
->top
->their_pool
== NULL
) {
1420 * XXX We need to free anything allocated.
1421 * At this point, we failed in the middle of decoding. But we
1422 * can't free the data we previously allocated with PR_Malloc
1423 * unless we keep track of every pointer. So instead we have a
1424 * memory leak when decoding fails half-way, unless an arena is
1425 * used. See bug 95311 .
1428 state
->child
= NULL
;
1429 state
->our_mark
= NULL
;
1432 * It is important that we do not leave a mark unreleased/unmarked.
1433 * But I do not think we should ever have one set in this case, only
1434 * if we had a child (handled above). So check for that. If this
1435 * assertion should ever get hit, then we probably need to add code
1436 * here to release back to our_mark (and then set our_mark to NULL).
1438 PORT_Assert (state
->our_mark
== NULL
);
1440 state
->place
= beforeEndOfContents
;
1443 /* We have just saved an entire encoded ASN.1 object (type) for a SAVE
1444 ** template, and now in the next template, we are going to decode that
1445 ** saved data by calling SEC_ASN1DecoderUpdate recursively.
1446 ** If that recursive call fails with needBytes, it is a fatal error,
1447 ** because the encoded object should have been complete.
1448 ** If that recursive call fails with decodeError, it will have already
1449 ** cleaned up the state stack, so we must bail out quickly.
1451 ** These checks of the status returned by the recursive call are now
1452 ** done in the caller of this function, immediately after it returns.
1455 sec_asn1d_reuse_encoding (sec_asn1d_state
*state
)
1457 sec_asn1d_state
*child
;
1458 unsigned long consumed
;
1463 child
= state
->child
;
1464 PORT_Assert (child
!= NULL
);
1466 consumed
= child
->consumed
;
1467 child
->consumed
= 0;
1469 item
= (SECItem
*)(state
->dest
);
1470 PORT_Assert (item
!= NULL
);
1472 PORT_Assert (item
->len
== consumed
);
1475 * Free any grandchild.
1477 sec_asn1d_free_child (child
, PR_FALSE
);
1480 * Notify after the SAVE field.
1482 sec_asn1d_notify_after (state
->top
, state
->dest
, state
->depth
);
1485 * Adjust to get new dest and move forward.
1487 dest
= (char *)state
->dest
- state
->theTemplate
->offset
;
1488 state
->theTemplate
++;
1489 child
->dest
= (char *)dest
+ state
->theTemplate
->offset
;
1490 child
->theTemplate
= state
->theTemplate
;
1493 * Notify before the "real" field.
1495 PORT_Assert (state
->depth
== child
->depth
);
1496 sec_asn1d_notify_before (state
->top
, child
->dest
, child
->depth
);
1499 * This will tell DecoderUpdate to return when it is done.
1501 state
->place
= afterSaveEncoding
;
1504 * We already have a child; "push" it by making it current.
1506 state
->top
->current
= child
;
1509 * And initialize it so it is ready to parse.
1511 (void) sec_asn1d_init_state_based_on_template(child
);
1514 * Now parse that out of our data.
1516 if (SEC_ASN1DecoderUpdate (state
->top
,
1517 (char *) item
->data
, item
->len
) != SECSuccess
)
1519 if (state
->top
->status
== needBytes
) {
1523 PORT_Assert (state
->top
->current
== state
);
1524 PORT_Assert (state
->child
== child
);
1527 * That should have consumed what we consumed before.
1529 PORT_Assert (consumed
== child
->consumed
);
1530 child
->consumed
= 0;
1535 state
->consumed
+= consumed
;
1536 child
->place
= notInUse
;
1537 state
->place
= afterEndOfContents
;
1541 static unsigned long
1542 sec_asn1d_parse_leaf (sec_asn1d_state
*state
,
1543 const char *buf
, unsigned long len
)
1546 unsigned long bufLen
;
1549 state
->top
->status
= needBytes
;
1553 if (state
->pending
< len
)
1554 len
= state
->pending
;
1558 item
= (SECItem
*)(state
->dest
);
1559 if (item
!= NULL
&& item
->data
!= NULL
) {
1560 /* Strip leading zeroes when target is unsigned integer */
1561 if (state
->underlying_kind
== SEC_ASN1_INTEGER
&& /* INTEGER */
1562 item
->len
== 0 && /* MSB */
1563 item
->type
== siUnsignedInteger
) /* unsigned */
1565 while (len
> 1 && buf
[0] == 0) { /* leading 0 */
1570 PORT_Memcpy (item
->data
+ item
->len
, buf
, len
);
1573 state
->pending
-= bufLen
;
1574 if (state
->pending
== 0)
1575 state
->place
= beforeEndOfContents
;
1581 static unsigned long
1582 sec_asn1d_parse_bit_string (sec_asn1d_state
*state
,
1583 const char *buf
, unsigned long len
)
1587 /*PORT_Assert (state->pending > 0); */
1588 PORT_Assert (state
->place
== beforeBitString
);
1590 if (state
->pending
== 0) {
1591 if (state
->dest
!= NULL
) {
1592 SECItem
*item
= (SECItem
*)(state
->dest
);
1595 state
->place
= beforeEndOfContents
;
1601 state
->top
->status
= needBytes
;
1605 byte
= (unsigned char) *buf
;
1607 PORT_SetError (SEC_ERROR_BAD_DER
);
1608 state
->top
->status
= decodeError
;
1612 state
->bit_string_unused_bits
= byte
;
1613 state
->place
= duringBitString
;
1614 state
->pending
-= 1;
1620 static unsigned long
1621 sec_asn1d_parse_more_bit_string (sec_asn1d_state
*state
,
1622 const char *buf
, unsigned long len
)
1624 PORT_Assert (state
->place
== duringBitString
);
1625 if (state
->pending
== 0) {
1626 /* An empty bit string with some unused bits is invalid. */
1627 if (state
->bit_string_unused_bits
) {
1628 PORT_SetError (SEC_ERROR_BAD_DER
);
1629 state
->top
->status
= decodeError
;
1631 /* An empty bit string with no unused bits is OK. */
1632 state
->place
= beforeEndOfContents
;
1637 len
= sec_asn1d_parse_leaf (state
, buf
, len
);
1638 if (state
->place
== beforeEndOfContents
&& state
->dest
!= NULL
) {
1641 item
= (SECItem
*)(state
->dest
);
1643 item
->len
= (item
->len
<< 3) - state
->bit_string_unused_bits
;
1651 * XXX All callers should be looking at return value to detect
1652 * out-of-memory errors (and stop!).
1654 static struct subitem
*
1655 sec_asn1d_add_to_subitems (sec_asn1d_state
*state
,
1656 const void *data
, unsigned long len
,
1659 struct subitem
*thing
;
1661 thing
= (struct subitem
*)sec_asn1d_zalloc (state
->top
->our_pool
,
1662 sizeof (struct subitem
));
1663 if (thing
== NULL
) {
1664 state
->top
->status
= decodeError
;
1670 copy
= sec_asn1d_alloc (state
->top
->our_pool
, len
);
1672 state
->top
->status
= decodeError
;
1673 if (!state
->top
->our_pool
)
1677 PORT_Memcpy (copy
, data
, len
);
1685 if (state
->subitems_head
== NULL
) {
1686 PORT_Assert (state
->subitems_tail
== NULL
);
1687 state
->subitems_head
= state
->subitems_tail
= thing
;
1689 state
->subitems_tail
->next
= thing
;
1690 state
->subitems_tail
= thing
;
1698 sec_asn1d_record_any_header (sec_asn1d_state
*state
,
1704 item
= (SECItem
*)(state
->dest
);
1705 if (item
!= NULL
&& item
->data
!= NULL
) {
1706 PORT_Assert (state
->substring
);
1707 PORT_Memcpy (item
->data
+ item
->len
, buf
, len
);
1710 sec_asn1d_add_to_subitems (state
, buf
, len
, PR_TRUE
);
1716 * We are moving along through the substrings of a constructed string,
1717 * and have just finished parsing one -- we need to save our child data
1718 * (if the child was not already writing directly into the destination)
1719 * and then move forward by one.
1721 * We also have to detect when we are done:
1722 * - a definite-length encoding stops when our pending value hits 0
1723 * - an indefinite-length encoding stops when our child is empty
1724 * (which means it was the end-of-contents octets)
1727 sec_asn1d_next_substring (sec_asn1d_state
*state
)
1729 sec_asn1d_state
*child
;
1731 unsigned long child_consumed
;
1734 PORT_Assert (state
->place
== duringConstructedString
);
1735 PORT_Assert (state
->child
!= NULL
);
1737 child
= state
->child
;
1739 child_consumed
= child
->consumed
;
1740 child
->consumed
= 0;
1741 state
->consumed
+= child_consumed
;
1745 if (state
->pending
) {
1746 PORT_Assert (!state
->indefinite
);
1747 if (child_consumed
> state
->pending
) {
1748 PORT_SetError (SEC_ERROR_BAD_DER
);
1749 state
->top
->status
= decodeError
;
1753 state
->pending
-= child_consumed
;
1754 if (state
->pending
== 0)
1757 PORT_Assert (state
->indefinite
);
1759 item
= (SECItem
*)(child
->dest
);
1760 if (item
!= NULL
&& item
->data
!= NULL
) {
1762 * Save the string away for later concatenation.
1764 PORT_Assert (item
->data
!= NULL
);
1765 sec_asn1d_add_to_subitems (state
, item
->data
, item
->len
, PR_FALSE
);
1767 * Clear the child item for the next round.
1774 * If our child was just our end-of-contents octets, we are done.
1776 if (child
->endofcontents
)
1781 * Stop or do the next one.
1784 child
->place
= notInUse
;
1785 state
->place
= afterConstructedString
;
1787 sec_asn1d_scrub_state (child
);
1788 state
->top
->current
= child
;
1794 * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
1797 sec_asn1d_next_in_group (sec_asn1d_state
*state
)
1799 sec_asn1d_state
*child
;
1800 unsigned long child_consumed
;
1802 PORT_Assert (state
->place
== duringGroup
);
1803 PORT_Assert (state
->child
!= NULL
);
1805 child
= state
->child
;
1807 child_consumed
= child
->consumed
;
1808 child
->consumed
= 0;
1809 state
->consumed
+= child_consumed
;
1812 * If our child was just our end-of-contents octets, we are done.
1814 if (child
->endofcontents
) {
1815 /* XXX I removed the PORT_Assert (child->dest == NULL) because there
1816 * was a bug in that a template that was a sequence of which also had
1817 * a child of a sequence of, in an indefinite group was not working
1818 * properly. This fix seems to work, (added the if statement below),
1819 * and nothing appears broken, but I am putting this note here just
1822 * XXX No matter how many times I read that comment,
1823 * I cannot figure out what case he was fixing. I believe what he
1824 * did was deliberate, so I am loathe to touch it. I need to
1825 * understand how it could ever be that child->dest != NULL but
1826 * child->endofcontents is true, and why it is important to check
1827 * that state->subitems_head is NULL. This really needs to be
1828 * figured out, as I am not sure if the following code should be
1829 * compensating for "offset", as is done a little farther below
1830 * in the more normal case.
1832 PORT_Assert (state
->indefinite
);
1833 PORT_Assert (state
->pending
== 0);
1834 if(child
->dest
&& !state
->subitems_head
) {
1835 sec_asn1d_add_to_subitems (state
, child
->dest
, 0, PR_FALSE
);
1839 child
->place
= notInUse
;
1840 state
->place
= afterGroup
;
1845 * Do the "after" field notification for next in group.
1847 sec_asn1d_notify_after (state
->top
, child
->dest
, child
->depth
);
1850 * Save it away (unless we are not storing).
1852 if (child
->dest
!= NULL
) {
1856 dest
= (char *)dest
- child
->theTemplate
->offset
;
1857 sec_asn1d_add_to_subitems (state
, dest
, 0, PR_FALSE
);
1862 * Account for those bytes; see if we are done.
1864 if (state
->pending
) {
1865 PORT_Assert (!state
->indefinite
);
1866 if (child_consumed
> state
->pending
) {
1867 PORT_SetError (SEC_ERROR_BAD_DER
);
1868 state
->top
->status
= decodeError
;
1872 state
->pending
-= child_consumed
;
1873 if (state
->pending
== 0) {
1874 child
->place
= notInUse
;
1875 state
->place
= afterGroup
;
1881 * Do the "before" field notification for next item in group.
1883 sec_asn1d_notify_before (state
->top
, child
->dest
, child
->depth
);
1886 * Now we do the next one.
1888 sec_asn1d_scrub_state (child
);
1890 /* Initialize child state from the template */
1891 sec_asn1d_init_state_based_on_template(child
);
1893 state
->top
->current
= child
;
1898 * We are moving along through a sequence; move forward by one,
1899 * (detecting end-of-sequence when it happens).
1900 * XXX The handling of "missing" is ugly. Fix it.
1903 sec_asn1d_next_in_sequence (sec_asn1d_state
*state
)
1905 sec_asn1d_state
*child
;
1906 unsigned long child_consumed
;
1907 PRBool child_missing
;
1909 PORT_Assert (state
->place
== duringSequence
);
1910 PORT_Assert (state
->child
!= NULL
);
1912 child
= state
->child
;
1915 * Do the "after" field notification.
1917 sec_asn1d_notify_after (state
->top
, child
->dest
, child
->depth
);
1919 child_missing
= (PRBool
) child
->missing
;
1920 child_consumed
= child
->consumed
;
1921 child
->consumed
= 0;
1924 * Take care of accounting.
1926 if (child_missing
) {
1927 PORT_Assert (child
->optional
);
1929 state
->consumed
+= child_consumed
;
1931 * Free any grandchild.
1933 sec_asn1d_free_child (child
, PR_FALSE
);
1934 if (state
->pending
) {
1935 PORT_Assert (!state
->indefinite
);
1936 if (child_consumed
> state
->pending
) {
1937 PORT_SetError (SEC_ERROR_BAD_DER
);
1938 state
->top
->status
= decodeError
;
1941 state
->pending
-= child_consumed
;
1942 if (state
->pending
== 0) {
1943 child
->theTemplate
++;
1944 while (child
->theTemplate
->kind
!= 0) {
1945 if ((child
->theTemplate
->kind
& SEC_ASN1_OPTIONAL
) == 0) {
1946 PORT_SetError (SEC_ERROR_BAD_DER
);
1947 state
->top
->status
= decodeError
;
1950 child
->theTemplate
++;
1952 child
->place
= notInUse
;
1953 state
->place
= afterEndOfContents
;
1962 child
->theTemplate
++;
1963 if (child
->theTemplate
->kind
== 0) {
1965 * We are done with this sequence.
1967 child
->place
= notInUse
;
1968 if (state
->pending
) {
1969 PORT_SetError (SEC_ERROR_BAD_DER
);
1970 state
->top
->status
= decodeError
;
1971 } else if (child_missing
) {
1973 * We got to the end, but have a child that started parsing
1974 * and ended up "missing". The only legitimate reason for
1975 * this is that we had one or more optional fields at the
1976 * end of our sequence, and we were encoded indefinite-length,
1977 * so when we went looking for those optional fields we
1978 * found our end-of-contents octets instead.
1979 * (Yes, this is ugly; dunno a better way to handle it.)
1980 * So, first confirm the situation, and then mark that we
1983 if (state
->indefinite
&& child
->endofcontents
) {
1984 PORT_Assert (child_consumed
== 2);
1985 if (child_consumed
!= 2) {
1986 PORT_SetError (SEC_ERROR_BAD_DER
);
1987 state
->top
->status
= decodeError
;
1989 state
->consumed
+= child_consumed
;
1990 state
->place
= afterEndOfContents
;
1993 PORT_SetError (SEC_ERROR_BAD_DER
);
1994 state
->top
->status
= decodeError
;
1998 * We have to finish out, maybe reading end-of-contents octets;
1999 * let the normal logic do the right thing.
2001 state
->place
= beforeEndOfContents
;
2004 unsigned char child_found_tag_modifiers
= 0;
2005 unsigned long child_found_tag_number
= 0;
2008 * Reset state and push.
2010 if (state
->dest
!= NULL
)
2011 child
->dest
= (char *)state
->dest
+ child
->theTemplate
->offset
;
2014 * Do the "before" field notification.
2016 sec_asn1d_notify_before (state
->top
, child
->dest
, child
->depth
);
2018 if (child_missing
) { /* if previous child was missing, copy the tag data we already have */
2019 child_found_tag_modifiers
= child
->found_tag_modifiers
;
2020 child_found_tag_number
= child
->found_tag_number
;
2022 state
->top
->current
= child
;
2023 child
= sec_asn1d_init_state_based_on_template (child
);
2024 if (child_missing
&& child
) {
2025 child
->place
= afterIdentifier
;
2026 child
->found_tag_modifiers
= child_found_tag_modifiers
;
2027 child
->found_tag_number
= child_found_tag_number
;
2028 child
->consumed
= child_consumed
;
2029 if (child
->underlying_kind
== SEC_ASN1_ANY
2030 && !child
->top
->filter_only
) {
2032 * If the new field is an ANY, and we are storing, then
2033 * we need to save the tag out. We would have done this
2034 * already in the normal case, but since we were looking
2035 * for an optional field, and we did not find it, we only
2036 * now realize we need to save the tag.
2038 unsigned char identifier
;
2041 * Check that we did not end up with a high tag; for that
2042 * we need to re-encode the tag into multiple bytes in order
2043 * to store it back to look like what we parsed originally.
2044 * In practice this does not happen, but for completeness
2045 * sake it should probably be made to work at some point.
2047 PORT_Assert (child_found_tag_number
< SEC_ASN1_HIGH_TAG_NUMBER
);
2048 identifier
= (unsigned char)(child_found_tag_modifiers
| child_found_tag_number
);
2049 sec_asn1d_record_any_header (child
, (char *) &identifier
, 1);
2057 sec_asn1d_concat_substrings (sec_asn1d_state
*state
)
2059 PORT_Assert (state
->place
== afterConstructedString
);
2061 if (state
->subitems_head
!= NULL
) {
2062 struct subitem
*substring
;
2063 unsigned long alloc_len
, item_len
;
2064 unsigned char *where
;
2066 PRBool is_bit_string
;
2069 is_bit_string
= (state
->underlying_kind
== SEC_ASN1_BIT_STRING
)
2070 ? PR_TRUE
: PR_FALSE
;
2072 substring
= state
->subitems_head
;
2073 while (substring
!= NULL
) {
2075 * All bit-string substrings except the last one should be
2076 * a clean multiple of 8 bits.
2078 if (is_bit_string
&& (substring
->next
== NULL
)
2079 && (substring
->len
& 0x7)) {
2080 PORT_SetError (SEC_ERROR_BAD_DER
);
2081 state
->top
->status
= decodeError
;
2084 item_len
+= substring
->len
;
2085 substring
= substring
->next
;
2088 if (is_bit_string
) {
2089 #ifdef XP_WIN16 /* win16 compiler gets an internal error otherwise */
2090 alloc_len
= (((long)item_len
+ 7) / 8);
2092 alloc_len
= ((item_len
+ 7) >> 3);
2096 * Add 2 for the end-of-contents octets of an indefinite-length
2097 * ANY that is *not* also an INNER. Because we zero-allocate
2098 * below, all we need to do is increase the length here.
2100 if (state
->underlying_kind
== SEC_ASN1_ANY
&& state
->indefinite
)
2102 alloc_len
= item_len
;
2105 item
= (SECItem
*)(state
->dest
);
2106 PORT_Assert (item
!= NULL
);
2107 PORT_Assert (item
->data
== NULL
);
2108 item
->data
= (unsigned char*)sec_asn1d_zalloc (state
->top
->their_pool
,
2110 if (item
->data
== NULL
) {
2111 state
->top
->status
= decodeError
;
2114 item
->len
= item_len
;
2117 substring
= state
->subitems_head
;
2118 while (substring
!= NULL
) {
2120 item_len
= (substring
->len
+ 7) >> 3;
2122 item_len
= substring
->len
;
2123 PORT_Memcpy (where
, substring
->data
, item_len
);
2125 substring
= substring
->next
;
2129 * Because we use arenas and have a mark set, we later free
2130 * everything we have allocated, so this does *not* present
2131 * a memory leak (it is just temporarily left dangling).
2133 state
->subitems_head
= state
->subitems_tail
= NULL
;
2136 state
->place
= afterEndOfContents
;
2141 sec_asn1d_concat_group (sec_asn1d_state
*state
)
2143 const void ***placep
;
2145 PORT_Assert (state
->place
== afterGroup
);
2147 placep
= (const void***)state
->dest
;
2148 PORT_Assert(state
->subitems_head
== NULL
|| placep
!= NULL
);
2149 if (placep
!= NULL
) {
2150 struct subitem
*item
;
2155 item
= state
->subitems_head
;
2156 while (item
!= NULL
) {
2157 PORT_Assert (item
->next
!= NULL
|| item
== state
->subitems_tail
);
2162 group
= (const void**)sec_asn1d_zalloc (state
->top
->their_pool
,
2163 (count
+ 1) * (sizeof(void *)));
2164 if (group
== NULL
) {
2165 state
->top
->status
= decodeError
;
2171 item
= state
->subitems_head
;
2172 while (item
!= NULL
) {
2173 *group
++ = item
->data
;
2179 * Because we use arenas and have a mark set, we later free
2180 * everything we have allocated, so this does *not* present
2181 * a memory leak (it is just temporarily left dangling).
2183 state
->subitems_head
= state
->subitems_tail
= NULL
;
2186 state
->place
= afterEndOfContents
;
2191 * For those states that push a child to handle a subtemplate,
2192 * "absorb" that child (transfer necessary information).
2195 sec_asn1d_absorb_child (sec_asn1d_state
*state
)
2198 * There is absolutely supposed to be a child there.
2200 PORT_Assert (state
->child
!= NULL
);
2203 * Inherit the missing status of our child, and do the ugly
2204 * backing-up if necessary.
2206 state
->missing
= state
->child
->missing
;
2207 if (state
->missing
) {
2208 state
->found_tag_number
= state
->child
->found_tag_number
;
2209 state
->found_tag_modifiers
= state
->child
->found_tag_modifiers
;
2210 state
->endofcontents
= state
->child
->endofcontents
;
2214 * Add in number of bytes consumed by child.
2215 * (Only EXPLICIT should have already consumed bytes itself.)
2217 PORT_Assert (state
->place
== afterExplicit
|| state
->consumed
== 0);
2218 state
->consumed
+= state
->child
->consumed
;
2221 * Subtract from bytes pending; this only applies to a definite-length
2224 if (state
->pending
) {
2225 PORT_Assert (!state
->indefinite
);
2226 PORT_Assert (state
->place
== afterExplicit
);
2229 * If we had a definite-length explicit, then what the child
2230 * consumed should be what was left pending.
2232 if (state
->pending
!= state
->child
->consumed
) {
2233 if (state
->pending
< state
->child
->consumed
) {
2234 PORT_SetError (SEC_ERROR_BAD_DER
);
2235 state
->top
->status
= decodeError
;
2239 * Okay, this is a hack. It *should* be an error whether
2240 * pending is too big or too small, but it turns out that
2241 * we had a bug in our *old* DER encoder that ended up
2242 * counting an explicit header twice in the case where
2243 * the underlying type was an ANY. So, because we cannot
2244 * prevent receiving these (our own certificate server can
2245 * send them to us), we need to be lenient and accept them.
2246 * To do so, we need to pretend as if we read all of the
2247 * bytes that the header said we would find, even though
2248 * we actually came up short.
2250 state
->consumed
+= (state
->pending
- state
->child
->consumed
);
2256 * Indicate that we are done with child.
2258 state
->child
->consumed
= 0;
2261 * And move on to final state.
2262 * (Technically everybody could move to afterEndOfContents except
2263 * for an indefinite-length EXPLICIT; for simplicity though we assert
2264 * that but let the end-of-contents code do the real determination.)
2266 PORT_Assert (state
->place
== afterExplicit
|| (! state
->indefinite
));
2267 state
->place
= beforeEndOfContents
;
2272 sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state
*state
)
2274 PORT_Assert (state
->place
== beforeEndOfContents
);
2276 if (state
->indefinite
) {
2277 state
->place
= duringEndOfContents
;
2280 state
->place
= afterEndOfContents
;
2285 static unsigned long
2286 sec_asn1d_parse_end_of_contents (sec_asn1d_state
*state
,
2287 const char *buf
, unsigned long len
)
2291 PORT_Assert (state
->pending
<= 2);
2292 PORT_Assert (state
->place
== duringEndOfContents
);
2295 state
->top
->status
= needBytes
;
2299 if (state
->pending
< len
)
2300 len
= state
->pending
;
2302 for (i
= 0; i
< len
; i
++) {
2305 * We expect to find only zeros; if not, just give up.
2307 PORT_SetError (SEC_ERROR_BAD_DER
);
2308 state
->top
->status
= decodeError
;
2313 state
->pending
-= len
;
2315 if (state
->pending
== 0) {
2316 state
->place
= afterEndOfContents
;
2317 state
->endofcontents
= PR_TRUE
;
2325 sec_asn1d_pop_state (sec_asn1d_state
*state
)
2327 #if 0 /* XXX I think this should always be handled explicitly by parent? */
2329 * Account for our child.
2331 if (state
->child
!= NULL
) {
2332 state
->consumed
+= state
->child
->consumed
;
2333 if (state
->pending
) {
2334 PORT_Assert (!state
->indefinite
);
2335 if (state
->child
->consumed
> state
->pending
) {
2336 PORT_SetError (SEC_ERROR_BAD_DER
);
2337 state
->top
->status
= decodeError
;
2339 state
->pending
-= state
->child
->consumed
;
2342 state
->child
->consumed
= 0;
2349 sec_asn1d_free_child (state
, PR_FALSE
);
2352 * Just make my parent be the current state. It will then clean
2353 * up after me and free me (or reuse me).
2355 state
->top
->current
= state
->parent
;
2358 static sec_asn1d_state
*
2359 sec_asn1d_before_choice (sec_asn1d_state
*state
)
2361 sec_asn1d_state
*child
;
2363 if (state
->allocate
) {
2366 dest
= sec_asn1d_zalloc(state
->top
->their_pool
, state
->theTemplate
->size
);
2367 if ((void *)NULL
== dest
) {
2368 state
->top
->status
= decodeError
;
2369 return (sec_asn1d_state
*)NULL
;
2372 state
->dest
= (char *)dest
+ state
->theTemplate
->offset
;
2375 child
= sec_asn1d_push_state(state
->top
, state
->theTemplate
+ 1,
2376 (char *)state
->dest
- state
->theTemplate
->offset
,
2378 if ((sec_asn1d_state
*)NULL
== child
) {
2379 return (sec_asn1d_state
*)NULL
;
2382 sec_asn1d_scrub_state(child
);
2383 child
= sec_asn1d_init_state_based_on_template(child
);
2384 if ((sec_asn1d_state
*)NULL
== child
) {
2385 return (sec_asn1d_state
*)NULL
;
2388 child
->optional
= PR_TRUE
;
2390 state
->place
= duringChoice
;
2395 static sec_asn1d_state
*
2396 sec_asn1d_during_choice (sec_asn1d_state
*state
)
2398 sec_asn1d_state
*child
= state
->child
;
2400 PORT_Assert((sec_asn1d_state
*)NULL
!= child
);
2402 if (child
->missing
) {
2403 unsigned char child_found_tag_modifiers
= 0;
2404 unsigned long child_found_tag_number
= 0;
2407 state
->consumed
+= child
->consumed
;
2409 if (child
->endofcontents
) {
2410 /* This choice is probably the first item in a GROUP
2411 ** (e.g. SET_OF) that was indefinite-length encoded.
2412 ** We're actually at the end of that GROUP.
2413 ** We look up the stack to be sure that we find
2414 ** a state with indefinite length encoding before we
2415 ** find a state (like a SEQUENCE) that is definite.
2417 child
->place
= notInUse
;
2418 state
->place
= afterChoice
;
2419 state
->endofcontents
= PR_TRUE
; /* propagate this up */
2420 if (sec_asn1d_parent_allows_EOC(state
))
2422 PORT_SetError(SEC_ERROR_BAD_DER
);
2423 state
->top
->status
= decodeError
;
2427 dest
= (char *)child
->dest
- child
->theTemplate
->offset
;
2428 child
->theTemplate
++;
2430 if (0 == child
->theTemplate
->kind
) {
2431 /* Ran out of choices */
2432 PORT_SetError(SEC_ERROR_BAD_DER
);
2433 state
->top
->status
= decodeError
;
2434 return (sec_asn1d_state
*)NULL
;
2436 child
->dest
= (char *)dest
+ child
->theTemplate
->offset
;
2438 /* cargo'd from next_in_sequence innards */
2439 if (state
->pending
) {
2440 PORT_Assert(!state
->indefinite
);
2441 if (child
->consumed
> state
->pending
) {
2442 PORT_SetError (SEC_ERROR_BAD_DER
);
2443 state
->top
->status
= decodeError
;
2446 state
->pending
-= child
->consumed
;
2447 if (0 == state
->pending
) {
2448 /* XXX uh.. not sure if I should have stopped this
2449 * from happening before. */
2451 PORT_SetError(SEC_ERROR_BAD_DER
);
2452 state
->top
->status
= decodeError
;
2453 return (sec_asn1d_state
*)NULL
;
2457 child
->consumed
= 0;
2458 sec_asn1d_scrub_state(child
);
2460 /* move it on top again */
2461 state
->top
->current
= child
;
2463 child_found_tag_modifiers
= child
->found_tag_modifiers
;
2464 child_found_tag_number
= child
->found_tag_number
;
2466 child
= sec_asn1d_init_state_based_on_template(child
);
2467 if ((sec_asn1d_state
*)NULL
== child
) {
2468 return (sec_asn1d_state
*)NULL
;
2471 /* copy our findings to the new top */
2472 child
->found_tag_modifiers
= child_found_tag_modifiers
;
2473 child
->found_tag_number
= child_found_tag_number
;
2475 child
->optional
= PR_TRUE
;
2476 child
->place
= afterIdentifier
;
2480 if ((void *)NULL
!= state
->dest
) {
2481 /* Store the enum */
2482 int *which
= (int *)state
->dest
;
2483 *which
= (int)child
->theTemplate
->size
;
2486 child
->place
= notInUse
;
2488 state
->place
= afterChoice
;
2493 sec_asn1d_after_choice (sec_asn1d_state
*state
)
2495 state
->consumed
+= state
->child
->consumed
;
2496 state
->child
->consumed
= 0;
2497 state
->place
= afterEndOfContents
;
2498 sec_asn1d_pop_state(state
);
2502 sec_asn1d_uinteger(SECItem
*src
)
2504 unsigned long value
;
2507 if (src
->len
> 5 || (src
->len
> 4 && src
->data
[0] == 0))
2514 value
|= src
->data
[--len
];
2520 SEC_ASN1DecodeInteger(SECItem
*src
, unsigned long *value
)
2526 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2530 if (src
->len
> sizeof(unsigned long)) {
2531 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2535 if (src
->data
== NULL
) {
2536 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
2540 if (src
->data
[0] & 0x80)
2541 v
= -1; /* signed and negative - start with all 1's */
2545 for (i
= 0; i
< src
->len
; i
++) {
2546 /* shift in next byte */
2554 #ifdef DEBUG_ASN1D_STATES
2556 dump_states(SEC_ASN1DecoderContext
*cx
)
2558 sec_asn1d_state
*state
;
2561 for (state
= cx
->current
; state
->parent
; state
= state
->parent
) {
2565 for (; state
; state
= state
->child
) {
2567 for (i
= 0; i
< state
->depth
; i
++) {
2571 i
= formatKind(state
->theTemplate
->kind
, kindBuf
);
2572 printf("%s: tmpl %08x, kind%s",
2573 (state
== cx
->current
) ? "STATE" : "State",
2576 printf(" %s", (state
->place
>= 0 && state
->place
<= notInUse
)
2577 ? place_names
[ state
->place
]
2580 printf(", expect 0x%02x",
2581 state
->expect_tag_number
| state
->expect_tag_modifiers
);
2583 printf("%s%s%s %d\n",
2584 state
->indefinite
? ", indef" : "",
2585 state
->missing
? ", miss" : "",
2586 state
->endofcontents
? ", EOC" : "",
2593 #endif /* DEBUG_ASN1D_STATES */
2596 SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext
*cx
,
2597 const char *buf
, unsigned long len
)
2599 sec_asn1d_state
*state
= NULL
;
2600 unsigned long consumed
;
2601 SEC_ASN1EncodingPart what
;
2602 sec_asn1d_state
*stateEnd
= cx
->current
;
2604 if (cx
->status
== needBytes
)
2605 cx
->status
= keepGoing
;
2607 while (cx
->status
== keepGoing
) {
2608 state
= cx
->current
;
2609 what
= SEC_ASN1_Contents
;
2611 #ifdef DEBUG_ASN1D_STATES
2612 printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
2613 (state
->place
>= 0 && state
->place
<= notInUse
) ?
2614 place_names
[ state
->place
] : "(undefined)",
2615 (unsigned int)((unsigned char *)buf
)[ consumed
],
2618 #endif /* DEBUG_ASN1D_STATES */
2619 switch (state
->place
) {
2620 case beforeIdentifier
:
2621 consumed
= sec_asn1d_parse_identifier (state
, buf
, len
);
2622 what
= SEC_ASN1_Identifier
;
2624 case duringIdentifier
:
2625 consumed
= sec_asn1d_parse_more_identifier (state
, buf
, len
);
2626 what
= SEC_ASN1_Identifier
;
2628 case afterIdentifier
:
2629 sec_asn1d_confirm_identifier (state
);
2632 consumed
= sec_asn1d_parse_length (state
, buf
, len
);
2633 what
= SEC_ASN1_Length
;
2636 consumed
= sec_asn1d_parse_more_length (state
, buf
, len
);
2637 what
= SEC_ASN1_Length
;
2640 sec_asn1d_prepare_for_contents (state
);
2642 case beforeBitString
:
2643 consumed
= sec_asn1d_parse_bit_string (state
, buf
, len
);
2645 case duringBitString
:
2646 consumed
= sec_asn1d_parse_more_bit_string (state
, buf
, len
);
2648 case duringConstructedString
:
2649 sec_asn1d_next_substring (state
);
2652 sec_asn1d_next_in_group (state
);
2655 consumed
= sec_asn1d_parse_leaf (state
, buf
, len
);
2657 case duringSaveEncoding
:
2658 sec_asn1d_reuse_encoding (state
);
2659 if (cx
->status
== decodeError
) {
2660 /* recursive call has already popped all states from stack.
2661 ** Bail out quickly.
2665 if (cx
->status
== needBytes
) {
2666 /* recursive call wanted more data. Fatal. Clean up below. */
2667 PORT_SetError (SEC_ERROR_BAD_DER
);
2668 cx
->status
= decodeError
;
2671 case duringSequence
:
2672 sec_asn1d_next_in_sequence (state
);
2674 case afterConstructedString
:
2675 sec_asn1d_concat_substrings (state
);
2681 sec_asn1d_absorb_child (state
);
2684 sec_asn1d_concat_group (state
);
2686 case afterSaveEncoding
:
2687 /* SEC_ASN1DecoderUpdate has called itself recursively to
2688 ** decode SAVEd encoded data, and now is done decoding that.
2689 ** Return to the calling copy of SEC_ASN1DecoderUpdate.
2692 case beforeEndOfContents
:
2693 sec_asn1d_prepare_for_end_of_contents (state
);
2695 case duringEndOfContents
:
2696 consumed
= sec_asn1d_parse_end_of_contents (state
, buf
, len
);
2697 what
= SEC_ASN1_EndOfContents
;
2699 case afterEndOfContents
:
2700 sec_asn1d_pop_state (state
);
2703 state
= sec_asn1d_before_choice(state
);
2706 state
= sec_asn1d_during_choice(state
);
2709 sec_asn1d_after_choice(state
);
2713 /* This is not an error, but rather a plain old BUG! */
2715 PORT_SetError (SEC_ERROR_BAD_DER
);
2716 cx
->status
= decodeError
;
2720 if (cx
->status
== decodeError
)
2723 /* We should not consume more than we have. */
2724 PORT_Assert (consumed
<= len
);
2725 if (consumed
> len
) {
2726 PORT_SetError (SEC_ERROR_BAD_DER
);
2727 cx
->status
= decodeError
;
2731 /* It might have changed, so we have to update our local copy. */
2732 state
= cx
->current
;
2734 /* If it is NULL, we have popped all the way to the top. */
2735 if (state
== NULL
) {
2736 PORT_Assert (consumed
== 0);
2737 #if 0 /* XXX I want this here, but it seems that we have situations (like
2738 * downloading a pkcs7 cert chain from some issuers) that give us a
2739 * length which is greater than the entire encoding. So, we cannot
2740 * have this be an error.
2743 PORT_SetError (SEC_ERROR_BAD_DER
);
2744 cx
->status
= decodeError
;
2747 cx
->status
= allDone
;
2750 else if (state
->theTemplate
->kind
== SEC_ASN1_SKIP_REST
) {
2751 cx
->status
= allDone
;
2759 * The following check is specifically looking for an ANY
2760 * that is *not* also an INNER, because we need to save aside
2761 * all bytes in that case -- the contents parts will get
2762 * handled like all other contents, and the end-of-contents
2763 * bytes are added by the concat code, but the outer header
2764 * bytes need to get saved too, so we do them explicitly here.
2766 if (state
->underlying_kind
== SEC_ASN1_ANY
2767 && !cx
->filter_only
&& (what
== SEC_ASN1_Identifier
2768 || what
== SEC_ASN1_Length
)) {
2769 sec_asn1d_record_any_header (state
, buf
, consumed
);
2773 * We had some number of good, accepted bytes. If the caller
2774 * has registered to see them, pass them along.
2776 if (state
->top
->filter_proc
!= NULL
) {
2779 depth
= state
->depth
;
2780 if (what
== SEC_ASN1_EndOfContents
&& !state
->indefinite
) {
2781 PORT_Assert (state
->parent
!= NULL
2782 && state
->parent
->indefinite
);
2784 PORT_Assert (depth
== state
->parent
->depth
);
2786 (* state
->top
->filter_proc
) (state
->top
->filter_arg
,
2787 buf
, consumed
, depth
, what
);
2790 state
->consumed
+= consumed
;
2795 if (cx
->status
== decodeError
) {
2796 while (state
!= NULL
&& stateEnd
->parent
!=state
) {
2797 sec_asn1d_free_child (state
, PR_TRUE
);
2798 state
= state
->parent
;
2800 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
2801 * XXX This does not work because we can
2802 * end up leaving behind dangling pointers
2803 * to stuff that was allocated. In order
2804 * to make this really work (which would
2805 * be a good thing, I think), we need to
2806 * keep track of every place/pointer that
2807 * was allocated and make sure to NULL it
2808 * out before we then free back to the mark.
2810 if (cx
->their_pool
!= NULL
) {
2811 PORT_Assert (cx
->their_mark
!= NULL
);
2812 PORT_ArenaRelease (cx
->their_pool
, cx
->their_mark
);
2818 #if 0 /* XXX This is what I want, but cannot have because it seems we
2819 * have situations (like when downloading a pkcs7 cert chain from
2820 * some issuers) that give us a total length which is greater than
2821 * the entire encoding. So, we have to allow allDone to have a
2822 * remaining length greater than zero. I wanted to catch internal
2823 * bugs with this, noticing when we do not have the right length.
2826 PORT_Assert (len
== 0
2827 && (cx
->status
== needBytes
|| cx
->status
== allDone
));
2829 PORT_Assert ((len
== 0 && cx
->status
== needBytes
)
2830 || cx
->status
== allDone
);
2837 SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext
*cx
)
2841 if (cx
->status
== needBytes
) {
2842 PORT_SetError (SEC_ERROR_BAD_DER
);
2849 * XXX anything else that needs to be finished?
2852 PORT_FreeArena (cx
->our_pool
, PR_TRUE
);
2858 SEC_ASN1DecoderContext
*
2859 SEC_ASN1DecoderStart (PRArenaPool
*their_pool
, void *dest
,
2860 const SEC_ASN1Template
*theTemplate
)
2862 PRArenaPool
*our_pool
;
2863 SEC_ASN1DecoderContext
*cx
;
2865 our_pool
= PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE
);
2866 if (our_pool
== NULL
)
2869 cx
= (SEC_ASN1DecoderContext
*)PORT_ArenaZAlloc (our_pool
, sizeof(*cx
));
2871 PORT_FreeArena (our_pool
, PR_FALSE
);
2875 cx
->our_pool
= our_pool
;
2876 if (their_pool
!= NULL
) {
2877 cx
->their_pool
= their_pool
;
2878 #ifdef SEC_ASN1D_FREE_ON_ERROR
2879 cx
->their_mark
= PORT_ArenaMark (their_pool
);
2883 cx
->status
= needBytes
;
2885 if (sec_asn1d_push_state(cx
, theTemplate
, dest
, PR_FALSE
) == NULL
2886 || sec_asn1d_init_state_based_on_template (cx
->current
) == NULL
) {
2888 * Trouble initializing (probably due to failed allocations)
2889 * requires that we just give up.
2891 PORT_FreeArena (our_pool
, PR_FALSE
);
2900 SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext
*cx
,
2901 SEC_ASN1WriteProc fn
, void *arg
,
2904 /* check that we are "between" fields here */
2905 PORT_Assert (cx
->during_notify
);
2907 cx
->filter_proc
= fn
;
2908 cx
->filter_arg
= arg
;
2909 cx
->filter_only
= only
;
2914 SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext
*cx
)
2916 /* check that we are "between" fields here */
2917 PORT_Assert (cx
->during_notify
);
2919 cx
->filter_proc
= NULL
;
2920 cx
->filter_arg
= NULL
;
2921 cx
->filter_only
= PR_FALSE
;
2926 SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext
*cx
,
2927 SEC_ASN1NotifyProc fn
, void *arg
)
2929 cx
->notify_proc
= fn
;
2930 cx
->notify_arg
= arg
;
2935 SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext
*cx
)
2937 cx
->notify_proc
= NULL
;
2938 cx
->notify_arg
= NULL
; /* not necessary; just being clean */
2942 SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext
*cx
, int error
)
2945 PORT_SetError(error
);
2946 cx
->status
= decodeError
;
2951 SEC_ASN1Decode (PRArenaPool
*poolp
, void *dest
,
2952 const SEC_ASN1Template
*theTemplate
,
2953 const char *buf
, long len
)
2955 SEC_ASN1DecoderContext
*dcx
;
2958 dcx
= SEC_ASN1DecoderStart (poolp
, dest
, theTemplate
);
2962 urv
= SEC_ASN1DecoderUpdate (dcx
, buf
, len
);
2963 frv
= SEC_ASN1DecoderFinish (dcx
);
2965 if (urv
!= SECSuccess
)
2973 SEC_ASN1DecodeItem (PRArenaPool
*poolp
, void *dest
,
2974 const SEC_ASN1Template
*theTemplate
,
2977 return SEC_ASN1Decode (poolp
, dest
, theTemplate
,
2978 (const char *)src
->data
, src
->len
);
2981 #ifdef DEBUG_ASN1D_STATES
2982 void sec_asn1d_Assert(const char *s
, const char *file
, PRIntn ln
)
2984 printf("Assertion failed, \"%s\", file %s, line %d\n", s
, file
, ln
);
2990 * Generic templates for individual/simple items and pointers to
2993 * If you need to add a new one, please note the following:
2994 * - For each new basic type you should add *four* templates:
2995 * one plain, one PointerTo, one SequenceOf and one SetOf.
2996 * - If the new type can be constructed (meaning, it is a
2997 * *string* type according to BER/DER rules), then you should
2998 * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
2999 * See the definition of the OctetString template for an example.
3000 * - It may not be obvious, but these are in *alphabetical*
3001 * order based on the SEC_ASN1_XXX name; so put new ones in
3002 * the appropriate place.
3005 const SEC_ASN1Template SEC_AnyTemplate
[] = {
3006 { SEC_ASN1_ANY
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3009 const SEC_ASN1Template SEC_PointerToAnyTemplate
[] = {
3010 { SEC_ASN1_POINTER
, 0, SEC_AnyTemplate
}
3013 const SEC_ASN1Template SEC_SequenceOfAnyTemplate
[] = {
3014 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_AnyTemplate
}
3017 const SEC_ASN1Template SEC_SetOfAnyTemplate
[] = {
3018 { SEC_ASN1_SET_OF
, 0, SEC_AnyTemplate
}
3021 const SEC_ASN1Template SEC_BitStringTemplate
[] = {
3022 { SEC_ASN1_BIT_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3025 const SEC_ASN1Template SEC_PointerToBitStringTemplate
[] = {
3026 { SEC_ASN1_POINTER
, 0, SEC_BitStringTemplate
}
3029 const SEC_ASN1Template SEC_SequenceOfBitStringTemplate
[] = {
3030 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_BitStringTemplate
}
3033 const SEC_ASN1Template SEC_SetOfBitStringTemplate
[] = {
3034 { SEC_ASN1_SET_OF
, 0, SEC_BitStringTemplate
}
3037 const SEC_ASN1Template SEC_BMPStringTemplate
[] = {
3038 { SEC_ASN1_BMP_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3041 const SEC_ASN1Template SEC_PointerToBMPStringTemplate
[] = {
3042 { SEC_ASN1_POINTER
, 0, SEC_BMPStringTemplate
}
3045 const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate
[] = {
3046 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_BMPStringTemplate
}
3049 const SEC_ASN1Template SEC_SetOfBMPStringTemplate
[] = {
3050 { SEC_ASN1_SET_OF
, 0, SEC_BMPStringTemplate
}
3053 const SEC_ASN1Template SEC_BooleanTemplate
[] = {
3054 { SEC_ASN1_BOOLEAN
, 0, NULL
, sizeof(SECItem
) }
3057 const SEC_ASN1Template SEC_PointerToBooleanTemplate
[] = {
3058 { SEC_ASN1_POINTER
, 0, SEC_BooleanTemplate
}
3061 const SEC_ASN1Template SEC_SequenceOfBooleanTemplate
[] = {
3062 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_BooleanTemplate
}
3065 const SEC_ASN1Template SEC_SetOfBooleanTemplate
[] = {
3066 { SEC_ASN1_SET_OF
, 0, SEC_BooleanTemplate
}
3069 const SEC_ASN1Template SEC_EnumeratedTemplate
[] = {
3070 { SEC_ASN1_ENUMERATED
, 0, NULL
, sizeof(SECItem
) }
3073 const SEC_ASN1Template SEC_PointerToEnumeratedTemplate
[] = {
3074 { SEC_ASN1_POINTER
, 0, SEC_EnumeratedTemplate
}
3077 const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate
[] = {
3078 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_EnumeratedTemplate
}
3081 const SEC_ASN1Template SEC_SetOfEnumeratedTemplate
[] = {
3082 { SEC_ASN1_SET_OF
, 0, SEC_EnumeratedTemplate
}
3085 const SEC_ASN1Template SEC_GeneralizedTimeTemplate
[] = {
3086 { SEC_ASN1_GENERALIZED_TIME
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
)}
3089 const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate
[] = {
3090 { SEC_ASN1_POINTER
, 0, SEC_GeneralizedTimeTemplate
}
3093 const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate
[] = {
3094 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_GeneralizedTimeTemplate
}
3097 const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate
[] = {
3098 { SEC_ASN1_SET_OF
, 0, SEC_GeneralizedTimeTemplate
}
3101 const SEC_ASN1Template SEC_IA5StringTemplate
[] = {
3102 { SEC_ASN1_IA5_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3105 const SEC_ASN1Template SEC_PointerToIA5StringTemplate
[] = {
3106 { SEC_ASN1_POINTER
, 0, SEC_IA5StringTemplate
}
3109 const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate
[] = {
3110 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_IA5StringTemplate
}
3113 const SEC_ASN1Template SEC_SetOfIA5StringTemplate
[] = {
3114 { SEC_ASN1_SET_OF
, 0, SEC_IA5StringTemplate
}
3117 const SEC_ASN1Template SEC_IntegerTemplate
[] = {
3118 { SEC_ASN1_INTEGER
, 0, NULL
, sizeof(SECItem
) }
3121 const SEC_ASN1Template SEC_PointerToIntegerTemplate
[] = {
3122 { SEC_ASN1_POINTER
, 0, SEC_IntegerTemplate
}
3125 const SEC_ASN1Template SEC_SequenceOfIntegerTemplate
[] = {
3126 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_IntegerTemplate
}
3129 const SEC_ASN1Template SEC_SetOfIntegerTemplate
[] = {
3130 { SEC_ASN1_SET_OF
, 0, SEC_IntegerTemplate
}
3133 const SEC_ASN1Template SEC_NullTemplate
[] = {
3134 { SEC_ASN1_NULL
, 0, NULL
, sizeof(SECItem
) }
3137 const SEC_ASN1Template SEC_PointerToNullTemplate
[] = {
3138 { SEC_ASN1_POINTER
, 0, SEC_NullTemplate
}
3141 const SEC_ASN1Template SEC_SequenceOfNullTemplate
[] = {
3142 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_NullTemplate
}
3145 const SEC_ASN1Template SEC_SetOfNullTemplate
[] = {
3146 { SEC_ASN1_SET_OF
, 0, SEC_NullTemplate
}
3149 const SEC_ASN1Template SEC_ObjectIDTemplate
[] = {
3150 { SEC_ASN1_OBJECT_ID
, 0, NULL
, sizeof(SECItem
) }
3153 const SEC_ASN1Template SEC_PointerToObjectIDTemplate
[] = {
3154 { SEC_ASN1_POINTER
, 0, SEC_ObjectIDTemplate
}
3157 const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate
[] = {
3158 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_ObjectIDTemplate
}
3161 const SEC_ASN1Template SEC_SetOfObjectIDTemplate
[] = {
3162 { SEC_ASN1_SET_OF
, 0, SEC_ObjectIDTemplate
}
3165 const SEC_ASN1Template SEC_OctetStringTemplate
[] = {
3166 { SEC_ASN1_OCTET_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3169 const SEC_ASN1Template SEC_PointerToOctetStringTemplate
[] = {
3170 { SEC_ASN1_POINTER
| SEC_ASN1_MAY_STREAM
, 0, SEC_OctetStringTemplate
}
3173 const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate
[] = {
3174 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_OctetStringTemplate
}
3177 const SEC_ASN1Template SEC_SetOfOctetStringTemplate
[] = {
3178 { SEC_ASN1_SET_OF
, 0, SEC_OctetStringTemplate
}
3181 const SEC_ASN1Template SEC_PrintableStringTemplate
[] = {
3182 { SEC_ASN1_PRINTABLE_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
)}
3185 const SEC_ASN1Template SEC_PointerToPrintableStringTemplate
[] = {
3186 { SEC_ASN1_POINTER
, 0, SEC_PrintableStringTemplate
}
3189 const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate
[] = {
3190 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_PrintableStringTemplate
}
3193 const SEC_ASN1Template SEC_SetOfPrintableStringTemplate
[] = {
3194 { SEC_ASN1_SET_OF
, 0, SEC_PrintableStringTemplate
}
3197 const SEC_ASN1Template SEC_T61StringTemplate
[] = {
3198 { SEC_ASN1_T61_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3201 const SEC_ASN1Template SEC_PointerToT61StringTemplate
[] = {
3202 { SEC_ASN1_POINTER
, 0, SEC_T61StringTemplate
}
3205 const SEC_ASN1Template SEC_SequenceOfT61StringTemplate
[] = {
3206 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_T61StringTemplate
}
3209 const SEC_ASN1Template SEC_SetOfT61StringTemplate
[] = {
3210 { SEC_ASN1_SET_OF
, 0, SEC_T61StringTemplate
}
3213 const SEC_ASN1Template SEC_UniversalStringTemplate
[] = {
3214 { SEC_ASN1_UNIVERSAL_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
)}
3217 const SEC_ASN1Template SEC_PointerToUniversalStringTemplate
[] = {
3218 { SEC_ASN1_POINTER
, 0, SEC_UniversalStringTemplate
}
3221 const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate
[] = {
3222 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_UniversalStringTemplate
}
3225 const SEC_ASN1Template SEC_SetOfUniversalStringTemplate
[] = {
3226 { SEC_ASN1_SET_OF
, 0, SEC_UniversalStringTemplate
}
3229 const SEC_ASN1Template SEC_UTCTimeTemplate
[] = {
3230 { SEC_ASN1_UTC_TIME
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3233 const SEC_ASN1Template SEC_PointerToUTCTimeTemplate
[] = {
3234 { SEC_ASN1_POINTER
, 0, SEC_UTCTimeTemplate
}
3237 const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate
[] = {
3238 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_UTCTimeTemplate
}
3241 const SEC_ASN1Template SEC_SetOfUTCTimeTemplate
[] = {
3242 { SEC_ASN1_SET_OF
, 0, SEC_UTCTimeTemplate
}
3245 const SEC_ASN1Template SEC_UTF8StringTemplate
[] = {
3246 { SEC_ASN1_UTF8_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
)}
3249 const SEC_ASN1Template SEC_PointerToUTF8StringTemplate
[] = {
3250 { SEC_ASN1_POINTER
, 0, SEC_UTF8StringTemplate
}
3253 const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate
[] = {
3254 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_UTF8StringTemplate
}
3257 const SEC_ASN1Template SEC_SetOfUTF8StringTemplate
[] = {
3258 { SEC_ASN1_SET_OF
, 0, SEC_UTF8StringTemplate
}
3261 const SEC_ASN1Template SEC_VisibleStringTemplate
[] = {
3262 { SEC_ASN1_VISIBLE_STRING
| SEC_ASN1_MAY_STREAM
, 0, NULL
, sizeof(SECItem
) }
3265 const SEC_ASN1Template SEC_PointerToVisibleStringTemplate
[] = {
3266 { SEC_ASN1_POINTER
, 0, SEC_VisibleStringTemplate
}
3269 const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate
[] = {
3270 { SEC_ASN1_SEQUENCE_OF
, 0, SEC_VisibleStringTemplate
}
3273 const SEC_ASN1Template SEC_SetOfVisibleStringTemplate
[] = {
3274 { SEC_ASN1_SET_OF
, 0, SEC_VisibleStringTemplate
}
3279 * Template for skipping a subitem.
3281 * Note that it only makes sense to use this for decoding (when you want
3282 * to decode something where you are only interested in one or two of
3283 * the fields); you cannot encode a SKIP!
3285 const SEC_ASN1Template SEC_SkipTemplate
[] = {
3290 /* These functions simply return the address of the above-declared templates.
3291 ** This is necessary for Windows DLLs. Sigh.
3293 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_AnyTemplate
)
3294 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BMPStringTemplate
)
3295 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BooleanTemplate
)
3296 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BitStringTemplate
)
3297 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IA5StringTemplate
)
3298 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_GeneralizedTimeTemplate
)
3299 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IntegerTemplate
)
3300 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_NullTemplate
)
3301 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_ObjectIDTemplate
)
3302 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_OctetStringTemplate
)
3303 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToAnyTemplate
)
3304 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToOctetStringTemplate
)
3305 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SetOfAnyTemplate
)
3306 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTCTimeTemplate
)
3307 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTF8StringTemplate
)