]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c
04374a35cb293a739a2b8ab87e60bf53e5601f0a
[apple/security.git] / OSX / libsecurity_keychain / libDER / libDER / DER_Decode.c
1 /*
2 * Copyright (c) 2005-2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * DER_Decode.c - DER decoding routines
26 */
27
28 #include <libDER/DER_Decode.h>
29 #include <libDER/asn1Types.h>
30
31 #include <libDER/libDER_config.h>
32
33 #ifndef DER_DECODE_ENABLE
34 #error Please define DER_DECODE_ENABLE.
35 #endif
36
37 #if DER_DECODE_ENABLE
38
39 #define DER_DECODE_DEBUG 0
40 #if DER_DECODE_DEBUG
41 #include <stdio.h>
42 #define derDecDbg(a) printf(a)
43 #define derDecDbg1(a, b) printf(a, b)
44 #define derDecDbg2(a, b, c) printf(a, b, c)
45 #define derDecDbg3(a, b, c, d) printf(a, b, c, d)
46 #else
47 #define derDecDbg(a)
48 #define derDecDbg1(a, b)
49 #define derDecDbg2(a, b, c)
50 #define derDecDbg3(a, b, c, d)
51 #endif /* DER_DECODE_DEBUG */
52
53 /*
54 * Basic decoding primitive. Only works with:
55 *
56 * -- definite length encoding
57 * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
58 * -- max content length fits in a DERSize
59 *
60 * No malloc or copy of the contents is performed; the returned
61 * content->content.data is a pointer into the incoming der data.
62 */
63 DERReturn DERDecodeItem(
64 const DERItem *der, /* data to decode */
65 DERDecodedInfo *decoded) /* RETURNED */
66 {
67 return DERDecodeItemPartialBufferGetLength(der, decoded, NULL);
68 }
69
70 /*
71 * Basic decoding primitive. Allows for decoding with a partial buffer.
72 * if allowPartialBuffer is true. A partial buffer would normally fail
73 * because the encoded length would be greater than the size of the buffer passed in.
74 * Only works with:
75 *
76 * -- definite length encoding
77 * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
78 * -- max content length fits in a DERSize
79 *
80 * No malloc or copy of the contents is performed; the returned
81 * content->content.data is a pointer into the incoming der data.
82 *
83 * WARNING: Using a partial buffer can return a DERDecodedInfo object with
84 * a length larger than the buffer. It is recommended to instead use
85 * DERDecodeItemPartialBufferGetLength if you need partial buffers.
86 *
87 */
88 DERReturn DERDecodeItemPartialBuffer(
89 const DERItem *der, /* data to decode */
90 DERDecodedInfo *decoded, /* RETURNED */
91 bool allowPartialBuffer)
92 {
93 DERByte tag1; /* first tag byte */
94 DERByte len1; /* first length byte */
95 DERTag tagNumber; /* tag number without class and method bits */
96 DERByte *derPtr = der->data;
97 DERSize derLen = der->length;
98
99 /* The tag decoding below is fully BER complient. We support a max tag
100 value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we
101 support tag values from 0 - 0x1F. For tag size 2 tag values
102 from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */
103 if(derLen < 2) {
104 return DR_DecodeError;
105 }
106 /* Grab the first byte of the tag. */
107 tag1 = *derPtr++;
108 derLen--;
109 tagNumber = tag1 & 0x1F;
110 if(tagNumber == 0x1F) {
111 #ifdef DER_MULTIBYTE_TAGS
112 /* Long tag form: bit 8 of each octet shall be set to one unless it is
113 the last octet of the tag */
114 const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7));
115 DERByte tagByte;
116 tagNumber = 0;
117 if (*derPtr == 0x80 || *derPtr < 0x1F)
118 return DR_DecodeError;
119 do {
120 if(derLen < 2 || (tagNumber & overflowMask) != 0) {
121 return DR_DecodeError;
122 }
123 tagByte = *derPtr++;
124 derLen--;
125 tagNumber = (tagNumber << 7) | (tagByte & 0x7F);
126 } while((tagByte & 0x80) != 0);
127
128 /* Check for any of the top 3 reserved bits being set. */
129 if ((tagNumber & (overflowMask << 4)) != 0)
130 #endif
131 return DR_DecodeError;
132 }
133 /* Returned tag, top 3 bits are class/method remaining bits are number. */
134 decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber;
135
136 /* Tag decoding above ensured we have at least one more input byte left. */
137 len1 = *derPtr++;
138 derLen--;
139 if(len1 & 0x80) {
140 /* long length form - first byte is length of length */
141 DERSize longLen = 0; /* long form length */
142
143 unsigned dex;
144 len1 &= 0x7f;
145 if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) {
146 /* no can do */
147 return DR_DecodeError;
148 }
149 for(dex=0; dex<len1; dex++) {
150 longLen <<= 8;
151 longLen |= *derPtr++;
152 derLen--;
153 }
154 if(longLen > derLen && !allowPartialBuffer) {
155 /* not enough data left for this encoding */
156 return DR_DecodeError;
157 }
158 decoded->content.data = derPtr;
159 decoded->content.length = longLen;
160 }
161 else {
162 /* short length form, len1 is the length */
163 if(len1 > derLen && !allowPartialBuffer) {
164 /* not enough data left for this encoding */
165 return DR_DecodeError;
166 }
167 decoded->content.data = derPtr;
168 decoded->content.length = len1;
169 }
170
171 return DR_Success;
172 }
173
174 /*
175 * Same as above, but returns a DERDecodedInfo with a length no larger than the buffer.
176 * The actual encoded length can be retrieved from encodedLength parameter.
177 * encodedLength can be NULL to achieve the same behavior as DERDecodeItemPartialBuffer,
178 * with allowPartialBuffer=false
179 *
180 * NOTE: The DERDecoded length will never be larger than the input buffer.
181 * This is a key difference from DERDecodeItemPartialBuffer which could return invalid length.
182 *
183 */
184 DERReturn DERDecodeItemPartialBufferGetLength(
185 const DERItem *der, /* data to decode */
186 DERDecodedInfo *decoded, /* RETURNED */
187 DERSize *encodedLength)
188 {
189 DERByte tag1; /* first tag byte */
190 DERByte len1; /* first length byte */
191 DERTag tagNumber; /* tag number without class and method bits */
192 DERByte *derPtr = der->data;
193 DERSize derLen = der->length;
194
195 /* The tag decoding below is fully BER complient. We support a max tag
196 value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we
197 support tag values from 0 - 0x1F. For tag size 2 tag values
198 from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */
199 if(derLen < 2) {
200 return DR_DecodeError;
201 }
202 /* Grab the first byte of the tag. */
203 tag1 = *derPtr++;
204 derLen--;
205 tagNumber = tag1 & 0x1F;
206 if(tagNumber == 0x1F) {
207 #ifdef DER_MULTIBYTE_TAGS
208 /* Long tag form: bit 8 of each octet shall be set to one unless it is
209 the last octet of the tag */
210 const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7));
211 DERByte tagByte;
212 tagNumber = 0;
213 if (*derPtr == 0x80 || *derPtr < 0x1F)
214 return DR_DecodeError;
215 do {
216 if(derLen < 2 || (tagNumber & overflowMask) != 0) {
217 return DR_DecodeError;
218 }
219 tagByte = *derPtr++;
220 derLen--;
221 tagNumber = (tagNumber << 7) | (tagByte & 0x7F);
222 } while((tagByte & 0x80) != 0);
223
224 /* Check for any of the top 3 reserved bits being set. */
225 if ((tagNumber & (overflowMask << 4)) != 0)
226 #endif
227 return DR_DecodeError;
228 }
229 /* Returned tag, top 3 bits are class/method remaining bits are number. */
230 decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber;
231
232 /* Tag decoding above ensured we have at least one more input byte left. */
233 len1 = *derPtr++;
234 derLen--;
235 if(len1 & 0x80) {
236 /* long length form - first byte is length of length */
237 DERSize longLen = 0; /* long form length */
238 unsigned dex;
239
240 len1 &= 0x7f;
241 if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) {
242 /* no can do */
243 return DR_DecodeError;
244 }
245 for(dex=0; dex<len1; dex++) {
246 longLen <<= 8;
247 longLen |= *derPtr++;
248 derLen--;
249 }
250 if(longLen > derLen && !encodedLength) {
251 /* not enough data left for this encoding */
252 return DR_DecodeError;
253 }
254 if (longLen<derLen) {
255 derLen = longLen;
256 }
257 decoded->content.data = derPtr;
258 decoded->content.length = derLen;
259 if (encodedLength) {
260 *encodedLength = longLen;
261 }
262 }
263 else {
264 /* short length form, len1 is the length */
265 if(len1 > derLen && !encodedLength) {
266 /* not enough data left for this encoding */
267 return DR_DecodeError;
268 }
269 if (len1<derLen) {
270 derLen=len1;
271 }
272 decoded->content.data = derPtr;
273 decoded->content.length = derLen;
274 if (encodedLength) {
275 *encodedLength = len1;
276 }
277 }
278
279 return DR_Success;
280 }
281
282 /*
283 * Given a BIT_STRING, in the form of its raw content bytes,
284 * obtain the number of unused bits and the raw bit string bytes.
285 */
286 DERReturn DERParseBitString(
287 const DERItem *contents,
288 DERItem *bitStringBytes, /* RETURNED */
289 DERByte *numUnusedBits) /* RETURNED */
290 {
291 if(contents->length < 2) {
292 /* not enough room for actual bits after the unused bits field */
293 *numUnusedBits = 0;
294 bitStringBytes->data = NULL;
295 bitStringBytes->length = 0;
296 return DR_Success;
297 }
298 *numUnusedBits = contents->data[0];
299 bitStringBytes->data = contents->data + 1;
300 bitStringBytes->length = contents->length - 1;
301 return DR_Success;
302 }
303
304 /*
305 * Given a BOOLEAN, in the form of its raw content bytes,
306 * obtain it's value.
307 */
308 DERReturn DERParseBoolean(
309 const DERItem *contents,
310 bool *value) { /* RETURNED */
311 if (contents->length != 1 ||
312 (contents->data[0] != 0 && contents->data[0] != 0xFF))
313 return DR_DecodeError;
314
315 *value = contents->data[0] != 0;
316 return DR_Success;
317 }
318
319 /*
320 * Given a BOOLEAN, in the form of its raw content bytes,
321 * obtain it's value.
322 */
323 DERReturn DERParseBooleanWithDefault(
324 const DERItem *contents,
325 bool defaultValue,
326 bool *value) { /* RETURNED */
327 if (contents->length == 0) {
328 *value = defaultValue;
329 return DR_Success;
330 }
331 return DERParseBoolean(contents, value);
332 }
333
334
335 DERReturn DERParseInteger(
336 const DERItem *contents,
337 uint32_t *result) { /* RETURNED */
338 uint64_t value;
339 DERReturn drtn = DERParseInteger64(contents, &value);
340 if (drtn == DR_Success) {
341 if (value > UINT32_MAX)
342 drtn = DR_BufOverflow;
343 else
344 *result = (uint32_t)value;
345 }
346 return drtn;
347 }
348
349 DERReturn DERParseInteger64(
350 const DERItem *contents,
351 uint64_t *result) { /* RETURNED */
352 DERSize ix, length = contents->length;
353 if (length == 0)
354 return DR_DecodeError;
355 if (contents->data[0] & 0x80)
356 return DR_DecodeError;
357 if (contents->data[0] == 0) {
358 if (length > 1 && (contents->data[1] & 0x80) == 0)
359 return DR_DecodeError;
360 if (length > sizeof(*result) + 1)
361 return DR_BufOverflow;
362 } else if (length > sizeof(*result)) {
363 return DR_BufOverflow;
364 }
365 uint64_t value = 0;
366 for (ix = 0; ix < length; ++ix) {
367 value <<= 8;
368 value += contents->data[ix];
369 }
370 *result = value;
371 return DR_Success;
372 }
373
374 /* Sequence/set support */
375
376 /*
377 * To decode a set or sequence, call DERDecodeSeqInit once, then
378 * call DERDecodeSeqNext to get each enclosed item.
379 * DERDecodeSeqNext returns DR_EndOfSequence when no more
380 * items are available.
381 */
382 DERReturn DERDecodeSeqInit(
383 const DERItem *der, /* data to decode */
384 DERTag *tag, /* RETURNED tag of sequence/set. This will be
385 * either ASN1_CONSTR_SEQUENCE or ASN1_CONSTR_SET. */
386 DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
387 {
388 DERDecodedInfo decoded;
389 DERReturn drtn;
390
391 drtn = DERDecodeItem(der, &decoded);
392 if(drtn) {
393 return drtn;
394 }
395 *tag = decoded.tag;
396 switch(decoded.tag) {
397 case ASN1_CONSTR_SEQUENCE:
398 case ASN1_CONSTR_SET:
399 break;
400 default:
401 return DR_UnexpectedTag;
402 }
403 derSeq->nextItem = decoded.content.data;
404 derSeq->end = decoded.content.data + decoded.content.length;
405 return DR_Success;
406 }
407
408 /*
409 * Use this to start in on decoding a sequence's content, when
410 * the top-level tag and content have already been decoded.
411 */
412 DERReturn DERDecodeSeqContentInit(
413 const DERItem *content,
414 DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
415 {
416 /* just prepare for decoding items in content */
417 derSeq->nextItem = content->data;
418 derSeq->end = content->data + content->length;
419 return DR_Success;
420 }
421
422 DERReturn DERDecodeSeqNext(
423 DERSequence *derSeq,
424 DERDecodedInfo *decoded) /* RETURNED */
425 {
426 DERReturn drtn;
427 DERItem item;
428
429 if(derSeq->nextItem >= derSeq->end) {
430 /* normal termination, contents all used up */
431 return DR_EndOfSequence;
432 }
433
434 /* decode next item */
435 item.data = derSeq->nextItem;
436 item.length = (DERSize) (derSeq->end - derSeq->nextItem);
437 drtn = DERDecodeItem(&item, decoded);
438 if(drtn) {
439 return drtn;
440 }
441
442 /* skip over the item we just decoded */
443 derSeq->nextItem = decoded->content.data + decoded->content.length;
444 return DR_Success;
445 }
446
447 /*
448 * High level sequence parse, starting with top-level tag and content.
449 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
450 * OK, use DERParseSequenceContent().
451 */
452 DERReturn DERParseSequence(
453 const DERItem *der,
454 DERShort numItems, /* size of itemSpecs[] */
455 const DERItemSpec *itemSpecs,
456 void *dest, /* DERDecodedInfo(s) here RETURNED */
457 DERSize sizeToZero) /* optional */
458 {
459 DERReturn drtn;
460 DERDecodedInfo topDecode;
461
462 drtn = DERDecodeItem(der, &topDecode);
463 if(drtn) {
464 return drtn;
465 }
466 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
467 return DR_UnexpectedTag;
468 }
469 return DERParseSequenceContent(&topDecode.content,
470 numItems, itemSpecs, dest, sizeToZero);
471 }
472
473 /* high level sequence parse, starting with sequence's content */
474 DERReturn DERParseSequenceContent(
475 const DERItem *content,
476 DERShort numItems, /* size of itemSpecs[] */
477 const DERItemSpec *itemSpecs,
478 void *dest, /* DERDecodedInfo(s) here RETURNED */
479 DERSize sizeToZero) /* optional */
480 {
481 DERSequence derSeq;
482 DERReturn drtn;
483 DERShort itemDex;
484 DERByte *currDER; /* full DER encoding of current item */
485
486 if(sizeToZero) {
487 DERMemset(dest, 0, sizeToZero);
488 }
489
490 drtn = DERDecodeSeqContentInit(content, &derSeq);
491 if(drtn) {
492 return drtn;
493 }
494
495 /* main loop */
496 for(itemDex=0 ; itemDex<numItems; ) {
497 DERDecodedInfo currDecoded;
498 DERShort i;
499 DERTag foundTag;
500 char foundMatch = 0;
501
502 /* save this in case of DER_DEC_SAVE_DER */
503 currDER = derSeq.nextItem;
504
505 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
506 if(drtn) {
507 /*
508 * One legal error here is DR_EndOfSequence when
509 * all remaining DERSequenceItems are optional.
510 */
511 if(drtn == DR_EndOfSequence) {
512 for(i=itemDex; i<numItems; i++) {
513 if(!(itemSpecs[i].options & DER_DEC_OPTIONAL)) {
514 /* unexpected end of sequence */
515 return DR_IncompleteSeq;
516 }
517 }
518 /* the rest are optional; success */
519 return DR_Success;
520 }
521 else {
522 /* any other error is fatal */
523 return drtn;
524 }
525 } /* decode error */
526
527 /*
528 * Seek matching tag or ASN_ANY in itemSpecs, skipping
529 * over optional items.
530 */
531 foundTag = currDecoded.tag;
532 derDecDbg1("--- foundTag 0x%llx\n", foundTag);
533
534 for(i=itemDex; i<numItems; i++) {
535 const DERItemSpec *currItemSpec = &itemSpecs[i];
536 DERShort currOptions = currItemSpec->options;
537 derDecDbg3("--- currItem %u expectTag 0x%llx currOptions 0x%x\n",
538 i, currItemSpec->tag, currOptions);
539
540 if((currOptions & DER_DEC_ASN_ANY) ||
541 (foundTag == currItemSpec->tag)) {
542 /*
543 * We're good with this one. Cook up destination address
544 * as appropriate.
545 */
546 if(!(currOptions & DER_DEC_SKIP)) {
547 derDecDbg1("--- MATCH at currItem %u\n", i);
548 DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
549 DERItem *dst = (DERItem *)byteDst;
550 *dst = currDecoded.content;
551 if(currOptions & DER_DEC_SAVE_DER) {
552 /* recreate full DER encoding of this item */
553 derDecDbg1("--- SAVE_DER at currItem %u\n", i);
554 dst->data = currDER;
555 dst->length += (currDecoded.content.data - currDER);
556 }
557 }
558
559 /* on to next item */
560 itemDex = i + 1;
561
562 /* is this the end? */
563 if(itemDex == numItems) {
564 /* normal termination if we consumed everything */
565 if (currDecoded.content.data + currDecoded.content.length == content->data + content->length)
566 return DR_Success;
567 else
568 return DR_DecodeError;
569 }
570 else {
571 /* on to next item */
572 foundMatch = 1;
573 break;
574 }
575 } /* ASN_ANY, or match */
576
577 /*
578 * If current itemSpec isn't optional, abort - else on to
579 * next item
580 */
581 if(!(currOptions & DER_DEC_OPTIONAL)) {
582 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
583 return DR_UnexpectedTag;
584 }
585
586 /* else this was optional, on to next item */
587 } /* searching for tag match */
588
589 if(foundMatch == 0) {
590 /*
591 * Found an item we couldn't match to any tag spec and we're at
592 * the end.
593 */
594 derDecDbg("--- TAG NOT FOUND, abort\n");
595 return DR_UnexpectedTag;
596 }
597
598 /* else on to next item */
599 } /* main loop */
600
601 /* Template has 0 items if we get here. */
602 /* normal termination if we consumed everything, (the sequence was empty) */
603 if (derSeq.nextItem == derSeq.end)
604 return DR_Success;
605 else
606 return DR_DecodeError;
607 }
608
609 #if 0
610 /*
611 * High level sequence parse, starting with top-level tag and content.
612 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
613 * OK, use DERParseSequenceContent().
614 */
615 DERReturn DERParseSequenceOf(
616 const DERItem *der,
617 DERShort numItems, /* size of itemSpecs[] */
618 const DERItemSpec *itemSpecs,
619 void *dest, /* DERDecodedInfo(s) here RETURNED */
620 DERSize *numDestItems) /* output */
621 {
622 DERReturn drtn;
623 DERDecodedInfo topDecode;
624
625 drtn = DERDecodeItem(der, &topDecode);
626 if(drtn) {
627 return drtn;
628 }
629 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
630 return DR_UnexpectedTag;
631 }
632 return DERParseSequenceContent(&topDecode.content,
633 numItems, itemSpecs, dest, sizeToZero);
634 }
635
636 /*
637 * High level set of parse, starting with top-level tag and content.
638 * Top level tag must be ASN1_CONSTR_SET - if it's not, and that's
639 * OK, use DERParseSetOrSequenceOfContent().
640 */
641 DERReturn DERParseSetOf(
642 const DERItem *der,
643 DERShort numItems, /* size of itemSpecs[] */
644 const DERItemSpec *itemSpecs,
645 void *dest, /* DERDecodedInfo(s) here RETURNED */
646 DERSize *numDestItems) /* output */
647 {
648 DERReturn drtn;
649 DERDecodedInfo topDecode;
650
651 drtn = DERDecodeItem(der, &topDecode);
652 if(drtn) {
653 return drtn;
654 }
655 if(topDecode.tag != ASN1_CONSTR_SET) {
656 return DR_UnexpectedTag;
657 }
658 return DERParseSetOrSequenceOfContent(&topDecode.content,
659 numItems, itemSpecs, dest, numDestItems);
660 }
661
662 /* High level set of or sequence of parse, starting with set or
663 sequence's content */
664 DERReturn DERParseSetOrSequenceOfContent(
665 const DERItem *content,
666 void(*itemHandeler)(void *, const DERDecodedInfo *)
667 void *itemHandelerContext);
668 {
669 DERSequence derSeq;
670 DERShort itemDex;
671
672 drtn = DERDecodeSeqContentInit(content, &derSeq);
673 require_noerr_quiet(drtn, badCert);
674
675 /* main loop */
676 for (;;) {
677 DERDecodedInfo currDecoded;
678 DERShort i;
679 DERByte foundTag;
680 char foundMatch = 0;
681
682 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
683 if(drtn) {
684 /* The only legal error here is DR_EndOfSequence. */
685 if(drtn == DR_EndOfSequence) {
686 /* no more items left in the sequence; success */
687 return DR_Success;
688 }
689 else {
690 /* any other error is fatal */
691 require_noerr_quiet(drtn, badCert);
692 }
693 } /* decode error */
694
695 /* Each element can be anything. */
696 foundTag = currDecoded.tag;
697
698 /*
699 * We're good with this one. Cook up destination address
700 * as appropriate.
701 */
702 DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
703 DERItem *dst = (DERItem *)byteDst;
704 *dst = currDecoded.content;
705 if(currOptions & DER_DEC_SAVE_DER) {
706 /* recreate full DER encoding of this item */
707 derDecDbg1("--- SAVE_DER at currItem %u\n", i);
708 dst->data = currDER;
709 dst->length += (currDecoded.content.data - currDER);
710 }
711
712 /* on to next item */
713 itemDex = i + 1;
714
715 /* is this the end? */
716 if(itemDex == numItems) {
717 /* normal termination */
718 return DR_Success;
719 }
720 else {
721 /* on to next item */
722 foundMatch = 1;
723 break;
724 }
725
726 /*
727 * If current itemSpec isn't optional, abort - else on to
728 * next item
729 */
730 if(!(currOptions & DER_DEC_OPTIONAL)) {
731 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
732 return DR_UnexpectedTag;
733 }
734
735 /* else this was optional, on to next item */
736 } /* searching for tag match */
737
738 if(foundMatch == 0) {
739 /*
740 * Found an item we couldn't match to any tag spec and we're at
741 * the end.
742 */
743 derDecDbg("--- TAG NOT FOUND, abort\n");
744 return DR_UnexpectedTag;
745 }
746
747 /* else on to next item */
748 } /* main loop */
749
750 /*
751 * If we get here, there appears to be more to process, but we've
752 * given the caller everything they want.
753 */
754 return DR_Success;
755 }
756 }
757 #endif
758
759 #endif /* DER_DECODE_ENABLE */