Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/util/derdec.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
#include "secder.h"
6
#include "secerr.h"
7
8
static PRUint32
9
der_indefinite_length(unsigned char *buf, unsigned char *end)
10
0
{
11
0
    PRUint32 len, ret, dataLen;
12
0
    unsigned char tag, lenCode;
13
0
    int dataLenLen;
14
15
0
    len = 0;
16
0
    while (1) {
17
0
        if ((buf + 2) > end) {
18
0
            return (0);
19
0
        }
20
21
0
        tag = *buf++;
22
0
        lenCode = *buf++;
23
0
        len += 2;
24
25
0
        if ((tag == 0) && (lenCode == 0)) {
26
0
            return (len);
27
0
        }
28
29
0
        if (lenCode == 0x80) {                     /* indefinite length */
30
0
            ret = der_indefinite_length(buf, end); /* recurse to find length */
31
0
            if (ret == 0)
32
0
                return 0;
33
0
            len += ret;
34
0
            buf += ret;
35
0
        } else { /* definite length */
36
0
            if (lenCode & 0x80) {
37
                /* Length of data is in multibyte format */
38
0
                dataLenLen = lenCode & 0x7f;
39
0
                switch (dataLenLen) {
40
0
                    case 1:
41
0
                        dataLen = buf[0];
42
0
                        break;
43
0
                    case 2:
44
0
                        dataLen = (buf[0] << 8) | buf[1];
45
0
                        break;
46
0
                    case 3:
47
0
                        dataLen = ((unsigned long)buf[0] << 16) | (buf[1] << 8) | buf[2];
48
0
                        break;
49
0
                    case 4:
50
0
                        dataLen = ((unsigned long)buf[0] << 24) |
51
0
                                  ((unsigned long)buf[1] << 16) | (buf[2] << 8) | buf[3];
52
0
                        break;
53
0
                    default:
54
0
                        PORT_SetError(SEC_ERROR_BAD_DER);
55
0
                        return SECFailure;
56
0
                }
57
0
            } else {
58
                /* Length of data is in single byte */
59
0
                dataLen = lenCode;
60
0
                dataLenLen = 0;
61
0
            }
62
63
            /* skip this item */
64
0
            buf = buf + dataLenLen + dataLen;
65
0
            len = len + dataLenLen + dataLen;
66
0
        }
67
0
    }
68
0
}
69
70
/*
71
** Capture the next thing in the buffer.
72
** Returns the length of the header and the length of the contents.
73
*/
74
static SECStatus
75
der_capture(unsigned char *buf, unsigned char *end,
76
            int *header_len_p, PRUint32 *contents_len_p)
77
0
{
78
0
    unsigned char *bp;
79
0
    unsigned char whole_tag;
80
0
    PRUint32 contents_len;
81
0
    int tag_number;
82
83
0
    if ((buf + 2) > end) {
84
0
        *header_len_p = 0;
85
0
        *contents_len_p = 0;
86
0
        if (buf == end)
87
0
            return SECSuccess;
88
0
        return SECFailure;
89
0
    }
90
91
0
    bp = buf;
92
93
    /* Get tag and verify that it is ok. */
94
0
    whole_tag = *bp++;
95
0
    tag_number = whole_tag & DER_TAGNUM_MASK;
96
97
    /*
98
     * XXX This code does not (yet) handle the high-tag-number form!
99
     */
100
0
    if (tag_number == DER_HIGH_TAG_NUMBER) {
101
0
        PORT_SetError(SEC_ERROR_BAD_DER);
102
0
        return SECFailure;
103
0
    }
104
105
0
    if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
106
        /* Check that the universal tag number is one we implement.  */
107
0
        switch (tag_number) {
108
0
            case DER_BOOLEAN:
109
0
            case DER_INTEGER:
110
0
            case DER_BIT_STRING:
111
0
            case DER_OCTET_STRING:
112
0
            case DER_NULL:
113
0
            case DER_OBJECT_ID:
114
0
            case DER_SEQUENCE:
115
0
            case DER_SET:
116
0
            case DER_PRINTABLE_STRING:
117
0
            case DER_T61_STRING:
118
0
            case DER_IA5_STRING:
119
0
            case DER_VISIBLE_STRING:
120
0
            case DER_UTC_TIME:
121
0
            case 0: /* end-of-contents tag */
122
0
                break;
123
0
            default:
124
0
                PORT_SetError(SEC_ERROR_BAD_DER);
125
0
                return SECFailure;
126
0
        }
127
0
    }
128
129
    /*
130
     * Get first byte of length code (might contain entire length, might not).
131
     */
132
0
    contents_len = *bp++;
133
134
    /*
135
     * If the high bit is set, then the length is in multibyte format,
136
     * or the thing has an indefinite-length.
137
     */
138
0
    if (contents_len & 0x80) {
139
0
        int bytes_of_encoded_len;
140
141
0
        bytes_of_encoded_len = contents_len & 0x7f;
142
0
        contents_len = 0;
143
144
0
        switch (bytes_of_encoded_len) {
145
0
            case 4:
146
0
                contents_len |= *bp++;
147
0
                contents_len <<= 8;
148
            /* fallthru */
149
0
            case 3:
150
0
                contents_len |= *bp++;
151
0
                contents_len <<= 8;
152
            /* fallthru */
153
0
            case 2:
154
0
                contents_len |= *bp++;
155
0
                contents_len <<= 8;
156
            /* fallthru */
157
0
            case 1:
158
0
                contents_len |= *bp++;
159
0
                break;
160
161
0
            case 0:
162
0
                contents_len = der_indefinite_length(bp, end);
163
0
                if (contents_len)
164
0
                    break;
165
            /* fallthru */
166
0
            default:
167
0
                PORT_SetError(SEC_ERROR_BAD_DER);
168
0
                return SECFailure;
169
0
        }
170
0
    }
171
172
0
    if ((bp + contents_len) > end) {
173
        /* Ran past end of buffer */
174
0
        PORT_SetError(SEC_ERROR_BAD_DER);
175
0
        return SECFailure;
176
0
    }
177
178
0
    *header_len_p = (int)(bp - buf);
179
0
    *contents_len_p = contents_len;
180
181
0
    return SECSuccess;
182
0
}
183
184
SECStatus
185
DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p)
186
0
{
187
0
    return (der_capture(item->data, &item->data[item->len], header_len_p,
188
0
                        contents_len_p));
189
0
}