Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/util/quickder.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 /* | |
6 Optimized ASN.1 DER decoder | |
7 | |
8 */ | |
9 | |
10 #include "secerr.h" | |
11 #include "secasn1.h" /* for SEC_ASN1GetSubtemplate */ | |
12 #include "secitem.h" | |
13 | |
14 /* | |
15 * simple definite-length ASN.1 decoder | |
16 */ | |
17 | |
18 static unsigned char* definite_length_decoder(const unsigned char *buf, | |
19 const unsigned int length, | |
20 unsigned int *data_length, | |
21 PRBool includeTag) | |
22 { | |
23 unsigned char tag; | |
24 unsigned int used_length= 0; | |
25 unsigned int data_len; | |
26 | |
27 if (used_length >= length) | |
28 { | |
29 return NULL; | |
30 } | |
31 tag = buf[used_length++]; | |
32 | |
33 /* blow out when we come to the end */ | |
34 if (tag == 0) | |
35 { | |
36 return NULL; | |
37 } | |
38 | |
39 if (used_length >= length) | |
40 { | |
41 return NULL; | |
42 } | |
43 data_len = buf[used_length++]; | |
44 | |
45 if (data_len&0x80) | |
46 { | |
47 int len_count = data_len & 0x7f; | |
48 | |
49 data_len = 0; | |
50 | |
51 while (len_count-- > 0) | |
52 { | |
53 if (used_length >= length) | |
54 { | |
55 return NULL; | |
56 } | |
57 data_len = (data_len << 8) | buf[used_length++]; | |
58 } | |
59 } | |
60 | |
61 if (data_len > (length-used_length) ) | |
62 { | |
63 return NULL; | |
64 } | |
65 if (includeTag) data_len += used_length; | |
66 | |
67 *data_length = data_len; | |
68 return ((unsigned char*)buf + (includeTag ? 0 : used_length)); | |
69 } | |
70 | |
71 static SECStatus GetItem(SECItem* src, SECItem* dest, PRBool includeTag) | |
72 { | |
73 if ( (!src) || (!dest) || (!src->data && src->len) ) | |
74 { | |
75 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
76 return SECFailure; | |
77 } | |
78 | |
79 if (!src->len) | |
80 { | |
81 /* reaching the end of the buffer is not an error */ | |
82 dest->data = NULL; | |
83 dest->len = 0; | |
84 return SECSuccess; | |
85 } | |
86 | |
87 dest->data = definite_length_decoder(src->data, src->len, &dest->len, | |
88 includeTag); | |
89 if (dest->data == NULL) | |
90 { | |
91 PORT_SetError(SEC_ERROR_BAD_DER); | |
92 return SECFailure; | |
93 } | |
94 src->len -= (dest->data - src->data) + dest->len; | |
95 src->data = dest->data + dest->len; | |
96 return SECSuccess; | |
97 } | |
98 | |
99 /* check if the actual component's type matches the type in the template */ | |
100 | |
101 static SECStatus MatchComponentType(const SEC_ASN1Template* templateEntry, | |
102 SECItem* item, PRBool* match, void* dest) | |
103 { | |
104 unsigned long kind = 0; | |
105 unsigned char tag = 0; | |
106 | |
107 if ( (!item) || (!item->data && item->len) || (!templateEntry) || (!match) ) | |
108 { | |
109 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
110 return SECFailure; | |
111 } | |
112 | |
113 if (!item->len) | |
114 { | |
115 *match = PR_FALSE; | |
116 return SECSuccess; | |
117 } | |
118 | |
119 kind = templateEntry->kind; | |
120 tag = *(unsigned char*) item->data; | |
121 | |
122 if ( ( (kind & SEC_ASN1_INLINE) || | |
123 (kind & SEC_ASN1_POINTER) ) && | |
124 (0 == (kind & SEC_ASN1_TAG_MASK) ) ) | |
125 { | |
126 /* These cases are special because the template's "kind" does not | |
127 give us the information for the ASN.1 tag of the next item. It can | |
128 only be figured out from the subtemplate. */ | |
129 if (!(kind & SEC_ASN1_OPTIONAL)) | |
130 { | |
131 /* This is a required component. If there is a type mismatch, | |
132 the decoding of the subtemplate will fail, so assume this | |
133 is a match at the parent level and let it fail later. This | |
134 avoids a redundant check in matching cases */ | |
135 *match = PR_TRUE; | |
136 return SECSuccess; | |
137 } | |
138 else | |
139 { | |
140 /* optional component. This is the hard case. Now we need to | |
141 look at the subtemplate to get the expected kind */ | |
142 const SEC_ASN1Template* subTemplate = | |
143 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE); | |
144 if (!subTemplate) | |
145 { | |
146 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); | |
147 return SECFailure; | |
148 } | |
149 if ( (subTemplate->kind & SEC_ASN1_INLINE) || | |
150 (subTemplate->kind & SEC_ASN1_POINTER) ) | |
151 { | |
152 /* disallow nesting SEC_ASN1_POINTER and SEC_ASN1_INLINE, | |
153 otherwise you may get a false positive due to the recursion | |
154 optimization above that always matches the type if the | |
155 component is required . Nesting these should never be | |
156 required, so that no one should miss this ability */ | |
157 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); | |
158 return SECFailure; | |
159 } | |
160 return MatchComponentType(subTemplate, item, match, | |
161 (void*)((char*)dest + templateEntry->offset)); | |
162 } | |
163 } | |
164 | |
165 if (kind & SEC_ASN1_CHOICE) | |
166 { | |
167 /* we need to check the component's tag against each choice's tag */ | |
168 /* XXX it would be nice to save the index of the choice here so that | |
169 DecodeChoice wouldn't have to do this again. However, due to the | |
170 recursivity of MatchComponentType, we don't know if we are in a | |
171 required or optional component, so we can't write anywhere in | |
172 the destination within this function */ | |
173 unsigned choiceIndex = 1; | |
174 const SEC_ASN1Template* choiceEntry; | |
175 while ( (choiceEntry = &templateEntry[choiceIndex++]) && (choiceEntry->kind)) | |
176 { | |
177 if ( (SECSuccess == MatchComponentType(choiceEntry, item, match, | |
178 (void*)((char*)dest + choiceEntry->offset))) && | |
179 (PR_TRUE == *match) ) | |
180 { | |
181 return SECSuccess; | |
182 } | |
183 } | |
184 /* no match, caller must decide if this is BAD DER, or not. */ | |
185 *match = PR_FALSE; | |
186 return SECSuccess; | |
187 } | |
188 | |
189 if (kind & SEC_ASN1_ANY) | |
190 { | |
191 /* SEC_ASN1_ANY always matches */ | |
192 *match = PR_TRUE; | |
193 return SECSuccess; | |
194 } | |
195 | |
196 if ( (0 == ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK)) && | |
197 (!(kind & SEC_ASN1_EXPLICIT)) && | |
198 ( ( (kind & SEC_ASN1_SAVE) || | |
199 (kind & SEC_ASN1_SKIP) ) && | |
200 (!(kind & SEC_ASN1_OPTIONAL)) | |
201 ) | |
202 ) | |
203 { | |
204 /* when saving or skipping a required component, a type is not | |
205 required in the template. This is for legacy support of | |
206 SEC_ASN1_SAVE and SEC_ASN1_SKIP only. XXX I would like to | |
207 deprecate these usages and always require a type, as this | |
208 disables type checking, and effectively forbids us from | |
209 transparently ignoring optional components we aren't aware of */ | |
210 *match = PR_TRUE; | |
211 return SECSuccess; | |
212 } | |
213 | |
214 /* first, do a class check */ | |
215 if ( (tag & SEC_ASN1_CLASS_MASK) != | |
216 (((unsigned char)kind) & SEC_ASN1_CLASS_MASK) ) | |
217 { | |
218 #ifdef DEBUG | |
219 /* this is only to help debugging of the decoder in case of problems */ | |
220 unsigned char tagclass = tag & SEC_ASN1_CLASS_MASK; | |
221 unsigned char expectedclass = (unsigned char)kind & SEC_ASN1_CLASS_MASK; | |
222 tagclass = tagclass; | |
223 expectedclass = expectedclass; | |
224 #endif | |
225 *match = PR_FALSE; | |
226 return SECSuccess; | |
227 } | |
228 | |
229 /* now do a tag check */ | |
230 if ( ((unsigned char)kind & SEC_ASN1_TAGNUM_MASK) != | |
231 (tag & SEC_ASN1_TAGNUM_MASK)) | |
232 { | |
233 *match = PR_FALSE; | |
234 return SECSuccess; | |
235 } | |
236 | |
237 /* now, do a method check. This depends on the class */ | |
238 switch (tag & SEC_ASN1_CLASS_MASK) | |
239 { | |
240 case SEC_ASN1_UNIVERSAL: | |
241 /* For types of the SEC_ASN1_UNIVERSAL class, we know which must be | |
242 primitive or constructed based on the tag */ | |
243 switch (tag & SEC_ASN1_TAGNUM_MASK) | |
244 { | |
245 case SEC_ASN1_SEQUENCE: | |
246 case SEC_ASN1_SET: | |
247 case SEC_ASN1_EMBEDDED_PDV: | |
248 /* this component must be a constructed type */ | |
249 /* XXX add any new universal constructed type here */ | |
250 if (tag & SEC_ASN1_CONSTRUCTED) | |
251 { | |
252 *match = PR_TRUE; | |
253 return SECSuccess; | |
254 } | |
255 break; | |
256 | |
257 default: | |
258 /* this component must be a primitive type */ | |
259 if (! (tag & SEC_ASN1_CONSTRUCTED)) | |
260 { | |
261 *match = PR_TRUE; | |
262 return SECSuccess; | |
263 } | |
264 break; | |
265 } | |
266 break; | |
267 | |
268 default: | |
269 /* for all other classes, we check the method based on the template */ | |
270 if ( (unsigned char)(kind & SEC_ASN1_METHOD_MASK) == | |
271 (tag & SEC_ASN1_METHOD_MASK) ) | |
272 { | |
273 *match = PR_TRUE; | |
274 return SECSuccess; | |
275 } | |
276 /* method does not match between template and component */ | |
277 break; | |
278 } | |
279 | |
280 *match = PR_FALSE; | |
281 return SECSuccess; | |
282 } | |
283 | |
284 #ifdef DEBUG | |
285 | |
286 static SECStatus CheckSequenceTemplate(const SEC_ASN1Template* sequenceTemplate) | |
287 { | |
288 SECStatus rv = SECSuccess; | |
289 const SEC_ASN1Template* sequenceEntry = NULL; | |
290 unsigned long seqIndex = 0; | |
291 unsigned long lastEntryIndex = 0; | |
292 unsigned long ambiguityIndex = 0; | |
293 PRBool foundAmbiguity = PR_FALSE; | |
294 | |
295 do | |
296 { | |
297 sequenceEntry = &sequenceTemplate[seqIndex++]; | |
298 if (sequenceEntry->kind) | |
299 { | |
300 /* ensure that we don't have an optional component of SEC_ASN1_ANY | |
301 in the middle of the sequence, since we could not handle it */ | |
302 /* XXX this function needs to dig into the subtemplates to find | |
303 the next tag */ | |
304 if ( (PR_FALSE == foundAmbiguity) && | |
305 (sequenceEntry->kind & SEC_ASN1_OPTIONAL) && | |
306 (sequenceEntry->kind & SEC_ASN1_ANY) ) | |
307 { | |
308 foundAmbiguity = PR_TRUE; | |
309 ambiguityIndex = seqIndex - 1; | |
310 } | |
311 } | |
312 } while (sequenceEntry->kind); | |
313 | |
314 lastEntryIndex = seqIndex - 2; | |
315 | |
316 if (PR_FALSE != foundAmbiguity) | |
317 { | |
318 if (ambiguityIndex < lastEntryIndex) | |
319 { | |
320 /* ambiguity can only be tolerated on the last entry */ | |
321 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); | |
322 rv = SECFailure; | |
323 } | |
324 } | |
325 | |
326 /* XXX also enforce ASN.1 requirement that tags be | |
327 distinct for consecutive optional components */ | |
328 | |
329 return rv; | |
330 } | |
331 | |
332 #endif | |
333 | |
334 static SECStatus DecodeItem(void* dest, | |
335 const SEC_ASN1Template* templateEntry, | |
336 SECItem* src, PLArenaPool* arena, PRBool checkTag); | |
337 | |
338 static SECStatus DecodeSequence(void* dest, | |
339 const SEC_ASN1Template* templateEntry, | |
340 SECItem* src, PLArenaPool* arena) | |
341 { | |
342 SECStatus rv = SECSuccess; | |
343 SECItem source; | |
344 SECItem sequence; | |
345 const SEC_ASN1Template* sequenceTemplate = &(templateEntry[1]); | |
346 const SEC_ASN1Template* sequenceEntry = NULL; | |
347 unsigned long seqindex = 0; | |
348 | |
349 #ifdef DEBUG | |
350 /* for a sequence, we need to validate the template. */ | |
351 rv = CheckSequenceTemplate(sequenceTemplate); | |
352 #endif | |
353 | |
354 source = *src; | |
355 | |
356 /* get the sequence */ | |
357 if (SECSuccess == rv) | |
358 { | |
359 rv = GetItem(&source, &sequence, PR_FALSE); | |
360 } | |
361 | |
362 /* process it */ | |
363 if (SECSuccess == rv) | |
364 do | |
365 { | |
366 sequenceEntry = &sequenceTemplate[seqindex++]; | |
367 if ( (sequenceEntry && sequenceEntry->kind) && | |
368 (sequenceEntry->kind != SEC_ASN1_SKIP_REST) ) | |
369 { | |
370 rv = DecodeItem(dest, sequenceEntry, &sequence, arena, PR_TRUE); | |
371 } | |
372 } while ( (SECSuccess == rv) && | |
373 (sequenceEntry->kind && | |
374 sequenceEntry->kind != SEC_ASN1_SKIP_REST) ); | |
375 /* we should have consumed all the bytes in the sequence by now | |
376 unless the caller doesn't care about the rest of the sequence */ | |
377 if (SECSuccess == rv && sequence.len && | |
378 sequenceEntry && sequenceEntry->kind != SEC_ASN1_SKIP_REST) | |
379 { | |
380 /* it isn't 100% clear whether this is a bad DER or a bad template. | |
381 The problem is that logically, they don't match - there is extra | |
382 data in the DER that the template doesn't know about */ | |
383 PORT_SetError(SEC_ERROR_BAD_DER); | |
384 rv = SECFailure; | |
385 } | |
386 | |
387 return rv; | |
388 } | |
389 | |
390 static SECStatus DecodeInline(void* dest, | |
391 const SEC_ASN1Template* templateEntry, | |
392 SECItem* src, PLArenaPool* arena, PRBool checkTag) | |
393 { | |
394 const SEC_ASN1Template* inlineTemplate = | |
395 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE); | |
396 return DecodeItem((void*)((char*)dest + templateEntry->offset), | |
397 inlineTemplate, src, arena, checkTag); | |
398 } | |
399 | |
400 static SECStatus DecodePointer(void* dest, | |
401 const SEC_ASN1Template* templateEntry, | |
402 SECItem* src, PLArenaPool* arena, PRBool checkTag) | |
403 { | |
404 const SEC_ASN1Template* ptrTemplate = | |
405 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE); | |
406 void* subdata = PORT_ArenaZAlloc(arena, ptrTemplate->size); | |
407 *(void**)((char*)dest + templateEntry->offset) = subdata; | |
408 if (subdata) | |
409 { | |
410 return DecodeItem(subdata, ptrTemplate, src, arena, checkTag); | |
411 } | |
412 else | |
413 { | |
414 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
415 return SECFailure; | |
416 } | |
417 } | |
418 | |
419 static SECStatus DecodeImplicit(void* dest, | |
420 const SEC_ASN1Template* templateEntry, | |
421 SECItem* src, PLArenaPool* arena) | |
422 { | |
423 if (templateEntry->kind & SEC_ASN1_POINTER) | |
424 { | |
425 return DecodePointer((void*)((char*)dest ), | |
426 templateEntry, src, arena, PR_FALSE); | |
427 } | |
428 else | |
429 { | |
430 return DecodeInline((void*)((char*)dest ), | |
431 templateEntry, src, arena, PR_FALSE); | |
432 } | |
433 } | |
434 | |
435 static SECStatus DecodeChoice(void* dest, | |
436 const SEC_ASN1Template* templateEntry, | |
437 SECItem* src, PLArenaPool* arena) | |
438 { | |
439 SECStatus rv = SECSuccess; | |
440 SECItem choice; | |
441 const SEC_ASN1Template* choiceTemplate = &(templateEntry[1]); | |
442 const SEC_ASN1Template* choiceEntry = NULL; | |
443 unsigned long choiceindex = 0; | |
444 | |
445 /* XXX for a choice component, we should validate the template to make | |
446 sure the tags are distinct, in debug builds. This hasn't been | |
447 implemented yet */ | |
448 /* rv = CheckChoiceTemplate(sequenceTemplate); */ | |
449 | |
450 /* process it */ | |
451 do | |
452 { | |
453 choice = *src; | |
454 choiceEntry = &choiceTemplate[choiceindex++]; | |
455 if (choiceEntry->kind) | |
456 { | |
457 rv = DecodeItem(dest, choiceEntry, &choice, arena, PR_TRUE); | |
458 } | |
459 } while ( (SECFailure == rv) && (choiceEntry->kind)); | |
460 | |
461 if (SECFailure == rv) | |
462 { | |
463 /* the component didn't match any of the choices */ | |
464 PORT_SetError(SEC_ERROR_BAD_DER); | |
465 } | |
466 else | |
467 { | |
468 /* set the type in the union here */ | |
469 int *which = (int *)((char *)dest + templateEntry->offset); | |
470 *which = (int)choiceEntry->size; | |
471 } | |
472 | |
473 /* we should have consumed all the bytes by now */ | |
474 /* fail if we have not */ | |
475 if (SECSuccess == rv && choice.len) | |
476 { | |
477 /* there is extra data that isn't listed in the template */ | |
478 PORT_SetError(SEC_ERROR_BAD_DER); | |
479 rv = SECFailure; | |
480 } | |
481 return rv; | |
482 } | |
483 | |
484 static SECStatus DecodeGroup(void* dest, | |
485 const SEC_ASN1Template* templateEntry, | |
486 SECItem* src, PLArenaPool* arena) | |
487 { | |
488 SECStatus rv = SECSuccess; | |
489 SECItem source; | |
490 SECItem group; | |
491 PRUint32 totalEntries = 0; | |
492 PRUint32 entryIndex = 0; | |
493 void** entries = NULL; | |
494 | |
495 const SEC_ASN1Template* subTemplate = | |
496 SEC_ASN1GetSubtemplate (templateEntry, dest, PR_FALSE); | |
497 | |
498 source = *src; | |
499 | |
500 /* get the group */ | |
501 if (SECSuccess == rv) | |
502 { | |
503 rv = GetItem(&source, &group, PR_FALSE); | |
504 } | |
505 | |
506 /* XXX we should check the subtemplate in debug builds */ | |
507 if (SECSuccess == rv) | |
508 { | |
509 /* first, count the number of entries. Benchmarking showed that this | |
510 counting pass is more efficient than trying to allocate entries as | |
511 we read the DER, even if allocating many entries at a time | |
512 */ | |
513 SECItem counter = group; | |
514 do | |
515 { | |
516 SECItem anitem; | |
517 rv = GetItem(&counter, &anitem, PR_TRUE); | |
518 if (SECSuccess == rv && (anitem.len) ) | |
519 { | |
520 totalEntries++; | |
521 } | |
522 } while ( (SECSuccess == rv) && (counter.len) ); | |
523 | |
524 if (SECSuccess == rv) | |
525 { | |
526 /* allocate room for pointer array and entries */ | |
527 /* we want to allocate the array even if there is 0 entry */ | |
528 entries = (void**)PORT_ArenaZAlloc(arena, sizeof(void*)* | |
529 (totalEntries + 1 ) + /* the extra one is for NULL termination */ | |
530 subTemplate->size*totalEntries); | |
531 | |
532 if (entries) | |
533 { | |
534 entries[totalEntries] = NULL; /* terminate the array */ | |
535 } | |
536 else | |
537 { | |
538 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
539 rv = SECFailure; | |
540 } | |
541 if (SECSuccess == rv) | |
542 { | |
543 void* entriesData = (unsigned char*)entries + (unsigned long)(sizeof(void*)*(totalEntries + 1 )); | |
544 /* and fix the pointers in the array */ | |
545 PRUint32 entriesIndex = 0; | |
546 for (entriesIndex = 0;entriesIndex<totalEntries;entriesIndex++) | |
547 { | |
548 entries[entriesIndex] = | |
549 (char*)entriesData + (subTemplate->size*entriesIndex); | |
550 } | |
551 } | |
552 } | |
553 } | |
554 | |
555 if (SECSuccess == rv && totalEntries) | |
556 do | |
557 { | |
558 if (!(entryIndex<totalEntries)) | |
559 { | |
560 rv = SECFailure; | |
561 break; | |
562 } | |
563 rv = DecodeItem(entries[entryIndex++], subTemplate, &group, arena, PR_TRUE); | |
564 } while ( (SECSuccess == rv) && (group.len) ); | |
565 /* we should be at the end of the set by now */ | |
566 /* save the entries where requested */ | |
567 memcpy(((char*)dest + templateEntry->offset), &entries, sizeof(void**)); | |
568 | |
569 return rv; | |
570 } | |
571 | |
572 static SECStatus DecodeExplicit(void* dest, | |
573 const SEC_ASN1Template* templateEntry, | |
574 SECItem* src, PLArenaPool* arena) | |
575 { | |
576 SECStatus rv = SECSuccess; | |
577 SECItem subItem; | |
578 SECItem constructed = *src; | |
579 | |
580 rv = GetItem(&constructed, &subItem, PR_FALSE); | |
581 | |
582 if (SECSuccess == rv) | |
583 { | |
584 if (templateEntry->kind & SEC_ASN1_POINTER) | |
585 { | |
586 rv = DecodePointer(dest, templateEntry, &subItem, arena, PR_TRUE); | |
587 } | |
588 else | |
589 { | |
590 rv = DecodeInline(dest, templateEntry, &subItem, arena, PR_TRUE); | |
591 } | |
592 } | |
593 | |
594 return rv; | |
595 } | |
596 | |
597 /* new decoder implementation. This is a recursive function */ | |
598 | |
599 static SECStatus DecodeItem(void* dest, | |
600 const SEC_ASN1Template* templateEntry, | |
601 SECItem* src, PLArenaPool* arena, PRBool checkTag) | |
602 { | |
603 SECStatus rv = SECSuccess; | |
604 SECItem temp; | |
605 SECItem mark; | |
606 PRBool pop = PR_FALSE; | |
607 PRBool decode = PR_TRUE; | |
608 PRBool save = PR_FALSE; | |
609 unsigned long kind; | |
610 PRBool match = PR_TRUE; | |
611 PRBool optional = PR_FALSE; | |
612 | |
613 PR_ASSERT(src && dest && templateEntry && arena); | |
614 #if 0 | |
615 if (!src || !dest || !templateEntry || !arena) | |
616 { | |
617 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
618 rv = SECFailure; | |
619 } | |
620 #endif | |
621 | |
622 if (SECSuccess == rv) | |
623 { | |
624 /* do the template validation */ | |
625 kind = templateEntry->kind; | |
626 optional = (0 != (kind & SEC_ASN1_OPTIONAL)); | |
627 if (!kind) | |
628 { | |
629 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); | |
630 rv = SECFailure; | |
631 } | |
632 } | |
633 | |
634 if (SECSuccess == rv) | |
635 { | |
636 #ifdef DEBUG | |
637 if (kind & SEC_ASN1_DEBUG_BREAK) | |
638 { | |
639 /* when debugging the decoder or a template that fails to | |
640 decode, put SEC_ASN1_DEBUG in the component that gives you | |
641 trouble. The decoder will then get to this block and assert. | |
642 If you want to debug the rest of the code, you can set a | |
643 breakpoint and set dontassert to PR_TRUE, which will let | |
644 you skip over the assert and continue the debugging session | |
645 past it. */ | |
646 PRBool dontassert = PR_FALSE; | |
647 PR_ASSERT(dontassert); /* set bkpoint here & set dontassert*/ | |
648 } | |
649 #endif | |
650 | |
651 if ((kind & SEC_ASN1_SKIP) || | |
652 (kind & SEC_ASN1_SAVE)) | |
653 { | |
654 /* if skipping or saving this component, don't decode it */ | |
655 decode = PR_FALSE; | |
656 } | |
657 | |
658 if (kind & (SEC_ASN1_SAVE | SEC_ASN1_OPTIONAL)) | |
659 { | |
660 /* if saving this component, or if it is optional, we may not want to | |
661 move past it, so save the position in case we have to rewind */ | |
662 mark = *src; | |
663 if (kind & SEC_ASN1_SAVE) | |
664 { | |
665 save = PR_TRUE; | |
666 if (0 == (kind & SEC_ASN1_SKIP)) | |
667 { | |
668 /* we will for sure have to rewind when saving this | |
669 component and not skipping it. This is true for all | |
670 legacy uses of SEC_ASN1_SAVE where the following entry | |
671 in the template would causes the same component to be | |
672 processed again */ | |
673 pop = PR_TRUE; | |
674 } | |
675 } | |
676 } | |
677 | |
678 rv = GetItem(src, &temp, PR_TRUE); | |
679 } | |
680 | |
681 if (SECSuccess == rv) | |
682 { | |
683 /* now check if the component matches what we expect in the template */ | |
684 | |
685 if (PR_TRUE == checkTag) | |
686 | |
687 { | |
688 rv = MatchComponentType(templateEntry, &temp, &match, dest); | |
689 } | |
690 | |
691 if ( (SECSuccess == rv) && (PR_TRUE != match) ) | |
692 { | |
693 if (kind & SEC_ASN1_OPTIONAL) | |
694 { | |
695 | |
696 /* the optional component is missing. This is not fatal. */ | |
697 /* Rewind, don't decode, and don't save */ | |
698 pop = PR_TRUE; | |
699 decode = PR_FALSE; | |
700 save = PR_FALSE; | |
701 } | |
702 else | |
703 { | |
704 /* a required component is missing. abort */ | |
705 PORT_SetError(SEC_ERROR_BAD_DER); | |
706 rv = SECFailure; | |
707 } | |
708 } | |
709 } | |
710 | |
711 if ((SECSuccess == rv) && (PR_TRUE == decode)) | |
712 { | |
713 /* the order of processing here is is the tricky part */ | |
714 /* we start with our special cases */ | |
715 /* first, check the component class */ | |
716 if (kind & SEC_ASN1_INLINE) | |
717 { | |
718 /* decode inline template */ | |
719 rv = DecodeInline(dest, templateEntry, &temp , arena, PR_TRUE); | |
720 } | |
721 | |
722 else | |
723 if (kind & SEC_ASN1_EXPLICIT) | |
724 { | |
725 rv = DecodeExplicit(dest, templateEntry, &temp, arena); | |
726 } | |
727 else | |
728 if ( (SEC_ASN1_UNIVERSAL != (kind & SEC_ASN1_CLASS_MASK)) && | |
729 | |
730 (!(kind & SEC_ASN1_EXPLICIT))) | |
731 { | |
732 | |
733 /* decode implicitly tagged components */ | |
734 rv = DecodeImplicit(dest, templateEntry, &temp , arena); | |
735 } | |
736 else | |
737 if (kind & SEC_ASN1_POINTER) | |
738 { | |
739 rv = DecodePointer(dest, templateEntry, &temp, arena, PR_TRUE); | |
740 } | |
741 else | |
742 if (kind & SEC_ASN1_CHOICE) | |
743 { | |
744 rv = DecodeChoice(dest, templateEntry, &temp, arena); | |
745 } | |
746 else | |
747 if (kind & SEC_ASN1_ANY) | |
748 { | |
749 /* catch-all ANY type, don't decode */ | |
750 save = PR_TRUE; | |
751 if (kind & SEC_ASN1_INNER) | |
752 { | |
753 /* skip the tag and length */ | |
754 SECItem newtemp = temp; | |
755 rv = GetItem(&newtemp, &temp, PR_FALSE); | |
756 } | |
757 } | |
758 else | |
759 if (kind & SEC_ASN1_GROUP) | |
760 { | |
761 if ( (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) || | |
762 (SEC_ASN1_SET == (kind & SEC_ASN1_TAGNUM_MASK)) ) | |
763 { | |
764 rv = DecodeGroup(dest, templateEntry, &temp , arena); | |
765 } | |
766 else | |
767 { | |
768 /* a group can only be a SET OF or SEQUENCE OF */ | |
769 PORT_SetError(SEC_ERROR_BAD_TEMPLATE); | |
770 rv = SECFailure; | |
771 } | |
772 } | |
773 else | |
774 if (SEC_ASN1_SEQUENCE == (kind & SEC_ASN1_TAGNUM_MASK)) | |
775 { | |
776 /* plain SEQUENCE */ | |
777 rv = DecodeSequence(dest, templateEntry, &temp , arena); | |
778 } | |
779 else | |
780 { | |
781 /* handle all other types as "save" */ | |
782 /* we should only get here for primitive universal types */ | |
783 SECItem newtemp = temp; | |
784 rv = GetItem(&newtemp, &temp, PR_FALSE); | |
785 save = PR_TRUE; | |
786 if ((SECSuccess == rv) && | |
787 SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK)) | |
788 { | |
789 unsigned long tagnum = kind & SEC_ASN1_TAGNUM_MASK; | |
790 if ( temp.len == 0 && (tagnum == SEC_ASN1_BOOLEAN || | |
791 tagnum == SEC_ASN1_INTEGER || | |
792 tagnum == SEC_ASN1_BIT_STRING || | |
793 tagnum == SEC_ASN1_OBJECT_ID || | |
794 tagnum == SEC_ASN1_ENUMERATED || | |
795 tagnum == SEC_ASN1_UTC_TIME || | |
796 tagnum == SEC_ASN1_GENERALIZED_TIME) ) | |
797 { | |
798 /* these types MUST have at least one content octet */ | |
799 PORT_SetError(SEC_ERROR_BAD_DER); | |
800 rv = SECFailure; | |
801 } | |
802 else | |
803 switch (tagnum) | |
804 { | |
805 /* special cases of primitive types */ | |
806 case SEC_ASN1_INTEGER: | |
807 { | |
808 /* remove leading zeroes if the caller requested | |
809 siUnsignedInteger | |
810 This is to allow RSA key operations to work */ | |
811 SECItem* destItem = (SECItem*) ((char*)dest + | |
812 templateEntry->offset); | |
813 if (destItem && (siUnsignedInteger == destItem->type)) | |
814 { | |
815 while (temp.len > 1 && temp.data[0] == 0) | |
816 { /* leading 0 */ | |
817 temp.data++; | |
818 temp.len--; | |
819 } | |
820 } | |
821 break; | |
822 } | |
823 | |
824 case SEC_ASN1_BIT_STRING: | |
825 { | |
826 /* change the length in the SECItem to be the number | |
827 of bits */ | |
828 temp.len = (temp.len-1)*8 - (temp.data[0] & 0x7); | |
829 temp.data++; | |
830 break; | |
831 } | |
832 | |
833 default: | |
834 { | |
835 break; | |
836 } | |
837 } | |
838 } | |
839 } | |
840 } | |
841 | |
842 if ((SECSuccess == rv) && (PR_TRUE == save)) | |
843 { | |
844 SECItem* destItem = (SECItem*) ((char*)dest + templateEntry->offset); | |
845 if (destItem) | |
846 { | |
847 /* we leave the type alone in the destination SECItem. | |
848 If part of the destination was allocated by the decoder, in | |
849 cases of POINTER, SET OF and SEQUENCE OF, then type is set to | |
850 siBuffer due to the use of PORT_ArenaZAlloc*/ | |
851 destItem->data = temp.len ? temp.data : NULL; | |
852 destItem->len = temp.len; | |
853 } | |
854 else | |
855 { | |
856 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
857 rv = SECFailure; | |
858 } | |
859 } | |
860 | |
861 if (PR_TRUE == pop) | |
862 { | |
863 /* we don't want to move ahead, so restore the position */ | |
864 *src = mark; | |
865 } | |
866 return rv; | |
867 } | |
868 | |
869 /* the function below is the public one */ | |
870 | |
871 SECStatus SEC_QuickDERDecodeItem(PLArenaPool* arena, void* dest, | |
872 const SEC_ASN1Template* templateEntry, | |
873 const SECItem* src) | |
874 { | |
875 SECStatus rv = SECSuccess; | |
876 SECItem newsrc; | |
877 | |
878 if (!arena || !templateEntry || !src) | |
879 { | |
880 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
881 rv = SECFailure; | |
882 } | |
883 | |
884 if (SECSuccess == rv) | |
885 { | |
886 newsrc = *src; | |
887 rv = DecodeItem(dest, templateEntry, &newsrc, arena, PR_TRUE); | |
888 if (SECSuccess == rv && newsrc.len) | |
889 { | |
890 rv = SECFailure; | |
891 PORT_SetError(SEC_ERROR_EXTRA_INPUT); | |
892 } | |
893 } | |
894 | |
895 return rv; | |
896 } | |
897 |