Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/util/dersubr.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 <limits.h>
7
#include "secerr.h"
8
9
int
10
DER_LengthLength(PRUint32 len)
11
225k
{
12
225k
    if (len > 127) {
13
137
        if (len > 255) {
14
56
            if (len > 65535L) {
15
0
                if (len > 16777215L) {
16
0
                    return 5;
17
0
                } else {
18
0
                    return 4;
19
0
                }
20
56
            } else {
21
56
                return 3;
22
56
            }
23
81
        } else {
24
81
            return 2;
25
81
        }
26
225k
    } else {
27
225k
        return 1;
28
225k
    }
29
225k
}
30
31
unsigned char *
32
DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len)
33
100k
{
34
100k
    unsigned char b[4];
35
36
100k
    b[0] = (unsigned char)(len >> 24);
37
100k
    b[1] = (unsigned char)(len >> 16);
38
100k
    b[2] = (unsigned char)(len >> 8);
39
100k
    b[3] = (unsigned char)len;
40
100k
    if ((code & DER_TAGNUM_MASK) == DER_SET || (code & DER_TAGNUM_MASK) == DER_SEQUENCE)
41
31.2k
        code |= DER_CONSTRUCTED;
42
100k
    *buf++ = code;
43
100k
    if (len > 127) {
44
137
        if (len > 255) {
45
56
            if (len > 65535) {
46
0
                if (len > 16777215) {
47
0
                    *buf++ = 0x84;
48
0
                    *buf++ = b[0];
49
0
                    *buf++ = b[1];
50
0
                    *buf++ = b[2];
51
0
                    *buf++ = b[3];
52
0
                } else {
53
0
                    *buf++ = 0x83;
54
0
                    *buf++ = b[1];
55
0
                    *buf++ = b[2];
56
0
                    *buf++ = b[3];
57
0
                }
58
56
            } else {
59
56
                *buf++ = 0x82;
60
56
                *buf++ = b[2];
61
56
                *buf++ = b[3];
62
56
            }
63
81
        } else {
64
81
            *buf++ = 0x81;
65
81
            *buf++ = b[3];
66
81
        }
67
100k
    } else {
68
100k
        *buf++ = b[3];
69
100k
    }
70
100k
    return buf;
71
100k
}
72
73
/*
74
 * XXX This should be rewritten, generalized, to take a long instead
75
 * of a PRInt32.
76
 */
77
SECStatus
78
DER_SetInteger(PLArenaPool *arena, SECItem *it, PRInt32 i)
79
0
{
80
0
    unsigned char bb[4];
81
0
    unsigned len;
82
83
0
    bb[0] = (unsigned char)(i >> 24);
84
0
    bb[1] = (unsigned char)(i >> 16);
85
0
    bb[2] = (unsigned char)(i >> 8);
86
0
    bb[3] = (unsigned char)(i);
87
88
    /*
89
    ** Small integers are encoded in a single byte. Larger integers
90
    ** require progressively more space.
91
    */
92
0
    if (i < -128) {
93
0
        if (i < -32768L) {
94
0
            if (i < -8388608L) {
95
0
                len = 4;
96
0
            } else {
97
0
                len = 3;
98
0
            }
99
0
        } else {
100
0
            len = 2;
101
0
        }
102
0
    } else if (i > 127) {
103
0
        if (i > 32767L) {
104
0
            if (i > 8388607L) {
105
0
                len = 4;
106
0
            } else {
107
0
                len = 3;
108
0
            }
109
0
        } else {
110
0
            len = 2;
111
0
        }
112
0
    } else {
113
0
        len = 1;
114
0
    }
115
0
    it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
116
0
    if (!it->data) {
117
0
        return SECFailure;
118
0
    }
119
0
    it->len = len;
120
0
    PORT_Memcpy(it->data, bb + (4 - len), len);
121
0
    return SECSuccess;
122
0
}
123
124
/*
125
 * XXX This should be rewritten, generalized, to take an unsigned long instead
126
 * of a PRUint32.
127
 */
128
SECStatus
129
DER_SetUInteger(PLArenaPool *arena, SECItem *it, PRUint32 ui)
130
79.6k
{
131
79.6k
    unsigned char bb[5];
132
79.6k
    int len;
133
134
79.6k
    bb[0] = 0;
135
79.6k
    bb[1] = (unsigned char)(ui >> 24);
136
79.6k
    bb[2] = (unsigned char)(ui >> 16);
137
79.6k
    bb[3] = (unsigned char)(ui >> 8);
138
79.6k
    bb[4] = (unsigned char)(ui);
139
140
    /*
141
    ** Small integers are encoded in a single byte. Larger integers
142
    ** require progressively more space.
143
    */
144
79.6k
    if (ui > 0x7f) {
145
0
        if (ui > 0x7fff) {
146
0
            if (ui > 0x7fffffL) {
147
0
                if (ui >= 0x80000000L) {
148
0
                    len = 5;
149
0
                } else {
150
0
                    len = 4;
151
0
                }
152
0
            } else {
153
0
                len = 3;
154
0
            }
155
0
        } else {
156
0
            len = 2;
157
0
        }
158
79.6k
    } else {
159
79.6k
        len = 1;
160
79.6k
    }
161
162
79.6k
    it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
163
79.6k
    if (it->data == NULL) {
164
0
        return SECFailure;
165
0
    }
166
167
79.6k
    it->len = len;
168
79.6k
    PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
169
170
79.6k
    return SECSuccess;
171
79.6k
}
172
173
/*
174
** Convert a der encoded *signed* integer into a machine integral value.
175
** If an underflow/overflow occurs, sets error code and returns min/max.
176
*/
177
long
178
DER_GetInteger(const SECItem *it)
179
9.33k
{
180
9.33k
    unsigned long ival;
181
9.33k
    PRBool negative;
182
9.33k
    unsigned int len = it->len;
183
9.33k
    unsigned char *cp = it->data;
184
9.33k
    size_t lsize = sizeof(ival);
185
186
9.33k
    PORT_Assert(len);
187
9.33k
    if (!len) {
188
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
189
0
        return 0;
190
0
    }
191
192
9.33k
    negative = (PRBool)(*cp & 0x80);
193
9.33k
    ival = negative ? ~0 : 0;
194
195
    /* Ignore leading zeros/ones. */
196
10.2k
    while (len && *cp == (unsigned char)ival) {
197
929
        len--;
198
929
        cp++;
199
929
    }
200
201
    /* Check for overflow/underflow. */
202
9.33k
    if (len > lsize || (len == lsize && (*cp & 0x80) != negative)) {
203
3
        PORT_SetError(SEC_ERROR_BAD_DER);
204
3
        return negative ? LONG_MIN : LONG_MAX;
205
3
    }
206
207
18.1k
    while (len--) {
208
8.83k
        ival <<= 8;
209
8.83k
        ival |= *cp++;
210
8.83k
    }
211
212
9.33k
    return ival;
213
9.33k
}
214
215
/*
216
** Convert a der encoded *unsigned* integer into a machine integral value.
217
** If an overflow occurs, sets error code and returns max.
218
*/
219
unsigned long
220
DER_GetUInteger(SECItem *it)
221
0
{
222
0
    unsigned long ival = 0;
223
0
    unsigned len = it->len;
224
0
    unsigned char *cp = it->data;
225
0
    unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8);
226
227
0
    PORT_Assert(len);
228
0
    if (!len) {
229
0
        PORT_SetError(SEC_ERROR_INPUT_LEN);
230
0
        return 0;
231
0
    }
232
233
    /* Cannot put a negative value into an unsigned container. */
234
0
    if (*cp & 0x80) {
235
0
        PORT_SetError(SEC_ERROR_BAD_DER);
236
0
        return 0;
237
0
    }
238
239
0
    while (len) {
240
0
        if (ival & overflow) {
241
0
            PORT_SetError(SEC_ERROR_BAD_DER);
242
0
            return ULONG_MAX;
243
0
        }
244
0
        ival = ival << 8;
245
0
        ival |= *cp++;
246
0
        --len;
247
0
    }
248
0
    return ival;
249
0
}