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

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 Optimized ASN.1 DER decoder
7
8 */
9
10 #include "secerr.h"
11 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */
12 #include "secitem.h"
13
14 /*
15 * simple definite-length ASN.1 decoder
16 */
17
18 static unsigned char* definite_length_decoder(const unsigned char *buf,
19 const unsigned int length,
20 unsigned int *data_length,
21 PRBool includeTag)
22 {
23 unsigned char tag;
24 unsigned int used_length= 0;
25 unsigned int data_len;
26
27 if (used_length >= length)
28 {
29 return NULL;
30 }
31 tag = buf[used_length++];
32
33 /* blow out when we come to the end */
34 if (tag == 0)
35 {
36 return NULL;
37 }
38
39 if (used_length >= length)
40 {
41 return NULL;
42 }
43 data_len = buf[used_length++];
44
45 if (data_len&0x80)
46 {
47 int len_count = data_len & 0x7f;
48
49 data_len = 0;
50
51 while (len_count-- > 0)
52 {
53 if (used_length >= length)
54 {
55 return NULL;
56 }
57 data_len = (data_len << 8) | buf[used_length++];
58 }
59 }
60
61 if (data_len > (length-used_length) )
62 {
63 return NULL;
64 }
65 if (includeTag) data_len += used_length;
66
67 *data_length = data_len;
68 return ((unsigned char*)buf + (includeTag ? 0 : used_length));
69 }
70
71 static SECStatus GetItem(SECItem* src, SECItem* dest, PRBool includeTag)
72 {
73 if ( (!src) || (!dest) || (!src->data && src->len) )
74 {
75 PORT_SetError(SEC_ERROR_INVALID_ARGS);
76 return SECFailure;
77 }
78
79 if (!src->len)
80 {
81 /* reaching the end of the buffer is not an error */
82 dest->data = NULL;
83 dest->len = 0;
84 return SECSuccess;
85 }
86
87 dest->data = definite_length_decoder(src->data, src->len, &dest->len,
88 includeTag);
89 if (dest->data == NULL)
90 {
91 PORT_SetError(SEC_ERROR_BAD_DER);
92 return SECFailure;
93 }
94 src->len -= (dest->data - src->data) + dest->len;
95 src->data = dest->data + dest->len;
96 return SECSuccess;
97 }
98
99 /* check if the actual component's type matches the type in the template */
100
101 static SECStatus MatchComponentType(const SEC_ASN1Template* templateEntry,
102 SECItem* item, PRBool* match, void* dest)
103 {
104 unsigned long kind = 0;
105 unsigned char tag = 0;
106
107 if ( (!item) || (!item->data && item->len) || (!templateEntry) || (!match) )
108 {
109 PORT_SetError(SEC_ERROR_INVALID_ARGS);
110 return SECFailure;
111 }
112
113 if (!item->len)
114 {
115 *match = PR_FALSE;
116 return SECSuccess;
117 }
118
119 kind = templateEntry->kind;
120 tag = *(unsigned char*) item->data;
121
122 if ( ( (kind & SEC_ASN1_INLINE) ||
123 (kind & SEC_ASN1_POINTER) ) &&
124 (0 == (kind & SEC_ASN1_TAG_MASK) ) )
125 {
126 /* These cases are special because the template's "kind" does not
127 give us the information for the ASN.1 tag of the next item. It can
128 only be figured out from the subtemplate. */
129 if (!(kind & SEC_ASN1_OPTIONAL))
130 {
131 /* This is a required component. If there is a type mismatch,
132 the decoding of the subtemplate will fail, so assume this
133 is a match at the parent level and let it fail later. This
134 avoids a redundant check in matching cases */
135 *match = PR_TRUE;
136 return SECSuccess;
137 }
138 else
139 {
140 /* optional component. This is the hard case. Now we need to
141 look at the subtemplate to get the expected kind */
142 const SEC_ASN1Template* subTemplate =
143 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE);
144 if (!subTemplate)
145 {
146 PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
147 return SECFailure;
148 }
149 if ( (subTemplate->kind & SEC_ASN1_INLINE) ||
150 (subTemplate->kind & SEC_ASN1_POINTER) )
151 {
152 /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE,
153 otherwise you may get a false positive due to the recursion
154 optimization above that always matches the type if the
155 component is required . Nesting these should never be
156 required, so that no one should miss this ability */
157 PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
158 return SECFailure;
159 }
160 return MatchComponentType(subTemplate, item, match,
161 (void*)((char*)dest + templateEntry->offset));
162 }
163 }
164
165 if (kind & SEC_ASN1_CHOICE)
166 {
167 /* we need to check the component's tag against each choice's tag */
168 /* XXX it would be nice to save the index of the choice here so that
169 DecodeChoice wouldn't have to do this again. However, due to the
170 recursivity of MatchComponentType, we don't know if we are in a
171 required or optional component, so we can't write anywhere in
172 the destination within this function */
173 unsigned choiceIndex = 1;
174 const SEC_ASN1Template* choiceEntry;
175 while ( (choiceEntry = &templateEntry[choiceIndex++]) && (choiceEntry->kind))
176 {
177 if ( (SECSuccess == MatchComponentType(choiceEntry, item, match,
178 (void*)((char*)dest + choiceEntry->offset))) &&
179 (PR_TRUE == *match) )
180 {
181 return SECSuccess;
182 }
183 }
184 /* no match, caller must decide if this is BAD DER, or not. */
185 *match = PR_FALSE;
186 return SECSuccess;
187 }
188
189 if (kind & SEC_ASN1_ANY)
190 {
191 /* SEC_ASN1_ANY always matches */
192 *match = PR_TRUE;
193 return SECSuccess;
194 }
195
196 if ( (0 == ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK)) &&
197 (!(kind & SEC_ASN1_EXPLICIT)) &&
198 ( ( (kind & SEC_ASN1_SAVE) ||
199 (kind & SEC_ASN1_SKIP) ) &&
200 (!(kind & SEC_ASN1_OPTIONAL))
201 )
202 )
203 {
204 /* when saving or skipping a required component, a type is not
205 required in the template. This is for legacy support of
206 SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to
207 deprecate these usages and always require a type, as this
208 disables type checking, and effectively forbids us from
209 transparently ignoring optional components we aren't aware of */
210 *match = PR_TRUE;
211 return SECSuccess;
212 }
213
214 /* first, do a class check */
215 if ( (tag & SEC_ASN1_CLASS_MASK) !=
216 (((unsigned char)kind) & SEC_ASN1_CLASS_MASK) )
217 {
218 #ifdef DEBUG
219 /* this is only to help debugging of the decoder in case of problems */
220 unsigned char tagclass = tag & SEC_ASN1_CLASS_MASK;
221 unsigned char expectedclass = (unsigned char)kind & SEC_ASN1_CLASS_MASK;
222 tagclass = tagclass;
223 expectedclass = expectedclass;
224 #endif
225 *match = PR_FALSE;
226 return SECSuccess;
227 }
228
229 /* now do a tag check */
230 if ( ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK) !=
231 (tag & SEC_ASN1_TAGNUM_MASK))
232 {
233 *match = PR_FALSE;
234 return SECSuccess;
235 }
236
237 /* now, do a method check. This depends on the class */
238 switch (tag & SEC_ASN1_CLASS_MASK)
239 {
240 case SEC_ASN1_UNIVERSAL:
241 /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be
242 primitive or constructed based on the tag */
243 switch (tag & SEC_ASN1_TAGNUM_MASK)
244 {
245 case SEC_ASN1_SEQUENCE:
246 case SEC_ASN1_SET:
247 case SEC_ASN1_EMBEDDED_PDV:
248 /* this component must be a constructed type */
249 /* XXX add any new universal constructed type here */
250 if (tag & SEC_ASN1_CONSTRUCTED)
251 {
252 *match = PR_TRUE;
253 return SECSuccess;
254 }
255 break;
256
257 default:
258 /* this component must be a primitive type */
259 if (! (tag & SEC_ASN1_CONSTRUCTED))
260 {
261 *match = PR_TRUE;
262 return SECSuccess;
263 }
264 break;
265 }
266 break;
267
268 default:
269 /* for all other classes, we check the method based on the template */
270 if ( (unsigned char)(kind & SEC_ASN1_METHOD_MASK) ==
271 (tag & SEC_ASN1_METHOD_MASK) )
272 {
273 *match = PR_TRUE;
274 return SECSuccess;
275 }
276 /* method does not match between template and component */
277 break;
278 }
279
280 *match = PR_FALSE;
281 return SECSuccess;
282 }
283
284 #ifdef DEBUG
285
286 static SECStatus CheckSequenceTemplate(const SEC_ASN1Template* sequenceTemplate)
287 {
288 SECStatus rv = SECSuccess;
289 const SEC_ASN1Template* sequenceEntry = NULL;
290 unsigned long seqIndex = 0;
291 unsigned long lastEntryIndex = 0;
292 unsigned long ambiguityIndex = 0;
293 PRBool foundAmbiguity = PR_FALSE;
294
295 do
296 {
297 sequenceEntry = &sequenceTemplate[seqIndex++];
298 if (sequenceEntry->kind)
299 {
300 /* ensure that we don't have an optional component of SEC_ASN1_ANY
301 in the middle of the sequence, since we could not handle it */
302 /* XXX this function needs to dig into the subtemplates to find
303 the next tag */
304 if ( (PR_FALSE == foundAmbiguity) &&
305 (sequenceEntry->kind & SEC_ASN1_OPTIONAL) &&
306 (sequenceEntry->kind & SEC_ASN1_ANY) )
307 {
308 foundAmbiguity = PR_TRUE;
309 ambiguityIndex = seqIndex - 1;
310 }
311 }
312 } while (sequenceEntry->kind);
313
314 lastEntryIndex = seqIndex - 2;
315
316 if (PR_FALSE != foundAmbiguity)
317 {
318 if (ambiguityIndex < lastEntryIndex)
319 {
320 /* ambiguity can only be tolerated on the last entry */
321 PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
322 rv = SECFailure;
323 }
324 }
325
326 /* XXX also enforce ASN.1 requirement that tags be
327 distinct for consecutive optional components */
328
329 return rv;
330 }
331
332 #endif
333
334 static SECStatus DecodeItem(void* dest,
335 const SEC_ASN1Template* templateEntry,
336 SECItem* src, PLArenaPool* arena, PRBool checkTag);
337
338 static SECStatus DecodeSequence(void* dest,
339 const SEC_ASN1Template* templateEntry,
340 SECItem* src, PLArenaPool* arena)
341 {
342 SECStatus rv = SECSuccess;
343 SECItem source;
344 SECItem sequence;
345 const SEC_ASN1Template* sequenceTemplate = &(templateEntry[1]);
346 const SEC_ASN1Template* sequenceEntry = NULL;
347 unsigned long seqindex = 0;
348
349 #ifdef DEBUG
350 /* for a sequence, we need to validate the template. */
351 rv = CheckSequenceTemplate(sequenceTemplate);
352 #endif
353
354 source = *src;
355
356 /* get the sequence */
357 if (SECSuccess == rv)
358 {
359 rv = GetItem(&source, &sequence, PR_FALSE);
360 }
361
362 /* process it */
363 if (SECSuccess == rv)
364 do
365 {
366 sequenceEntry = &sequenceTemplate[seqindex++];
367 if ( (sequenceEntry && sequenceEntry->kind) &&
368 (sequenceEntry->kind != SEC_ASN1_SKIP_REST) )
369 {
370 rv = DecodeItem(dest, sequenceEntry, &sequence, arena, PR_TRUE);
371 }
372 } while ( (SECSuccess == rv) &&
373 (sequenceEntry->kind &&
374 sequenceEntry->kind != SEC_ASN1_SKIP_REST) );
375 /* we should have consumed all the bytes in the sequence by now
376 unless the caller doesn't care about the rest of the sequence */
377 if (SECSuccess == rv && sequence.len &&
378 sequenceEntry && sequenceEntry->kind != SEC_ASN1_SKIP_REST)
379 {
380 /* it isn't 100% clear whether this is a bad DER or a bad template.
381 The problem is that logically, they don't match - there is extra
382 data in the DER that the template doesn't know about */
383 PORT_SetError(SEC_ERROR_BAD_DER);
384 rv = SECFailure;
385 }
386
387 return rv;
388 }
389
390 static SECStatus DecodeInline(void* dest,
391 const SEC_ASN1Template* templateEntry,
392 SECItem* src, PLArenaPool* arena, PRBool checkTag)
393 {
394 const SEC_ASN1Template* inlineTemplate =
395 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE);
396 return DecodeItem((void*)((char*)dest + templateEntry->offset),
397 inlineTemplate, src, arena, checkTag);
398 }
399
400 static SECStatus DecodePointer(void* dest,
401 const SEC_ASN1Template* templateEntry,
402 SECItem* src, PLArenaPool* arena, PRBool checkTag)
403 {
404 const SEC_ASN1Template* ptrTemplate =
405 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE);
406 void* subdata = PORT_ArenaZAlloc(arena, ptrTemplate->size);
407 *(void**)((char*)dest + templateEntry->offset) = subdata;
408 if (subdata)
409 {
410 return DecodeItem(subdata, ptrTemplate, src, arena, checkTag);
411 }
412 else
413 {
414 PORT_SetError(SEC_ERROR_NO_MEMORY);
415 return SECFailure;
416 }
417 }
418
419 static SECStatus DecodeImplicit(void* dest,
420 const SEC_ASN1Template* templateEntry,
421 SECItem* src, PLArenaPool* arena)
422 {
423 if (templateEntry->kind & SEC_ASN1_POINTER)
424 {
425 return DecodePointer((void*)((char*)dest ),
426 templateEntry, src, arena, PR_FALSE);
427 }
428 else
429 {
430 return DecodeInline((void*)((char*)dest ),
431 templateEntry, src, arena, PR_FALSE);
432 }
433 }
434
435 static SECStatus DecodeChoice(void* dest,
436 const SEC_ASN1Template* templateEntry,
437 SECItem* src, PLArenaPool* arena)
438 {
439 SECStatus rv = SECSuccess;
440 SECItem choice;
441 const SEC_ASN1Template* choiceTemplate = &(templateEntry[1]);
442 const SEC_ASN1Template* choiceEntry = NULL;
443 unsigned long choiceindex = 0;
444
445 /* XXX for a choice component, we should validate the template to make
446 sure the tags are distinct, in debug builds. This hasn't been
447 implemented yet */
448 /* rv = CheckChoiceTemplate(sequenceTemplate); */
449
450 /* process it */
451 do
452 {
453 choice = *src;
454 choiceEntry = &choiceTemplate[choiceindex++];
455 if (choiceEntry->kind)
456 {
457 rv = DecodeItem(dest, choiceEntry, &choice, arena, PR_TRUE);
458 }
459 } while ( (SECFailure == rv) && (choiceEntry->kind));
460
461 if (SECFailure == rv)
462 {
463 /* the component didn't match any of the choices */
464 PORT_SetError(SEC_ERROR_BAD_DER);
465 }
466 else
467 {
468 /* set the type in the union here */
469 int *which = (int *)((char *)dest + templateEntry->offset);
470 *which = (int)choiceEntry->size;
471 }
472
473 /* we should have consumed all the bytes by now */
474 /* fail if we have not */
475 if (SECSuccess == rv && choice.len)
476 {
477 /* there is extra data that isn't listed in the template */
478 PORT_SetError(SEC_ERROR_BAD_DER);
479 rv = SECFailure;
480 }
481 return rv;
482 }
483
484 static SECStatus DecodeGroup(void* dest,
485 const SEC_ASN1Template* templateEntry,
486 SECItem* src, PLArenaPool* arena)
487 {
488 SECStatus rv = SECSuccess;
489 SECItem source;
490 SECItem group;
491 PRUint32 totalEntries = 0;
492 PRUint32 entryIndex = 0;
493 void** entries = NULL;
494
495 const SEC_ASN1Template* subTemplate =
496 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE);
497
498 source = *src;
499
500 /* get the group */
501 if (SECSuccess == rv)
502 {
503 rv = GetItem(&source, &group, PR_FALSE);
504 }
505
506 /* XXX we should check the subtemplate in debug builds */
507 if (SECSuccess == rv)
508 {
509 /* first, count the number of entries. Benchmarking showed that this
510 counting pass is more efficient than trying to allocate entries as
511 we read the DER, even if allocating many entries at a time
512 */
513 SECItem counter = group;
514 do
515 {
516 SECItem anitem;
517 rv = GetItem(&counter, &anitem, PR_TRUE);
518 if (SECSuccess == rv && (anitem.len) )
519 {
520 totalEntries++;
521 }
522 } while ( (SECSuccess == rv) && (counter.len) );
523
524 if (SECSuccess == rv)
525 {
526 /* allocate room for pointer array and entries */
527 /* we want to allocate the array even if there is 0 entry */
528 entries = (void**)PORT_ArenaZAlloc(arena, sizeof(void*)*
529 (totalEntries + 1 ) + /* the extra one is for NULL termination */
530 subTemplate->size*totalEntries);
531
532 if (entries)
533 {
534 entries[totalEntries] = NULL; /* terminate the array */
535 }
536 else
537 {
538 PORT_SetError(SEC_ERROR_NO_MEMORY);
539 rv = SECFailure;
540 }
541 if (SECSuccess == rv)
542 {
543 void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*)*(totalEntries + 1 ));
544 /* and fix the pointers in the array */
545 PRUint32 entriesIndex = 0;
546 for (entriesIndex = 0;entriesIndex<totalEntries;entriesIndex++)
547 {
548 entries[entriesIndex] =
549 (char*)entriesData + (subTemplate->size*entriesIndex);
550 }
551 }
552 }
553 }
554
555 if (SECSuccess == rv && totalEntries)
556 do
557 {
558 if (!(entryIndex<totalEntries))
559 {
560 rv = SECFailure;
561 break;
562 }
563 rv = DecodeItem(entries[entryIndex++], subTemplate, &group, arena, PR_TRUE);
564 } while ( (SECSuccess == rv) && (group.len) );
565 /* we should be at the end of the set by now */
566 /* save the entries where requested */
567 memcpy(((char*)dest + templateEntry->offset), &entries, sizeof(void**));
568
569 return rv;
570 }
571
572 static SECStatus DecodeExplicit(void* dest,
573 const SEC_ASN1Template* templateEntry,
574 SECItem* src, PLArenaPool* arena)
575 {
576 SECStatus rv = SECSuccess;
577 SECItem subItem;
578 SECItem constructed = *src;
579
580 rv = GetItem(&constructed, &subItem, PR_FALSE);
581
582 if (SECSuccess == rv)
583 {
584 if (templateEntry->kind & SEC_ASN1_POINTER)
585 {
586 rv = DecodePointer(dest, templateEntry, &subItem, arena, PR_TRUE);
587 }
588 else
589 {
590 rv = DecodeInline(dest, templateEntry, &subItem, arena, PR_TRUE);
591 }
592 }
593
594 return rv;
595 }
596
597 /* new decoder implementation. This is a recursive function */
598
599 static SECStatus DecodeItem(void* dest,
600 const SEC_ASN1Template* templateEntry,
601 SECItem* src, PLArenaPool* arena, PRBool checkTag)
602 {
603 SECStatus rv = SECSuccess;
604 SECItem temp;
605 SECItem mark;
606 PRBool pop = PR_FALSE;
607 PRBool decode = PR_TRUE;
608 PRBool save = PR_FALSE;
609 unsigned long kind;
610 PRBool match = PR_TRUE;
611 PRBool optional = PR_FALSE;
612
613 PR_ASSERT(src && dest && templateEntry && arena);
614 #if 0
615 if (!src || !dest || !templateEntry || !arena)
616 {
617 PORT_SetError(SEC_ERROR_INVALID_ARGS);
618 rv = SECFailure;
619 }
620 #endif
621
622 if (SECSuccess == rv)
623 {
624 /* do the template validation */
625 kind = templateEntry->kind;
626 optional = (0 != (kind & SEC_ASN1_OPTIONAL));
627 if (!kind)
628 {
629 PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
630 rv = SECFailure;
631 }
632 }
633
634 if (SECSuccess == rv)
635 {
636 #ifdef DEBUG
637 if (kind & SEC_ASN1_DEBUG_BREAK)
638 {
639 /* when debugging the decoder or a template that fails to
640 decode, put SEC_ASN1_DEBUG in the component that gives you
641 trouble. The decoder will then get to this block and assert.
642 If you want to debug the rest of the code, you can set a
643 breakpoint and set dontassert to PR_TRUE, which will let
644 you skip over the assert and continue the debugging session
645 past it. */
646 PRBool dontassert = PR_FALSE;
647 PR_ASSERT(dontassert); /* set bkpoint here & set dontassert*/
648 }
649 #endif
650
651 if ((kind & SEC_ASN1_SKIP) ||
652 (kind & SEC_ASN1_SAVE))
653 {
654 /* if skipping or saving this component, don't decode it */
655 decode = PR_FALSE;
656 }
657
658 if (kind & (SEC_ASN1_SAVE | SEC_ASN1_OPTIONAL))
659 {
660 /* if saving this component, or if it is optional, we may not want to
661 move past it, so save the position in case we have to rewind */
662 mark = *src;
663 if (kind & SEC_ASN1_SAVE)
664 {
665 save = PR_TRUE;
666 if (0 == (kind & SEC_ASN1_SKIP))
667 {
668 /* we will for sure have to rewind when saving this
669 component and not skipping it. This is true for all
670 legacy uses of SEC_ASN1_SAVE where the following entry
671 in the template would causes the same component to be
672 processed again */
673 pop = PR_TRUE;
674 }
675 }
676 }
677
678 rv = GetItem(src, &temp, PR_TRUE);
679 }
680
681 if (SECSuccess == rv)
682 {
683 /* now check if the component matches what we expect in the template */
684
685 if (PR_TRUE == checkTag)
686
687 {
688 rv = MatchComponentType(templateEntry, &temp, &match, dest);
689 }
690
691 if ( (SECSuccess == rv) && (PR_TRUE != match) )
692 {
693 if (kind & SEC_ASN1_OPTIONAL)
694 {
695
696 /* the optional component is missing. This is not fatal. */
697 /* Rewind, don't decode, and don't save */
698 pop = PR_TRUE;
699 decode = PR_FALSE;
700 save = PR_FALSE;
701 }
702 else
703 {
704 /* a required component is missing. abort */
705 PORT_SetError(SEC_ERROR_BAD_DER);
706 rv = SECFailure;
707 }
708 }
709 }
710
711 if ((SECSuccess == rv) && (PR_TRUE == decode))
712 {
713 /* the order of processing here is is the tricky part */
714 /* we start with our special cases */
715 /* first, check the component class */
716 if (kind & SEC_ASN1_INLINE)
717 {
718 /* decode inline template */
719 rv = DecodeInline(dest, templateEntry, &temp , arena, PR_TRUE);
720 }
721
722 else
723 if (kind & SEC_ASN1_EXPLICIT)
724 {
725 rv = DecodeExplicit(dest, templateEntry, &temp, arena);
726 }
727 else
728 if ( (SEC_ASN1_UNIVERSAL != (kind & SEC_ASN1_CLASS_MASK)) &&
729
730 (!(kind & SEC_ASN1_EXPLICIT)))
731 {
732
733 /* decode implicitly tagged components */
734 rv = DecodeImplicit(dest, templateEntry, &temp , arena);
735 }
736 else
737 if (kind & SEC_ASN1_POINTER)
738 {
739 rv = DecodePointer(dest, templateEntry, &temp, arena, PR_TRUE);
740 }
741 else
742 if (kind & SEC_ASN1_CHOICE)
743 {
744 rv = DecodeChoice(dest, templateEntry, &temp, arena);
745 }
746 else
747 if (kind & SEC_ASN1_ANY)
748 {
749 /* catch-all ANY type, don't decode */
750 save = PR_TRUE;
751 if (kind & SEC_ASN1_INNER)
752 {
753 /* skip the tag and length */
754 SECItem newtemp = temp;
755 rv = GetItem(&newtemp, &temp, PR_FALSE);
756 }
757 }
758 else
759 if (kind & SEC_ASN1_GROUP)
760 {
761 if ( (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) ||
762 (SEC_ASN1_SET == (kind & SEC_ASN1_TAGNUM_MASK)) )
763 {
764 rv = DecodeGroup(dest, templateEntry, &temp , arena);
765 }
766 else
767 {
768 /* a group can only be a SET OF or SEQUENCE OF */
769 PORT_SetError(SEC_ERROR_BAD_TEMPLATE);
770 rv = SECFailure;
771 }
772 }
773 else
774 if (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK))
775 {
776 /* plain SEQUENCE */
777 rv = DecodeSequence(dest, templateEntry, &temp , arena);
778 }
779 else
780 {
781 /* handle all other types as "save" */
782 /* we should only get here for primitive universal types */
783 SECItem newtemp = temp;
784 rv = GetItem(&newtemp, &temp, PR_FALSE);
785 save = PR_TRUE;
786 if ((SECSuccess == rv) &&
787 SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK))
788 {
789 unsigned long tagnum = kind & SEC_ASN1_TAGNUM_MASK;
790 if ( temp.len == 0 && (tagnum == SEC_ASN1_BOOLEAN ||
791 tagnum == SEC_ASN1_INTEGER ||
792 tagnum == SEC_ASN1_BIT_STRING ||
793 tagnum == SEC_ASN1_OBJECT_ID ||
794 tagnum == SEC_ASN1_ENUMERATED ||
795 tagnum == SEC_ASN1_UTC_TIME ||
796 tagnum == SEC_ASN1_GENERALIZED_TIME) )
797 {
798 /* these types MUST have at least one content octet */
799 PORT_SetError(SEC_ERROR_BAD_DER);
800 rv = SECFailure;
801 }
802 else
803 switch (tagnum)
804 {
805 /* special cases of primitive types */
806 case SEC_ASN1_INTEGER:
807 {
808 /* remove leading zeroes if the caller requested
809 siUnsignedInteger
810 This is to allow RSA key operations to work */
811 SECItem* destItem = (SECItem*) ((char*)dest +
812 templateEntry->offset);
813 if (destItem && (siUnsignedInteger == destItem->type))
814 {
815 while (temp.len > 1 && temp.data[0] == 0)
816 { /* leading 0 */
817 temp.data++;
818 temp.len--;
819 }
820 }
821 break;
822 }
823
824 case SEC_ASN1_BIT_STRING:
825 {
826 /* change the length in the SECItem to be the number
827 of bits */
828 temp.len = (temp.len-1)*8 - (temp.data[0] & 0x7);
829 temp.data++;
830 break;
831 }
832
833 default:
834 {
835 break;
836 }
837 }
838 }
839 }
840 }
841
842 if ((SECSuccess == rv) && (PR_TRUE == save))
843 {
844 SECItem* destItem = (SECItem*) ((char*)dest + templateEntry->offset);
845 if (destItem)
846 {
847 /* we leave the type alone in the destination SECItem.
848 If part of the destination was allocated by the decoder, in
849 cases of POINTER, SET OF and SEQUENCE OF, then type is set to
850 siBuffer due to the use of PORT_ArenaZAlloc*/
851 destItem->data = temp.len ? temp.data : NULL;
852 destItem->len = temp.len;
853 }
854 else
855 {
856 PORT_SetError(SEC_ERROR_INVALID_ARGS);
857 rv = SECFailure;
858 }
859 }
860
861 if (PR_TRUE == pop)
862 {
863 /* we don't want to move ahead, so restore the position */
864 *src = mark;
865 }
866 return rv;
867 }
868
869 /* the function below is the public one */
870
871 SECStatus SEC_QuickDERDecodeItem(PLArenaPool* arena, void* dest,
872 const SEC_ASN1Template* templateEntry,
873 const SECItem* src)
874 {
875 SECStatus rv = SECSuccess;
876 SECItem newsrc;
877
878 if (!arena || !templateEntry || !src)
879 {
880 PORT_SetError(SEC_ERROR_INVALID_ARGS);
881 rv = SECFailure;
882 }
883
884 if (SECSuccess == rv)
885 {
886 newsrc = *src;
887 rv = DecodeItem(dest, templateEntry, &newsrc, arena, PR_TRUE);
888 if (SECSuccess == rv && newsrc.len)
889 {
890 rv = SECFailure;
891 PORT_SetError(SEC_ERROR_EXTRA_INPUT);
892 }
893 }
894
895 return rv;
896 }
897
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)