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 Optimized ASN.1 DER decoder
43 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */
47 * simple definite-length ASN.1 decoder
50 static unsigned char* definite_length_decoder(const unsigned char *buf
,
51 const unsigned int length
,
52 unsigned int *data_length
,
56 unsigned int used_length
= 0;
57 unsigned int data_len
;
59 if (used_length
>= length
)
63 tag
= buf
[used_length
++];
65 /* blow out when we come to the end */
71 if (used_length
>= length
)
75 data_len
= buf
[used_length
++];
79 int len_count
= data_len
& 0x7f;
83 while (len_count
-- > 0)
85 if (used_length
>= length
)
89 data_len
= (data_len
<< 8) | buf
[used_length
++];
93 if (data_len
> (length
-used_length
) )
97 if (includeTag
) data_len
+= used_length
;
99 *data_length
= data_len
;
100 return ((unsigned char*)buf
+ (includeTag
? 0 : used_length
));
103 static SECStatus
GetItem(SECItem
* src
, SECItem
* dest
, PRBool includeTag
)
105 if ( (!src
) || (!dest
) || (!src
->data
) )
107 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
113 /* reaching the end of the buffer is not an error */
119 dest
->data
= definite_length_decoder(src
->data
, src
->len
, &dest
->len
,
121 if (dest
->data
== NULL
)
123 PORT_SetError(SEC_ERROR_BAD_DER
);
126 src
->len
-= (dest
->data
- src
->data
) + dest
->len
;
127 src
->data
= dest
->data
+ dest
->len
;
131 /* check if the actual component's type matches the type in the template */
133 static SECStatus
MatchComponentType(const SEC_ASN1Template
* templateEntry
,
134 SECItem
* item
, PRBool
* match
, void* dest
)
136 unsigned long kind
= 0;
137 unsigned char tag
= 0;
139 if ( (!item
) || (!templateEntry
) || (!match
) )
141 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
145 if (!item
->len
|| !item
->data
)
151 kind
= templateEntry
->kind
;
152 tag
= *(unsigned char*) item
->data
;
154 if ( ( (kind
& SEC_ASN1_INLINE
) ||
155 (kind
& SEC_ASN1_POINTER
) ) &&
156 (0 == (kind
& SEC_ASN1_TAG_MASK
) ) )
158 /* These cases are special because the template's "kind" does not
159 give us the information for the ASN.1 tag of the next item. It can
160 only be figured out from the subtemplate. */
161 if (!(kind
& SEC_ASN1_OPTIONAL
))
163 /* This is a required component. If there is a type mismatch,
164 the decoding of the subtemplate will fail, so assume this
165 is a match at the parent level and let it fail later. This
166 avoids a redundant check in matching cases */
172 /* optional component. This is the hard case. Now we need to
173 look at the subtemplate to get the expected kind */
174 const SEC_ASN1Template
* subTemplate
=
175 SEC_ASN1GetSubtemplate (templateEntry
, dest
, PR_FALSE
);
178 PORT_SetError(SEC_ERROR_BAD_TEMPLATE
);
181 if ( (subTemplate
->kind
& SEC_ASN1_INLINE
) ||
182 (subTemplate
->kind
& SEC_ASN1_POINTER
) )
184 /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE,
185 otherwise you may get a false positive due to the recursion
186 optimization above that always matches the type if the
187 component is required . Nesting these should never be
188 required, so that no one should miss this ability */
189 PORT_SetError(SEC_ERROR_BAD_TEMPLATE
);
192 return MatchComponentType(subTemplate
, item
, match
,
193 (void*)((char*)dest
+ templateEntry
->offset
));
197 if (kind
& SEC_ASN1_CHOICE
)
199 /* we need to check the component's tag against each choice's tag */
200 /* XXX it would be nice to save the index of the choice here so that
201 DecodeChoice wouldn't have to do this again. However, due to the
202 recursivity of MatchComponentType, we don't know if we are in a
203 required or optional component, so we can't write anywhere in
204 the destination within this function */
205 unsigned choiceIndex
= 1;
206 const SEC_ASN1Template
* choiceEntry
;
207 while ( (choiceEntry
= &templateEntry
[choiceIndex
++]) && (choiceEntry
->kind
))
209 if ( (SECSuccess
== MatchComponentType(choiceEntry
, item
, match
,
210 (void*)((char*)dest
+ choiceEntry
->offset
))) &&
211 (PR_TRUE
== *match
) )
216 /* no match, caller must decide if this is BAD DER, or not. */
221 if (kind
& SEC_ASN1_ANY
)
223 /* SEC_ASN1_ANY always matches */
228 if ( (0 == ((unsigned char)kind
& SEC_ASN1_TAGNUM_MASK
)) &&
229 (!(kind
& SEC_ASN1_EXPLICIT
)) &&
230 ( ( (kind
& SEC_ASN1_SAVE
) ||
231 (kind
& SEC_ASN1_SKIP
) ) &&
232 (!(kind
& SEC_ASN1_OPTIONAL
))
236 /* when saving or skipping a required component, a type is not
237 required in the template. This is for legacy support of
238 SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to
239 deprecate these usages and always require a type, as this
240 disables type checking, and effectively forbids us from
241 transparently ignoring optional components we aren't aware of */
246 /* first, do a class check */
247 if ( (tag
& SEC_ASN1_CLASS_MASK
) !=
248 (((unsigned char)kind
) & SEC_ASN1_CLASS_MASK
) )
251 /* this is only to help debugging of the decoder in case of problems */
252 unsigned char tagclass
= tag
& SEC_ASN1_CLASS_MASK
;
253 unsigned char expectedclass
= (unsigned char)kind
& SEC_ASN1_CLASS_MASK
;
255 expectedclass
= expectedclass
;
261 /* now do a tag check */
262 if ( ((unsigned char)kind
& SEC_ASN1_TAGNUM_MASK
) !=
263 (tag
& SEC_ASN1_TAGNUM_MASK
))
269 /* now, do a method check. This depends on the class */
270 switch (tag
& SEC_ASN1_CLASS_MASK
)
272 case SEC_ASN1_UNIVERSAL
:
273 /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be
274 primitive or constructed based on the tag */
275 switch (tag
& SEC_ASN1_TAGNUM_MASK
)
277 case SEC_ASN1_SEQUENCE
:
279 case SEC_ASN1_EMBEDDED_PDV
:
280 /* this component must be a constructed type */
281 /* XXX add any new universal constructed type here */
282 if (tag
& SEC_ASN1_CONSTRUCTED
)
290 /* this component must be a primitive type */
291 if (! (tag
& SEC_ASN1_CONSTRUCTED
))
301 /* for all other classes, we check the method based on the template */
302 if ( (unsigned char)(kind
& SEC_ASN1_METHOD_MASK
) ==
303 (tag
& SEC_ASN1_METHOD_MASK
) )
308 /* method does not match between template and component */
318 static SECStatus
CheckSequenceTemplate(const SEC_ASN1Template
* sequenceTemplate
)
320 SECStatus rv
= SECSuccess
;
321 const SEC_ASN1Template
* sequenceEntry
= NULL
;
322 unsigned long seqIndex
= 0;
323 unsigned long lastEntryIndex
= 0;
324 unsigned long ambiguityIndex
= 0;
325 PRBool foundAmbiguity
= PR_FALSE
;
329 sequenceEntry
= &sequenceTemplate
[seqIndex
++];
330 if (sequenceEntry
->kind
)
332 /* ensure that we don't have an optional component of SEC_ASN1_ANY
333 in the middle of the sequence, since we could not handle it */
334 /* XXX this function needs to dig into the subtemplates to find
336 if ( (PR_FALSE
== foundAmbiguity
) &&
337 (sequenceEntry
->kind
& SEC_ASN1_OPTIONAL
) &&
338 (sequenceEntry
->kind
& SEC_ASN1_ANY
) )
340 foundAmbiguity
= PR_TRUE
;
341 ambiguityIndex
= seqIndex
- 1;
344 } while (sequenceEntry
->kind
);
346 lastEntryIndex
= seqIndex
- 2;
348 if (PR_FALSE
!= foundAmbiguity
)
350 if (ambiguityIndex
< lastEntryIndex
)
352 /* ambiguity can only be tolerated on the last entry */
353 PORT_SetError(SEC_ERROR_BAD_TEMPLATE
);
358 /* XXX also enforce ASN.1 requirement that tags be
359 distinct for consecutive optional components */
366 static SECStatus
DecodeItem(void* dest
,
367 const SEC_ASN1Template
* templateEntry
,
368 SECItem
* src
, PRArenaPool
* arena
, PRBool checkTag
);
370 static SECStatus
DecodeSequence(void* dest
,
371 const SEC_ASN1Template
* templateEntry
,
372 SECItem
* src
, PRArenaPool
* arena
)
374 SECStatus rv
= SECSuccess
;
377 const SEC_ASN1Template
* sequenceTemplate
= &(templateEntry
[1]);
378 const SEC_ASN1Template
* sequenceEntry
= NULL
;
379 unsigned long seqindex
= 0;
382 /* for a sequence, we need to validate the template. */
383 rv
= CheckSequenceTemplate(sequenceTemplate
);
388 /* get the sequence */
389 if (SECSuccess
== rv
)
391 rv
= GetItem(&source
, &sequence
, PR_FALSE
);
395 if (SECSuccess
== rv
)
398 sequenceEntry
= &sequenceTemplate
[seqindex
++];
399 if ( (sequenceEntry
&& sequenceEntry
->kind
) &&
400 (sequenceEntry
->kind
!= SEC_ASN1_SKIP_REST
) )
402 rv
= DecodeItem(dest
, sequenceEntry
, &sequence
, arena
, PR_TRUE
);
404 } while ( (SECSuccess
== rv
) &&
405 (sequenceEntry
->kind
&&
406 sequenceEntry
->kind
!= SEC_ASN1_SKIP_REST
) );
407 /* we should have consumed all the bytes in the sequence by now
408 unless the caller doesn't care about the rest of the sequence */
409 if (SECSuccess
== rv
&& sequence
.len
&&
410 sequenceEntry
&& sequenceEntry
->kind
!= SEC_ASN1_SKIP_REST
)
412 /* it isn't 100% clear whether this is a bad DER or a bad template.
413 The problem is that logically, they don't match - there is extra
414 data in the DER that the template doesn't know about */
415 PORT_SetError(SEC_ERROR_BAD_DER
);
422 static SECStatus
DecodeInline(void* dest
,
423 const SEC_ASN1Template
* templateEntry
,
424 SECItem
* src
, PRArenaPool
* arena
, PRBool checkTag
)
426 const SEC_ASN1Template
* inlineTemplate
=
427 SEC_ASN1GetSubtemplate (templateEntry
, dest
, PR_FALSE
);
428 return DecodeItem((void*)((char*)dest
+ templateEntry
->offset
),
429 inlineTemplate
, src
, arena
, checkTag
);
432 static SECStatus
DecodePointer(void* dest
,
433 const SEC_ASN1Template
* templateEntry
,
434 SECItem
* src
, PRArenaPool
* arena
, PRBool checkTag
)
436 const SEC_ASN1Template
* ptrTemplate
=
437 SEC_ASN1GetSubtemplate (templateEntry
, dest
, PR_FALSE
);
438 void* subdata
= PORT_ArenaZAlloc(arena
, ptrTemplate
->size
);
439 *(void**)((char*)dest
+ templateEntry
->offset
) = subdata
;
442 return DecodeItem(subdata
, ptrTemplate
, src
, arena
, checkTag
);
446 PORT_SetError(SEC_ERROR_NO_MEMORY
);
451 static SECStatus
DecodeImplicit(void* dest
,
452 const SEC_ASN1Template
* templateEntry
,
453 SECItem
* src
, PRArenaPool
* arena
)
455 if (templateEntry
->kind
& SEC_ASN1_POINTER
)
457 return DecodePointer((void*)((char*)dest
),
458 templateEntry
, src
, arena
, PR_FALSE
);
462 return DecodeInline((void*)((char*)dest
),
463 templateEntry
, src
, arena
, PR_FALSE
);
467 static SECStatus
DecodeChoice(void* dest
,
468 const SEC_ASN1Template
* templateEntry
,
469 SECItem
* src
, PRArenaPool
* arena
)
471 SECStatus rv
= SECSuccess
;
473 const SEC_ASN1Template
* choiceTemplate
= &(templateEntry
[1]);
474 const SEC_ASN1Template
* choiceEntry
= NULL
;
475 unsigned long choiceindex
= 0;
477 /* XXX for a choice component, we should validate the template to make
478 sure the tags are distinct, in debug builds. This hasn't been
480 /* rv = CheckChoiceTemplate(sequenceTemplate); */
486 choiceEntry
= &choiceTemplate
[choiceindex
++];
487 if (choiceEntry
->kind
)
489 rv
= DecodeItem(dest
, choiceEntry
, &choice
, arena
, PR_TRUE
);
491 } while ( (SECFailure
== rv
) && (choiceEntry
->kind
));
493 if (SECFailure
== rv
)
495 /* the component didn't match any of the choices */
496 PORT_SetError(SEC_ERROR_BAD_DER
);
500 /* set the type in the union here */
501 int *which
= (int *)((char *)dest
+ templateEntry
->offset
);
502 *which
= (int)choiceEntry
->size
;
505 /* we should have consumed all the bytes by now */
506 /* fail if we have not */
507 if (SECSuccess
== rv
&& choice
.len
)
509 /* there is extra data that isn't listed in the template */
510 PORT_SetError(SEC_ERROR_BAD_DER
);
516 static SECStatus
DecodeGroup(void* dest
,
517 const SEC_ASN1Template
* templateEntry
,
518 SECItem
* src
, PRArenaPool
* arena
)
520 SECStatus rv
= SECSuccess
;
523 PRUint32 totalEntries
= 0;
524 PRUint32 entryIndex
= 0;
525 void** entries
= NULL
;
527 const SEC_ASN1Template
* subTemplate
=
528 SEC_ASN1GetSubtemplate (templateEntry
, dest
, PR_FALSE
);
533 if (SECSuccess
== rv
)
535 rv
= GetItem(&source
, &group
, PR_FALSE
);
538 /* XXX we should check the subtemplate in debug builds */
539 if (SECSuccess
== rv
)
541 /* first, count the number of entries. Benchmarking showed that this
542 counting pass is more efficient than trying to allocate entries as
543 we read the DER, even if allocating many entries at a time
545 SECItem counter
= group
;
549 rv
= GetItem(&counter
, &anitem
, PR_TRUE
);
550 if (SECSuccess
== rv
&& (anitem
.len
) )
554 } while ( (SECSuccess
== rv
) && (counter
.len
) );
556 if (SECSuccess
== rv
)
558 /* allocate room for pointer array and entries */
559 /* we want to allocate the array even if there is 0 entry */
560 entries
= (void**)PORT_ArenaZAlloc(arena
, sizeof(void*)*
561 (totalEntries
+ 1 ) + /* the extra one is for NULL termination */
562 subTemplate
->size
*totalEntries
);
566 entries
[totalEntries
] = NULL
; /* terminate the array */
570 PORT_SetError(SEC_ERROR_NO_MEMORY
);
573 if (SECSuccess
== rv
)
575 void* entriesData
= (unsigned char*)entries
+ (unsigned long)(sizeof(void*)*(totalEntries
+ 1 ));
576 /* and fix the pointers in the array */
577 PRUint32 entriesIndex
= 0;
578 for (entriesIndex
= 0;entriesIndex
<totalEntries
;entriesIndex
++)
580 entries
[entriesIndex
] =
581 (char*)entriesData
+ (subTemplate
->size
*entriesIndex
);
587 if (SECSuccess
== rv
&& totalEntries
)
590 if (!(entryIndex
<totalEntries
))
595 rv
= DecodeItem(entries
[entryIndex
++], subTemplate
, &group
, arena
, PR_TRUE
);
596 } while ( (SECSuccess
== rv
) && (group
.len
) );
597 /* we should be at the end of the set by now */
598 /* save the entries where requested */
599 memcpy(((char*)dest
+ templateEntry
->offset
), &entries
, sizeof(void**));
604 static SECStatus
DecodeExplicit(void* dest
,
605 const SEC_ASN1Template
* templateEntry
,
606 SECItem
* src
, PRArenaPool
* arena
)
608 SECStatus rv
= SECSuccess
;
610 SECItem constructed
= *src
;
612 rv
= GetItem(&constructed
, &subItem
, PR_FALSE
);
614 if (SECSuccess
== rv
)
616 if (templateEntry
->kind
& SEC_ASN1_POINTER
)
618 rv
= DecodePointer(dest
, templateEntry
, &subItem
, arena
, PR_TRUE
);
622 rv
= DecodeInline(dest
, templateEntry
, &subItem
, arena
, PR_TRUE
);
629 /* new decoder implementation. This is a recursive function */
631 static SECStatus
DecodeItem(void* dest
,
632 const SEC_ASN1Template
* templateEntry
,
633 SECItem
* src
, PRArenaPool
* arena
, PRBool checkTag
)
635 SECStatus rv
= SECSuccess
;
638 PRBool pop
= PR_FALSE
;
639 PRBool decode
= PR_TRUE
;
640 PRBool save
= PR_FALSE
;
642 PRBool match
= PR_TRUE
;
643 PRBool optional
= PR_FALSE
;
645 PR_ASSERT(src
&& dest
&& templateEntry
&& arena
);
647 if (!src
|| !dest
|| !templateEntry
|| !arena
)
649 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
654 if (SECSuccess
== rv
)
656 /* do the template validation */
657 kind
= templateEntry
->kind
;
658 optional
= (0 != (kind
& SEC_ASN1_OPTIONAL
));
661 PORT_SetError(SEC_ERROR_BAD_TEMPLATE
);
666 if (SECSuccess
== rv
)
669 if (kind
& SEC_ASN1_DEBUG_BREAK
)
671 /* when debugging the decoder or a template that fails to
672 decode, put SEC_ASN1_DEBUG in the component that gives you
673 trouble. The decoder will then get to this block and assert.
674 If you want to debug the rest of the code, you can set a
675 breakpoint and set dontassert to PR_TRUE, which will let
676 you skip over the assert and continue the debugging session
678 PRBool dontassert
= PR_FALSE
;
679 PR_ASSERT(dontassert
); /* set bkpoint here & set dontassert*/
683 if ((kind
& SEC_ASN1_SKIP
) ||
684 (kind
& SEC_ASN1_SAVE
))
686 /* if skipping or saving this component, don't decode it */
690 if (kind
& (SEC_ASN1_SAVE
| SEC_ASN1_OPTIONAL
))
692 /* if saving this component, or if it is optional, we may not want to
693 move past it, so save the position in case we have to rewind */
695 if (kind
& SEC_ASN1_SAVE
)
698 if (0 == (kind
& SEC_ASN1_SKIP
))
700 /* we will for sure have to rewind when saving this
701 component and not skipping it. This is true for all
702 legacy uses of SEC_ASN1_SAVE where the following entry
703 in the template would causes the same component to be
710 rv
= GetItem(src
, &temp
, PR_TRUE
);
713 if (SECSuccess
== rv
)
715 /* now check if the component matches what we expect in the template */
717 if (PR_TRUE
== checkTag
)
720 rv
= MatchComponentType(templateEntry
, &temp
, &match
, dest
);
723 if ( (SECSuccess
== rv
) && (PR_TRUE
!= match
) )
725 if (kind
& SEC_ASN1_OPTIONAL
)
728 /* the optional component is missing. This is not fatal. */
729 /* Rewind, don't decode, and don't save */
736 /* a required component is missing. abort */
737 PORT_SetError(SEC_ERROR_BAD_DER
);
743 if ((SECSuccess
== rv
) && (PR_TRUE
== decode
))
745 /* the order of processing here is is the tricky part */
746 /* we start with our special cases */
747 /* first, check the component class */
748 if (kind
& SEC_ASN1_INLINE
)
750 /* decode inline template */
751 rv
= DecodeInline(dest
, templateEntry
, &temp
, arena
, PR_TRUE
);
755 if (kind
& SEC_ASN1_EXPLICIT
)
757 rv
= DecodeExplicit(dest
, templateEntry
, &temp
, arena
);
760 if ( (SEC_ASN1_UNIVERSAL
!= (kind
& SEC_ASN1_CLASS_MASK
)) &&
762 (!(kind
& SEC_ASN1_EXPLICIT
)))
765 /* decode implicitly tagged components */
766 rv
= DecodeImplicit(dest
, templateEntry
, &temp
, arena
);
769 if (kind
& SEC_ASN1_POINTER
)
771 rv
= DecodePointer(dest
, templateEntry
, &temp
, arena
, PR_TRUE
);
774 if (kind
& SEC_ASN1_CHOICE
)
776 rv
= DecodeChoice(dest
, templateEntry
, &temp
, arena
);
779 if (kind
& SEC_ASN1_ANY
)
781 /* catch-all ANY type, don't decode */
783 if (kind
& SEC_ASN1_INNER
)
785 /* skip the tag and length */
786 SECItem newtemp
= temp
;
787 rv
= GetItem(&newtemp
, &temp
, PR_FALSE
);
791 if (kind
& SEC_ASN1_GROUP
)
793 if ( (SEC_ASN1_SEQUENCE
== (kind
& SEC_ASN1_TAGNUM_MASK
)) ||
794 (SEC_ASN1_SET
== (kind
& SEC_ASN1_TAGNUM_MASK
)) )
796 rv
= DecodeGroup(dest
, templateEntry
, &temp
, arena
);
800 /* a group can only be a SET OF or SEQUENCE OF */
801 PORT_SetError(SEC_ERROR_BAD_TEMPLATE
);
806 if (SEC_ASN1_SEQUENCE
== (kind
& SEC_ASN1_TAGNUM_MASK
))
809 rv
= DecodeSequence(dest
, templateEntry
, &temp
, arena
);
813 /* handle all other types as "save" */
814 /* we should only get here for primitive universal types */
815 SECItem newtemp
= temp
;
816 rv
= GetItem(&newtemp
, &temp
, PR_FALSE
);
818 if ((SECSuccess
== rv
) && SEC_ASN1_UNIVERSAL
== (kind
& SEC_ASN1_CLASS_MASK
))
819 switch (kind
& SEC_ASN1_TAGNUM_MASK
)
821 /* special cases of primitive types */
822 case SEC_ASN1_INTEGER
:
824 /* remove leading zeroes if the caller requested siUnsignedInteger
825 This is to allow RSA key operations to work */
826 SECItem
* destItem
= (SECItem
*) ((char*)dest
+ templateEntry
->offset
);
827 if (destItem
&& (siUnsignedInteger
== destItem
->type
))
829 while (temp
.len
> 1 && temp
.data
[0] == 0)
838 case SEC_ASN1_BIT_STRING
:
840 /* change the length in the SECItem to be the number of bits */
841 if (temp
.len
&& temp
.data
)
843 temp
.len
= (temp
.len
-1)*8 - ((*(unsigned char*)temp
.data
) & 0x7);
844 temp
.data
= (unsigned char*)(temp
.data
+1);
857 if ((SECSuccess
== rv
) && (PR_TRUE
== save
))
859 SECItem
* destItem
= (SECItem
*) ((char*)dest
+ templateEntry
->offset
);
862 /* we leave the type alone in the destination SECItem.
863 If part of the destination was allocated by the decoder, in
864 cases of POINTER, SET OF and SEQUENCE OF, then type is set to
865 siBuffer due to the use of PORT_ArenaZAlloc*/
866 destItem
->data
= temp
.data
;
867 destItem
->len
= temp
.len
;
871 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
878 /* we don't want to move ahead, so restore the position */
884 /* the function below is the public one */
886 SECStatus
SEC_QuickDERDecodeItem(PRArenaPool
* arena
, void* dest
,
887 const SEC_ASN1Template
* templateEntry
,
890 SECStatus rv
= SECSuccess
;
893 if (!arena
|| !templateEntry
|| !src
)
895 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
899 if (SECSuccess
== rv
)
902 rv
= DecodeItem(dest
, templateEntry
, &newsrc
, arena
, PR_TRUE
);
903 if (SECSuccess
== rv
&& newsrc
.len
)
906 PORT_SetError(SEC_ERROR_EXTRA_INPUT
);