~ubuntu-branches/ubuntu/precise/nss/precise-security

« back to all changes in this revision

Viewing changes to nss/lib/util/quickder.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2013-11-14 14:58:07 UTC
  • mfrom: (1.1.19)
  • Revision ID: package-import@ubuntu.com-20131114145807-ay302kimn72ovt88
Tags: 3.15.3-0ubuntu0.12.04.1
* SECURITY UPDATE: New upstream release to fix multiple security issues
  and add TLSv1.2 support.
  - CVE-2013-1739
  - CVE-2013-1741
  - CVE-2013-5605
  - CVE-2013-5606
* Adjusted packaging for 3.15.3:
  - debian/patches/*: refreshed.
  - debian/patches/lower-dhe-priority.patch: removed, no longer needed,
    was a workaround for an old version of firefox.
  - debian/libnss3.symbols: added new symbols.
  - debian/rules: updated for new source layout.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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