2 * Copyright (c) 2005-2017 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * DER_Decode.c - DER decoding routines
28 #include <libDER/DER_Decode.h>
29 #include <libDER/asn1Types.h>
31 #include <libDER/libDER_config.h>
33 #ifndef DER_DECODE_ENABLE
34 #error Please define DER_DECODE_ENABLE.
39 #define DER_DECODE_DEBUG 0
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)
48 #define derDecDbg1(a, b)
49 #define derDecDbg2(a, b, c)
50 #define derDecDbg3(a, b, c, d)
51 #endif /* DER_DECODE_DEBUG */
54 * Basic decoding primitive. Only works with:
56 * -- definite length encoding
57 * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
58 * -- max content length fits in a DERSize
60 * No malloc or copy of the contents is performed; the returned
61 * content->content.data is a pointer into the incoming der data.
63 DERReturn
DERDecodeItem(
64 const DERItem
*der
, /* data to decode */
65 DERDecodedInfo
*decoded
) /* RETURNED */
67 return DERDecodeItemPartialBufferGetLength(der
, decoded
, NULL
);
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.
76 * -- definite length encoding
77 * -- one-byte tags (unless DER_MULTIBYTE_TAGS is defined)
78 * -- max content length fits in a DERSize
80 * No malloc or copy of the contents is performed; the returned
81 * content->content.data is a pointer into the incoming der data.
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.
88 DERReturn
DERDecodeItemPartialBuffer(
89 const DERItem
*der
, /* data to decode */
90 DERDecodedInfo
*decoded
, /* RETURNED */
91 bool allowPartialBuffer
)
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
;
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. */
104 return DR_DecodeError
;
106 /* Grab the first byte of the tag. */
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));
117 if (*derPtr
== 0x80 || *derPtr
< 0x1F)
118 return DR_DecodeError
;
120 if(derLen
< 2 || (tagNumber
& overflowMask
) != 0) {
121 return DR_DecodeError
;
125 tagNumber
= (tagNumber
<< 7) | (tagByte
& 0x7F);
126 } while((tagByte
& 0x80) != 0);
128 /* Check for any of the top 3 reserved bits being set. */
129 if ((tagNumber
& (overflowMask
<< 4)) != 0)
131 return DR_DecodeError
;
133 /* Returned tag, top 3 bits are class/method remaining bits are number. */
134 decoded
->tag
= ((DERTag
)(tag1
& 0xE0) << ((sizeof(DERTag
) - 1) * 8)) | tagNumber
;
136 /* Tag decoding above ensured we have at least one more input byte left. */
140 /* long length form - first byte is length of length */
141 DERSize longLen
= 0; /* long form length */
145 if((len1
> sizeof(DERSize
)) || (len1
> derLen
) || len1
== 0 || *derPtr
== 0) {
147 return DR_DecodeError
;
149 for(dex
=0; dex
<len1
; dex
++) {
151 longLen
|= *derPtr
++;
154 if(longLen
> derLen
&& !allowPartialBuffer
) {
155 /* not enough data left for this encoding */
156 return DR_DecodeError
;
158 decoded
->content
.data
= derPtr
;
159 decoded
->content
.length
= longLen
;
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
;
167 decoded
->content
.data
= derPtr
;
168 decoded
->content
.length
= len1
;
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
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.
184 DERReturn
DERDecodeItemPartialBufferGetLength(
185 const DERItem
*der
, /* data to decode */
186 DERDecodedInfo
*decoded
, /* RETURNED */
187 DERSize
*encodedLength
)
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
;
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. */
200 return DR_DecodeError
;
202 /* Grab the first byte of the tag. */
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));
213 if (*derPtr
== 0x80 || *derPtr
< 0x1F)
214 return DR_DecodeError
;
216 if(derLen
< 2 || (tagNumber
& overflowMask
) != 0) {
217 return DR_DecodeError
;
221 tagNumber
= (tagNumber
<< 7) | (tagByte
& 0x7F);
222 } while((tagByte
& 0x80) != 0);
224 /* Check for any of the top 3 reserved bits being set. */
225 if ((tagNumber
& (overflowMask
<< 4)) != 0)
227 return DR_DecodeError
;
229 /* Returned tag, top 3 bits are class/method remaining bits are number. */
230 decoded
->tag
= ((DERTag
)(tag1
& 0xE0) << ((sizeof(DERTag
) - 1) * 8)) | tagNumber
;
232 /* Tag decoding above ensured we have at least one more input byte left. */
236 /* long length form - first byte is length of length */
237 DERSize longLen
= 0; /* long form length */
241 if((len1
> sizeof(DERSize
)) || (len1
> derLen
) || len1
== 0 || *derPtr
== 0) {
243 return DR_DecodeError
;
245 for(dex
=0; dex
<len1
; dex
++) {
247 longLen
|= *derPtr
++;
250 if(longLen
> derLen
&& !encodedLength
) {
251 /* not enough data left for this encoding */
252 return DR_DecodeError
;
254 if (longLen
<derLen
) {
257 decoded
->content
.data
= derPtr
;
258 decoded
->content
.length
= derLen
;
260 *encodedLength
= longLen
;
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
;
272 decoded
->content
.data
= derPtr
;
273 decoded
->content
.length
= derLen
;
275 *encodedLength
= len1
;
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.
286 DERReturn
DERParseBitString(
287 const DERItem
*contents
,
288 DERItem
*bitStringBytes
, /* RETURNED */
289 DERByte
*numUnusedBits
) /* RETURNED */
291 if(contents
->length
< 2) {
292 /* not enough room for actual bits after the unused bits field */
294 bitStringBytes
->data
= NULL
;
295 bitStringBytes
->length
= 0;
298 *numUnusedBits
= contents
->data
[0];
299 bitStringBytes
->data
= contents
->data
+ 1;
300 bitStringBytes
->length
= contents
->length
- 1;
305 * Given a BOOLEAN, in the form of its raw content bytes,
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
;
315 *value
= contents
->data
[0] != 0;
320 * Given a BOOLEAN, in the form of its raw content bytes,
323 DERReturn
DERParseBooleanWithDefault(
324 const DERItem
*contents
,
326 bool *value
) { /* RETURNED */
327 if (contents
->length
== 0) {
328 *value
= defaultValue
;
331 return DERParseBoolean(contents
, value
);
335 DERReturn
DERParseInteger(
336 const DERItem
*contents
,
337 uint32_t *result
) { /* RETURNED */
339 DERReturn drtn
= DERParseInteger64(contents
, &value
);
340 if (drtn
== DR_Success
) {
341 if (value
> UINT32_MAX
)
342 drtn
= DR_BufOverflow
;
344 *result
= (uint32_t)value
;
349 DERReturn
DERParseInteger64(
350 const DERItem
*contents
,
351 uint64_t *result
) { /* RETURNED */
352 DERSize ix
, length
= contents
->length
;
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
;
366 for (ix
= 0; ix
< length
; ++ix
) {
368 value
+= contents
->data
[ix
];
374 /* Sequence/set support */
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.
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 */
388 DERDecodedInfo decoded
;
391 drtn
= DERDecodeItem(der
, &decoded
);
396 switch(decoded
.tag
) {
397 case ASN1_CONSTR_SEQUENCE
:
398 case ASN1_CONSTR_SET
:
401 return DR_UnexpectedTag
;
403 derSeq
->nextItem
= decoded
.content
.data
;
404 derSeq
->end
= decoded
.content
.data
+ decoded
.content
.length
;
409 * Use this to start in on decoding a sequence's content, when
410 * the top-level tag and content have already been decoded.
412 DERReturn
DERDecodeSeqContentInit(
413 const DERItem
*content
,
414 DERSequence
*derSeq
) /* RETURNED, to use in DERDecodeSeqNext */
416 /* just prepare for decoding items in content */
417 derSeq
->nextItem
= content
->data
;
418 derSeq
->end
= content
->data
+ content
->length
;
422 DERReturn
DERDecodeSeqNext(
424 DERDecodedInfo
*decoded
) /* RETURNED */
429 if(derSeq
->nextItem
>= derSeq
->end
) {
430 /* normal termination, contents all used up */
431 return DR_EndOfSequence
;
434 /* decode next item */
435 item
.data
= derSeq
->nextItem
;
436 item
.length
= (DERSize
) (derSeq
->end
- derSeq
->nextItem
);
437 drtn
= DERDecodeItem(&item
, decoded
);
442 /* skip over the item we just decoded */
443 derSeq
->nextItem
= decoded
->content
.data
+ decoded
->content
.length
;
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().
452 DERReturn
DERParseSequence(
454 DERShort numItems
, /* size of itemSpecs[] */
455 const DERItemSpec
*itemSpecs
,
456 void *dest
, /* DERDecodedInfo(s) here RETURNED */
457 DERSize sizeToZero
) /* optional */
460 DERDecodedInfo topDecode
;
462 drtn
= DERDecodeItem(der
, &topDecode
);
466 if(topDecode
.tag
!= ASN1_CONSTR_SEQUENCE
) {
467 return DR_UnexpectedTag
;
469 return DERParseSequenceContent(&topDecode
.content
,
470 numItems
, itemSpecs
, dest
, sizeToZero
);
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 */
484 DERByte
*currDER
; /* full DER encoding of current item */
487 DERMemset(dest
, 0, sizeToZero
);
490 drtn
= DERDecodeSeqContentInit(content
, &derSeq
);
496 for(itemDex
=0 ; itemDex
<numItems
; ) {
497 DERDecodedInfo currDecoded
;
502 /* save this in case of DER_DEC_SAVE_DER */
503 currDER
= derSeq
.nextItem
;
505 drtn
= DERDecodeSeqNext(&derSeq
, &currDecoded
);
508 * One legal error here is DR_EndOfSequence when
509 * all remaining DERSequenceItems are optional.
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
;
518 /* the rest are optional; success */
522 /* any other error is fatal */
528 * Seek matching tag or ASN_ANY in itemSpecs, skipping
529 * over optional items.
531 foundTag
= currDecoded
.tag
;
532 derDecDbg1("--- foundTag 0x%llx\n", foundTag
);
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
);
540 if((currOptions
& DER_DEC_ASN_ANY
) ||
541 (foundTag
== currItemSpec
->tag
)) {
543 * We're good with this one. Cook up destination address
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
);
555 dst
->length
+= (currDecoded
.content
.data
- currDER
);
559 /* on to next item */
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
)
568 return DR_DecodeError
;
571 /* on to next item */
575 } /* ASN_ANY, or match */
578 * If current itemSpec isn't optional, abort - else on to
581 if(!(currOptions
& DER_DEC_OPTIONAL
)) {
582 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i
);
583 return DR_UnexpectedTag
;
586 /* else this was optional, on to next item */
587 } /* searching for tag match */
589 if(foundMatch
== 0) {
591 * Found an item we couldn't match to any tag spec and we're at
594 derDecDbg("--- TAG NOT FOUND, abort\n");
595 return DR_UnexpectedTag
;
598 /* else on to next item */
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
)
606 return DR_DecodeError
;
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().
615 DERReturn
DERParseSequenceOf(
617 DERShort numItems
, /* size of itemSpecs[] */
618 const DERItemSpec
*itemSpecs
,
619 void *dest
, /* DERDecodedInfo(s) here RETURNED */
620 DERSize
*numDestItems
) /* output */
623 DERDecodedInfo topDecode
;
625 drtn
= DERDecodeItem(der
, &topDecode
);
629 if(topDecode
.tag
!= ASN1_CONSTR_SEQUENCE
) {
630 return DR_UnexpectedTag
;
632 return DERParseSequenceContent(&topDecode
.content
,
633 numItems
, itemSpecs
, dest
, sizeToZero
);
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().
641 DERReturn
DERParseSetOf(
643 DERShort numItems
, /* size of itemSpecs[] */
644 const DERItemSpec
*itemSpecs
,
645 void *dest
, /* DERDecodedInfo(s) here RETURNED */
646 DERSize
*numDestItems
) /* output */
649 DERDecodedInfo topDecode
;
651 drtn
= DERDecodeItem(der
, &topDecode
);
655 if(topDecode
.tag
!= ASN1_CONSTR_SET
) {
656 return DR_UnexpectedTag
;
658 return DERParseSetOrSequenceOfContent(&topDecode
.content
,
659 numItems
, itemSpecs
, dest
, numDestItems
);
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
);
672 drtn
= DERDecodeSeqContentInit(content
, &derSeq
);
673 require_noerr_quiet(drtn
, badCert
);
677 DERDecodedInfo currDecoded
;
682 drtn
= DERDecodeSeqNext(&derSeq
, &currDecoded
);
684 /* The only legal error here is DR_EndOfSequence. */
685 if(drtn
== DR_EndOfSequence
) {
686 /* no more items left in the sequence; success */
690 /* any other error is fatal */
691 require_noerr_quiet(drtn
, badCert
);
695 /* Each element can be anything. */
696 foundTag
= currDecoded
.tag
;
699 * We're good with this one. Cook up destination address
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
);
709 dst
->length
+= (currDecoded
.content
.data
- currDER
);
712 /* on to next item */
715 /* is this the end? */
716 if(itemDex
== numItems
) {
717 /* normal termination */
721 /* on to next item */
727 * If current itemSpec isn't optional, abort - else on to
730 if(!(currOptions
& DER_DEC_OPTIONAL
)) {
731 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i
);
732 return DR_UnexpectedTag
;
735 /* else this was optional, on to next item */
736 } /* searching for tag match */
738 if(foundMatch
== 0) {
740 * Found an item we couldn't match to any tag spec and we're at
743 derDecDbg("--- TAG NOT FOUND, abort\n");
744 return DR_UnexpectedTag
;
747 /* else on to next item */
751 * If we get here, there appears to be more to process, but we've
752 * given the caller everything they want.
759 #endif /* DER_DECODE_ENABLE */