Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/nss/lib/util/secasn1d.c
Line
Count
Source (jump to first uncovered line)
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
 * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
7
 * Encoding Rules).
8
 */
9
10
/* #define DEBUG_ASN1D_STATES 1 */
11
12
#ifdef DEBUG_ASN1D_STATES
13
#include <stdio.h>
14
#define PR_Assert sec_asn1d_Assert
15
#endif
16
17
#include <limits.h>
18
19
#include "secasn1.h"
20
#include "secerr.h"
21
22
typedef enum {
23
    beforeIdentifier,
24
    duringIdentifier,
25
    afterIdentifier,
26
    beforeLength,
27
    duringLength,
28
    afterLength,
29
    beforeBitString,
30
    duringBitString,
31
    duringConstructedString,
32
    duringGroup,
33
    duringLeaf,
34
    duringSaveEncoding,
35
    duringSequence,
36
    afterConstructedString,
37
    afterGroup,
38
    afterExplicit,
39
    afterImplicit,
40
    afterInline,
41
    afterPointer,
42
    afterSaveEncoding,
43
    beforeEndOfContents,
44
    duringEndOfContents,
45
    afterEndOfContents,
46
    beforeChoice,
47
    duringChoice,
48
    afterChoice,
49
    notInUse
50
} sec_asn1d_parse_place;
51
52
#ifdef DEBUG_ASN1D_STATES
53
static const char *const place_names[] = {
54
    "beforeIdentifier",
55
    "duringIdentifier",
56
    "afterIdentifier",
57
    "beforeLength",
58
    "duringLength",
59
    "afterLength",
60
    "beforeBitString",
61
    "duringBitString",
62
    "duringConstructedString",
63
    "duringGroup",
64
    "duringLeaf",
65
    "duringSaveEncoding",
66
    "duringSequence",
67
    "afterConstructedString",
68
    "afterGroup",
69
    "afterExplicit",
70
    "afterImplicit",
71
    "afterInline",
72
    "afterPointer",
73
    "afterSaveEncoding",
74
    "beforeEndOfContents",
75
    "duringEndOfContents",
76
    "afterEndOfContents",
77
    "beforeChoice",
78
    "duringChoice",
79
    "afterChoice",
80
    "notInUse"
81
};
82
83
static const char *const class_names[] = {
84
    "UNIVERSAL",
85
    "APPLICATION",
86
    "CONTEXT_SPECIFIC",
87
    "PRIVATE"
88
};
89
90
static const char *const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
91
92
static const char *const type_names[] = {
93
    "END_OF_CONTENTS",
94
    "BOOLEAN",
95
    "INTEGER",
96
    "BIT_STRING",
97
    "OCTET_STRING",
98
    "NULL",
99
    "OBJECT_ID",
100
    "OBJECT_DESCRIPTOR",
101
    "(type 08)",
102
    "REAL",
103
    "ENUMERATED",
104
    "EMBEDDED",
105
    "UTF8_STRING",
106
    "(type 0d)",
107
    "(type 0e)",
108
    "(type 0f)",
109
    "SEQUENCE",
110
    "SET",
111
    "NUMERIC_STRING",
112
    "PRINTABLE_STRING",
113
    "T61_STRING",
114
    "VIDEOTEXT_STRING",
115
    "IA5_STRING",
116
    "UTC_TIME",
117
    "GENERALIZED_TIME",
118
    "GRAPHIC_STRING",
119
    "VISIBLE_STRING",
120
    "GENERAL_STRING",
121
    "UNIVERSAL_STRING",
122
    "(type 1d)",
123
    "BMP_STRING",
124
    "HIGH_TAG_VALUE"
125
};
126
127
static const char *const flag_names[] = {
128
    /* flags, right to left */
129
    "OPTIONAL",
130
    "EXPLICIT",
131
    "ANY",
132
    "INLINE",
133
    "POINTER",
134
    "GROUP",
135
    "DYNAMIC",
136
    "SKIP",
137
    "INNER",
138
    "SAVE",
139
    "", /* decoder ignores "MAY_STREAM", */
140
    "SKIP_REST",
141
    "CHOICE",
142
    "NO_STREAM",
143
    "DEBUG_BREAK",
144
    "unknown 08",
145
    "unknown 10",
146
    "unknown 20",
147
    "unknown 40",
148
    "unknown 80"
149
};
150
151
static int /* bool */
152
    formatKind(unsigned long kind, char *buf)
153
{
154
    int i;
155
    unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
156
    unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
157
                                  SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
158
159
    buf[0] = 0;
160
    if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
161
        sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6]);
162
        buf += strlen(buf);
163
    }
164
    if (kind & SEC_ASN1_METHOD_MASK) {
165
        sprintf(buf, " %s", method_names[1]);
166
        buf += strlen(buf);
167
    }
168
    if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
169
        if (k || !notag) {
170
            sprintf(buf, " %s", type_names[k]);
171
            if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
172
                (kind & SEC_ASN1_GROUP)) {
173
                buf += strlen(buf);
174
                sprintf(buf, "_OF");
175
            }
176
        }
177
    } else {
178
        sprintf(buf, " [%lu]", k);
179
    }
180
    buf += strlen(buf);
181
182
    for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
183
        if (k & 1) {
184
            sprintf(buf, " %s", flag_names[i]);
185
            buf += strlen(buf);
186
        }
187
    }
188
    return notag != 0;
189
}
190
191
#endif /* DEBUG_ASN1D_STATES */
192
193
typedef enum {
194
    allDone,
195
    decodeError,
196
    keepGoing,
197
    needBytes
198
} sec_asn1d_parse_status;
199
200
struct subitem {
201
    const void *data;
202
    unsigned long len; /* only used for substrings */
203
    struct subitem *next;
204
};
205
206
typedef struct sec_asn1d_state_struct {
207
    SEC_ASN1DecoderContext *top;
208
    const SEC_ASN1Template *theTemplate;
209
    void *dest;
210
211
    void *our_mark; /* free on completion */
212
213
    struct sec_asn1d_state_struct *parent; /* aka prev */
214
    struct sec_asn1d_state_struct *child;  /* aka next */
215
216
    sec_asn1d_parse_place place;
217
218
    /*
219
     * XXX explain the next fields as clearly as possible...
220
     */
221
    unsigned char found_tag_modifiers;
222
    unsigned char expect_tag_modifiers;
223
    unsigned long check_tag_mask;
224
    unsigned long found_tag_number;
225
    unsigned long expect_tag_number;
226
    unsigned long underlying_kind;
227
228
    unsigned long contents_length;
229
    unsigned long pending;
230
    unsigned long consumed;
231
232
    int depth;
233
234
    /*
235
     * Bit strings have their length adjusted -- the first octet of the
236
     * contents contains a value between 0 and 7 which says how many bits
237
     * at the end of the octets are not actually part of the bit string;
238
     * when parsing bit strings we put that value here because we need it
239
     * later, for adjustment of the length (when the whole string is done).
240
     */
241
    unsigned int bit_string_unused_bits;
242
243
    /*
244
     * The following are used for indefinite-length constructed strings.
245
     */
246
    struct subitem *subitems_head;
247
    struct subitem *subitems_tail;
248
249
    PRPackedBool
250
        allocate,      /* when true, need to allocate the destination */
251
        endofcontents, /* this state ended up parsing end-of-contents octets */
252
        explicit,      /* we are handling an explicit header */
253
        indefinite,    /* the current item has indefinite-length encoding */
254
        missing,       /* an optional field that was not present */
255
        optional,      /* the template says this field may be omitted */
256
        substring;     /* this is a substring of a constructed string */
257
258
} sec_asn1d_state;
259
260
0
#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
261
0
#define LAST_TAG_NUMBER_BYTE(b) (((b)&0x80) == 0)
262
0
#define TAG_NUMBER_BITS 7
263
0
#define TAG_NUMBER_MASK 0x7f
264
265
0
#define LENGTH_IS_SHORT_FORM(b) (((b)&0x80) == 0)
266
0
#define LONG_FORM_LENGTH(b) ((b)&0x7f)
267
268
0
#define HIGH_BITS(field, cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
269
270
/*
271
 * An "outsider" will have an opaque pointer to this, created by calling
272
 * SEC_ASN1DecoderStart().  It will be passed back in to all subsequent
273
 * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
274
 * SEC_ASN1DecoderFinish().
275
 */
276
struct sec_DecoderContext_struct {
277
    PLArenaPool *our_pool;     /* for our internal allocs */
278
    PLArenaPool *their_pool;   /* for destination structure allocs */
279
#ifdef SEC_ASN1D_FREE_ON_ERROR /*                                 \
280
                                * XXX see comment below (by same  \
281
                                * ifdef) that explains why this   \
282
                                * does not work (need more smarts \
283
                                * in order to free back to mark)  \
284
                                */
285
    /*
286
     * XXX how to make their_mark work in the case where they do NOT
287
     * give us a pool pointer?
288
     */
289
    void *their_mark; /* free on error */
290
#endif
291
292
    sec_asn1d_state *current;
293
    sec_asn1d_parse_status status;
294
295
    /* The maximum size the caller is willing to allow a single element
296
     * to be before returning an error.
297
     *
298
     * In the case of an indefinite length element, this is the sum total
299
     * of all child elements.
300
     *
301
     * In the case of a definite length element, this represents the maximum
302
     * size of the top-level element.
303
     */
304
    unsigned long max_element_size;
305
306
    SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
307
    void *notify_arg;               /* argument to notify_proc */
308
    PRBool during_notify;           /* true during call to notify_proc */
309
310
    SEC_ASN1WriteProc filter_proc; /* pass field bytes to this  */
311
    void *filter_arg;              /* argument to that function */
312
    PRBool filter_only;            /* do not allocate/store fields */
313
};
314
315
/*
316
 * XXX this is a fairly generic function that may belong elsewhere
317
 */
318
static void *
319
sec_asn1d_alloc(PLArenaPool *poolp, unsigned long len)
320
0
{
321
0
    void *thing;
322
0
323
0
    if (poolp != NULL) {
324
0
        /*
325
0
         * Allocate from the pool.
326
0
         */
327
0
        thing = PORT_ArenaAlloc(poolp, len);
328
0
    } else {
329
0
        /*
330
0
         * Allocate generically.
331
0
         */
332
0
        thing = PORT_Alloc(len);
333
0
    }
334
0
335
0
    return thing;
336
0
}
337
338
/*
339
 * XXX this is a fairly generic function that may belong elsewhere
340
 */
341
static void *
342
sec_asn1d_zalloc(PLArenaPool *poolp, unsigned long len)
343
0
{
344
0
    void *thing;
345
0
346
0
    thing = sec_asn1d_alloc(poolp, len);
347
0
    if (thing != NULL)
348
0
        PORT_Memset(thing, 0, len);
349
0
    return thing;
350
0
}
351
352
static sec_asn1d_state *
353
sec_asn1d_push_state(SEC_ASN1DecoderContext *cx,
354
                     const SEC_ASN1Template *theTemplate,
355
                     void *dest, PRBool new_depth)
356
0
{
357
0
    sec_asn1d_state *state, *new_state;
358
0
359
0
    state = cx->current;
360
0
361
0
    PORT_Assert(state == NULL || state->child == NULL);
362
0
363
0
    if (state != NULL) {
364
0
        PORT_Assert(state->our_mark == NULL);
365
0
        state->our_mark = PORT_ArenaMark(cx->our_pool);
366
0
    }
367
0
368
0
    new_state = (sec_asn1d_state *)sec_asn1d_zalloc(cx->our_pool,
369
0
                                                    sizeof(*new_state));
370
0
    if (new_state == NULL) {
371
0
        goto loser;
372
0
    }
373
0
374
0
    new_state->top = cx;
375
0
    new_state->parent = state;
376
0
    new_state->theTemplate = theTemplate;
377
0
    new_state->place = notInUse;
378
0
    if (dest != NULL)
379
0
        new_state->dest = (char *)dest + theTemplate->offset;
380
0
381
0
    if (state != NULL) {
382
0
        new_state->depth = state->depth;
383
0
        if (new_depth) {
384
0
            if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
385
0
                PORT_SetError(SEC_ERROR_BAD_DER);
386
0
                goto loser;
387
0
            }
388
0
        }
389
0
        state->child = new_state;
390
0
    }
391
0
392
0
    cx->current = new_state;
393
0
    return new_state;
394
0
395
0
loser:
396
0
    cx->status = decodeError;
397
0
    if (state != NULL) {
398
0
        PORT_ArenaRelease(cx->our_pool, state->our_mark);
399
0
        state->our_mark = NULL;
400
0
    }
401
0
    return NULL;
402
0
}
403
404
static void
405
sec_asn1d_scrub_state(sec_asn1d_state *state)
406
0
{
407
0
    /*
408
0
     * Some default "scrubbing".
409
0
     * XXX right set of initializations?
410
0
     */
411
0
    state->place = beforeIdentifier;
412
0
    state->endofcontents = PR_FALSE;
413
0
    state->indefinite = PR_FALSE;
414
0
    state->missing = PR_FALSE;
415
0
    PORT_Assert(state->consumed == 0);
416
0
}
417
418
static void
419
sec_asn1d_notify_before(SEC_ASN1DecoderContext *cx, void *dest, int depth)
420
0
{
421
0
    if (cx->notify_proc == NULL)
422
0
        return;
423
0
424
0
    cx->during_notify = PR_TRUE;
425
0
    (*cx->notify_proc)(cx->notify_arg, PR_TRUE, dest, depth);
426
0
    cx->during_notify = PR_FALSE;
427
0
}
428
429
static void
430
sec_asn1d_notify_after(SEC_ASN1DecoderContext *cx, void *dest, int depth)
431
0
{
432
0
    if (cx->notify_proc == NULL)
433
0
        return;
434
0
435
0
    cx->during_notify = PR_TRUE;
436
0
    (*cx->notify_proc)(cx->notify_arg, PR_FALSE, dest, depth);
437
0
    cx->during_notify = PR_FALSE;
438
0
}
439
440
static sec_asn1d_state *
441
sec_asn1d_init_state_based_on_template(sec_asn1d_state *state)
442
0
{
443
0
    PRBool explicit, optional, universal;
444
0
    unsigned char expect_tag_modifiers;
445
0
    unsigned long encode_kind, under_kind;
446
0
    unsigned long check_tag_mask, expect_tag_number;
447
0
448
0
    /* XXX Check that both of these tests are really needed/appropriate. */
449
0
    if (state == NULL || state->top->status == decodeError)
450
0
        return state;
451
0
452
0
    encode_kind = state->theTemplate->kind;
453
0
454
0
    if (encode_kind & SEC_ASN1_SAVE) {
455
0
        /*
456
0
         * This is a "magic" field that saves away all bytes, allowing
457
0
         * the immediately following field to still be decoded from this
458
0
         * same spot -- sort of a fork.
459
0
         */
460
0
        /* check that there are no extraneous bits */
461
0
        PORT_Assert(encode_kind == SEC_ASN1_SAVE);
462
0
        if (state->top->filter_only) {
463
0
            /*
464
0
             * If we are not storing, then we do not do the SAVE field
465
0
             * at all.  Just move ahead to the "real" field instead,
466
0
             * doing the appropriate notify calls before and after.
467
0
             */
468
0
            sec_asn1d_notify_after(state->top, state->dest, state->depth);
469
0
            /*
470
0
             * Since we are not storing, allow for our current dest value
471
0
             * to be NULL.  (This might not actually occur, but right now I
472
0
             * cannot convince myself one way or the other.)  If it is NULL,
473
0
             * assume that our parent dest can help us out.
474
0
             */
475
0
            if (state->dest == NULL)
476
0
                state->dest = state->parent->dest;
477
0
            else
478
0
                state->dest = (char *)state->dest - state->theTemplate->offset;
479
0
            state->theTemplate++;
480
0
            if (state->dest != NULL)
481
0
                state->dest = (char *)state->dest + state->theTemplate->offset;
482
0
            sec_asn1d_notify_before(state->top, state->dest, state->depth);
483
0
            encode_kind = state->theTemplate->kind;
484
0
            PORT_Assert((encode_kind & SEC_ASN1_SAVE) == 0);
485
0
        } else {
486
0
            sec_asn1d_scrub_state(state);
487
0
            state->place = duringSaveEncoding;
488
0
            state = sec_asn1d_push_state(state->top, SEC_AnyTemplate,
489
0
                                         state->dest, PR_FALSE);
490
0
            if (state != NULL)
491
0
                state = sec_asn1d_init_state_based_on_template(state);
492
0
            return state;
493
0
        }
494
0
    }
495
0
496
0
    universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
497
0
                    ? PR_TRUE
498
0
                    : PR_FALSE;
499
0
500
0
    explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
501
0
    encode_kind &= ~SEC_ASN1_EXPLICIT;
502
0
503
0
    optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
504
0
    encode_kind &= ~SEC_ASN1_OPTIONAL;
505
0
506
0
    PORT_Assert(!(explicit && universal)); /* bad templates */
507
0
508
0
    encode_kind &= ~SEC_ASN1_DYNAMIC;
509
0
    encode_kind &= ~SEC_ASN1_MAY_STREAM;
510
0
511
0
    if (encode_kind & SEC_ASN1_CHOICE) {
512
#if 0 /* XXX remove? */
513
      sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
514
      if ((sec_asn1d_state *)NULL == child) {
515
        return (sec_asn1d_state *)NULL;
516
      }
517
518
      child->allocate = state->allocate;
519
      child->place = beforeChoice;
520
      return child;
521
#else
522
        state->place = beforeChoice;
523
0
        return state;
524
0
#endif
525
0
    }
526
0
527
0
    if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal && !explicit)) {
528
0
        const SEC_ASN1Template *subt;
529
0
        void *dest;
530
0
        PRBool child_allocate;
531
0
532
0
        PORT_Assert((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
533
0
534
0
        sec_asn1d_scrub_state(state);
535
0
        child_allocate = PR_FALSE;
536
0
537
0
        if (encode_kind & SEC_ASN1_POINTER) {
538
0
            /*
539
0
             * A POINTER means we need to allocate the destination for
540
0
             * this field.  But, since it may also be an optional field,
541
0
             * we defer the allocation until later; we just record that
542
0
             * it needs to be done.
543
0
             *
544
0
             * There are two possible scenarios here -- one is just a
545
0
             * plain POINTER (kind of like INLINE, except with allocation)
546
0
             * and the other is an implicitly-tagged POINTER.  We don't
547
0
             * need to do anything special here for the two cases, but
548
0
             * since the template definition can be tricky, we do check
549
0
             * that there are no extraneous bits set in encode_kind.
550
0
             *
551
0
             * XXX The same conditions which assert should set an error.
552
0
             */
553
0
            if (universal) {
554
0
                /*
555
0
                 * "universal" means this entry is a standalone POINTER;
556
0
                 * there should be no other bits set in encode_kind.
557
0
                 */
558
0
                PORT_Assert(encode_kind == SEC_ASN1_POINTER);
559
0
            } else {
560
0
                /*
561
0
                 * If we get here we have an implicitly-tagged field
562
0
                 * that needs to be put into a POINTER.  The subtemplate
563
0
                 * will determine how to decode the field, but encode_kind
564
0
                 * describes the (implicit) tag we are looking for.
565
0
                 * The non-tag bits of encode_kind will be ignored by
566
0
                 * the code below; none of them should be set, however,
567
0
                 * except for the POINTER bit itself -- so check that.
568
0
                 */
569
0
                PORT_Assert((encode_kind & ~SEC_ASN1_TAG_MASK) == SEC_ASN1_POINTER);
570
0
            }
571
0
            if (!state->top->filter_only)
572
0
                child_allocate = PR_TRUE;
573
0
            dest = NULL;
574
0
            state->place = afterPointer;
575
0
        } else {
576
0
            dest = state->dest;
577
0
            if (encode_kind & SEC_ASN1_INLINE) {
578
0
                /* check that there are no extraneous bits */
579
0
                PORT_Assert(encode_kind == SEC_ASN1_INLINE && !optional);
580
0
                state->place = afterInline;
581
0
            } else {
582
0
                state->place = afterImplicit;
583
0
            }
584
0
        }
585
0
586
0
        state->optional = optional;
587
0
        subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest, PR_FALSE);
588
0
        state = sec_asn1d_push_state(state->top, subt, dest, PR_FALSE);
589
0
        if (state == NULL)
590
0
            return NULL;
591
0
592
0
        state->allocate = child_allocate;
593
0
594
0
        if (universal) {
595
0
            state = sec_asn1d_init_state_based_on_template(state);
596
0
            if (state != NULL) {
597
0
                /*
598
0
                 * If this field is optional, we need to record that on
599
0
                 * the pushed child so it won't fail if the field isn't
600
0
                 * found.  I can't think of a way that this new state
601
0
                 * could already have optional set (which we would wipe
602
0
                 * out below if our local optional is not set) -- but
603
0
                 * just to be sure, assert that it isn't set.
604
0
                 */
605
0
                PORT_Assert(!state->optional);
606
0
                state->optional = optional;
607
0
            }
608
0
            return state;
609
0
        }
610
0
611
0
        under_kind = state->theTemplate->kind;
612
0
        under_kind &= ~SEC_ASN1_MAY_STREAM;
613
0
    } else if (explicit) {
614
0
        /*
615
0
         * For explicit, we only need to match the encoding tag next,
616
0
         * then we will push another state to handle the entire inner
617
0
         * part.  In this case, there is no underlying kind which plays
618
0
         * any part in the determination of the outer, explicit tag.
619
0
         * So we just set under_kind to 0, which is not a valid tag,
620
0
         * and the rest of the tag matching stuff should be okay.
621
0
         */
622
0
        under_kind = 0;
623
0
    } else {
624
0
        /*
625
0
         * Nothing special; the underlying kind and the given encoding
626
0
         * information are the same.
627
0
         */
628
0
        under_kind = encode_kind;
629
0
    }
630
0
631
0
    /* XXX is this the right set of bits to test here? */
632
0
    PORT_Assert((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
633
0
634
0
    if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
635
0
        PORT_Assert(encode_kind == under_kind);
636
0
        if (encode_kind & SEC_ASN1_SKIP) {
637
0
            PORT_Assert(!optional);
638
0
            PORT_Assert(encode_kind == SEC_ASN1_SKIP);
639
0
            state->dest = NULL;
640
0
        }
641
0
        check_tag_mask = 0;
642
0
        expect_tag_modifiers = 0;
643
0
        expect_tag_number = 0;
644
0
    } else {
645
0
        check_tag_mask = SEC_ASN1_TAG_MASK;
646
0
        expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK;
647
0
        /*
648
0
         * XXX This assumes only single-octet identifiers.  To handle
649
0
         * the HIGH TAG form we would need to do some more work, especially
650
0
         * in how to specify them in the template, because right now we
651
0
         * do not provide a way to specify more *tag* bits in encode_kind.
652
0
         */
653
0
        expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
654
0
655
0
        switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
656
0
            case SEC_ASN1_SET:
657
0
                /*
658
0
                 * XXX A plain old SET (as opposed to a SET OF) is not implemented.
659
0
                 * If it ever is, remove this assert...
660
0
                 */
661
0
                PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0);
662
0
            /* fallthru */
663
0
            case SEC_ASN1_SEQUENCE:
664
0
                expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
665
0
                break;
666
0
            case SEC_ASN1_BIT_STRING:
667
0
            case SEC_ASN1_BMP_STRING:
668
0
            case SEC_ASN1_GENERALIZED_TIME:
669
0
            case SEC_ASN1_IA5_STRING:
670
0
            case SEC_ASN1_OCTET_STRING:
671
0
            case SEC_ASN1_PRINTABLE_STRING:
672
0
            case SEC_ASN1_T61_STRING:
673
0
            case SEC_ASN1_UNIVERSAL_STRING:
674
0
            case SEC_ASN1_UTC_TIME:
675
0
            case SEC_ASN1_UTF8_STRING:
676
0
            case SEC_ASN1_VISIBLE_STRING:
677
0
                check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
678
0
                break;
679
0
        }
680
0
    }
681
0
682
0
    state->check_tag_mask = check_tag_mask;
683
0
    state->expect_tag_modifiers = expect_tag_modifiers;
684
0
    state->expect_tag_number = expect_tag_number;
685
0
    state->underlying_kind = under_kind;
686
0
    state->explicit = explicit;
687
0
    state->optional = optional;
688
0
689
0
    sec_asn1d_scrub_state(state);
690
0
691
0
    return state;
692
0
}
693
694
static sec_asn1d_state *
695
sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
696
0
{
697
0
    for (state = state->parent; state; state = state->parent) {
698
0
        sec_asn1d_parse_place place = state->place;
699
0
        if (place != afterImplicit &&
700
0
            place != afterPointer &&
701
0
            place != afterInline &&
702
0
            place != afterSaveEncoding &&
703
0
            place != duringSaveEncoding &&
704
0
            place != duringChoice) {
705
0
706
0
            /* we've walked up the stack to a state that represents
707
0
            ** the enclosing construct.
708
0
            */
709
0
            break;
710
0
        }
711
0
    }
712
0
    return state;
713
0
}
714
715
static PRBool
716
sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
717
0
{
718
0
    /* get state of enclosing construct. */
719
0
    state = sec_asn1d_get_enclosing_construct(state);
720
0
    if (state) {
721
0
        sec_asn1d_parse_place place = state->place;
722
0
        /* Is it one of the types that permits an unexpected EOC? */
723
0
        int eoc_permitted =
724
0
            (place == duringGroup ||
725
0
             place == duringConstructedString ||
726
0
             state->child->optional);
727
0
        return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
728
0
    }
729
0
    return PR_FALSE;
730
0
}
731
732
static unsigned long
733
sec_asn1d_parse_identifier(sec_asn1d_state *state,
734
                           const char *buf, unsigned long len)
735
0
{
736
0
    unsigned char byte;
737
0
    unsigned char tag_number;
738
0
739
0
    PORT_Assert(state->place == beforeIdentifier);
740
0
741
0
    if (len == 0) {
742
0
        state->top->status = needBytes;
743
0
        return 0;
744
0
    }
745
0
746
0
    byte = (unsigned char)*buf;
747
#ifdef DEBUG_ASN1D_STATES
748
    {
749
        char kindBuf[256];
750
        formatKind(byte, kindBuf);
751
        printf("Found tag %02x %s\n", byte, kindBuf);
752
    }
753
#endif
754
0
    tag_number = byte & SEC_ASN1_TAGNUM_MASK;
755
0
756
0
    if (IS_HIGH_TAG_NUMBER(tag_number)) {
757
0
        state->place = duringIdentifier;
758
0
        state->found_tag_number = 0;
759
0
        /*
760
0
         * Actually, we have no idea how many bytes are pending, but we
761
0
         * do know that it is at least 1.  That is all we know; we have
762
0
         * to look at each byte to know if there is another, etc.
763
0
         */
764
0
        state->pending = 1;
765
0
    } else {
766
0
        if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
767
0
            /*
768
0
             * Our parent has indefinite-length encoding, and the
769
0
             * entire tag found is 0, so it seems that we have hit the
770
0
             * end-of-contents octets.  To handle this, we just change
771
0
             * our state to that which expects to get the bytes of the
772
0
             * end-of-contents octets and let that code re-read this byte
773
0
             * so that our categorization of field types is correct.
774
0
             * After that, our parent will then deal with everything else.
775
0
             */
776
0
            state->place = duringEndOfContents;
777
0
            state->pending = 2;
778
0
            state->found_tag_number = 0;
779
0
            state->found_tag_modifiers = 0;
780
0
            /*
781
0
             * We might be an optional field that is, as we now find out,
782
0
             * missing.  Give our parent a clue that this happened.
783
0
             */
784
0
            if (state->optional)
785
0
                state->missing = PR_TRUE;
786
0
            return 0;
787
0
        }
788
0
        state->place = afterIdentifier;
789
0
        state->found_tag_number = tag_number;
790
0
    }
791
0
    state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
792
0
793
0
    return 1;
794
0
}
795
796
static unsigned long
797
sec_asn1d_parse_more_identifier(sec_asn1d_state *state,
798
                                const char *buf, unsigned long len)
799
0
{
800
0
    unsigned char byte;
801
0
    int count;
802
0
803
0
    PORT_Assert(state->pending == 1);
804
0
    PORT_Assert(state->place == duringIdentifier);
805
0
806
0
    if (len == 0) {
807
0
        state->top->status = needBytes;
808
0
        return 0;
809
0
    }
810
0
811
0
    count = 0;
812
0
813
0
    while (len && state->pending) {
814
0
        if (HIGH_BITS(state->found_tag_number, TAG_NUMBER_BITS) != 0) {
815
0
            /*
816
0
             * The given high tag number overflows our container;
817
0
             * just give up.  This is not likely to *ever* happen.
818
0
             */
819
0
            PORT_SetError(SEC_ERROR_BAD_DER);
820
0
            state->top->status = decodeError;
821
0
            return 0;
822
0
        }
823
0
824
0
        state->found_tag_number <<= TAG_NUMBER_BITS;
825
0
826
0
        byte = (unsigned char)buf[count++];
827
0
        state->found_tag_number |= (byte & TAG_NUMBER_MASK);
828
0
829
0
        len--;
830
0
        if (LAST_TAG_NUMBER_BYTE(byte))
831
0
            state->pending = 0;
832
0
    }
833
0
834
0
    if (state->pending == 0)
835
0
        state->place = afterIdentifier;
836
0
837
0
    return count;
838
0
}
839
840
static void
841
sec_asn1d_confirm_identifier(sec_asn1d_state *state)
842
0
{
843
0
    PRBool match;
844
0
845
0
    PORT_Assert(state->place == afterIdentifier);
846
0
847
0
    match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) == state->expect_tag_modifiers) && ((state->found_tag_number & state->check_tag_mask) == state->expect_tag_number));
848
0
    if (match) {
849
0
        state->place = beforeLength;
850
0
    } else {
851
0
        if (state->optional) {
852
0
            state->missing = PR_TRUE;
853
0
            state->place = afterEndOfContents;
854
0
        } else {
855
0
            PORT_SetError(SEC_ERROR_BAD_DER);
856
0
            state->top->status = decodeError;
857
0
        }
858
0
    }
859
0
}
860
861
static unsigned long
862
sec_asn1d_parse_length(sec_asn1d_state *state,
863
                       const char *buf, unsigned long len)
864
0
{
865
0
    unsigned char byte;
866
0
867
0
    PORT_Assert(state->place == beforeLength);
868
0
869
0
    if (len == 0) {
870
0
        state->top->status = needBytes;
871
0
        return 0;
872
0
    }
873
0
874
0
    /*
875
0
     * The default/likely outcome.  It may get adjusted below.
876
0
     */
877
0
    state->place = afterLength;
878
0
879
0
    byte = (unsigned char)*buf;
880
0
881
0
    if (LENGTH_IS_SHORT_FORM(byte)) {
882
0
        state->contents_length = byte;
883
0
    } else {
884
0
        state->contents_length = 0;
885
0
        state->pending = LONG_FORM_LENGTH(byte);
886
0
        if (state->pending == 0) {
887
0
            state->indefinite = PR_TRUE;
888
0
        } else {
889
0
            state->place = duringLength;
890
0
        }
891
0
    }
892
0
893
0
    /* If we're parsing an ANY, SKIP, or SAVE template, and
894
0
    ** the object being saved is definite length encoded and constructed,
895
0
    ** there's no point in decoding that construct's members.
896
0
    ** So, just forget it's constructed and treat it as primitive.
897
0
    ** (SAVE appears as an ANY at this point)
898
0
    */
899
0
    if (!state->indefinite &&
900
0
        (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
901
0
        state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
902
0
    }
903
0
904
0
    return 1;
905
0
}
906
907
static unsigned long
908
sec_asn1d_parse_more_length(sec_asn1d_state *state,
909
                            const char *buf, unsigned long len)
910
0
{
911
0
    int count;
912
0
913
0
    PORT_Assert(state->pending > 0);
914
0
    PORT_Assert(state->place == duringLength);
915
0
916
0
    if (len == 0) {
917
0
        state->top->status = needBytes;
918
0
        return 0;
919
0
    }
920
0
921
0
    count = 0;
922
0
923
0
    while (len && state->pending) {
924
0
        if (HIGH_BITS(state->contents_length, 9) != 0) {
925
0
            /*
926
0
             * The given full content length overflows our container;
927
0
             * just give up.
928
0
             */
929
0
            PORT_SetError(SEC_ERROR_BAD_DER);
930
0
            state->top->status = decodeError;
931
0
            return 0;
932
0
        }
933
0
934
0
        state->contents_length <<= 8;
935
0
        state->contents_length |= (unsigned char)buf[count++];
936
0
937
0
        len--;
938
0
        state->pending--;
939
0
    }
940
0
941
0
    if (state->pending == 0)
942
0
        state->place = afterLength;
943
0
944
0
    return count;
945
0
}
946
947
/*
948
 * Helper function for sec_asn1d_prepare_for_contents.
949
 * Checks that a value representing a number of bytes consumed can be
950
 * subtracted from a remaining length. If so, returns PR_TRUE.
951
 * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a
952
 * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
953
 */
954
static PRBool
955
sec_asn1d_check_and_subtract_length(unsigned long *remaining,
956
                                    unsigned long consumed,
957
                                    SEC_ASN1DecoderContext *cx)
958
0
{
959
0
    PORT_Assert(remaining);
960
0
    PORT_Assert(cx);
961
0
    if (!remaining || !cx) {
962
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
963
0
        cx->status = decodeError;
964
0
        return PR_FALSE;
965
0
    }
966
0
    if (*remaining < consumed) {
967
0
        PORT_SetError(SEC_ERROR_BAD_DER);
968
0
        cx->status = decodeError;
969
0
        return PR_FALSE;
970
0
    }
971
0
    *remaining -= consumed;
972
0
    return PR_TRUE;
973
0
}
974
975
static void
976
sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
977
0
{
978
0
    SECItem *item;
979
0
    PLArenaPool *poolp;
980
0
    unsigned long alloc_len;
981
0
    sec_asn1d_state *parent;
982
0
983
#ifdef DEBUG_ASN1D_STATES
984
    {
985
        printf("Found Length %lu %s\n", state->contents_length,
986
               state->indefinite ? "indefinite" : "");
987
    }
988
#endif
989
990
0
    /**
991
0
     * The maximum length for a child element should be constrained to the
992
0
     * length remaining in the first definite length element in the ancestor
993
0
     * stack. If there is no definite length element in the ancestor stack,
994
0
     * there's nothing to constrain the length of the child, so there's no
995
0
     * further processing necessary.
996
0
     *
997
0
     * It's necessary to walk the ancestor stack, because it's possible to have
998
0
     * definite length children that are part of an indefinite length element,
999
0
     * which is itself part of an indefinite length element, and which is
1000
0
     * ultimately part of a definite length element. A simple example of this
1001
0
     * would be the handling of constructed OCTET STRINGs in BER encoding.
1002
0
     *
1003
0
     * This algorithm finds the first definite length element in the ancestor
1004
0
     * stack, if any, and if so, ensures that the length of the child element
1005
0
     * is consistent with the number of bytes remaining in the constraining
1006
0
     * ancestor element (that is, after accounting for any other sibling
1007
0
     * elements that may have been read).
1008
0
     *
1009
0
     * It's slightly complicated by the need to account both for integer
1010
0
     * underflow and overflow, as well as ensure that for indefinite length
1011
0
     * encodings, there's also enough space for the End-of-Contents (EOC)
1012
0
     * octets (Tag = 0x00, Length = 0x00, or two bytes).
1013
0
     */
1014
0
1015
0
    /* Determine the maximum length available for this element by finding the
1016
0
     * first definite length ancestor, if any. */
1017
0
    parent = sec_asn1d_get_enclosing_construct(state);
1018
0
    while (parent && parent->indefinite) {
1019
0
        parent = sec_asn1d_get_enclosing_construct(parent);
1020
0
    }
1021
0
    /* If parent is null, state is either the outermost state / at the top of
1022
0
     * the stack, or the outermost state uses indefinite length encoding. In
1023
0
     * these cases, there's nothing external to constrain this element, so
1024
0
     * there's nothing to check. */
1025
0
    if (parent) {
1026
0
        unsigned long remaining = parent->pending;
1027
0
        parent = state;
1028
0
        do {
1029
0
            if (!sec_asn1d_check_and_subtract_length(
1030
0
                    &remaining, parent->consumed, state->top) ||
1031
0
                /* If parent->indefinite is true, parent->contents_length is
1032
0
                 * zero and this is a no-op. */
1033
0
                !sec_asn1d_check_and_subtract_length(
1034
0
                    &remaining, parent->contents_length, state->top) ||
1035
0
                /* If parent->indefinite is true, then ensure there is enough
1036
0
                 * space for an EOC tag of 2 bytes. */
1037
0
                (parent->indefinite && !sec_asn1d_check_and_subtract_length(&remaining, 2, state->top))) {
1038
0
                /* This element is larger than its enclosing element, which is
1039
0
                 * invalid. */
1040
0
                return;
1041
0
            }
1042
0
        } while ((parent = sec_asn1d_get_enclosing_construct(parent)) &&
1043
0
                 parent->indefinite);
1044
0
    }
1045
0
1046
0
    /*
1047
0
     * XXX I cannot decide if this allocation should exclude the case
1048
0
     *     where state->endofcontents is true -- figure it out!
1049
0
     */
1050
0
    if (state->allocate) {
1051
0
        void *dest;
1052
0
1053
0
        PORT_Assert(state->dest == NULL);
1054
0
        /*
1055
0
         * We are handling a POINTER or a member of a GROUP, and need to
1056
0
         * allocate for the data structure.
1057
0
         */
1058
0
        dest = sec_asn1d_zalloc(state->top->their_pool,
1059
0
                                state->theTemplate->size);
1060
0
        if (dest == NULL) {
1061
0
            state->top->status = decodeError;
1062
0
            return;
1063
0
        }
1064
0
        state->dest = (char *)dest + state->theTemplate->offset;
1065
0
1066
0
        /*
1067
0
         * For a member of a GROUP, our parent will later put the
1068
0
         * pointer wherever it belongs.  But for a POINTER, we need
1069
0
         * to record the destination now, in case notify or filter
1070
0
         * procs need access to it -- they cannot find it otherwise,
1071
0
         * until it is too late (for one-pass processing).
1072
0
         */
1073
0
        if (state->parent->place == afterPointer) {
1074
0
            void **placep;
1075
0
1076
0
            placep = state->parent->dest;
1077
0
            *placep = dest;
1078
0
        }
1079
0
    }
1080
0
1081
0
    /*
1082
0
     * Remember, length may be indefinite here!  In that case,
1083
0
     * both contents_length and pending will be zero.
1084
0
     */
1085
0
    state->pending = state->contents_length;
1086
0
1087
0
    /*
1088
0
     * An EXPLICIT is nothing but an outer header, which we have
1089
0
     * already parsed and accepted.  Now we need to do the inner
1090
0
     * header and its contents.
1091
0
     */
1092
0
    if (state->explicit) {
1093
0
        state->place = afterExplicit;
1094
0
        state = sec_asn1d_push_state(state->top,
1095
0
                                     SEC_ASN1GetSubtemplate(state->theTemplate,
1096
0
                                                            state->dest,
1097
0
                                                            PR_FALSE),
1098
0
                                     state->dest, PR_TRUE);
1099
0
        if (state != NULL) {
1100
0
            (void)sec_asn1d_init_state_based_on_template(state);
1101
0
        }
1102
0
        return;
1103
0
    }
1104
0
1105
0
    /*
1106
0
     * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
1107
0
     * we cannot tell how many items we will end up with ... so push a
1108
0
     * state that can keep track of "children" (the individual members
1109
0
     * of the group; we will allocate as we go and put them all together
1110
0
     * at the end.
1111
0
     */
1112
0
    if (state->underlying_kind & SEC_ASN1_GROUP) {
1113
0
        /* XXX If this assertion holds (should be able to confirm it via
1114
0
         * inspection, too) then move this code into the switch statement
1115
0
         * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
1116
0
         */
1117
0
        PORT_Assert(state->underlying_kind == SEC_ASN1_SET_OF || state->underlying_kind == SEC_ASN1_SEQUENCE_OF || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC) || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC));
1118
0
        if (state->contents_length != 0 || state->indefinite) {
1119
0
            const SEC_ASN1Template *subt;
1120
0
1121
0
            state->place = duringGroup;
1122
0
            subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest,
1123
0
                                          PR_FALSE);
1124
0
            state = sec_asn1d_push_state(state->top, subt, NULL, PR_TRUE);
1125
0
            if (state != NULL) {
1126
0
                if (!state->top->filter_only)
1127
0
                    state->allocate = PR_TRUE; /* XXX propogate this? */
1128
0
                /*
1129
0
                 * Do the "before" field notification for next in group.
1130
0
                 */
1131
0
                sec_asn1d_notify_before(state->top, state->dest, state->depth);
1132
0
                (void)sec_asn1d_init_state_based_on_template(state);
1133
0
            }
1134
0
        } else {
1135
0
            /*
1136
0
             * A group of zero; we are done.
1137
0
             * Set state to afterGroup and let that code plant the NULL.
1138
0
             */
1139
0
            state->place = afterGroup;
1140
0
        }
1141
0
        return;
1142
0
    }
1143
0
1144
0
    switch (state->underlying_kind) {
1145
0
        case SEC_ASN1_SEQUENCE:
1146
0
            /*
1147
0
             * We need to push a child to handle the individual fields.
1148
0
             */
1149
0
            state->place = duringSequence;
1150
0
            state = sec_asn1d_push_state(state->top, state->theTemplate + 1,
1151
0
                                         state->dest, PR_TRUE);
1152
0
            if (state != NULL) {
1153
0
                /*
1154
0
                 * Do the "before" field notification.
1155
0
                 */
1156
0
                sec_asn1d_notify_before(state->top, state->dest, state->depth);
1157
0
                (void)sec_asn1d_init_state_based_on_template(state);
1158
0
            }
1159
0
            break;
1160
0
1161
0
        case SEC_ASN1_SET: /* XXX SET is not really implemented */
1162
0
            /*
1163
0
             * XXX A plain SET requires special handling; scanning of a
1164
0
             * template to see where a field should go (because by definition,
1165
0
             * they are not in any particular order, and you have to look at
1166
0
             * each tag to disambiguate what the field is).  We may never
1167
0
             * implement this because in practice, it seems to be unused.
1168
0
             */
1169
0
            PORT_Assert(0);
1170
0
            PORT_SetError(SEC_ERROR_BAD_DER); /* XXX */
1171
0
            state->top->status = decodeError;
1172
0
            break;
1173
0
1174
0
        case SEC_ASN1_NULL:
1175
0
            /*
1176
0
             * The NULL type, by definition, is "nothing", content length of zero.
1177
0
             * An indefinite-length encoding is not alloweed.
1178
0
             */
1179
0
            if (state->contents_length || state->indefinite) {
1180
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1181
0
                state->top->status = decodeError;
1182
0
                break;
1183
0
            }
1184
0
            if (state->dest != NULL) {
1185
0
                item = (SECItem *)(state->dest);
1186
0
                item->data = NULL;
1187
0
                item->len = 0;
1188
0
            }
1189
0
            state->place = afterEndOfContents;
1190
0
            break;
1191
0
1192
0
        case SEC_ASN1_BMP_STRING:
1193
0
            /* Error if length is not divisable by 2 */
1194
0
            if (state->contents_length % 2) {
1195
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1196
0
                state->top->status = decodeError;
1197
0
                break;
1198
0
            }
1199
0
            /* otherwise, handle as other string types */
1200
0
            goto regular_string_type;
1201
0
1202
0
        case SEC_ASN1_UNIVERSAL_STRING:
1203
0
            /* Error if length is not divisable by 4 */
1204
0
            if (state->contents_length % 4) {
1205
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1206
0
                state->top->status = decodeError;
1207
0
                break;
1208
0
            }
1209
0
            /* otherwise, handle as other string types */
1210
0
            goto regular_string_type;
1211
0
1212
0
        case SEC_ASN1_SKIP:
1213
0
        case SEC_ASN1_ANY:
1214
0
        case SEC_ASN1_ANY_CONTENTS:
1215
0
        /*
1216
0
         * These are not (necessarily) strings, but they need nearly
1217
0
         * identical handling (especially when we need to deal with
1218
0
         * constructed sub-pieces), so we pretend they are.
1219
0
         */
1220
0
        /* fallthru */
1221
0
        regular_string_type:
1222
0
        case SEC_ASN1_BIT_STRING:
1223
0
        case SEC_ASN1_IA5_STRING:
1224
0
        case SEC_ASN1_OCTET_STRING:
1225
0
        case SEC_ASN1_PRINTABLE_STRING:
1226
0
        case SEC_ASN1_T61_STRING:
1227
0
        case SEC_ASN1_UTC_TIME:
1228
0
        case SEC_ASN1_UTF8_STRING:
1229
0
        case SEC_ASN1_VISIBLE_STRING:
1230
0
            /*
1231
0
             * We are allocating for a primitive or a constructed string.
1232
0
             * If it is a constructed string, it may also be indefinite-length.
1233
0
             * If it is primitive, the length can (legally) be zero.
1234
0
             * Our first order of business is to allocate the memory for
1235
0
             * the string, if we can (if we know the length).
1236
0
             */
1237
0
            item = (SECItem *)(state->dest);
1238
0
1239
0
            /*
1240
0
             * If the item is a definite-length constructed string, then
1241
0
             * the contents_length is actually larger than what we need
1242
0
             * (because it also counts each intermediate header which we
1243
0
             * will be throwing away as we go), but it is a perfectly good
1244
0
             * upper bound that we just allocate anyway, and then concat
1245
0
             * as we go; we end up wasting a few extra bytes but save a
1246
0
             * whole other copy.
1247
0
             */
1248
0
            alloc_len = state->contents_length;
1249
0
            poolp = NULL; /* quiet compiler warnings about unused... */
1250
0
1251
0
            if (item == NULL || state->top->filter_only) {
1252
0
                if (item != NULL) {
1253
0
                    item->data = NULL;
1254
0
                    item->len = 0;
1255
0
                }
1256
0
                alloc_len = 0;
1257
0
            } else if (state->substring) {
1258
0
                /*
1259
0
                 * If we are a substring of a constructed string, then we may
1260
0
                 * not have to allocate anything (because our parent, the
1261
0
                 * actual constructed string, did it for us).  If we are a
1262
0
                 * substring and we *do* have to allocate, that means our
1263
0
                 * parent is an indefinite-length, so we allocate from our pool;
1264
0
                 * later our parent will copy our string into the aggregated
1265
0
                 * whole and free our pool allocation.
1266
0
                 */
1267
0
                if (item->data == NULL) {
1268
0
                    PORT_Assert(item->len == 0);
1269
0
                    poolp = state->top->our_pool;
1270
0
                } else {
1271
0
                    alloc_len = 0;
1272
0
                }
1273
0
            } else {
1274
0
                item->len = 0;
1275
0
                item->data = NULL;
1276
0
                poolp = state->top->their_pool;
1277
0
            }
1278
0
1279
0
            if (alloc_len || ((!state->indefinite) && (state->subitems_head != NULL))) {
1280
0
                struct subitem *subitem;
1281
0
                int len;
1282
0
1283
0
                PORT_Assert(item);
1284
0
                if (!item) {
1285
0
                    PORT_SetError(SEC_ERROR_BAD_DER);
1286
0
                    state->top->status = decodeError;
1287
0
                    return;
1288
0
                }
1289
0
                PORT_Assert(item->len == 0 && item->data == NULL);
1290
0
                /*
1291
0
                 * Check for and handle an ANY which has stashed aside the
1292
0
                 * header (identifier and length) bytes for us to include
1293
0
                 * in the saved contents.
1294
0
                 */
1295
0
                if (state->subitems_head != NULL) {
1296
0
                    PORT_Assert(state->underlying_kind == SEC_ASN1_ANY);
1297
0
                    for (subitem = state->subitems_head;
1298
0
                         subitem != NULL; subitem = subitem->next)
1299
0
                        alloc_len += subitem->len;
1300
0
                }
1301
0
1302
0
                if (state->top->max_element_size > 0 &&
1303
0
                    alloc_len > state->top->max_element_size) {
1304
0
                    PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1305
0
                    state->top->status = decodeError;
1306
0
                    return;
1307
0
                }
1308
0
1309
0
                item->data = (unsigned char *)sec_asn1d_zalloc(poolp, alloc_len);
1310
0
                if (item->data == NULL) {
1311
0
                    state->top->status = decodeError;
1312
0
                    break;
1313
0
                }
1314
0
1315
0
                len = 0;
1316
0
                for (subitem = state->subitems_head;
1317
0
                     subitem != NULL; subitem = subitem->next) {
1318
0
                    PORT_Memcpy(item->data + len, subitem->data, subitem->len);
1319
0
                    len += subitem->len;
1320
0
                }
1321
0
                item->len = len;
1322
0
1323
0
                /*
1324
0
                 * Because we use arenas and have a mark set, we later free
1325
0
                 * everything we have allocated, so this does *not* present
1326
0
                 * a memory leak (it is just temporarily left dangling).
1327
0
                 */
1328
0
                state->subitems_head = state->subitems_tail = NULL;
1329
0
            }
1330
0
1331
0
            if (state->contents_length == 0 && (!state->indefinite)) {
1332
0
                /*
1333
0
                 * A zero-length simple or constructed string; we are done.
1334
0
                 */
1335
0
                state->place = afterEndOfContents;
1336
0
            } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
1337
0
                const SEC_ASN1Template *sub;
1338
0
1339
0
                switch (state->underlying_kind) {
1340
0
                    case SEC_ASN1_ANY:
1341
0
                    case SEC_ASN1_ANY_CONTENTS:
1342
0
                        sub = SEC_AnyTemplate;
1343
0
                        break;
1344
0
                    case SEC_ASN1_BIT_STRING:
1345
0
                        sub = SEC_BitStringTemplate;
1346
0
                        break;
1347
0
                    case SEC_ASN1_BMP_STRING:
1348
0
                        sub = SEC_BMPStringTemplate;
1349
0
                        break;
1350
0
                    case SEC_ASN1_GENERALIZED_TIME:
1351
0
                        sub = SEC_GeneralizedTimeTemplate;
1352
0
                        break;
1353
0
                    case SEC_ASN1_IA5_STRING:
1354
0
                        sub = SEC_IA5StringTemplate;
1355
0
                        break;
1356
0
                    case SEC_ASN1_OCTET_STRING:
1357
0
                        sub = SEC_OctetStringTemplate;
1358
0
                        break;
1359
0
                    case SEC_ASN1_PRINTABLE_STRING:
1360
0
                        sub = SEC_PrintableStringTemplate;
1361
0
                        break;
1362
0
                    case SEC_ASN1_T61_STRING:
1363
0
                        sub = SEC_T61StringTemplate;
1364
0
                        break;
1365
0
                    case SEC_ASN1_UNIVERSAL_STRING:
1366
0
                        sub = SEC_UniversalStringTemplate;
1367
0
                        break;
1368
0
                    case SEC_ASN1_UTC_TIME:
1369
0
                        sub = SEC_UTCTimeTemplate;
1370
0
                        break;
1371
0
                    case SEC_ASN1_UTF8_STRING:
1372
0
                        sub = SEC_UTF8StringTemplate;
1373
0
                        break;
1374
0
                    case SEC_ASN1_VISIBLE_STRING:
1375
0
                        sub = SEC_VisibleStringTemplate;
1376
0
                        break;
1377
0
                    case SEC_ASN1_SKIP:
1378
0
                        sub = SEC_SkipTemplate;
1379
0
                        break;
1380
0
                    default:            /* redundant given outer switch cases, but */
1381
0
                        PORT_Assert(0); /* the compiler does not seem to know that, */
1382
0
                        sub = NULL;     /* so just do enough to quiet it. */
1383
0
                        break;
1384
0
                }
1385
0
1386
0
                state->place = duringConstructedString;
1387
0
                state = sec_asn1d_push_state(state->top, sub, item, PR_TRUE);
1388
0
                if (state != NULL) {
1389
0
                    state->substring = PR_TRUE; /* XXX propogate? */
1390
0
                    (void)sec_asn1d_init_state_based_on_template(state);
1391
0
                }
1392
0
            } else if (state->indefinite) {
1393
0
                /*
1394
0
                 * An indefinite-length string *must* be constructed!
1395
0
                 */
1396
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1397
0
                state->top->status = decodeError;
1398
0
            } else {
1399
0
                /*
1400
0
                 * A non-zero-length simple string.
1401
0
                 */
1402
0
                if (state->underlying_kind == SEC_ASN1_BIT_STRING)
1403
0
                    state->place = beforeBitString;
1404
0
                else
1405
0
                    state->place = duringLeaf;
1406
0
            }
1407
0
            break;
1408
0
1409
0
        default:
1410
0
            /*
1411
0
             * We are allocating for a simple leaf item.
1412
0
             */
1413
0
            if (state->contents_length) {
1414
0
                if (state->dest != NULL) {
1415
0
                    item = (SECItem *)(state->dest);
1416
0
                    item->len = 0;
1417
0
                    if (state->top->max_element_size > 0 &&
1418
0
                        state->contents_length > state->top->max_element_size) {
1419
0
                        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
1420
0
                        state->top->status = decodeError;
1421
0
                        return;
1422
0
                    }
1423
0
1424
0
                    if (state->top->filter_only) {
1425
0
                        item->data = NULL;
1426
0
                    } else {
1427
0
                        item->data = (unsigned char *)
1428
0
                            sec_asn1d_zalloc(state->top->their_pool,
1429
0
                                             state->contents_length);
1430
0
                        if (item->data == NULL) {
1431
0
                            state->top->status = decodeError;
1432
0
                            return;
1433
0
                        }
1434
0
                    }
1435
0
                }
1436
0
                state->place = duringLeaf;
1437
0
            } else {
1438
0
                /*
1439
0
                 * An indefinite-length or zero-length item is not allowed.
1440
0
                 * (All legal cases of such were handled above.)
1441
0
                 */
1442
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1443
0
                state->top->status = decodeError;
1444
0
            }
1445
0
    }
1446
0
}
1447
1448
static void
1449
sec_asn1d_free_child(sec_asn1d_state *state, PRBool error)
1450
0
{
1451
0
    if (state->child != NULL) {
1452
0
        PORT_Assert(error || state->child->consumed == 0);
1453
0
        PORT_Assert(state->our_mark != NULL);
1454
0
        PORT_ArenaZRelease(state->top->our_pool, state->our_mark);
1455
0
        if (error && state->top->their_pool == NULL) {
1456
0
            /*
1457
0
             * XXX We need to free anything allocated.
1458
0
             * At this point, we failed in the middle of decoding. But we
1459
0
             * can't free the data we previously allocated with PR_Malloc
1460
0
             * unless we keep track of every pointer. So instead we have a
1461
0
             * memory leak when decoding fails half-way, unless an arena is
1462
0
             * used. See bug 95311 .
1463
0
            */
1464
0
        }
1465
0
        state->child = NULL;
1466
0
        state->our_mark = NULL;
1467
0
    } else {
1468
0
        /*
1469
0
         * It is important that we do not leave a mark unreleased/unmarked.
1470
0
         * But I do not think we should ever have one set in this case, only
1471
0
         * if we had a child (handled above).  So check for that.  If this
1472
0
         * assertion should ever get hit, then we probably need to add code
1473
0
         * here to release back to our_mark (and then set our_mark to NULL).
1474
0
         */
1475
0
        PORT_Assert(state->our_mark == NULL);
1476
0
    }
1477
0
    state->place = beforeEndOfContents;
1478
0
}
1479
1480
/* We have just saved an entire encoded ASN.1 object (type) for a SAVE
1481
** template, and now in the next template, we are going to decode that
1482
** saved data  by calling SEC_ASN1DecoderUpdate recursively.
1483
** If that recursive call fails with needBytes, it is a fatal error,
1484
** because the encoded object should have been complete.
1485
** If that recursive call fails with decodeError, it will have already
1486
** cleaned up the state stack, so we must bail out quickly.
1487
**
1488
** These checks of the status returned by the recursive call are now
1489
** done in the caller of this function, immediately after it returns.
1490
*/
1491
static void
1492
sec_asn1d_reuse_encoding(sec_asn1d_state *state)
1493
0
{
1494
0
    sec_asn1d_state *child;
1495
0
    unsigned long consumed;
1496
0
    SECItem *item;
1497
0
    void *dest;
1498
0
1499
0
    child = state->child;
1500
0
    PORT_Assert(child != NULL);
1501
0
1502
0
    consumed = child->consumed;
1503
0
    child->consumed = 0;
1504
0
1505
0
    item = (SECItem *)(state->dest);
1506
0
    PORT_Assert(item != NULL);
1507
0
1508
0
    PORT_Assert(item->len == consumed);
1509
0
1510
0
    /*
1511
0
     * Free any grandchild.
1512
0
     */
1513
0
    sec_asn1d_free_child(child, PR_FALSE);
1514
0
1515
0
    /*
1516
0
     * Notify after the SAVE field.
1517
0
     */
1518
0
    sec_asn1d_notify_after(state->top, state->dest, state->depth);
1519
0
1520
0
    /*
1521
0
     * Adjust to get new dest and move forward.
1522
0
     */
1523
0
    dest = (char *)state->dest - state->theTemplate->offset;
1524
0
    state->theTemplate++;
1525
0
    child->dest = (char *)dest + state->theTemplate->offset;
1526
0
    child->theTemplate = state->theTemplate;
1527
0
1528
0
    /*
1529
0
     * Notify before the "real" field.
1530
0
     */
1531
0
    PORT_Assert(state->depth == child->depth);
1532
0
    sec_asn1d_notify_before(state->top, child->dest, child->depth);
1533
0
1534
0
    /*
1535
0
     * This will tell DecoderUpdate to return when it is done.
1536
0
     */
1537
0
    state->place = afterSaveEncoding;
1538
0
1539
0
    /*
1540
0
     * We already have a child; "push" it by making it current.
1541
0
     */
1542
0
    state->top->current = child;
1543
0
1544
0
    /*
1545
0
     * And initialize it so it is ready to parse.
1546
0
     */
1547
0
    (void)sec_asn1d_init_state_based_on_template(child);
1548
0
1549
0
    /*
1550
0
     * Now parse that out of our data.
1551
0
     */
1552
0
    if (SEC_ASN1DecoderUpdate(state->top,
1553
0
                              (char *)item->data, item->len) != SECSuccess)
1554
0
        return;
1555
0
    if (state->top->status == needBytes) {
1556
0
        return;
1557
0
    }
1558
0
1559
0
    PORT_Assert(state->top->current == state);
1560
0
    PORT_Assert(state->child == child);
1561
0
1562
0
    /*
1563
0
     * That should have consumed what we consumed before.
1564
0
     */
1565
0
    PORT_Assert(consumed == child->consumed);
1566
0
    child->consumed = 0;
1567
0
1568
0
    /*
1569
0
     * Done.
1570
0
     */
1571
0
    state->consumed += consumed;
1572
0
    child->place = notInUse;
1573
0
    state->place = afterEndOfContents;
1574
0
}
1575
1576
static unsigned long
1577
sec_asn1d_parse_leaf(sec_asn1d_state *state,
1578
                     const char *buf, unsigned long len)
1579
0
{
1580
0
    SECItem *item;
1581
0
    unsigned long bufLen;
1582
0
1583
0
    if (len == 0) {
1584
0
        state->top->status = needBytes;
1585
0
        return 0;
1586
0
    }
1587
0
1588
0
    if (state->pending < len)
1589
0
        len = state->pending;
1590
0
1591
0
    bufLen = len;
1592
0
1593
0
    item = (SECItem *)(state->dest);
1594
0
    if (item != NULL && item->data != NULL) {
1595
0
        unsigned long offset;
1596
0
        /* Strip leading zeroes when target is unsigned integer */
1597
0
        if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER   */
1598
0
            item->len == 0 &&                             /* MSB       */
1599
0
            item->type == siUnsignedInteger)              /* unsigned  */
1600
0
        {
1601
0
            while (len > 1 && buf[0] == 0) { /* leading 0 */
1602
0
                buf++;
1603
0
                len--;
1604
0
            }
1605
0
        }
1606
0
        offset = item->len;
1607
0
        if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
1608
0
            // The previous bit string must have no unused bits.
1609
0
            if (item->len & 0x7) {
1610
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1611
0
                state->top->status = decodeError;
1612
0
                return 0;
1613
0
            }
1614
0
            // If this is a bit string, the length is bits, not bytes.
1615
0
            offset = item->len >> 3;
1616
0
        }
1617
0
        if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
1618
0
            unsigned long len_in_bits;
1619
0
            // Protect against overflow during the bytes-to-bits conversion.
1620
0
            if (len >= (ULONG_MAX >> 3) + 1) {
1621
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1622
0
                state->top->status = decodeError;
1623
0
                return 0;
1624
0
            }
1625
0
            len_in_bits = (len << 3) - state->bit_string_unused_bits;
1626
0
            // Protect against overflow when computing the total length in bits.
1627
0
            if (UINT_MAX - item->len < len_in_bits) {
1628
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1629
0
                state->top->status = decodeError;
1630
0
                return 0;
1631
0
            }
1632
0
            item->len += len_in_bits;
1633
0
        } else {
1634
0
            if (UINT_MAX - item->len < len) {
1635
0
                PORT_SetError(SEC_ERROR_BAD_DER);
1636
0
                state->top->status = decodeError;
1637
0
                return 0;
1638
0
            }
1639
0
            item->len += len;
1640
0
        }
1641
0
        PORT_Memcpy(item->data + offset, buf, len);
1642
0
    }
1643
0
    state->pending -= bufLen;
1644
0
    if (state->pending == 0)
1645
0
        state->place = beforeEndOfContents;
1646
0
1647
0
    return bufLen;
1648
0
}
1649
1650
static unsigned long
1651
sec_asn1d_parse_bit_string(sec_asn1d_state *state,
1652
                           const char *buf, unsigned long len)
1653
0
{
1654
0
    unsigned char byte;
1655
0
1656
0
    /*PORT_Assert (state->pending > 0); */
1657
0
    PORT_Assert(state->place == beforeBitString);
1658
0
1659
0
    if (state->pending == 0) {
1660
0
        if (state->dest != NULL) {
1661
0
            SECItem *item = (SECItem *)(state->dest);
1662
0
            item->data = NULL;
1663
0
            item->len = 0;
1664
0
            state->place = beforeEndOfContents;
1665
0
            return 0;
1666
0
        }
1667
0
    }
1668
0
1669
0
    if (len == 0) {
1670
0
        state->top->status = needBytes;
1671
0
        return 0;
1672
0
    }
1673
0
1674
0
    byte = (unsigned char)*buf;
1675
0
    if (byte > 7) {
1676
0
        PORT_SetError(SEC_ERROR_BAD_DER);
1677
0
        state->top->status = decodeError;
1678
0
        return 0;
1679
0
    }
1680
0
1681
0
    state->bit_string_unused_bits = byte;
1682
0
    state->place = duringBitString;
1683
0
    state->pending -= 1;
1684
0
1685
0
    return 1;
1686
0
}
1687
1688
static unsigned long
1689
sec_asn1d_parse_more_bit_string(sec_asn1d_state *state,
1690
                                const char *buf, unsigned long len)
1691
0
{
1692
0
    PORT_Assert(state->place == duringBitString);
1693
0
    if (state->pending == 0) {
1694
0
        /* An empty bit string with some unused bits is invalid. */
1695
0
        if (state->bit_string_unused_bits) {
1696
0
            PORT_SetError(SEC_ERROR_BAD_DER);
1697
0
            state->top->status = decodeError;
1698
0
        } else {
1699
0
            /* An empty bit string with no unused bits is OK. */
1700
0
            state->place = beforeEndOfContents;
1701
0
        }
1702
0
        return 0;
1703
0
    }
1704
0
1705
0
    len = sec_asn1d_parse_leaf(state, buf, len);
1706
0
    return len;
1707
0
}
1708
1709
/*
1710
 * XXX All callers should be looking at return value to detect
1711
 * out-of-memory errors (and stop!).
1712
 */
1713
static struct subitem *
1714
sec_asn1d_add_to_subitems(sec_asn1d_state *state,
1715
                          const void *data, unsigned long len,
1716
                          PRBool copy_data)
1717
0
{
1718
0
    struct subitem *thing;
1719
0
1720
0
    thing = (struct subitem *)sec_asn1d_zalloc(state->top->our_pool,
1721
0
                                               sizeof(struct subitem));
1722
0
    if (thing == NULL) {
1723
0
        state->top->status = decodeError;
1724
0
        return NULL;
1725
0
    }
1726
0
1727
0
    if (copy_data) {
1728
0
        void *copy;
1729
0
        copy = sec_asn1d_alloc(state->top->our_pool, len);
1730
0
        if (copy == NULL) {
1731
0
            state->top->status = decodeError;
1732
0
            if (!state->top->our_pool)
1733
0
                PORT_Free(thing);
1734
0
            return NULL;
1735
0
        }
1736
0
        PORT_Memcpy(copy, data, len);
1737
0
        thing->data = copy;
1738
0
    } else {
1739
0
        thing->data = data;
1740
0
    }
1741
0
    thing->len = len;
1742
0
    thing->next = NULL;
1743
0
1744
0
    if (state->subitems_head == NULL) {
1745
0
        PORT_Assert(state->subitems_tail == NULL);
1746
0
        state->subitems_head = state->subitems_tail = thing;
1747
0
    } else {
1748
0
        state->subitems_tail->next = thing;
1749
0
        state->subitems_tail = thing;
1750
0
    }
1751
0
1752
0
    return thing;
1753
0
}
1754
1755
static void
1756
sec_asn1d_record_any_header(sec_asn1d_state *state,
1757
                            const char *buf,
1758
                            unsigned long len)
1759
0
{
1760
0
    SECItem *item;
1761
0
1762
0
    item = (SECItem *)(state->dest);
1763
0
    if (item != NULL && item->data != NULL) {
1764
0
        PORT_Assert(state->substring);
1765
0
        PORT_Memcpy(item->data + item->len, buf, len);
1766
0
        item->len += len;
1767
0
    } else {
1768
0
        sec_asn1d_add_to_subitems(state, buf, len, PR_TRUE);
1769
0
    }
1770
0
}
1771
1772
/*
1773
 * We are moving along through the substrings of a constructed string,
1774
 * and have just finished parsing one -- we need to save our child data
1775
 * (if the child was not already writing directly into the destination)
1776
 * and then move forward by one.
1777
 *
1778
 * We also have to detect when we are done:
1779
 *  - a definite-length encoding stops when our pending value hits 0
1780
 *  - an indefinite-length encoding stops when our child is empty
1781
 *    (which means it was the end-of-contents octets)
1782
 */
1783
static void
1784
sec_asn1d_next_substring(sec_asn1d_state *state)
1785
0
{
1786
0
    sec_asn1d_state *child;
1787
0
    SECItem *item;
1788
0
    unsigned long child_consumed;
1789
0
    PRBool done;
1790
0
1791
0
    PORT_Assert(state->place == duringConstructedString);
1792
0
    PORT_Assert(state->child != NULL);
1793
0
1794
0
    child = state->child;
1795
0
1796
0
    child_consumed = child->consumed;
1797
0
    child->consumed = 0;
1798
0
    state->consumed += child_consumed;
1799
0
1800
0
    done = PR_FALSE;
1801
0
1802
0
    if (state->pending) {
1803
0
        PORT_Assert(!state->indefinite);
1804
0
        if (child_consumed > state->pending) {
1805
0
            PORT_SetError(SEC_ERROR_BAD_DER);
1806
0
            state->top->status = decodeError;
1807
0
            return;
1808
0
        }
1809
0
1810
0
        state->pending -= child_consumed;
1811
0
        if (state->pending == 0)
1812
0
            done = PR_TRUE;
1813
0
    } else {
1814
0
        PRBool preallocatedString;
1815
0
        sec_asn1d_state *temp_state;
1816
0
        PORT_Assert(state->indefinite);
1817
0
1818
0
        item = (SECItem *)(child->dest);
1819
0
1820
0
        /**
1821
0
         * At this point, there's three states at play:
1822
0
         *   child: The element that was just parsed
1823
0
         *   state: The currently processed element
1824
0
         *   'parent' (aka state->parent): The enclosing construct
1825
0
         *      of state, or NULL if this is the top-most element.
1826
0
         *
1827
0
         * This state handles both substrings of a constructed string AND
1828
0
         * child elements of items whose template type was that of
1829
0
         * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
1830
0
         * template, as described in sec_asn1d_prepare_for_contents. For
1831
0
         * brevity, these will be referred to as 'string' and 'any' types.
1832
0
         *
1833
0
         * This leads to the following possibilities:
1834
0
         *   1: This element is an indefinite length string, part of a
1835
0
         *      definite length string.
1836
0
         *   2: This element is an indefinite length string, part of an
1837
0
         *      indefinite length string.
1838
0
         *   3: This element is an indefinite length any, part of a
1839
0
         *      definite length any.
1840
0
         *   4: This element is an indefinite length any, part of an
1841
0
         *      indefinite length any.
1842
0
         *   5: This element is an indefinite length any and does not
1843
0
         *      meet any of the above criteria. Note that this would include
1844
0
         *      an indefinite length string type matching an indefinite
1845
0
         *      length any template.
1846
0
         *
1847
0
         * In Cases #1 and #3, the definite length 'parent' element will
1848
0
         * have allocated state->dest based on the parent elements definite
1849
0
         * size. During the processing of 'child', sec_asn1d_parse_leaf will
1850
0
         * have copied the (string, any) data directly into the offset of
1851
0
         * dest, as appropriate, so there's no need for this class to still
1852
0
         * store the child - it's already been processed.
1853
0
         *
1854
0
         * In Cases #2 and #4, dest will be set to the parent element's dest,
1855
0
         * but dest->data will not have been allocated yet, due to the
1856
0
         * indefinite length encoding. In this situation, it's necessary to
1857
0
         * hold onto child (and all other children) until the EOC, at which
1858
0
         * point, it becomes possible to compute 'state's overall length. Once
1859
0
         * 'state' has a computed length, this can then be fed to 'parent' (via
1860
0
         * this state), and then 'parent' can similarly compute the length of
1861
0
         * all of its children up to the EOC, which will ultimately transit to
1862
0
         * sec_asn1d_concat_substrings, determine the overall size needed,
1863
0
         * allocate, and copy the contents (of all of parent's children, which
1864
0
         * would include 'state', just as 'state' will have copied all of its
1865
0
         * children via sec_asn1d_concat_substrings)
1866
0
         *
1867
0
         * The final case, Case #5, will manifest in that item->data and
1868
0
         * item->len will be NULL/0, respectively, since this element was
1869
0
         * indefinite-length encoded. In that case, both the tag and length will
1870
0
         * already exist in state's subitems, via sec_asn1d_record_any_header,
1871
0
         * and so the contents (aka 'child') should be added to that list of
1872
0
         * items to concatenate in sec_asn1d_concat_substrings once the EOC
1873
0
         * is encountered.
1874
0
         *
1875
0
         * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
1876
0
         * tree. If the current type is a string type, then the enclosing
1877
0
         * construct will be that same type (#1/#2). If the current type is an
1878
0
         * any type, then the enclosing construct is either an any type (#3/#4)
1879
0
         * or some other type (#5). Since this is BER, this nesting relationship
1880
0
         * between 'state' and 'parent' may go through several levels of
1881
0
         * constructed encoding, so continue walking the ancestor chain until a
1882
0
         * clear determination can be made.
1883
0
         *
1884
0
         * The variable preallocatedString is used to indicate Case #1/#3,
1885
0
         * indicating an in-place copy has already occurred, and Cases #2, #4,
1886
0
         * and #5 all have the same behaviour of adding a new substring.
1887
0
         */
1888
0
        preallocatedString = PR_FALSE;
1889
0
        temp_state = state;
1890
0
        while (temp_state && item == temp_state->dest && temp_state->indefinite) {
1891
0
            sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
1892
0
            if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
1893
0
                /* Case #5 - Either this is a top-level construct or it is part
1894
0
                 * of some other element (e.g. a SEQUENCE), in which case, a
1895
0
                 * new item should be allocated. */
1896
0
                break;
1897
0
            }
1898
0
            if (!parent->indefinite) {
1899
0
                /* Cases #1 / #3 - A definite length ancestor exists, for which
1900
0
                 * this is a substring that has already copied into dest. */
1901
0
                preallocatedString = PR_TRUE;
1902
0
                break;
1903
0
            }
1904
0
            if (!parent->substring) {
1905
0
                /* Cases #2 / #4 - If the parent is not a substring, but is
1906
0
                 * indefinite, then there's nothing further up that may have
1907
0
                 * preallocated dest, thus child will not have already
1908
0
                 * been copied in place, therefore it's necessary to save child
1909
0
                 * as a subitem. */
1910
0
                break;
1911
0
            }
1912
0
            temp_state = parent;
1913
0
        }
1914
0
        if (item != NULL && item->data != NULL && !preallocatedString) {
1915
0
            /*
1916
0
             * Save the string away for later concatenation.
1917
0
             */
1918
0
            PORT_Assert(item->data != NULL);
1919
0
            sec_asn1d_add_to_subitems(state, item->data, item->len, PR_FALSE);
1920
0
            /*
1921
0
             * Clear the child item for the next round.
1922
0
             */
1923
0
            item->data = NULL;
1924
0
            item->len = 0;
1925
0
        }
1926
0
1927
0
        /*
1928
0
         * If our child was just our end-of-contents octets, we are done.
1929
0
         */
1930
0
        if (child->endofcontents)
1931
0
            done = PR_TRUE;
1932
0
    }
1933
0
1934
0
    /*
1935
0
     * Stop or do the next one.
1936
0
     */
1937
0
    if (done) {
1938
0
        child->place = notInUse;
1939
0
        state->place = afterConstructedString;
1940
0
    } else {
1941
0
        sec_asn1d_scrub_state(child);
1942
0
        state->top->current = child;
1943
0
    }
1944
0
}
1945
1946
/*
1947
 * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
1948
 */
1949
static void
1950
sec_asn1d_next_in_group(sec_asn1d_state *state)
1951
0
{
1952
0
    sec_asn1d_state *child;
1953
0
    unsigned long child_consumed;
1954
0
1955
0
    PORT_Assert(state->place == duringGroup);
1956
0
    PORT_Assert(state->child != NULL);
1957
0
1958
0
    child = state->child;
1959
0
1960
0
    child_consumed = child->consumed;
1961
0
    child->consumed = 0;
1962
0
    state->consumed += child_consumed;
1963
0
1964
0
    /*
1965
0
     * If our child was just our end-of-contents octets, we are done.
1966
0
     */
1967
0
    if (child->endofcontents) {
1968
0
        /* XXX I removed the PORT_Assert (child->dest == NULL) because there
1969
0
         * was a bug in that a template that was a sequence of which also had
1970
0
         * a child of a sequence of, in an indefinite group was not working
1971
0
         * properly.  This fix seems to work, (added the if statement below),
1972
0
         * and nothing appears broken, but I am putting this note here just
1973
0
         * in case. */
1974
0
        /*
1975
0
         * XXX No matter how many times I read that comment,
1976
0
         * I cannot figure out what case he was fixing.  I believe what he
1977
0
         * did was deliberate, so I am loathe to touch it.  I need to
1978
0
         * understand how it could ever be that child->dest != NULL but
1979
0
         * child->endofcontents is true, and why it is important to check
1980
0
         * that state->subitems_head is NULL.  This really needs to be
1981
0
         * figured out, as I am not sure if the following code should be
1982
0
         * compensating for "offset", as is done a little farther below
1983
0
         * in the more normal case.
1984
0
         */
1985
0
        PORT_Assert(state->indefinite);
1986
0
        PORT_Assert(state->pending == 0);
1987
0
        if (child->dest && !state->subitems_head) {
1988
0
            sec_asn1d_add_to_subitems(state, child->dest, 0, PR_FALSE);
1989
0
            child->dest = NULL;
1990
0
        }
1991
0
1992
0
        child->place = notInUse;
1993
0
        state->place = afterGroup;
1994
0
        return;
1995
0
    }
1996
0
1997
0
    /*
1998
0
     * Do the "after" field notification for next in group.
1999
0
     */
2000
0
    sec_asn1d_notify_after(state->top, child->dest, child->depth);
2001
0
2002
0
    /*
2003
0
     * Save it away (unless we are not storing).
2004
0
     */
2005
0
    if (child->dest != NULL) {
2006
0
        void *dest;
2007
0
2008
0
        dest = child->dest;
2009
0
        dest = (char *)dest - child->theTemplate->offset;
2010
0
        sec_asn1d_add_to_subitems(state, dest, 0, PR_FALSE);
2011
0
        child->dest = NULL;
2012
0
    }
2013
0
2014
0
    /*
2015
0
     * Account for those bytes; see if we are done.
2016
0
     */
2017
0
    if (state->pending) {
2018
0
        PORT_Assert(!state->indefinite);
2019
0
        if (child_consumed > state->pending) {
2020
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2021
0
            state->top->status = decodeError;
2022
0
            return;
2023
0
        }
2024
0
2025
0
        state->pending -= child_consumed;
2026
0
        if (state->pending == 0) {
2027
0
            child->place = notInUse;
2028
0
            state->place = afterGroup;
2029
0
            return;
2030
0
        }
2031
0
    }
2032
0
2033
0
    /*
2034
0
     * Do the "before" field notification for next item in group.
2035
0
     */
2036
0
    sec_asn1d_notify_before(state->top, child->dest, child->depth);
2037
0
2038
0
    /*
2039
0
     * Now we do the next one.
2040
0
     */
2041
0
    sec_asn1d_scrub_state(child);
2042
0
2043
0
    /* Initialize child state from the template */
2044
0
    sec_asn1d_init_state_based_on_template(child);
2045
0
2046
0
    state->top->current = child;
2047
0
}
2048
2049
/*
2050
 * We are moving along through a sequence; move forward by one,
2051
 * (detecting end-of-sequence when it happens).
2052
 * XXX The handling of "missing" is ugly.  Fix it.
2053
 */
2054
static void
2055
sec_asn1d_next_in_sequence(sec_asn1d_state *state)
2056
0
{
2057
0
    sec_asn1d_state *child;
2058
0
    unsigned long child_consumed;
2059
0
    PRBool child_missing;
2060
0
2061
0
    PORT_Assert(state->place == duringSequence);
2062
0
    PORT_Assert(state->child != NULL);
2063
0
2064
0
    child = state->child;
2065
0
2066
0
    /*
2067
0
     * Do the "after" field notification.
2068
0
     */
2069
0
    sec_asn1d_notify_after(state->top, child->dest, child->depth);
2070
0
2071
0
    child_missing = (PRBool)child->missing;
2072
0
    child_consumed = child->consumed;
2073
0
    child->consumed = 0;
2074
0
2075
0
    /*
2076
0
     * Take care of accounting.
2077
0
     */
2078
0
    if (child_missing) {
2079
0
        PORT_Assert(child->optional);
2080
0
    } else {
2081
0
        state->consumed += child_consumed;
2082
0
        /*
2083
0
         * Free any grandchild.
2084
0
         */
2085
0
        sec_asn1d_free_child(child, PR_FALSE);
2086
0
        if (state->pending) {
2087
0
            PORT_Assert(!state->indefinite);
2088
0
            if (child_consumed > state->pending) {
2089
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2090
0
                state->top->status = decodeError;
2091
0
                return;
2092
0
            }
2093
0
            state->pending -= child_consumed;
2094
0
            if (state->pending == 0) {
2095
0
                child->theTemplate++;
2096
0
                while (child->theTemplate->kind != 0) {
2097
0
                    if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
2098
0
                        PORT_SetError(SEC_ERROR_BAD_DER);
2099
0
                        state->top->status = decodeError;
2100
0
                        return;
2101
0
                    }
2102
0
                    child->theTemplate++;
2103
0
                }
2104
0
                child->place = notInUse;
2105
0
                state->place = afterEndOfContents;
2106
0
                return;
2107
0
            }
2108
0
        }
2109
0
    }
2110
0
2111
0
    /*
2112
0
     * Move forward.
2113
0
     */
2114
0
    child->theTemplate++;
2115
0
    if (child->theTemplate->kind == 0) {
2116
0
        /*
2117
0
         * We are done with this sequence.
2118
0
         */
2119
0
        child->place = notInUse;
2120
0
        if (state->pending) {
2121
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2122
0
            state->top->status = decodeError;
2123
0
        } else if (child_missing) {
2124
0
            /*
2125
0
             * We got to the end, but have a child that started parsing
2126
0
             * and ended up "missing".  The only legitimate reason for
2127
0
             * this is that we had one or more optional fields at the
2128
0
             * end of our sequence, and we were encoded indefinite-length,
2129
0
             * so when we went looking for those optional fields we
2130
0
             * found our end-of-contents octets instead.
2131
0
             * (Yes, this is ugly; dunno a better way to handle it.)
2132
0
             * So, first confirm the situation, and then mark that we
2133
0
             * are done.
2134
0
             */
2135
0
            if (state->indefinite && child->endofcontents) {
2136
0
                PORT_Assert(child_consumed == 2);
2137
0
                if (child_consumed != 2) {
2138
0
                    PORT_SetError(SEC_ERROR_BAD_DER);
2139
0
                    state->top->status = decodeError;
2140
0
                } else {
2141
0
                    state->consumed += child_consumed;
2142
0
                    state->place = afterEndOfContents;
2143
0
                }
2144
0
            } else {
2145
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2146
0
                state->top->status = decodeError;
2147
0
            }
2148
0
        } else {
2149
0
            /*
2150
0
             * We have to finish out, maybe reading end-of-contents octets;
2151
0
             * let the normal logic do the right thing.
2152
0
             */
2153
0
            state->place = beforeEndOfContents;
2154
0
        }
2155
0
    } else {
2156
0
        unsigned char child_found_tag_modifiers = 0;
2157
0
        unsigned long child_found_tag_number = 0;
2158
0
2159
0
        /*
2160
0
         * Reset state and push.
2161
0
         */
2162
0
        if (state->dest != NULL)
2163
0
            child->dest = (char *)state->dest + child->theTemplate->offset;
2164
0
2165
0
        /*
2166
0
         * Do the "before" field notification.
2167
0
         */
2168
0
        sec_asn1d_notify_before(state->top, child->dest, child->depth);
2169
0
2170
0
        if (child_missing) { /* if previous child was missing, copy the tag data we already have */
2171
0
            child_found_tag_modifiers = child->found_tag_modifiers;
2172
0
            child_found_tag_number = child->found_tag_number;
2173
0
        }
2174
0
        state->top->current = child;
2175
0
        child = sec_asn1d_init_state_based_on_template(child);
2176
0
        if (child_missing && child) {
2177
0
            child->place = afterIdentifier;
2178
0
            child->found_tag_modifiers = child_found_tag_modifiers;
2179
0
            child->found_tag_number = child_found_tag_number;
2180
0
            child->consumed = child_consumed;
2181
0
            if (child->underlying_kind == SEC_ASN1_ANY && !child->top->filter_only) {
2182
0
                /*
2183
0
                 * If the new field is an ANY, and we are storing, then
2184
0
                 * we need to save the tag out.  We would have done this
2185
0
                 * already in the normal case, but since we were looking
2186
0
                 * for an optional field, and we did not find it, we only
2187
0
                 * now realize we need to save the tag.
2188
0
                 */
2189
0
                unsigned char identifier;
2190
0
2191
0
                /*
2192
0
                 * Check that we did not end up with a high tag; for that
2193
0
                 * we need to re-encode the tag into multiple bytes in order
2194
0
                 * to store it back to look like what we parsed originally.
2195
0
                 * In practice this does not happen, but for completeness
2196
0
                 * sake it should probably be made to work at some point.
2197
0
                 */
2198
0
                PORT_Assert(child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
2199
0
                identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
2200
0
                sec_asn1d_record_any_header(child, (char *)&identifier, 1);
2201
0
            }
2202
0
        }
2203
0
    }
2204
0
}
2205
2206
static void
2207
sec_asn1d_concat_substrings(sec_asn1d_state *state)
2208
0
{
2209
0
    PORT_Assert(state->place == afterConstructedString);
2210
0
2211
0
    if (state->subitems_head != NULL) {
2212
0
        struct subitem *substring;
2213
0
        unsigned long alloc_len, item_len;
2214
0
        unsigned char *where;
2215
0
        SECItem *item;
2216
0
        PRBool is_bit_string;
2217
0
2218
0
        item_len = 0;
2219
0
        is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
2220
0
                            ? PR_TRUE
2221
0
                            : PR_FALSE;
2222
0
2223
0
        substring = state->subitems_head;
2224
0
        while (substring != NULL) {
2225
0
            /*
2226
0
             * All bit-string substrings except the last one should be
2227
0
             * a clean multiple of 8 bits.
2228
0
             */
2229
0
            if (is_bit_string && (substring->next != NULL) && (substring->len & 0x7)) {
2230
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2231
0
                state->top->status = decodeError;
2232
0
                return;
2233
0
            }
2234
0
            item_len += substring->len;
2235
0
            substring = substring->next;
2236
0
        }
2237
0
2238
0
        if (is_bit_string) {
2239
0
            alloc_len = ((item_len + 7) >> 3);
2240
0
        } else {
2241
0
            /*
2242
0
             * Add 2 for the end-of-contents octets of an indefinite-length
2243
0
             * ANY that is *not* also an INNER.  Because we zero-allocate
2244
0
             * below, all we need to do is increase the length here.
2245
0
             */
2246
0
            if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
2247
0
                item_len += 2;
2248
0
            alloc_len = item_len;
2249
0
        }
2250
0
2251
0
        if (state->top->max_element_size > 0 &&
2252
0
            alloc_len > state->top->max_element_size) {
2253
0
            PORT_SetError(SEC_ERROR_OUTPUT_LEN);
2254
0
            state->top->status = decodeError;
2255
0
            return;
2256
0
        }
2257
0
2258
0
        item = (SECItem *)(state->dest);
2259
0
        PORT_Assert(item != NULL);
2260
0
        PORT_Assert(item->data == NULL);
2261
0
        item->data = (unsigned char *)sec_asn1d_zalloc(state->top->their_pool,
2262
0
                                                       alloc_len);
2263
0
        if (item->data == NULL) {
2264
0
            state->top->status = decodeError;
2265
0
            return;
2266
0
        }
2267
0
        item->len = item_len;
2268
0
2269
0
        where = item->data;
2270
0
        substring = state->subitems_head;
2271
0
        while (substring != NULL) {
2272
0
            if (is_bit_string)
2273
0
                item_len = (substring->len + 7) >> 3;
2274
0
            else
2275
0
                item_len = substring->len;
2276
0
            PORT_Memcpy(where, substring->data, item_len);
2277
0
            where += item_len;
2278
0
            substring = substring->next;
2279
0
        }
2280
0
2281
0
        /*
2282
0
         * Because we use arenas and have a mark set, we later free
2283
0
         * everything we have allocated, so this does *not* present
2284
0
         * a memory leak (it is just temporarily left dangling).
2285
0
         */
2286
0
        state->subitems_head = state->subitems_tail = NULL;
2287
0
    }
2288
0
2289
0
    state->place = afterEndOfContents;
2290
0
}
2291
2292
static void
2293
sec_asn1d_concat_group(sec_asn1d_state *state)
2294
0
{
2295
0
    const void ***placep;
2296
0
2297
0
    PORT_Assert(state->place == afterGroup);
2298
0
2299
0
    placep = (const void ***)state->dest;
2300
0
    PORT_Assert(state->subitems_head == NULL || placep != NULL);
2301
0
    if (placep != NULL) {
2302
0
        struct subitem *item;
2303
0
        const void **group;
2304
0
        int count;
2305
0
2306
0
        count = 0;
2307
0
        item = state->subitems_head;
2308
0
        while (item != NULL) {
2309
0
            PORT_Assert(item->next != NULL || item == state->subitems_tail);
2310
0
            count++;
2311
0
            item = item->next;
2312
0
        }
2313
0
2314
0
        group = (const void **)sec_asn1d_zalloc(state->top->their_pool,
2315
0
                                                (count + 1) * (sizeof(void *)));
2316
0
        if (group == NULL) {
2317
0
            state->top->status = decodeError;
2318
0
            return;
2319
0
        }
2320
0
2321
0
        *placep = group;
2322
0
2323
0
        item = state->subitems_head;
2324
0
        while (item != NULL) {
2325
0
            *group++ = item->data;
2326
0
            item = item->next;
2327
0
        }
2328
0
        *group = NULL;
2329
0
2330
0
        /*
2331
0
         * Because we use arenas and have a mark set, we later free
2332
0
         * everything we have allocated, so this does *not* present
2333
0
         * a memory leak (it is just temporarily left dangling).
2334
0
         */
2335
0
        state->subitems_head = state->subitems_tail = NULL;
2336
0
    }
2337
0
2338
0
    state->place = afterEndOfContents;
2339
0
}
2340
2341
/*
2342
 * For those states that push a child to handle a subtemplate,
2343
 * "absorb" that child (transfer necessary information).
2344
 */
2345
static void
2346
sec_asn1d_absorb_child(sec_asn1d_state *state)
2347
0
{
2348
0
    /*
2349
0
     * There is absolutely supposed to be a child there.
2350
0
     */
2351
0
    PORT_Assert(state->child != NULL);
2352
0
2353
0
    /*
2354
0
     * Inherit the missing status of our child, and do the ugly
2355
0
     * backing-up if necessary.
2356
0
     */
2357
0
    state->missing = state->child->missing;
2358
0
    if (state->missing) {
2359
0
        state->found_tag_number = state->child->found_tag_number;
2360
0
        state->found_tag_modifiers = state->child->found_tag_modifiers;
2361
0
        state->endofcontents = state->child->endofcontents;
2362
0
    }
2363
0
2364
0
    /*
2365
0
     * Add in number of bytes consumed by child.
2366
0
     * (Only EXPLICIT should have already consumed bytes itself.)
2367
0
     */
2368
0
    PORT_Assert(state->place == afterExplicit || state->consumed == 0);
2369
0
    state->consumed += state->child->consumed;
2370
0
2371
0
    /*
2372
0
     * Subtract from bytes pending; this only applies to a definite-length
2373
0
     * EXPLICIT field.
2374
0
     */
2375
0
    if (state->pending) {
2376
0
        PORT_Assert(!state->indefinite);
2377
0
        PORT_Assert(state->place == afterExplicit);
2378
0
2379
0
        /*
2380
0
         * If we had a definite-length explicit, then what the child
2381
0
         * consumed should be what was left pending.
2382
0
         */
2383
0
        if (state->pending != state->child->consumed) {
2384
0
            if (state->pending < state->child->consumed) {
2385
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2386
0
                state->top->status = decodeError;
2387
0
                return;
2388
0
            }
2389
0
            /*
2390
0
             * Okay, this is a hack.  It *should* be an error whether
2391
0
             * pending is too big or too small, but it turns out that
2392
0
             * we had a bug in our *old* DER encoder that ended up
2393
0
             * counting an explicit header twice in the case where
2394
0
             * the underlying type was an ANY.  So, because we cannot
2395
0
             * prevent receiving these (our own certificate server can
2396
0
             * send them to us), we need to be lenient and accept them.
2397
0
             * To do so, we need to pretend as if we read all of the
2398
0
             * bytes that the header said we would find, even though
2399
0
             * we actually came up short.
2400
0
             */
2401
0
            state->consumed += (state->pending - state->child->consumed);
2402
0
        }
2403
0
        state->pending = 0;
2404
0
    }
2405
0
2406
0
    /*
2407
0
     * Indicate that we are done with child.
2408
0
     */
2409
0
    state->child->consumed = 0;
2410
0
2411
0
    /*
2412
0
     * And move on to final state.
2413
0
     * (Technically everybody could move to afterEndOfContents except
2414
0
     * for an indefinite-length EXPLICIT; for simplicity though we assert
2415
0
     * that but let the end-of-contents code do the real determination.)
2416
0
     */
2417
0
    PORT_Assert(state->place == afterExplicit || (!state->indefinite));
2418
0
    state->place = beforeEndOfContents;
2419
0
}
2420
2421
static void
2422
sec_asn1d_prepare_for_end_of_contents(sec_asn1d_state *state)
2423
0
{
2424
0
    PORT_Assert(state->place == beforeEndOfContents);
2425
0
2426
0
    if (state->indefinite) {
2427
0
        state->place = duringEndOfContents;
2428
0
        state->pending = 2;
2429
0
    } else {
2430
0
        state->place = afterEndOfContents;
2431
0
    }
2432
0
}
2433
2434
static unsigned long
2435
sec_asn1d_parse_end_of_contents(sec_asn1d_state *state,
2436
                                const char *buf, unsigned long len)
2437
0
{
2438
0
    unsigned int i;
2439
0
2440
0
    PORT_Assert(state->pending <= 2);
2441
0
    PORT_Assert(state->place == duringEndOfContents);
2442
0
2443
0
    if (len == 0) {
2444
0
        state->top->status = needBytes;
2445
0
        return 0;
2446
0
    }
2447
0
2448
0
    if (state->pending < len)
2449
0
        len = state->pending;
2450
0
2451
0
    for (i = 0; i < len; i++) {
2452
0
        if (buf[i] != 0) {
2453
0
            /*
2454
0
             * We expect to find only zeros; if not, just give up.
2455
0
             */
2456
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2457
0
            state->top->status = decodeError;
2458
0
            return 0;
2459
0
        }
2460
0
    }
2461
0
2462
0
    state->pending -= len;
2463
0
2464
0
    if (state->pending == 0) {
2465
0
        state->place = afterEndOfContents;
2466
0
        state->endofcontents = PR_TRUE;
2467
0
    }
2468
0
2469
0
    return len;
2470
0
}
2471
2472
static void
2473
sec_asn1d_pop_state(sec_asn1d_state *state)
2474
0
{
2475
#if 0  /* XXX I think this should always be handled explicitly by parent? */
2476
    /*
2477
     * Account for our child.
2478
     */
2479
    if (state->child != NULL) {
2480
    state->consumed += state->child->consumed;
2481
    if (state->pending) {
2482
        PORT_Assert (!state->indefinite);
2483
        if (state->child->consumed > state->pending) {
2484
        PORT_SetError (SEC_ERROR_BAD_DER);
2485
        state->top->status = decodeError;
2486
        } else {
2487
        state->pending -= state->child->consumed;
2488
        }
2489
    }
2490
    state->child->consumed = 0;
2491
    }
2492
#endif /* XXX */
2493
2494
0
    /*
2495
0
     * Free our child.
2496
0
     */
2497
0
    sec_asn1d_free_child(state, PR_FALSE);
2498
0
2499
0
    /*
2500
0
     * Just make my parent be the current state.  It will then clean
2501
0
     * up after me and free me (or reuse me).
2502
0
     */
2503
0
    state->top->current = state->parent;
2504
0
}
2505
2506
static sec_asn1d_state *
2507
sec_asn1d_before_choice(sec_asn1d_state *state)
2508
0
{
2509
0
    sec_asn1d_state *child;
2510
0
2511
0
    if (state->allocate) {
2512
0
        void *dest;
2513
0
2514
0
        dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
2515
0
        if ((void *)NULL == dest) {
2516
0
            state->top->status = decodeError;
2517
0
            return (sec_asn1d_state *)NULL;
2518
0
        }
2519
0
2520
0
        state->dest = (char *)dest + state->theTemplate->offset;
2521
0
    }
2522
0
2523
0
    child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
2524
0
                                 (char *)state->dest - state->theTemplate->offset,
2525
0
                                 PR_FALSE);
2526
0
    if ((sec_asn1d_state *)NULL == child) {
2527
0
        return (sec_asn1d_state *)NULL;
2528
0
    }
2529
0
2530
0
    sec_asn1d_scrub_state(child);
2531
0
    child = sec_asn1d_init_state_based_on_template(child);
2532
0
    if ((sec_asn1d_state *)NULL == child) {
2533
0
        return (sec_asn1d_state *)NULL;
2534
0
    }
2535
0
2536
0
    child->optional = PR_TRUE;
2537
0
2538
0
    state->place = duringChoice;
2539
0
2540
0
    return child;
2541
0
}
2542
2543
static sec_asn1d_state *
2544
sec_asn1d_during_choice(sec_asn1d_state *state)
2545
0
{
2546
0
    sec_asn1d_state *child = state->child;
2547
0
2548
0
    PORT_Assert((sec_asn1d_state *)NULL != child);
2549
0
2550
0
    if (child->missing) {
2551
0
        unsigned char child_found_tag_modifiers = 0;
2552
0
        unsigned long child_found_tag_number = 0;
2553
0
        void *dest;
2554
0
2555
0
        state->consumed += child->consumed;
2556
0
2557
0
        if (child->endofcontents) {
2558
0
            /* This choice is probably the first item in a GROUP
2559
0
            ** (e.g. SET_OF) that was indefinite-length encoded.
2560
0
            ** We're actually at the end of that GROUP.
2561
0
            ** We look up the stack to be sure that we find
2562
0
            ** a state with indefinite length encoding before we
2563
0
            ** find a state (like a SEQUENCE) that is definite.
2564
0
            */
2565
0
            child->place = notInUse;
2566
0
            state->place = afterChoice;
2567
0
            state->endofcontents = PR_TRUE; /* propagate this up */
2568
0
            if (sec_asn1d_parent_allows_EOC(state))
2569
0
                return state;
2570
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2571
0
            state->top->status = decodeError;
2572
0
            return NULL;
2573
0
        }
2574
0
2575
0
        dest = (char *)child->dest - child->theTemplate->offset;
2576
0
        child->theTemplate++;
2577
0
2578
0
        if (0 == child->theTemplate->kind) {
2579
0
            /* Ran out of choices */
2580
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2581
0
            state->top->status = decodeError;
2582
0
            return (sec_asn1d_state *)NULL;
2583
0
        }
2584
0
        child->dest = (char *)dest + child->theTemplate->offset;
2585
0
2586
0
        /* cargo'd from next_in_sequence innards */
2587
0
        if (state->pending) {
2588
0
            PORT_Assert(!state->indefinite);
2589
0
            if (child->consumed > state->pending) {
2590
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2591
0
                state->top->status = decodeError;
2592
0
                return NULL;
2593
0
            }
2594
0
            state->pending -= child->consumed;
2595
0
            if (0 == state->pending) {
2596
0
                /* XXX uh.. not sure if I should have stopped this
2597
0
                 * from happening before. */
2598
0
                PORT_Assert(0);
2599
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2600
0
                state->top->status = decodeError;
2601
0
                return (sec_asn1d_state *)NULL;
2602
0
            }
2603
0
        }
2604
0
2605
0
        child->consumed = 0;
2606
0
        sec_asn1d_scrub_state(child);
2607
0
2608
0
        /* move it on top again */
2609
0
        state->top->current = child;
2610
0
2611
0
        child_found_tag_modifiers = child->found_tag_modifiers;
2612
0
        child_found_tag_number = child->found_tag_number;
2613
0
2614
0
        child = sec_asn1d_init_state_based_on_template(child);
2615
0
        if ((sec_asn1d_state *)NULL == child) {
2616
0
            return (sec_asn1d_state *)NULL;
2617
0
        }
2618
0
2619
0
        /* copy our findings to the new top */
2620
0
        child->found_tag_modifiers = child_found_tag_modifiers;
2621
0
        child->found_tag_number = child_found_tag_number;
2622
0
2623
0
        child->optional = PR_TRUE;
2624
0
        child->place = afterIdentifier;
2625
0
2626
0
        return child;
2627
0
    }
2628
0
    if ((void *)NULL != state->dest) {
2629
0
        /* Store the enum */
2630
0
        int *which = (int *)state->dest;
2631
0
        *which = (int)child->theTemplate->size;
2632
0
    }
2633
0
2634
0
    child->place = notInUse;
2635
0
2636
0
    state->place = afterChoice;
2637
0
    return state;
2638
0
}
2639
2640
static void
2641
sec_asn1d_after_choice(sec_asn1d_state *state)
2642
0
{
2643
0
    state->consumed += state->child->consumed;
2644
0
    state->child->consumed = 0;
2645
0
    state->place = afterEndOfContents;
2646
0
    sec_asn1d_pop_state(state);
2647
0
}
2648
2649
unsigned long
2650
sec_asn1d_uinteger(SECItem *src)
2651
0
{
2652
0
    unsigned long value;
2653
0
    int len;
2654
0
2655
0
    if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
2656
0
        return 0;
2657
0
2658
0
    value = 0;
2659
0
    len = src->len;
2660
0
    while (len) {
2661
0
        value <<= 8;
2662
0
        value |= src->data[--len];
2663
0
    }
2664
0
    return value;
2665
0
}
2666
2667
SECStatus
2668
SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
2669
0
{
2670
0
    unsigned long v;
2671
0
    unsigned int i;
2672
0
2673
0
    if (src == NULL) {
2674
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
2675
0
        return SECFailure;
2676
0
    }
2677
0
2678
0
    if (src->len > sizeof(unsigned long)) {
2679
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
2680
0
        return SECFailure;
2681
0
    }
2682
0
2683
0
    if (src->data == NULL) {
2684
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
2685
0
        return SECFailure;
2686
0
    }
2687
0
2688
0
    if (src->data[0] & 0x80)
2689
0
        v = -1; /* signed and negative - start with all 1's */
2690
0
    else
2691
0
        v = 0;
2692
0
2693
0
    for (i = 0; i < src->len; i++) {
2694
0
        /* shift in next byte */
2695
0
        v <<= 8;
2696
0
        v |= src->data[i];
2697
0
    }
2698
0
    *value = v;
2699
0
    return SECSuccess;
2700
0
}
2701
2702
#ifdef DEBUG_ASN1D_STATES
2703
static void
2704
dump_states(SEC_ASN1DecoderContext *cx)
2705
{
2706
    sec_asn1d_state *state;
2707
    char kindBuf[256];
2708
2709
    for (state = cx->current; state->parent; state = state->parent) {
2710
        ;
2711
    }
2712
2713
    for (; state; state = state->child) {
2714
        int i;
2715
        for (i = 0; i < state->depth; i++) {
2716
            printf("  ");
2717
        }
2718
2719
        i = formatKind(state->theTemplate->kind, kindBuf);
2720
        printf("%s: tmpl kind %s",
2721
               (state == cx->current) ? "STATE" : "State",
2722
               kindBuf);
2723
        printf(" %s", (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)");
2724
        if (!i)
2725
            printf(", expect 0x%02lx",
2726
                   state->expect_tag_number | state->expect_tag_modifiers);
2727
2728
        printf("%s%s%s %lu\n",
2729
               state->indefinite ? ", indef" : "",
2730
               state->missing ? ", miss" : "",
2731
               state->endofcontents ? ", EOC" : "",
2732
               state->pending);
2733
    }
2734
2735
    return;
2736
}
2737
#endif /* DEBUG_ASN1D_STATES */
2738
2739
SECStatus
2740
SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
2741
                      const char *buf, unsigned long len)
2742
0
{
2743
0
    sec_asn1d_state *state = NULL;
2744
0
    unsigned long consumed;
2745
0
    SEC_ASN1EncodingPart what;
2746
0
    sec_asn1d_state *stateEnd = cx->current;
2747
0
2748
0
    if (cx->status == needBytes)
2749
0
        cx->status = keepGoing;
2750
0
2751
0
    while (cx->status == keepGoing) {
2752
0
        state = cx->current;
2753
0
        what = SEC_ASN1_Contents;
2754
0
        consumed = 0;
2755
#ifdef DEBUG_ASN1D_STATES
2756
        printf("\nPLACE = %s, next byte = 0x%02x, %p[%lu]\n",
2757
               (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)",
2758
               len ? (unsigned int)((unsigned char *)buf)[consumed] : 0,
2759
               buf, consumed);
2760
        dump_states(cx);
2761
#endif /* DEBUG_ASN1D_STATES */
2762
        switch (state->place) {
2763
0
            case beforeIdentifier:
2764
0
                consumed = sec_asn1d_parse_identifier(state, buf, len);
2765
0
                what = SEC_ASN1_Identifier;
2766
0
                break;
2767
0
            case duringIdentifier:
2768
0
                consumed = sec_asn1d_parse_more_identifier(state, buf, len);
2769
0
                what = SEC_ASN1_Identifier;
2770
0
                break;
2771
0
            case afterIdentifier:
2772
0
                sec_asn1d_confirm_identifier(state);
2773
0
                break;
2774
0
            case beforeLength:
2775
0
                consumed = sec_asn1d_parse_length(state, buf, len);
2776
0
                what = SEC_ASN1_Length;
2777
0
                break;
2778
0
            case duringLength:
2779
0
                consumed = sec_asn1d_parse_more_length(state, buf, len);
2780
0
                what = SEC_ASN1_Length;
2781
0
                break;
2782
0
            case afterLength:
2783
0
                sec_asn1d_prepare_for_contents(state);
2784
0
                break;
2785
0
            case beforeBitString:
2786
0
                consumed = sec_asn1d_parse_bit_string(state, buf, len);
2787
0
                break;
2788
0
            case duringBitString:
2789
0
                consumed = sec_asn1d_parse_more_bit_string(state, buf, len);
2790
0
                break;
2791
0
            case duringConstructedString:
2792
0
                sec_asn1d_next_substring(state);
2793
0
                break;
2794
0
            case duringGroup:
2795
0
                sec_asn1d_next_in_group(state);
2796
0
                break;
2797
0
            case duringLeaf:
2798
0
                consumed = sec_asn1d_parse_leaf(state, buf, len);
2799
0
                break;
2800
0
            case duringSaveEncoding:
2801
0
                sec_asn1d_reuse_encoding(state);
2802
0
                if (cx->status == decodeError) {
2803
0
                    /* recursive call has already popped all states from stack.
2804
0
                    ** Bail out quickly.
2805
0
                    */
2806
0
                    return SECFailure;
2807
0
                }
2808
0
                if (cx->status == needBytes) {
2809
0
                    /* recursive call wanted more data. Fatal. Clean up below. */
2810
0
                    PORT_SetError(SEC_ERROR_BAD_DER);
2811
0
                    cx->status = decodeError;
2812
0
                }
2813
0
                break;
2814
0
            case duringSequence:
2815
0
                sec_asn1d_next_in_sequence(state);
2816
0
                break;
2817
0
            case afterConstructedString:
2818
0
                sec_asn1d_concat_substrings(state);
2819
0
                break;
2820
0
            case afterExplicit:
2821
0
            case afterImplicit:
2822
0
            case afterInline:
2823
0
            case afterPointer:
2824
0
                sec_asn1d_absorb_child(state);
2825
0
                break;
2826
0
            case afterGroup:
2827
0
                sec_asn1d_concat_group(state);
2828
0
                break;
2829
0
            case afterSaveEncoding:
2830
0
                /* SEC_ASN1DecoderUpdate has called itself recursively to
2831
0
                ** decode SAVEd encoded data, and now is done decoding that.
2832
0
                ** Return to the calling copy of SEC_ASN1DecoderUpdate.
2833
0
                */
2834
0
                return SECSuccess;
2835
0
            case beforeEndOfContents:
2836
0
                sec_asn1d_prepare_for_end_of_contents(state);
2837
0
                break;
2838
0
            case duringEndOfContents:
2839
0
                consumed = sec_asn1d_parse_end_of_contents(state, buf, len);
2840
0
                what = SEC_ASN1_EndOfContents;
2841
0
                break;
2842
0
            case afterEndOfContents:
2843
0
                sec_asn1d_pop_state(state);
2844
0
                break;
2845
0
            case beforeChoice:
2846
0
                state = sec_asn1d_before_choice(state);
2847
0
                break;
2848
0
            case duringChoice:
2849
0
                state = sec_asn1d_during_choice(state);
2850
0
                break;
2851
0
            case afterChoice:
2852
0
                sec_asn1d_after_choice(state);
2853
0
                break;
2854
0
            case notInUse:
2855
0
            default:
2856
0
                /* This is not an error, but rather a plain old BUG! */
2857
0
                PORT_Assert(0);
2858
0
                PORT_SetError(SEC_ERROR_BAD_DER);
2859
0
                cx->status = decodeError;
2860
0
                break;
2861
0
        }
2862
0
2863
0
        if (cx->status == decodeError)
2864
0
            break;
2865
0
2866
0
        /* We should not consume more than we have.  */
2867
0
        PORT_Assert(consumed <= len);
2868
0
        if (consumed > len) {
2869
0
            PORT_SetError(SEC_ERROR_BAD_DER);
2870
0
            cx->status = decodeError;
2871
0
            break;
2872
0
        }
2873
0
2874
0
        /* It might have changed, so we have to update our local copy.  */
2875
0
        state = cx->current;
2876
0
2877
0
        /* If it is NULL, we have popped all the way to the top.  */
2878
0
        if (state == NULL) {
2879
0
            PORT_Assert(consumed == 0);
2880
#if 0 /* XXX I want this here, but it seems that we have situations (like \
2881
       * downloading a pkcs7 cert chain from some issuers) that give us a \
2882
       * length which is greater than the entire encoding.  So, we cannot \
2883
       * have this be an error.                                           \
2884
       */
2885
        if (len > 0) {
2886
        PORT_SetError (SEC_ERROR_BAD_DER);
2887
        cx->status = decodeError;
2888
        } else
2889
#endif
2890
            cx->status = allDone;
2891
0
            break;
2892
0
        } else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
2893
0
            cx->status = allDone;
2894
0
            break;
2895
0
        }
2896
0
2897
0
        if (consumed == 0)
2898
0
            continue;
2899
0
2900
0
        /*
2901
0
         * The following check is specifically looking for an ANY
2902
0
         * that is *not* also an INNER, because we need to save aside
2903
0
         * all bytes in that case -- the contents parts will get
2904
0
         * handled like all other contents, and the end-of-contents
2905
0
         * bytes are added by the concat code, but the outer header
2906
0
         * bytes need to get saved too, so we do them explicitly here.
2907
0
         */
2908
0
        if (state->underlying_kind == SEC_ASN1_ANY && !cx->filter_only && (what == SEC_ASN1_Identifier || what == SEC_ASN1_Length)) {
2909
0
            sec_asn1d_record_any_header(state, buf, consumed);
2910
0
        }
2911
0
2912
0
        /*
2913
0
         * We had some number of good, accepted bytes.  If the caller
2914
0
         * has registered to see them, pass them along.
2915
0
         */
2916
0
        if (state->top->filter_proc != NULL) {
2917
0
            int depth;
2918
0
2919
0
            depth = state->depth;
2920
0
            if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
2921
0
                PORT_Assert(state->parent != NULL && state->parent->indefinite);
2922
0
                depth--;
2923
0
                PORT_Assert(depth == state->parent->depth);
2924
0
            }
2925
0
            (*state->top->filter_proc)(state->top->filter_arg,
2926
0
                                       buf, consumed, depth, what);
2927
0
        }
2928
0
2929
0
        state->consumed += consumed;
2930
0
        buf += consumed;
2931
0
        len -= consumed;
2932
0
    }
2933
0
2934
0
    if (cx->status == decodeError) {
2935
0
        while (state != NULL && stateEnd->parent != state) {
2936
0
            sec_asn1d_free_child(state, PR_TRUE);
2937
0
            state = state->parent;
2938
0
        }
2939
#ifdef SEC_ASN1D_FREE_ON_ERROR /*                                           \
2940
                                * XXX This does not work because we can     \
2941
                                * end up leaving behind dangling pointers   \
2942
                                * to stuff that was allocated.  In order    \
2943
                                * to make this really work (which would     \
2944
                                * be a good thing, I think), we need to     \
2945
                                * keep track of every place/pointer that    \
2946
                                * was allocated and make sure to NULL it    \
2947
                                * out before we then free back to the mark. \
2948
                                */
2949
        if (cx->their_pool != NULL) {
2950
            PORT_Assert(cx->their_mark != NULL);
2951
            PORT_ArenaRelease(cx->their_pool, cx->their_mark);
2952
            cx->their_mark = NULL;
2953
        }
2954
#endif
2955
        return SECFailure;
2956
0
    }
2957
0
2958
#if 0 /* XXX This is what I want, but cannot have because it seems we    \
2959
       * have situations (like when downloading a pkcs7 cert chain from  \
2960
       * some issuers) that give us a total length which is greater than \
2961
       * the entire encoding.  So, we have to allow allDone to have a    \
2962
       * remaining length greater than zero.  I wanted to catch internal \
2963
       * bugs with this, noticing when we do not have the right length.  \
2964
       * Oh well.                                                        \
2965
       */
2966
    PORT_Assert (len == 0
2967
         && (cx->status == needBytes || cx->status == allDone));
2968
#else
2969
0
    PORT_Assert((len == 0 && cx->status == needBytes) || cx->status == allDone);
2970
0
#endif
2971
0
    return SECSuccess;
2972
0
}
2973
2974
SECStatus
2975
SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx)
2976
0
{
2977
0
    SECStatus rv;
2978
0
2979
0
    if (!cx || cx->status == needBytes) {
2980
0
        PORT_SetError(SEC_ERROR_BAD_DER);
2981
0
        rv = SECFailure;
2982
0
    } else {
2983
0
        rv = SECSuccess;
2984
0
    }
2985
0
2986
0
    /*
2987
0
     * XXX anything else that needs to be finished?
2988
0
     */
2989
0
2990
0
    if (cx) {
2991
0
        PORT_FreeArena(cx->our_pool, PR_TRUE);
2992
0
    }
2993
0
2994
0
    return rv;
2995
0
}
2996
2997
SEC_ASN1DecoderContext *
2998
SEC_ASN1DecoderStart(PLArenaPool *their_pool, void *dest,
2999
                     const SEC_ASN1Template *theTemplate)
3000
0
{
3001
0
    PLArenaPool *our_pool;
3002
0
    SEC_ASN1DecoderContext *cx;
3003
0
3004
0
    our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
3005
0
    if (our_pool == NULL)
3006
0
        return NULL;
3007
0
3008
0
    cx = (SEC_ASN1DecoderContext *)PORT_ArenaZAlloc(our_pool, sizeof(*cx));
3009
0
    if (cx == NULL) {
3010
0
        PORT_FreeArena(our_pool, PR_FALSE);
3011
0
        return NULL;
3012
0
    }
3013
0
3014
0
    cx->our_pool = our_pool;
3015
0
    if (their_pool != NULL) {
3016
0
        cx->their_pool = their_pool;
3017
#ifdef SEC_ASN1D_FREE_ON_ERROR
3018
        cx->their_mark = PORT_ArenaMark(their_pool);
3019
#endif
3020
    }
3021
0
3022
0
    cx->status = needBytes;
3023
0
3024
0
    if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL || sec_asn1d_init_state_based_on_template(cx->current) == NULL) {
3025
0
        /*
3026
0
         * Trouble initializing (probably due to failed allocations)
3027
0
         * requires that we just give up.
3028
0
         */
3029
0
        PORT_FreeArena(our_pool, PR_FALSE);
3030
0
        return NULL;
3031
0
    }
3032
0
3033
0
    return cx;
3034
0
}
3035
3036
void
3037
SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx,
3038
                             SEC_ASN1WriteProc fn, void *arg,
3039
                             PRBool only)
3040
0
{
3041
0
    /* check that we are "between" fields here */
3042
0
    PORT_Assert(cx->during_notify);
3043
0
3044
0
    cx->filter_proc = fn;
3045
0
    cx->filter_arg = arg;
3046
0
    cx->filter_only = only;
3047
0
}
3048
3049
void
3050
SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx)
3051
0
{
3052
0
    /* check that we are "between" fields here */
3053
0
    PORT_Assert(cx->during_notify);
3054
0
3055
0
    cx->filter_proc = NULL;
3056
0
    cx->filter_arg = NULL;
3057
0
    cx->filter_only = PR_FALSE;
3058
0
}
3059
3060
void
3061
SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx,
3062
                             SEC_ASN1NotifyProc fn, void *arg)
3063
0
{
3064
0
    cx->notify_proc = fn;
3065
0
    cx->notify_arg = arg;
3066
0
}
3067
3068
void
3069
SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx)
3070
0
{
3071
0
    cx->notify_proc = NULL;
3072
0
    cx->notify_arg = NULL; /* not necessary; just being clean */
3073
0
}
3074
3075
void
3076
SEC_ASN1DecoderSetMaximumElementSize(SEC_ASN1DecoderContext *cx,
3077
                                     unsigned long max_size)
3078
0
{
3079
0
    cx->max_element_size = max_size;
3080
0
}
3081
3082
void
3083
SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
3084
0
{
3085
0
    PORT_Assert(cx);
3086
0
    PORT_SetError(error);
3087
0
    cx->status = decodeError;
3088
0
}
3089
3090
SECStatus
3091
SEC_ASN1Decode(PLArenaPool *poolp, void *dest,
3092
               const SEC_ASN1Template *theTemplate,
3093
               const char *buf, long len)
3094
0
{
3095
0
    SEC_ASN1DecoderContext *dcx;
3096
0
    SECStatus urv, frv;
3097
0
3098
0
    dcx = SEC_ASN1DecoderStart(poolp, dest, theTemplate);
3099
0
    if (dcx == NULL)
3100
0
        return SECFailure;
3101
0
3102
0
    /* In one-shot mode, there's no possibility of streaming data beyond the
3103
0
     * length of len */
3104
0
    SEC_ASN1DecoderSetMaximumElementSize(dcx, len);
3105
0
3106
0
    urv = SEC_ASN1DecoderUpdate(dcx, buf, len);
3107
0
    frv = SEC_ASN1DecoderFinish(dcx);
3108
0
3109
0
    if (urv != SECSuccess)
3110
0
        return urv;
3111
0
3112
0
    return frv;
3113
0
}
3114
3115
SECStatus
3116
SEC_ASN1DecodeItem(PLArenaPool *poolp, void *dest,
3117
                   const SEC_ASN1Template *theTemplate,
3118
                   const SECItem *src)
3119
0
{
3120
0
    return SEC_ASN1Decode(poolp, dest, theTemplate,
3121
0
                          (const char *)src->data, src->len);
3122
0
}
3123
3124
#ifdef DEBUG_ASN1D_STATES
3125
void
3126
sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
3127
{
3128
    printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
3129
    fflush(stdout);
3130
}
3131
#endif
3132
3133
/*
3134
 * Generic templates for individual/simple items and pointers to
3135
 * and sets of same.
3136
 *
3137
 * If you need to add a new one, please note the following:
3138
 *   - For each new basic type you should add *four* templates:
3139
 *  one plain, one PointerTo, one SequenceOf and one SetOf.
3140
 *   - If the new type can be constructed (meaning, it is a
3141
 *  *string* type according to BER/DER rules), then you should
3142
 *  or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
3143
 *  See the definition of the OctetString template for an example.
3144
 *   - It may not be obvious, but these are in *alphabetical*
3145
 *  order based on the SEC_ASN1_XXX name; so put new ones in
3146
 *  the appropriate place.
3147
 */
3148
3149
const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
3150
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
3151
};
3152
3153
#if 0
3154
3155
const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
3156
    { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
3157
};
3158
3159
const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
3160
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
3161
};
3162
3163
const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
3164
    { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
3165
};
3166
3167
const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
3168
    { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
3169
};
3170
3171
const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
3172
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
3173
};
3174
3175
const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
3176
    { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
3177
};
3178
3179
const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
3180
    { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
3181
};
3182
3183
const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
3184
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
3185
};
3186
3187
const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
3188
    { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
3189
};
3190
3191
#endif
3192
3193
const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
3194
    { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
3195
};
3196
3197
const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
3198
    { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
3199
};
3200
3201
#if 0
3202
3203
const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
3204
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
3205
};
3206
3207
#endif
3208
3209
const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
3210
    { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
3211
};
3212
3213
const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
3214
    { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
3215
};
3216
3217
#if 0
3218
3219
const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
3220
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
3221
};
3222
3223
const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
3224
    { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
3225
};
3226
3227
const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
3228
    { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
3229
};
3230
3231
const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
3232
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
3233
};
3234
3235
const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
3236
    { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
3237
};
3238
3239
const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
3240
    { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
3241
};
3242
3243
const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
3244
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
3245
};
3246
3247
const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
3248
    { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
3249
};
3250
3251
const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
3252
    { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
3253
};
3254
3255
const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
3256
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
3257
};
3258
3259
const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
3260
    { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
3261
};
3262
3263
const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
3264
    { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
3265
};
3266
3267
#endif
3268
3269
const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
3270
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
3271
};
3272
3273
#if 0
3274
3275
const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
3276
    { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
3277
};
3278
3279
const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
3280
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
3281
};
3282
3283
const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
3284
    { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
3285
};
3286
3287
#endif
3288
3289
const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
3290
    { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3291
};
3292
3293
#if 0
3294
3295
const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
3296
    { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
3297
};
3298
3299
const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
3300
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
3301
};
3302
3303
const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
3304
    { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
3305
};
3306
3307
#endif
3308
3309
const SEC_ASN1Template SEC_T61StringTemplate[] = {
3310
    { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3311
};
3312
3313
#if 0
3314
3315
const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
3316
    { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
3317
};
3318
3319
const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
3320
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
3321
};
3322
3323
const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
3324
    { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
3325
};
3326
3327
#endif
3328
3329
const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
3330
    { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3331
};
3332
3333
#if 0
3334
3335
const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
3336
    { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
3337
};
3338
3339
const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
3340
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
3341
};
3342
3343
const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
3344
    { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
3345
};
3346
3347
const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
3348
    { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
3349
};
3350
3351
const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
3352
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
3353
};
3354
3355
const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
3356
    { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
3357
};
3358
3359
const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
3360
    { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
3361
};
3362
3363
const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
3364
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
3365
};
3366
3367
const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
3368
    { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
3369
};
3370
3371
#endif
3372
3373
const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
3374
    { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3375
};
3376
3377
#if 0
3378
3379
const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
3380
    { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
3381
};
3382
3383
const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
3384
    { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
3385
};
3386
3387
const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
3388
    { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
3389
};
3390
3391
#endif
3392
3393
/*
3394
 * Template for skipping a subitem.
3395
 *
3396
 * Note that it only makes sense to use this for decoding (when you want
3397
 * to decode something where you are only interested in one or two of
3398
 * the fields); you cannot encode a SKIP!
3399
 */
3400
const SEC_ASN1Template SEC_SkipTemplate[] = {
3401
    { SEC_ASN1_SKIP }
3402
};
3403
3404
/* These functions simply return the address of the above-declared templates.
3405
** This is necessary for Windows DLLs.  Sigh.
3406
*/
3407
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_EnumeratedTemplate)
3408
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToEnumeratedTemplate)
3409
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfAnyTemplate)
3410
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfObjectIDTemplate)
3411
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SkipTemplate)
3412
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate)
3413
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate)
3414
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate)
3415
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate)