1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
41
der_indefinite_length(unsigned char *buf, unsigned char *end)
43
uint32 len, ret, dataLen;
44
unsigned char tag, lenCode;
49
if ((buf + 2) > end) {
57
if ( ( tag == 0 ) && ( lenCode == 0 ) ) {
61
if ( lenCode == 0x80 ) { /* indefinite length */
62
ret = der_indefinite_length(buf, end); /* recurse to find length */
67
} else { /* definite length */
69
/* Length of data is in multibyte format */
70
dataLenLen = lenCode & 0x7f;
76
dataLen = (buf[0]<<8)|buf[1];
79
dataLen = ((unsigned long)buf[0]<<16)|(buf[1]<<8)|buf[2];
82
dataLen = ((unsigned long)buf[0]<<24)|
83
((unsigned long)buf[1]<<16)|(buf[2]<<8)|buf[3];
86
PORT_SetError(SEC_ERROR_BAD_DER);
90
/* Length of data is in single byte */
96
buf = buf + dataLenLen + dataLen;
97
len = len + dataLenLen + dataLen;
103
** Capture the next thing in the buffer.
104
** Returns the length of the header and the length of the contents.
107
der_capture(unsigned char *buf, unsigned char *end,
108
int *header_len_p, uint32 *contents_len_p)
111
unsigned char whole_tag;
115
if ((buf + 2) > end) {
125
/* Get tag and verify that it is ok. */
127
tag_number = whole_tag & DER_TAGNUM_MASK;
130
* XXX This code does not (yet) handle the high-tag-number form!
132
if (tag_number == DER_HIGH_TAG_NUMBER) {
133
PORT_SetError(SEC_ERROR_BAD_DER);
137
if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) {
138
/* Check that the universal tag number is one we implement. */
139
switch (tag_number) {
143
case DER_OCTET_STRING:
148
case DER_PRINTABLE_STRING:
151
case DER_VISIBLE_STRING:
153
case 0: /* end-of-contents tag */
156
PORT_SetError(SEC_ERROR_BAD_DER);
162
* Get first byte of length code (might contain entire length, might not).
164
contents_len = *bp++;
167
* If the high bit is set, then the length is in multibyte format,
168
* or the thing has an indefinite-length.
170
if (contents_len & 0x80) {
171
int bytes_of_encoded_len;
173
bytes_of_encoded_len = contents_len & 0x7f;
176
switch (bytes_of_encoded_len) {
178
contents_len |= *bp++;
182
contents_len |= *bp++;
186
contents_len |= *bp++;
190
contents_len |= *bp++;
194
contents_len = der_indefinite_length (bp, end);
199
PORT_SetError(SEC_ERROR_BAD_DER);
204
if ((bp + contents_len) > end) {
205
/* Ran past end of buffer */
206
PORT_SetError(SEC_ERROR_BAD_DER);
210
*header_len_p = bp - buf;
211
*contents_len_p = contents_len;
216
static unsigned char *
217
der_decode(PRArenaPool *arena, void *dest, DERTemplate *dtemplate,
218
unsigned char *buf, int header_len, uint32 contents_len)
220
unsigned char *orig_buf, *end;
221
unsigned long encode_kind, under_kind;
222
PRBool explicit, optional, universal, check_tag;
225
PRBool indefinite_length, explicit_indefinite_length;
227
encode_kind = dtemplate->kind;
228
explicit = (encode_kind & DER_EXPLICIT) ? PR_TRUE : PR_FALSE;
229
optional = (encode_kind & DER_OPTIONAL) ? PR_TRUE : PR_FALSE;
230
universal = ((encode_kind & DER_CLASS_MASK) == DER_UNIVERSAL)
231
? PR_TRUE : PR_FALSE;
233
PORT_Assert (!(explicit && universal)); /* bad templates */
235
if (header_len == 0) {
236
if (optional || (encode_kind & DER_ANY))
238
PORT_SetError(SEC_ERROR_BAD_DER);
242
if (encode_kind & DER_POINTER) {
243
void *place, **placep;
246
if (dtemplate->sub != NULL) {
247
dtemplate = dtemplate->sub;
248
under_kind = dtemplate->kind;
250
encode_kind = under_kind;
252
place = PORT_ArenaZAlloc(arena, dtemplate->arg);
253
offset = dtemplate->offset;
256
under_kind = encode_kind & ~DER_POINTER;
258
under_kind = dtemplate->arg;
260
place = PORT_ArenaZAlloc(arena, sizeof(SECItem));
264
PORT_SetError(SEC_ERROR_NO_MEMORY);
265
return NULL; /* Out of memory */
267
placep = (void **)dest;
269
dest = (void *)((char *)place + offset);
270
} else if (encode_kind & DER_INLINE) {
271
PORT_Assert (dtemplate->sub != NULL);
272
dtemplate = dtemplate->sub;
273
under_kind = dtemplate->kind;
275
encode_kind = under_kind;
277
dest = (void *)((char *)dest + dtemplate->offset);
278
} else if (universal) {
279
under_kind = encode_kind;
281
under_kind = dtemplate->arg;
285
end = buf + header_len + contents_len;
287
explicit_indefinite_length = PR_FALSE;
291
* This tag is expected to match exactly.
292
* (The template has all of the bits specified.)
294
if (*buf != (encode_kind & DER_TAG_MASK)) {
297
PORT_SetError(SEC_ERROR_BAD_DER);
300
if ((header_len == 2) && (*(buf + 1) == 0x80))
301
explicit_indefinite_length = PR_TRUE;
303
rv = der_capture (buf, end, &header_len, &contents_len);
304
if (rv != SECSuccess)
306
if (header_len == 0) { /* XXX is this right? */
307
PORT_SetError(SEC_ERROR_BAD_DER);
310
optional = PR_FALSE; /* can no longer be optional */
311
encode_kind = under_kind;
315
if (encode_kind & (DER_DERPTR | DER_ANY | DER_FORCE | DER_SKIP)) {
316
PORT_Assert ((encode_kind & DER_ANY) || !optional);
317
encode_kind = encode_kind & (~DER_FORCE);
318
under_kind = under_kind & (~DER_FORCE);
319
check_tag = PR_FALSE;
324
unsigned char expect_tag, expect_num;
327
* This tag is expected to match, but the simple types
328
* may or may not have the constructed bit set, so we
329
* have to have all this extra logic.
332
expect_tag = (unsigned char)encode_kind & DER_TAG_MASK;
333
expect_num = expect_tag & DER_TAGNUM_MASK;
334
if (expect_num == DER_SET || expect_num == DER_SEQUENCE) {
335
if (*buf == (expect_tag | DER_CONSTRUCTED))
338
if (*buf == expect_tag)
340
else if (*buf == (expect_tag | DER_CONSTRUCTED))
346
PORT_SetError(SEC_ERROR_BAD_DER);
351
if (under_kind & DER_DERPTR) {
352
item = (SECItem *)dest;
353
if (under_kind & DER_OUTER) {
355
item->len = header_len + contents_len;
357
item->data = buf + header_len;
358
item->len = contents_len;
363
if (encode_kind & DER_ANY) {
364
contents_len += header_len;
368
if ((header_len == 2) && (*(buf + 1) == 0x80))
369
indefinite_length = PR_TRUE;
371
indefinite_length = PR_FALSE;
375
if (contents_len == 0)
378
under_kind &= ~DER_OPTIONAL;
380
if (under_kind & DER_INDEFINITE) {
381
int count, thing_size;
382
unsigned char *sub_buf;
384
void *things, **indp, ***placep;
386
under_kind &= ~DER_INDEFINITE;
393
while (sub_buf < end) {
394
if (indefinite_length && sub_buf[0] == 0 && sub_buf[1] == 0) {
397
rv = der_capture (sub_buf, end, &header_len, &contents_len);
398
if (rv != SECSuccess)
401
sub_buf += header_len + contents_len;
405
* Allocate an array of pointers to items; extra one is for a NULL.
407
indp = (void**)PORT_ArenaZAlloc(arena, (count + 1) * sizeof(void *));
409
PORT_SetError(SEC_ERROR_NO_MEMORY);
416
if (under_kind == DER_SET || under_kind == DER_SEQUENCE) {
417
tmpt = dtemplate->sub;
418
PORT_Assert (tmpt != NULL);
419
thing_size = tmpt->arg;
420
PORT_Assert (thing_size != 0);
423
thing_size = sizeof(SECItem);
427
* Allocate the items themselves.
429
things = PORT_ArenaZAlloc(arena, count * thing_size);
430
if (things == NULL) {
431
PORT_SetError(SEC_ERROR_NO_MEMORY);
435
placep = (void ***)dest;
439
/* ignore return value because we already did whole thing above */
440
(void) der_capture (buf, end, &header_len, &contents_len);
444
sub_thing = (void *)((char *)things + tmpt->offset);
445
buf = der_decode (arena, sub_thing, tmpt,
446
buf, header_len, contents_len);
450
item = (SECItem *)things;
451
if (under_kind == DER_ANY) {
452
contents_len += header_len;
456
if (under_kind == DER_BIT_STRING) {
457
item->data = buf + 1;
458
item->len = ((contents_len - 1) << 3) - *buf;
461
item->len = contents_len;
466
things = (void *)((char *)things + thing_size);
472
goto der_decode_done;
475
switch (under_kind) {
482
for (tmpt = dtemplate + 1; tmpt->kind; tmpt++) {
483
sub_dest = (void *)((char *)dest + tmpt->offset);
484
rv = der_capture (buf, end, &header_len, &contents_len);
485
if (rv != SECSuccess)
487
buf = der_decode (arena, sub_dest, tmpt,
488
buf, header_len, contents_len);
496
item = (SECItem *)dest;
497
item->data = buf + 1;
498
item->len = ((contents_len - 1) << 3) - *buf;
507
item = (SECItem *)dest;
509
item->len = contents_len;
516
if (indefinite_length && buf[0] == 0 && buf[1] == 0) {
520
if (explicit_indefinite_length && buf[0] == 0 && buf[1] == 0) {
528
DER_Decode(PRArenaPool *arena, void *dest, DERTemplate *dtemplate, SECItem *src)
531
uint32 buf_len, contents_len;
538
rv = der_capture (buf, buf + buf_len, &header_len, &contents_len);
539
if (rv != SECSuccess)
542
dest = (void *)((char *)dest + dtemplate->offset);
543
buf = der_decode (arena, dest, dtemplate, buf, header_len, contents_len);
551
DER_Lengths(SECItem *item, int *header_len_p, uint32 *contents_len_p)
553
return(der_capture(item->data, &item->data[item->len], header_len_p,