OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
DER_Decode.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005-2010 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 "DER_Decode.h"
29#include "asn1Types.h"
30
31#include "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
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 */
64 const DERItem *der, /* data to decode */
65 DERDecodedInfo *decoded) /* RETURNED */
66{
67 DERByte tag1; /* first tag byte */
68 DERByte len1; /* first length byte */
69 DERTag tagNumber; /* tag number without class and method bits */
70 DERByte *derPtr = der->data;
71 DERSize derLen = der->length;
72
73 /* The tag decoding below is fully BER complient. We support a max tag
74 value of 2 ^ ((sizeof(DERTag) * 8) - 3) - 1 so for tag size 1 byte we
75 support tag values from 0 - 0x1F. For tag size 2 tag values
76 from 0 - 0x1FFF and for tag size 4 values from 0 - 0x1FFFFFFF. */
77 if(derLen < 2) {
78 return DR_DecodeError;
79 }
80 /* Grab the first byte of the tag. */
81 tag1 = *derPtr++;
82 derLen--;
83 tagNumber = tag1 & 0x1F;
84 if(tagNumber == 0x1F) {
85#ifdef DER_MULTIBYTE_TAGS
86 /* Long tag form: bit 8 of each octet shall be set to one unless it is
87 the last octet of the tag */
88 const DERTag overflowMask = ((DERTag)0x7F << (sizeof(DERTag) * 8 - 7));
89 DERByte tagByte;
90 tagNumber = 0;
91 do {
92 if(derLen < 2 || (tagNumber & overflowMask) != 0) {
93 return DR_DecodeError;
94 }
95 tagByte = *derPtr++;
96 derLen--;
97 tagNumber = (tagNumber << 7) | (tagByte & 0x7F);
98 } while((tagByte & 0x80) != 0);
99
100 /* Check for any of the top 3 reserved bits being set. */
101 if ((tagNumber & (overflowMask << 4)) != 0)
102#endif
103 return DR_DecodeError;
104 }
105 /* Returned tag, top 3 bits are class/method remaining bits are number. */
106 decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber;
107
108 /* Tag decoding above ensured we have at least one more input byte left. */
109 len1 = *derPtr++;
110 derLen--;
111 if(len1 & 0x80) {
112 /* long length form - first byte is length of length */
113 DERSize longLen = 0; /* long form length */
114 unsigned dex;
115
116 len1 &= 0x7f;
117 if((len1 > sizeof(DERSize)) || (len1 > derLen)) {
118 /* no can do */
119 return DR_DecodeError;
120 }
121 for(dex=0; dex<len1; dex++) {
122 longLen <<= 8;
123 longLen |= *derPtr++;
124 derLen--;
125 }
126 if(longLen > derLen) {
127 /* not enough data left for this encoding */
128 return DR_DecodeError;
129 }
130 decoded->content.data = derPtr;
131 decoded->content.length = longLen;
132 }
133 else {
134 /* short length form, len1 is the length */
135 if(len1 > derLen) {
136 /* not enough data left for this encoding */
137 return DR_DecodeError;
138 }
139 decoded->content.data = derPtr;
140 decoded->content.length = len1;
141 }
142
143 return DR_Success;
144}
145
146/*
147 * Given a BIT_STRING, in the form of its raw content bytes,
148 * obtain the number of unused bits and the raw bit string bytes.
149 */
151 const DERItem *contents,
152 DERItem *bitStringBytes, /* RETURNED */
153 DERByte *numUnusedBits) /* RETURNED */
154{
155 if(contents->length < 2) {
156 /* not enough room for actual bits after the unused bits field */
157 *numUnusedBits = 0;
158 bitStringBytes->data = NULL;
159 bitStringBytes->length = 0;
160 return DR_Success;
161 }
162 *numUnusedBits = contents->data[0];
163 bitStringBytes->data = contents->data + 1;
164 bitStringBytes->length = contents->length - 1;
165 return DR_Success;
166}
167
168/*
169 * Given a BOOLEAN, in the form of its raw content bytes,
170 * obtain its value.
171 */
173 const DERItem *contents,
174 bool defaultValue,
175 bool *value) { /* RETURNED */
176 if (contents->length == 0) {
177 *value = defaultValue;
178 return DR_Success;
179 }
180 if (contents->length != 1 ||
181 (contents->data[0] != 0 && contents->data[0] != 0xFF))
182 return DR_DecodeError;
183
184 *value = contents->data[0] != 0;
185 return DR_Success;
186}
187
189 const DERItem *contents,
190 uint32_t *result) { /* RETURNED */
191 DERSize ix, length = contents->length;
192 if (length > 4)
193 return DR_BufOverflow;
194 uint32_t value = 0;
195 for (ix = 0; ix < length; ++ix) {
196 value <<= 8;
197 value += contents->data[ix];
198 }
199 *result = value;
200 return DR_Success;
201}
202
203/* Sequence/set support */
204
205/*
206 * To decode a set or sequence, call DERDecodeSeqInit once, then
207 * call DERDecodeSeqNext to get each enclosed item.
208 * DERDecodeSeqNext returns DR_EndOfSequence when no more
209 * items are available.
210 */
212 const DERItem *der, /* data to decode */
213 DERTag *tag, /* RETURNED tag of sequence/set. This will be
214 * either ASN1_CONSTR_SEQUENCE or ASN1_CONSTR_SET. */
215 DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
216{
217 DERDecodedInfo decoded;
218 DERReturn drtn;
219
220 drtn = DERDecodeItem(der, &decoded);
221 if(drtn) {
222 return drtn;
223 }
224 *tag = decoded.tag;
225 switch(decoded.tag) {
227 case ASN1_CONSTR_SET:
228 break;
229 default:
230 return DR_UnexpectedTag;
231 }
232 derSeq->nextItem = decoded.content.data;
233 derSeq->end = decoded.content.data + decoded.content.length;
234 return DR_Success;
235}
236
237/*
238 * Use this to start in on decoding a sequence's content, when
239 * the top-level tag and content have already been decoded.
240 */
242 const DERItem *content,
243 DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
244{
245 /* just prepare for decoding items in content */
246 derSeq->nextItem = content->data;
247 derSeq->end = content->data + content->length;
248 return DR_Success;
249}
250
252 DERSequence *derSeq,
253 DERDecodedInfo *decoded) /* RETURNED */
254{
255 DERReturn drtn;
256 DERItem item;
257
258 if(derSeq->nextItem >= derSeq->end) {
259 /* normal termination, contents all used up */
260 return DR_EndOfSequence;
261 }
262
263 /* decode next item */
264 item.data = derSeq->nextItem;
265 item.length = derSeq->end - derSeq->nextItem;
266 drtn = DERDecodeItem(&item, decoded);
267 if(drtn) {
268 return drtn;
269 }
270
271 /* skip over the item we just decoded */
272 derSeq->nextItem = decoded->content.data + decoded->content.length;
273 return DR_Success;
274}
275
276/*
277 * High level sequence parse, starting with top-level tag and content.
278 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
279 * OK, use DERParseSequenceContent().
280 */
282 const DERItem *der,
283 DERShort numItems, /* size of itemSpecs[] */
284 const DERItemSpec *itemSpecs,
285 void *dest, /* DERDecodedInfo(s) here RETURNED */
286 DERSize sizeToZero) /* optional */
287{
288 DERReturn drtn;
289 DERDecodedInfo topDecode;
290
291 drtn = DERDecodeItem(der, &topDecode);
292 if(drtn) {
293 return drtn;
294 }
295 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
296 return DR_UnexpectedTag;
297 }
298 return DERParseSequenceContent(&topDecode.content,
299 numItems, itemSpecs, dest, sizeToZero);
300}
301
302/* high level sequence parse, starting with sequence's content */
304 const DERItem *content,
305 DERShort numItems, /* size of itemSpecs[] */
306 const DERItemSpec *itemSpecs,
307 void *dest, /* DERDecodedInfo(s) here RETURNED */
308 DERSize sizeToZero) /* optional */
309{
310 DERSequence derSeq;
311 DERReturn drtn;
312 DERShort itemDex;
313 DERByte *currDER; /* full DER encoding of current item */
314
315 if(sizeToZero) {
316 DERMemset(dest, 0, sizeToZero);
317 }
318
319 drtn = DERDecodeSeqContentInit(content, &derSeq);
320 if(drtn) {
321 return drtn;
322 }
323
324 /* main loop */
325 for(itemDex=0 ; itemDex<numItems; ) {
326 DERDecodedInfo currDecoded;
327 DERShort i;
328 DERTag foundTag;
329 char foundMatch = 0;
330
331 /* save this in case of DER_DEC_SAVE_DER */
332 currDER = derSeq.nextItem;
333
334 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
335 if(drtn) {
336 /*
337 * One legal error here is DR_EndOfSequence when
338 * all remaining DERSequenceItems are optional.
339 */
340 if(drtn == DR_EndOfSequence) {
341 for(i=itemDex; i<numItems; i++) {
342 if(!(itemSpecs[i].options & DER_DEC_OPTIONAL)) {
343 /* unexpected end of sequence */
344 return DR_IncompleteSeq;
345 }
346 }
347 /* the rest are optional; success */
348 return DR_Success;
349 }
350 else {
351 /* any other error is fatal */
352 return drtn;
353 }
354 } /* decode error */
355
356 /*
357 * Seek matching tag or ASN_ANY in itemSpecs, skipping
358 * over optional items.
359 */
360 foundTag = currDecoded.tag;
361 derDecDbg1("--- foundTag 0x%x\n", foundTag);
362
363 for(i=itemDex; i<numItems; i++) {
364 const DERItemSpec *currItemSpec = &itemSpecs[i];
365 DERShort currOptions = currItemSpec->options;
366 derDecDbg3("--- currItem %u expectTag 0x%x currOptions 0x%x\n",
367 i, currItemSpec->tag, currOptions);
368
369 if((currOptions & DER_DEC_ASN_ANY) ||
370 (foundTag == currItemSpec->tag)) {
371 /*
372 * We're good with this one. Cook up destination address
373 * as appropriate.
374 */
375 if(!(currOptions & DER_DEC_SKIP)) {
376 derDecDbg1("--- MATCH at currItem %u\n", i);
377 DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
378 DERItem *dst = (DERItem *)byteDst;
379 *dst = currDecoded.content;
380 if(currOptions & DER_DEC_SAVE_DER) {
381 /* recreate full DER encoding of this item */
382 derDecDbg1("--- SAVE_DER at currItem %u\n", i);
383 dst->data = currDER;
384 dst->length += (currDecoded.content.data - currDER);
385 }
386 }
387
388 /* on to next item */
389 itemDex = i + 1;
390
391 /* is this the end? */
392 if(itemDex == numItems) {
393 /* normal termination */
394 return DR_Success;
395 }
396 else {
397 /* on to next item */
398 foundMatch = 1;
399 break;
400 }
401 } /* ASN_ANY, or match */
402
403 /*
404 * If current itemSpec isn't optional, abort - else on to
405 * next item
406 */
407 if(!(currOptions & DER_DEC_OPTIONAL)) {
408 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
409 return DR_UnexpectedTag;
410 }
411
412 /* else this was optional, on to next item */
413 } /* searching for tag match */
414
415 if(foundMatch == 0) {
416 /*
417 * Found an item we couldn't match to any tag spec and we're at
418 * the end.
419 */
420 derDecDbg("--- TAG NOT FOUND, abort\n");
421 return DR_UnexpectedTag;
422 }
423
424 /* else on to next item */
425 } /* main loop */
426
427 /*
428 * If we get here, there appears to be more to process, but we've
429 * given the caller everything they want.
430 */
431 return DR_Success;
432}
433
434#if 0
435/*
436 * High level sequence parse, starting with top-level tag and content.
437 * Top level tag must be ASN1_CONSTR_SEQUENCE - if it's not, and that's
438 * OK, use DERParseSequenceContent().
439 */
440DERReturn DERParseSequenceOf(
441 const DERItem *der,
442 DERShort numItems, /* size of itemSpecs[] */
443 const DERItemSpec *itemSpecs,
444 void *dest, /* DERDecodedInfo(s) here RETURNED */
445 DERSize *numDestItems) /* output */
446{
447 DERReturn drtn;
448 DERDecodedInfo topDecode;
449
450 drtn = DERDecodeItem(der, &topDecode);
451 if(drtn) {
452 return drtn;
453 }
454 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
455 return DR_UnexpectedTag;
456 }
457 return DERParseSequenceContent(&topDecode.content,
458 numItems, itemSpecs, dest, sizeToZero);
459}
460
461/*
462 * High level set of parse, starting with top-level tag and content.
463 * Top level tag must be ASN1_CONSTR_SET - if it's not, and that's
464 * OK, use DERParseSetOrSequenceOfContent().
465 */
466DERReturn DERParseSetOf(
467 const DERItem *der,
468 DERShort numItems, /* size of itemSpecs[] */
469 const DERItemSpec *itemSpecs,
470 void *dest, /* DERDecodedInfo(s) here RETURNED */
471 DERSize *numDestItems) /* output */
472{
473 DERReturn drtn;
474 DERDecodedInfo topDecode;
475
476 drtn = DERDecodeItem(der, &topDecode);
477 if(drtn) {
478 return drtn;
479 }
480 if(topDecode.tag != ASN1_CONSTR_SET) {
481 return DR_UnexpectedTag;
482 }
483 return DERParseSetOrSequenceOfContent(&topDecode.content,
484 numItems, itemSpecs, dest, numDestItems);
485}
486
487/* High level set of or sequence of parse, starting with set or
488 sequence's content */
489DERReturn DERParseSetOrSequenceOfContent(
490 const DERItem *content,
491 void(*itemHandeler)(void *, const DERDecodedInfo *)
492 void *itemHandelerContext);
493{
494 DERSequence derSeq;
495 DERShort itemDex;
496
497 drtn = DERDecodeSeqContentInit(content, &derSeq);
498 require_noerr_quiet(drtn, badCert);
499
500 /* main loop */
501 for (;;) {
502 DERDecodedInfo currDecoded;
503 DERShort i;
504 DERByte foundTag;
505 char foundMatch = 0;
506
507 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
508 if(drtn) {
509 /* The only legal error here is DR_EndOfSequence. */
510 if(drtn == DR_EndOfSequence) {
511 /* no more items left in the sequence; success */
512 return DR_Success;
513 }
514 else {
515 /* any other error is fatal */
516 require_noerr_quiet(drtn, badCert);
517 }
518 } /* decode error */
519
520 /* Each element can be anything. */
521 foundTag = currDecoded.tag;
522
523 /*
524 * We're good with this one. Cook up destination address
525 * as appropriate.
526 */
527 DERByte *byteDst = (DERByte *)dest + currItemSpec->offset;
528 DERItem *dst = (DERItem *)byteDst;
529 *dst = currDecoded.content;
530 if(currOptions & DER_DEC_SAVE_DER) {
531 /* recreate full DER encoding of this item */
532 derDecDbg1("--- SAVE_DER at currItem %u\n", i);
533 dst->data = currDER;
534 dst->length += (currDecoded.content.data - currDER);
535 }
536
537 /* on to next item */
538 itemDex = i + 1;
539
540 /* is this the end? */
541 if(itemDex == numItems) {
542 /* normal termination */
543 return DR_Success;
544 }
545 else {
546 /* on to next item */
547 foundMatch = 1;
548 break;
549 }
550
551 /*
552 * If current itemSpec isn't optional, abort - else on to
553 * next item
554 */
555 if(!(currOptions & DER_DEC_OPTIONAL)) {
556 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
557 return DR_UnexpectedTag;
558 }
559
560 /* else this was optional, on to next item */
561 } /* searching for tag match */
562
563 if(foundMatch == 0) {
564 /*
565 * Found an item we couldn't match to any tag spec and we're at
566 * the end.
567 */
568 derDecDbg("--- TAG NOT FOUND, abort\n");
569 return DR_UnexpectedTag;
570 }
571
572 /* else on to next item */
573 } /* main loop */
574
575 /*
576 * If we get here, there appears to be more to process, but we've
577 * given the caller everything they want.
578 */
579 return DR_Success;
580 }
581}
582#endif
583
584#endif /* DER_DECODE_ENABLE */
UINT8 value
#define derDecDbg1(a, b)
Definition DER_Decode.c:48
DERReturn DERParseSequenceContent(const DERItem *content, DERShort numItems, const DERItemSpec *itemSpecs, void *dest, DERSize sizeToZero)
Definition DER_Decode.c:303
DERReturn DERDecodeSeqInit(const DERItem *der, DERTag *tag, DERSequence *derSeq)
Definition DER_Decode.c:211
DERReturn DERDecodeSeqNext(DERSequence *derSeq, DERDecodedInfo *decoded)
Definition DER_Decode.c:251
DERReturn DERDecodeSeqContentInit(const DERItem *content, DERSequence *derSeq)
Definition DER_Decode.c:241
DERReturn DERDecodeItem(const DERItem *der, DERDecodedInfo *decoded)
Definition DER_Decode.c:63
DERReturn DERParseBitString(const DERItem *contents, DERItem *bitStringBytes, DERByte *numUnusedBits)
Definition DER_Decode.c:150
DERReturn DERParseInteger(const DERItem *contents, uint32_t *result)
Definition DER_Decode.c:188
#define derDecDbg3(a, b, c, d)
Definition DER_Decode.c:50
DERReturn DERParseSequence(const DERItem *der, DERShort numItems, const DERItemSpec *itemSpecs, void *dest, DERSize sizeToZero)
Definition DER_Decode.c:281
DERReturn DERParseBoolean(const DERItem *contents, bool defaultValue, bool *value)
Definition DER_Decode.c:172
#define derDecDbg(a)
Definition DER_Decode.c:47
#define DER_DEC_SKIP
Definition DER_Decode.h:143
#define DER_DEC_OPTIONAL
Definition DER_Decode.h:137
#define DER_DEC_SAVE_DER
Definition DER_Decode.h:147
#define DER_DEC_ASN_ANY
Definition DER_Decode.h:140
#define ASN1_CONSTR_SET
Definition asn1Types.h:84
#define ASN1_CONSTR_SEQUENCE
Definition asn1Types.h:83
DERReturn
Definition libDER.h:20
@ DR_Success
Definition libDER.h:21
@ DR_BufOverflow
Definition libDER.h:28
@ DR_EndOfSequence
Definition libDER.h:22
@ DR_UnexpectedTag
Definition libDER.h:23
@ DR_DecodeError
Definition libDER.h:24
@ DR_IncompleteSeq
Definition libDER.h:26
size_t DERSize
uint16_t DERShort
uint64_t DERTag
uint8_t DERByte
UINT32 uint32_t
#define DERMemset(ptr, c, len)
DERItem content
Definition DER_Decode.h:44
DERByte * data
Definition libDER.h:36
DERSize length
Definition libDER.h:37
DERTag tag
Definition libDER.h:47
DERShort options
Definition libDER.h:48
DERSize offset
Definition libDER.h:46
DERByte * end
Definition DER_Decode.h:90
DERByte * nextItem
Definition DER_Decode.h:89