2 * Copyright (c) 2005-2016 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 DERDecodeItemPartialBuffer(der
, decoded
, false);
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 DERReturn
DERDecodeItemPartialBuffer(
84 const DERItem
*der
, /* data to decode */
85 DERDecodedInfo
*decoded
, /* RETURNED */
86 bool allowPartialBuffer
)
88 DERByte tag1
; /* first tag byte */
89 DERByte len1
; /* first length byte */
90 DERTag tagNumber
; /* tag number without class and method bits */
91 DERByte
*derPtr
= der
->data
;
92 DERSize derLen
= der
->length
;
94 /* The tag decoding below is fully BER complient. We support a max tag
95 value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we
96 support tag values from 0 - 0x1F. For tag size 2 tag values
97 from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */
99 return DR_DecodeError
;
101 /* Grab the first byte of the tag. */
104 tagNumber
= tag1
& 0x1F;
105 if(tagNumber
== 0x1F) {
106 #ifdef DER_MULTIBYTE_TAGS
107 /* Long tag form: bit 8 of each octet shall be set to one unless it is
108 the last octet of the tag */
109 const DERTag overflowMask
= ((DERTag
)0x7F << (sizeof(DERTag
) * 8 - 7));
112 if (*derPtr
== 0x80 || *derPtr
< 0x1F)
113 return DR_DecodeError
;
115 if(derLen
< 2 || (tagNumber
& overflowMask
) != 0) {
116 return DR_DecodeError
;
120 tagNumber
= (tagNumber
<< 7) | (tagByte
& 0x7F);
121 } while((tagByte
& 0x80) != 0);
123 /* Check for any of the top 3 reserved bits being set. */
124 if ((tagNumber
& (overflowMask
<< 4)) != 0)
126 return DR_DecodeError
;
128 /* Returned tag, top 3 bits are class/method remaining bits are number. */
129 decoded
->tag
= ((DERTag
)(tag1
& 0xE0) << ((sizeof(DERTag
) - 1) * 8)) | tagNumber
;
131 /* Tag decoding above ensured we have at least one more input byte left. */
135 /* long length form - first byte is length of length */
136 DERSize longLen
= 0; /* long form length */
140 if((len1
> sizeof(DERSize
)) || (len1
> derLen
) || len1
== 0 || *derPtr
== 0) {
142 return DR_DecodeError
;
144 for(dex
=0; dex
<len1
; dex
++) {
146 longLen
|= *derPtr
++;
149 if(longLen
> derLen
&& !allowPartialBuffer
) {
150 /* not enough data left for this encoding */
151 return DR_DecodeError
;
153 decoded
->content
.data
= derPtr
;
154 decoded
->content
.length
= longLen
;
157 /* short length form, len1 is the length */
158 if(len1
> derLen
&& !allowPartialBuffer
) {
159 /* not enough data left for this encoding */
160 return DR_DecodeError
;
162 decoded
->content
.data
= derPtr
;
163 decoded
->content
.length
= len1
;
170 * Given a BIT_STRING, in the form of its raw content bytes,
171 * obtain the number of unused bits and the raw bit string bytes.
173 DERReturn
DERParseBitString(
174 const DERItem
*contents
,
175 DERItem
*bitStringBytes
, /* RETURNED */
176 DERByte
*numUnusedBits
) /* RETURNED */
178 if(contents
->length
< 2) {
179 /* not enough room for actual bits after the unused bits field */
181 bitStringBytes
->data
= NULL
;
182 bitStringBytes
->length
= 0;
185 *numUnusedBits
= contents
->data
[0];
186 bitStringBytes
->data
= contents
->data
+ 1;
187 bitStringBytes
->length
= contents
->length
- 1;
192 * Given a BOOLEAN, in the form of its raw content bytes,
195 DERReturn
DERParseBoolean(
196 const DERItem
*contents
,
197 bool *value
) { /* RETURNED */
198 if (contents
->length
!= 1 ||
199 (contents
->data
[0] != 0 && contents
->data
[0] != 0xFF))
200 return DR_DecodeError
;
202 *value
= contents
->data
[0] != 0;
207 * Given a BOOLEAN, in the form of its raw content bytes,
210 DERReturn
DERParseBooleanWithDefault(
211 const DERItem
*contents
,
213 bool *value
) { /* RETURNED */
214 if (contents
->length
== 0) {
215 *value
= defaultValue
;
218 return DERParseBoolean(contents
, value
);
222 DERReturn
DERParseInteger(
223 const DERItem
*contents
,
224 uint32_t *result
) { /* RETURNED */
226 DERReturn drtn
= DERParseInteger64(contents
, &value
);
227 if (drtn
== DR_Success
) {
228 if (value
> UINT32_MAX
)
229 drtn
= DR_BufOverflow
;
231 *result
= (uint32_t)value
;
236 DERReturn
DERParseInteger64(
237 const DERItem
*contents
,
238 uint64_t *result
) { /* RETURNED */
239 DERSize ix
, length
= contents
->length
;
241 return DR_DecodeError
;
242 if (contents
->data
[0] & 0x80)
243 return DR_DecodeError
;
244 if (contents
->data
[0] == 0) {
245 if (length
> 1 && (contents
->data
[1] & 0x80) == 0)
246 return DR_DecodeError
;
247 if (length
> sizeof(*result
) + 1)
248 return DR_BufOverflow
;
249 } else if (length
> sizeof(*result
)) {
250 return DR_BufOverflow
;
253 for (ix
= 0; ix
< length
; ++ix
) {
255 value
+= contents
->data
[ix
];
261 /* Sequence/set support */
264 * To decode a set or sequence, call DERDecodeSeqInit once, then
265 * call DERDecodeSeqNext to get each enclosed item.
266 * DERDecodeSeqNext returns DR_EndOfSequence when no more
267 * items are available.
269 DERReturn
DERDecodeSeqInit(
270 const DERItem
*der
, /* data to decode */
271 DERTag
*tag
, /* RETURNED tag of sequence/set. This will be
272 * either ASN1_CONSTR_SEQUENCE or ASN1_CONSTR_SET. */
273 DERSequence
*derSeq
) /* RETURNED, to use in DERDecodeSeqNext */
275 DERDecodedInfo decoded
;
278 drtn
= DERDecodeItem(der
, &decoded
);
283 switch(decoded
.tag
) {
284 case ASN1_CONSTR_SEQUENCE
:
285 case ASN1_CONSTR_SET
:
288 return DR_UnexpectedTag
;
290 derSeq
->nextItem
= decoded
.content
.data
;
291 derSeq
->end
= decoded
.content
.data
+ decoded
.content
.length
;
296 * Use this to start in on decoding a sequence's content, when
297 * the top-level tag and content have already been decoded.
299 DERReturn
DERDecodeSeqContentInit(
300 const DERItem
*content
,
301 DERSequence
*derSeq
) /* RETURNED, to use in DERDecodeSeqNext */
303 /* just prepare for decoding items in content */
304 derSeq
->nextItem
= content
->data
;
305 derSeq
->end
= content
->data
+ content
->length
;
309 DERReturn
DERDecodeSeqNext(
311 DERDecodedInfo
*decoded
) /* RETURNED */
316 if(derSeq
->nextItem
>= derSeq
->end
) {
317 /* normal termination, contents all used up */
318 return DR_EndOfSequence
;
321 /* decode next item */
322 item
.data
= derSeq
->nextItem
;
323 item
.length
= (DERSize
) (derSeq
->end
- derSeq
->nextItem
);
324 drtn
= DERDecodeItem(&item
, decoded
);
329 /* skip over the item we just decoded */
330 derSeq
->nextItem
= decoded
->content
.data
+ decoded
->content
.length
;
335 * High level sequence parse, starting with top-level tag and content.
336 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
337 * OK, use DERParseSequenceContent().
339 DERReturn
DERParseSequence(
341 DERShort numItems
, /* size of itemSpecs[] */
342 const DERItemSpec
*itemSpecs
,
343 void *dest
, /* DERDecodedInfo(s) here RETURNED */
344 DERSize sizeToZero
) /* optional */
347 DERDecodedInfo topDecode
;
349 drtn
= DERDecodeItem(der
, &topDecode
);
353 if(topDecode
.tag
!= ASN1_CONSTR_SEQUENCE
) {
354 return DR_UnexpectedTag
;
356 return DERParseSequenceContent(&topDecode
.content
,
357 numItems
, itemSpecs
, dest
, sizeToZero
);
360 /* high level sequence parse, starting with sequence's content */
361 DERReturn
DERParseSequenceContent(
362 const DERItem
*content
,
363 DERShort numItems
, /* size of itemSpecs[] */
364 const DERItemSpec
*itemSpecs
,
365 void *dest
, /* DERDecodedInfo(s) here RETURNED */
366 DERSize sizeToZero
) /* optional */
371 DERByte
*currDER
; /* full DER encoding of current item */
374 DERMemset(dest
, 0, sizeToZero
);
377 drtn
= DERDecodeSeqContentInit(content
, &derSeq
);
383 for(itemDex
=0 ; itemDex
<numItems
; ) {
384 DERDecodedInfo currDecoded
;
389 /* save this in case of DER_DEC_SAVE_DER */
390 currDER
= derSeq
.nextItem
;
392 drtn
= DERDecodeSeqNext(&derSeq
, &currDecoded
);
395 * One legal error here is DR_EndOfSequence when
396 * all remaining DERSequenceItems are optional.
398 if(drtn
== DR_EndOfSequence
) {
399 for(i
=itemDex
; i
<numItems
; i
++) {
400 if(!(itemSpecs
[i
].options
& DER_DEC_OPTIONAL
)) {
401 /* unexpected end of sequence */
402 return DR_IncompleteSeq
;
405 /* the rest are optional; success */
409 /* any other error is fatal */
415 * Seek matching tag or ASN_ANY in itemSpecs, skipping
416 * over optional items.
418 foundTag
= currDecoded
.tag
;
419 derDecDbg1("--- foundTag 0x%llx\n", foundTag
);
421 for(i
=itemDex
; i
<numItems
; i
++) {
422 const DERItemSpec
*currItemSpec
= &itemSpecs
[i
];
423 DERShort currOptions
= currItemSpec
->options
;
424 derDecDbg3("--- currItem %u expectTag 0x%llx currOptions 0x%x\n",
425 i
, currItemSpec
->tag
, currOptions
);
427 if((currOptions
& DER_DEC_ASN_ANY
) ||
428 (foundTag
== currItemSpec
->tag
)) {
430 * We're good with this one. Cook up destination address
433 if(!(currOptions
& DER_DEC_SKIP
)) {
434 derDecDbg1("--- MATCH at currItem %u\n", i
);
435 DERByte
*byteDst
= (DERByte
*)dest
+ currItemSpec
->offset
;
436 DERItem
*dst
= (DERItem
*)byteDst
;
437 *dst
= currDecoded
.content
;
438 if(currOptions
& DER_DEC_SAVE_DER
) {
439 /* recreate full DER encoding of this item */
440 derDecDbg1("--- SAVE_DER at currItem %u\n", i
);
442 dst
->length
+= (currDecoded
.content
.data
- currDER
);
446 /* on to next item */
449 /* is this the end? */
450 if(itemDex
== numItems
) {
451 /* normal termination if we consumed everything */
452 if (currDecoded
.content
.data
+ currDecoded
.content
.length
== content
->data
+ content
->length
)
455 return DR_DecodeError
;
458 /* on to next item */
462 } /* ASN_ANY, or match */
465 * If current itemSpec isn't optional, abort - else on to
468 if(!(currOptions
& DER_DEC_OPTIONAL
)) {
469 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i
);
470 return DR_UnexpectedTag
;
473 /* else this was optional, on to next item */
474 } /* searching for tag match */
476 if(foundMatch
== 0) {
478 * Found an item we couldn't match to any tag spec and we're at
481 derDecDbg("--- TAG NOT FOUND, abort\n");
482 return DR_UnexpectedTag
;
485 /* else on to next item */
488 /* Template has 0 items if we get here. */
489 /* normal termination if we consumed everything, (the sequence was empty) */
490 if (derSeq
.nextItem
== derSeq
.end
)
493 return DR_DecodeError
;
498 * High level sequence parse, starting with top-level tag and content.
499 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
500 * OK, use DERParseSequenceContent().
502 DERReturn
DERParseSequenceOf(
504 DERShort numItems
, /* size of itemSpecs[] */
505 const DERItemSpec
*itemSpecs
,
506 void *dest
, /* DERDecodedInfo(s) here RETURNED */
507 DERSize
*numDestItems
) /* output */
510 DERDecodedInfo topDecode
;
512 drtn
= DERDecodeItem(der
, &topDecode
);
516 if(topDecode
.tag
!= ASN1_CONSTR_SEQUENCE
) {
517 return DR_UnexpectedTag
;
519 return DERParseSequenceContent(&topDecode
.content
,
520 numItems
, itemSpecs
, dest
, sizeToZero
);
524 * High level set of parse, starting with top-level tag and content.
525 * Top level tag must be ASN1_CONSTR_SET - if it's not, and that's
526 * OK, use DERParseSetOrSequenceOfContent().
528 DERReturn
DERParseSetOf(
530 DERShort numItems
, /* size of itemSpecs[] */
531 const DERItemSpec
*itemSpecs
,
532 void *dest
, /* DERDecodedInfo(s) here RETURNED */
533 DERSize
*numDestItems
) /* output */
536 DERDecodedInfo topDecode
;
538 drtn
= DERDecodeItem(der
, &topDecode
);
542 if(topDecode
.tag
!= ASN1_CONSTR_SET
) {
543 return DR_UnexpectedTag
;
545 return DERParseSetOrSequenceOfContent(&topDecode
.content
,
546 numItems
, itemSpecs
, dest
, numDestItems
);
549 /* High level set of or sequence of parse, starting with set or
550 sequence's content */
551 DERReturn
DERParseSetOrSequenceOfContent(
552 const DERItem
*content
,
553 void(*itemHandeler
)(void *, const DERDecodedInfo
*)
554 void *itemHandelerContext
);
559 drtn
= DERDecodeSeqContentInit(content
, &derSeq
);
560 require_noerr_quiet(drtn
, badCert
);
564 DERDecodedInfo currDecoded
;
569 drtn
= DERDecodeSeqNext(&derSeq
, &currDecoded
);
571 /* The only legal error here is DR_EndOfSequence. */
572 if(drtn
== DR_EndOfSequence
) {
573 /* no more items left in the sequence; success */
577 /* any other error is fatal */
578 require_noerr_quiet(drtn
, badCert
);
582 /* Each element can be anything. */
583 foundTag
= currDecoded
.tag
;
586 * We're good with this one. Cook up destination address
589 DERByte
*byteDst
= (DERByte
*)dest
+ currItemSpec
->offset
;
590 DERItem
*dst
= (DERItem
*)byteDst
;
591 *dst
= currDecoded
.content
;
592 if(currOptions
& DER_DEC_SAVE_DER
) {
593 /* recreate full DER encoding of this item */
594 derDecDbg1("--- SAVE_DER at currItem %u\n", i
);
596 dst
->length
+= (currDecoded
.content
.data
- currDER
);
599 /* on to next item */
602 /* is this the end? */
603 if(itemDex
== numItems
) {
604 /* normal termination */
608 /* on to next item */
614 * If current itemSpec isn't optional, abort - else on to
617 if(!(currOptions
& DER_DEC_OPTIONAL
)) {
618 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i
);
619 return DR_UnexpectedTag
;
622 /* else this was optional, on to next item */
623 } /* searching for tag match */
625 if(foundMatch
== 0) {
627 * Found an item we couldn't match to any tag spec and we're at
630 derDecDbg("--- TAG NOT FOUND, abort\n");
631 return DR_UnexpectedTag
;
634 /* else on to next item */
638 * If we get here, there appears to be more to process, but we've
639 * given the caller everything they want.
646 #endif /* DER_DECODE_ENABLE */