]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/libDER/libDER/DER_Decode.c
6e8802b444beddc94cfcd486fbf4237443a1fd3b
[apple/security.git] / OSX / libsecurity_keychain / libDER / libDER / DER_Decode.c
1 /*
2 * Copyright (c) 2005-2016 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 DERDecodeItemPartialBuffer(der, decoded, false);
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 DERReturn DERDecodeItemPartialBuffer(
84 const DERItem *der, /* data to decode */
85 DERDecodedInfo *decoded, /* RETURNED */
86 bool allowPartialBuffer)
87 {
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;
93
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. */
98 if(derLen < 2) {
99 return DR_DecodeError;
100 }
101 /* Grab the first byte of the tag. */
102 tag1 = *derPtr++;
103 derLen--;
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));
110 DERByte tagByte;
111 tagNumber = 0;
112 if (*derPtr == 0x80 || *derPtr < 0x1F)
113 return DR_DecodeError;
114 do {
115 if(derLen < 2 || (tagNumber & overflowMask) != 0) {
116 return DR_DecodeError;
117 }
118 tagByte = *derPtr++;
119 derLen--;
120 tagNumber = (tagNumber << 7) | (tagByte & 0x7F);
121 } while((tagByte & 0x80) != 0);
122
123 /* Check for any of the top 3 reserved bits being set. */
124 if ((tagNumber & (overflowMask << 4)) != 0)
125 #endif
126 return DR_DecodeError;
127 }
128 /* Returned tag, top 3 bits are class/method remaining bits are number. */
129 decoded->tag = ((DERTag)(tag1 & 0xE0) << ((sizeof(DERTag) - 1) * 8)) | tagNumber;
130
131 /* Tag decoding above ensured we have at least one more input byte left. */
132 len1 = *derPtr++;
133 derLen--;
134 if(len1 & 0x80) {
135 /* long length form - first byte is length of length */
136 DERSize longLen = 0; /* long form length */
137
138 unsigned dex;
139 len1 &= 0x7f;
140 if((len1 > sizeof(DERSize)) || (len1 > derLen) || len1 == 0 || *derPtr == 0) {
141 /* no can do */
142 return DR_DecodeError;
143 }
144 for(dex=0; dex<len1; dex++) {
145 longLen <<= 8;
146 longLen |= *derPtr++;
147 derLen--;
148 }
149 if(longLen > derLen && !allowPartialBuffer) {
150 /* not enough data left for this encoding */
151 return DR_DecodeError;
152 }
153 decoded->content.data = derPtr;
154 decoded->content.length = longLen;
155 }
156 else {
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;
161 }
162 decoded->content.data = derPtr;
163 decoded->content.length = len1;
164 }
165
166 return DR_Success;
167 }
168
169 /*
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.
172 */
173 DERReturn DERParseBitString(
174 const DERItem *contents,
175 DERItem *bitStringBytes, /* RETURNED */
176 DERByte *numUnusedBits) /* RETURNED */
177 {
178 if(contents->length < 2) {
179 /* not enough room for actual bits after the unused bits field */
180 *numUnusedBits = 0;
181 bitStringBytes->data = NULL;
182 bitStringBytes->length = 0;
183 return DR_Success;
184 }
185 *numUnusedBits = contents->data[0];
186 bitStringBytes->data = contents->data + 1;
187 bitStringBytes->length = contents->length - 1;
188 return DR_Success;
189 }
190
191 /*
192 * Given a BOOLEAN, in the form of its raw content bytes,
193 * obtain it's value.
194 */
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;
201
202 *value = contents->data[0] != 0;
203 return DR_Success;
204 }
205
206 /*
207 * Given a BOOLEAN, in the form of its raw content bytes,
208 * obtain it's value.
209 */
210 DERReturn DERParseBooleanWithDefault(
211 const DERItem *contents,
212 bool defaultValue,
213 bool *value) { /* RETURNED */
214 if (contents->length == 0) {
215 *value = defaultValue;
216 return DR_Success;
217 }
218 return DERParseBoolean(contents, value);
219 }
220
221
222 DERReturn DERParseInteger(
223 const DERItem *contents,
224 uint32_t *result) { /* RETURNED */
225 uint64_t value;
226 DERReturn drtn = DERParseInteger64(contents, &value);
227 if (drtn == DR_Success) {
228 if (value > UINT32_MAX)
229 drtn = DR_BufOverflow;
230 else
231 *result = (uint32_t)value;
232 }
233 return drtn;
234 }
235
236 DERReturn DERParseInteger64(
237 const DERItem *contents,
238 uint64_t *result) { /* RETURNED */
239 DERSize ix, length = contents->length;
240 if (length == 0)
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;
251 }
252 uint64_t value = 0;
253 for (ix = 0; ix < length; ++ix) {
254 value <<= 8;
255 value += contents->data[ix];
256 }
257 *result = value;
258 return DR_Success;
259 }
260
261 /* Sequence/set support */
262
263 /*
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.
268 */
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 */
274 {
275 DERDecodedInfo decoded;
276 DERReturn drtn;
277
278 drtn = DERDecodeItem(der, &decoded);
279 if(drtn) {
280 return drtn;
281 }
282 *tag = decoded.tag;
283 switch(decoded.tag) {
284 case ASN1_CONSTR_SEQUENCE:
285 case ASN1_CONSTR_SET:
286 break;
287 default:
288 return DR_UnexpectedTag;
289 }
290 derSeq->nextItem = decoded.content.data;
291 derSeq->end = decoded.content.data + decoded.content.length;
292 return DR_Success;
293 }
294
295 /*
296 * Use this to start in on decoding a sequence's content, when
297 * the top-level tag and content have already been decoded.
298 */
299 DERReturn DERDecodeSeqContentInit(
300 const DERItem *content,
301 DERSequence *derSeq) /* RETURNED, to use in DERDecodeSeqNext */
302 {
303 /* just prepare for decoding items in content */
304 derSeq->nextItem = content->data;
305 derSeq->end = content->data + content->length;
306 return DR_Success;
307 }
308
309 DERReturn DERDecodeSeqNext(
310 DERSequence *derSeq,
311 DERDecodedInfo *decoded) /* RETURNED */
312 {
313 DERReturn drtn;
314 DERItem item;
315
316 if(derSeq->nextItem >= derSeq->end) {
317 /* normal termination, contents all used up */
318 return DR_EndOfSequence;
319 }
320
321 /* decode next item */
322 item.data = derSeq->nextItem;
323 item.length = (DERSize) (derSeq->end - derSeq->nextItem);
324 drtn = DERDecodeItem(&item, decoded);
325 if(drtn) {
326 return drtn;
327 }
328
329 /* skip over the item we just decoded */
330 derSeq->nextItem = decoded->content.data + decoded->content.length;
331 return DR_Success;
332 }
333
334 /*
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().
338 */
339 DERReturn DERParseSequence(
340 const DERItem *der,
341 DERShort numItems, /* size of itemSpecs[] */
342 const DERItemSpec *itemSpecs,
343 void *dest, /* DERDecodedInfo(s) here RETURNED */
344 DERSize sizeToZero) /* optional */
345 {
346 DERReturn drtn;
347 DERDecodedInfo topDecode;
348
349 drtn = DERDecodeItem(der, &topDecode);
350 if(drtn) {
351 return drtn;
352 }
353 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
354 return DR_UnexpectedTag;
355 }
356 return DERParseSequenceContent(&topDecode.content,
357 numItems, itemSpecs, dest, sizeToZero);
358 }
359
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 */
367 {
368 DERSequence derSeq;
369 DERReturn drtn;
370 DERShort itemDex;
371 DERByte *currDER; /* full DER encoding of current item */
372
373 if(sizeToZero) {
374 DERMemset(dest, 0, sizeToZero);
375 }
376
377 drtn = DERDecodeSeqContentInit(content, &derSeq);
378 if(drtn) {
379 return drtn;
380 }
381
382 /* main loop */
383 for(itemDex=0 ; itemDex<numItems; ) {
384 DERDecodedInfo currDecoded;
385 DERShort i;
386 DERTag foundTag;
387 char foundMatch = 0;
388
389 /* save this in case of DER_DEC_SAVE_DER */
390 currDER = derSeq.nextItem;
391
392 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
393 if(drtn) {
394 /*
395 * One legal error here is DR_EndOfSequence when
396 * all remaining DERSequenceItems are optional.
397 */
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;
403 }
404 }
405 /* the rest are optional; success */
406 return DR_Success;
407 }
408 else {
409 /* any other error is fatal */
410 return drtn;
411 }
412 } /* decode error */
413
414 /*
415 * Seek matching tag or ASN_ANY in itemSpecs, skipping
416 * over optional items.
417 */
418 foundTag = currDecoded.tag;
419 derDecDbg1("--- foundTag 0x%llx\n", foundTag);
420
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);
426
427 if((currOptions & DER_DEC_ASN_ANY) ||
428 (foundTag == currItemSpec->tag)) {
429 /*
430 * We're good with this one. Cook up destination address
431 * as appropriate.
432 */
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);
441 dst->data = currDER;
442 dst->length += (currDecoded.content.data - currDER);
443 }
444 }
445
446 /* on to next item */
447 itemDex = i + 1;
448
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)
453 return DR_Success;
454 else
455 return DR_DecodeError;
456 }
457 else {
458 /* on to next item */
459 foundMatch = 1;
460 break;
461 }
462 } /* ASN_ANY, or match */
463
464 /*
465 * If current itemSpec isn't optional, abort - else on to
466 * next item
467 */
468 if(!(currOptions & DER_DEC_OPTIONAL)) {
469 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
470 return DR_UnexpectedTag;
471 }
472
473 /* else this was optional, on to next item */
474 } /* searching for tag match */
475
476 if(foundMatch == 0) {
477 /*
478 * Found an item we couldn't match to any tag spec and we're at
479 * the end.
480 */
481 derDecDbg("--- TAG NOT FOUND, abort\n");
482 return DR_UnexpectedTag;
483 }
484
485 /* else on to next item */
486 } /* main loop */
487
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)
491 return DR_Success;
492 else
493 return DR_DecodeError;
494 }
495
496 #if 0
497 /*
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().
501 */
502 DERReturn DERParseSequenceOf(
503 const DERItem *der,
504 DERShort numItems, /* size of itemSpecs[] */
505 const DERItemSpec *itemSpecs,
506 void *dest, /* DERDecodedInfo(s) here RETURNED */
507 DERSize *numDestItems) /* output */
508 {
509 DERReturn drtn;
510 DERDecodedInfo topDecode;
511
512 drtn = DERDecodeItem(der, &topDecode);
513 if(drtn) {
514 return drtn;
515 }
516 if(topDecode.tag != ASN1_CONSTR_SEQUENCE) {
517 return DR_UnexpectedTag;
518 }
519 return DERParseSequenceContent(&topDecode.content,
520 numItems, itemSpecs, dest, sizeToZero);
521 }
522
523 /*
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().
527 */
528 DERReturn DERParseSetOf(
529 const DERItem *der,
530 DERShort numItems, /* size of itemSpecs[] */
531 const DERItemSpec *itemSpecs,
532 void *dest, /* DERDecodedInfo(s) here RETURNED */
533 DERSize *numDestItems) /* output */
534 {
535 DERReturn drtn;
536 DERDecodedInfo topDecode;
537
538 drtn = DERDecodeItem(der, &topDecode);
539 if(drtn) {
540 return drtn;
541 }
542 if(topDecode.tag != ASN1_CONSTR_SET) {
543 return DR_UnexpectedTag;
544 }
545 return DERParseSetOrSequenceOfContent(&topDecode.content,
546 numItems, itemSpecs, dest, numDestItems);
547 }
548
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);
555 {
556 DERSequence derSeq;
557 DERShort itemDex;
558
559 drtn = DERDecodeSeqContentInit(content, &derSeq);
560 require_noerr_quiet(drtn, badCert);
561
562 /* main loop */
563 for (;;) {
564 DERDecodedInfo currDecoded;
565 DERShort i;
566 DERByte foundTag;
567 char foundMatch = 0;
568
569 drtn = DERDecodeSeqNext(&derSeq, &currDecoded);
570 if(drtn) {
571 /* The only legal error here is DR_EndOfSequence. */
572 if(drtn == DR_EndOfSequence) {
573 /* no more items left in the sequence; success */
574 return DR_Success;
575 }
576 else {
577 /* any other error is fatal */
578 require_noerr_quiet(drtn, badCert);
579 }
580 } /* decode error */
581
582 /* Each element can be anything. */
583 foundTag = currDecoded.tag;
584
585 /*
586 * We're good with this one. Cook up destination address
587 * as appropriate.
588 */
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);
595 dst->data = currDER;
596 dst->length += (currDecoded.content.data - currDER);
597 }
598
599 /* on to next item */
600 itemDex = i + 1;
601
602 /* is this the end? */
603 if(itemDex == numItems) {
604 /* normal termination */
605 return DR_Success;
606 }
607 else {
608 /* on to next item */
609 foundMatch = 1;
610 break;
611 }
612
613 /*
614 * If current itemSpec isn't optional, abort - else on to
615 * next item
616 */
617 if(!(currOptions & DER_DEC_OPTIONAL)) {
618 derDecDbg1("--- MISMATCH at currItem %u, !OPTIONAL, abort\n", i);
619 return DR_UnexpectedTag;
620 }
621
622 /* else this was optional, on to next item */
623 } /* searching for tag match */
624
625 if(foundMatch == 0) {
626 /*
627 * Found an item we couldn't match to any tag spec and we're at
628 * the end.
629 */
630 derDecDbg("--- TAG NOT FOUND, abort\n");
631 return DR_UnexpectedTag;
632 }
633
634 /* else on to next item */
635 } /* main loop */
636
637 /*
638 * If we get here, there appears to be more to process, but we've
639 * given the caller everything they want.
640 */
641 return DR_Success;
642 }
643 }
644 #endif
645
646 #endif /* DER_DECODE_ENABLE */