~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/util/nssb64d.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
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/
 
8
 *
 
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
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
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.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
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.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
 
 
37
/*
 
38
 * Base64 decoding (ascii to binary).
 
39
 *
 
40
 * $Id: nssb64d.c,v 1.6 2004/04/25 15:03:17 gerv%gerv.net Exp $
 
41
 */
 
42
 
 
43
#include "nssb64.h"
 
44
#include "nspr.h"
 
45
#include "secitem.h"
 
46
#include "secerr.h"
 
47
 
 
48
/*
 
49
 * XXX We want this basic support to go into NSPR (the PL part).
 
50
 * Until that can happen, the PL interface is going to be kept entirely
 
51
 * internal here -- all static functions and opaque data structures.
 
52
 * When someone can get it moved over into NSPR, that should be done:
 
53
 *    - giving everything names that are accepted by the NSPR module owners
 
54
 *      (though I tried to choose ones that would work without modification)
 
55
 *    - exporting the functions (remove static declarations and add
 
56
 *      PR_IMPLEMENT as necessary)
 
57
 *    - put prototypes into appropriate header file (probably replacing
 
58
 *      the entire current lib/libc/include/plbase64.h in NSPR)
 
59
 *      along with a typedef for the context structure (which should be
 
60
 *      kept opaque -- definition in the source file only, but typedef
 
61
 *      ala "typedef struct PLBase64FooStr PLBase64Foo;" in header file)
 
62
 *    - modify anything else as necessary to conform to NSPR required style
 
63
 *      (I looked but found no formatting guide to follow)
 
64
 *
 
65
 * You will want to move over everything from here down to the comment
 
66
 * which says "XXX End of base64 decoding code to be moved into NSPR",
 
67
 * into a new file in NSPR.
 
68
 */
 
69
 
 
70
/*
 
71
 **************************************************************
 
72
 * XXX Beginning of base64 decoding code to be moved into NSPR.
 
73
 */
 
74
 
 
75
/*
 
76
 * This typedef would belong in the NSPR header file (i.e. plbase64.h).
 
77
 */
 
78
typedef struct PLBase64DecoderStr PLBase64Decoder;
 
79
 
 
80
/*
 
81
 * The following implementation of base64 decoding was based on code
 
82
 * found in libmime (specifically, in mimeenc.c).  It has been adapted to
 
83
 * use PR types and naming as well as to provide other necessary semantics
 
84
 * (like buffer-in/buffer-out in addition to "streaming" without undue
 
85
 * performance hit of extra copying if you made the buffer versions
 
86
 * use the output_fn).  It also incorporates some aspects of the current
 
87
 * NSPR base64 decoding code.  As such, you may find similarities to
 
88
 * both of those implementations.  I tried to use names that reflected
 
89
 * the original code when possible.  For this reason you may find some
 
90
 * inconsistencies -- libmime used lots of "in" and "out" whereas the
 
91
 * NSPR version uses "src" and "dest"; sometimes I changed one to the other
 
92
 * and sometimes I left them when I thought the subroutines were at least
 
93
 * self-consistent.
 
94
 */
 
95
 
 
96
PR_BEGIN_EXTERN_C
 
97
 
 
98
/*
 
99
 * Opaque object used by the decoder to store state.
 
100
 */
 
101
struct PLBase64DecoderStr {
 
102
    /* Current token (or portion, if token_size < 4) being decoded. */
 
103
    unsigned char token[4];
 
104
    int token_size;
 
105
 
 
106
    /*
 
107
     * Where to write the decoded data (used when streaming, not when
 
108
     * doing all in-memory (buffer) operations).
 
109
     *
 
110
     * Note that this definition is chosen to be compatible with PR_Write.
 
111
     */
 
112
    PRInt32 (*output_fn) (void *output_arg, const unsigned char *buf,
 
113
                          PRInt32 size);
 
114
    void *output_arg;
 
115
 
 
116
    /*
 
117
     * Where the decoded output goes -- either temporarily (in the streaming
 
118
     * case, staged here before it goes to the output function) or what will
 
119
     * be the entire buffered result for users of the buffer version.
 
120
     */
 
121
    unsigned char *output_buffer;
 
122
    PRUint32 output_buflen;     /* the total length of allocated buffer */
 
123
    PRUint32 output_length;     /* the length that is currently populated */
 
124
};
 
125
 
 
126
PR_END_EXTERN_C
 
127
 
 
128
 
 
129
/*
 
130
 * Table to convert an ascii "code" to its corresponding binary value.
 
131
 * For ease of use, the binary values in the table are the actual values
 
132
 * PLUS ONE.  This is so that the special value of zero can denote an
 
133
 * invalid mapping; that was much easier than trying to fill in the other
 
134
 * values with some value other than zero, and to check for it.
 
135
 * Just remember to SUBTRACT ONE when using the value retrieved.
 
136
 */
 
137
static unsigned char base64_codetovaluep1[256] = {
 
138
/*   0: */        0,      0,      0,      0,      0,      0,      0,      0,
 
139
/*   8: */        0,      0,      0,      0,      0,      0,      0,      0,
 
140
/*  16: */        0,      0,      0,      0,      0,      0,      0,      0,
 
141
/*  24: */        0,      0,      0,      0,      0,      0,      0,      0,
 
142
/*  32: */        0,      0,      0,      0,      0,      0,      0,      0,
 
143
/*  40: */        0,      0,      0,     63,      0,      0,      0,     64,
 
144
/*  48: */       53,     54,     55,     56,     57,     58,     59,     60,
 
145
/*  56: */       61,     62,      0,      0,      0,      0,      0,      0,
 
146
/*  64: */        0,      1,      2,      3,      4,      5,      6,      7,
 
147
/*  72: */        8,      9,     10,     11,     12,     13,     14,     15,
 
148
/*  80: */       16,     17,     18,     19,     20,     21,     22,     23,
 
149
/*  88: */       24,     25,     26,      0,      0,      0,      0,      0,
 
150
/*  96: */        0,     27,     28,     29,     30,     31,     32,     33,
 
151
/* 104: */       34,     35,     36,     37,     38,     39,     40,     41,
 
152
/* 112: */       42,     43,     44,     45,     46,     47,     48,     49,
 
153
/* 120: */       50,     51,     52,      0,      0,      0,      0,      0,
 
154
/* 128: */        0,      0,      0,      0,      0,      0,      0,      0
 
155
/* and rest are all zero as well */
 
156
};
 
157
 
 
158
#define B64_PAD '='
 
159
 
 
160
 
 
161
/*
 
162
 * Reads 4; writes 3 (known, or expected, to have no trailing padding).
 
163
 * Returns bytes written; -1 on error (unexpected character).
 
164
 */
 
165
static int
 
166
pl_base64_decode_4to3 (const unsigned char *in, unsigned char *out)
 
167
{
 
168
    int j;
 
169
    PRUint32 num = 0;
 
170
    unsigned char bits;
 
171
 
 
172
    for (j = 0; j < 4; j++) {
 
173
        bits = base64_codetovaluep1[in[j]];
 
174
        if (bits == 0)
 
175
            return -1;
 
176
        num = (num << 6) | (bits - 1);
 
177
    }
 
178
 
 
179
    out[0] = (unsigned char) (num >> 16);
 
180
    out[1] = (unsigned char) ((num >> 8) & 0xFF);
 
181
    out[2] = (unsigned char) (num & 0xFF);
 
182
 
 
183
    return 3;
 
184
}
 
185
 
 
186
/*
 
187
 * Reads 3; writes 2 (caller already confirmed EOF or trailing padding).
 
188
 * Returns bytes written; -1 on error (unexpected character).
 
189
 */
 
190
static int
 
191
pl_base64_decode_3to2 (const unsigned char *in, unsigned char *out)
 
192
{
 
193
    PRUint32 num = 0;
 
194
    unsigned char bits1, bits2, bits3;
 
195
 
 
196
    bits1 = base64_codetovaluep1[in[0]];
 
197
    bits2 = base64_codetovaluep1[in[1]];
 
198
    bits3 = base64_codetovaluep1[in[2]];
 
199
 
 
200
    if ((bits1 == 0) || (bits2 == 0) || (bits3 == 0))
 
201
        return -1;
 
202
 
 
203
    num = ((PRUint32)(bits1 - 1)) << 10;
 
204
    num |= ((PRUint32)(bits2 - 1)) << 4;
 
205
    num |= ((PRUint32)(bits3 - 1)) >> 2;
 
206
 
 
207
    out[0] = (unsigned char) (num >> 8);
 
208
    out[1] = (unsigned char) (num & 0xFF);
 
209
 
 
210
    return 2;
 
211
}
 
212
 
 
213
/*
 
214
 * Reads 2; writes 1 (caller already confirmed EOF or trailing padding).
 
215
 * Returns bytes written; -1 on error (unexpected character).
 
216
 */
 
217
static int
 
218
pl_base64_decode_2to1 (const unsigned char *in, unsigned char *out)
 
219
{
 
220
    PRUint32 num = 0;
 
221
    unsigned char bits1, bits2;
 
222
 
 
223
    bits1 = base64_codetovaluep1[in[0]];
 
224
    bits2 = base64_codetovaluep1[in[1]];
 
225
 
 
226
    if ((bits1 == 0) || (bits2 == 0))
 
227
        return -1;
 
228
 
 
229
    num = ((PRUint32)(bits1 - 1)) << 2;
 
230
    num |= ((PRUint32)(bits2 - 1)) >> 4;
 
231
 
 
232
    out[0] = (unsigned char) num;
 
233
 
 
234
    return 1;
 
235
}
 
236
 
 
237
/*
 
238
 * Reads 4; writes 0-3.  Returns bytes written or -1 on error.
 
239
 * (Writes less than 3 only at (presumed) EOF.)
 
240
 */
 
241
static int
 
242
pl_base64_decode_token (const unsigned char *in, unsigned char *out)
 
243
{
 
244
    if (in[3] != B64_PAD)
 
245
        return pl_base64_decode_4to3 (in, out);
 
246
 
 
247
    if (in[2] == B64_PAD)
 
248
        return pl_base64_decode_2to1 (in, out);
 
249
 
 
250
    return pl_base64_decode_3to2 (in, out);
 
251
}
 
252
 
 
253
static PRStatus
 
254
pl_base64_decode_buffer (PLBase64Decoder *data, const unsigned char *in,
 
255
                         PRUint32 length)
 
256
{
 
257
    unsigned char *out = data->output_buffer;
 
258
    unsigned char *token = data->token;
 
259
    int i, n = 0;
 
260
 
 
261
    i = data->token_size;
 
262
    data->token_size = 0;
 
263
 
 
264
    while (length > 0) {
 
265
        while (i < 4 && length > 0) {
 
266
            /*
 
267
             * XXX Note that the following simply ignores any unexpected
 
268
             * characters.  This is exactly what the original code in
 
269
             * libmime did, and I am leaving it.  We certainly want to skip
 
270
             * over whitespace (we must); this does much more than that.
 
271
             * I am not confident changing it, and I don't want to slow
 
272
             * the processing down doing more complicated checking, but
 
273
             * someone else might have different ideas in the future.
 
274
             */
 
275
            if (base64_codetovaluep1[*in] > 0 || *in == B64_PAD)
 
276
                token[i++] = *in;
 
277
            in++;
 
278
            length--;
 
279
        }
 
280
 
 
281
        if (i < 4) {
 
282
            /* Didn't get enough for a complete token. */
 
283
            data->token_size = i;
 
284
            break;
 
285
        }
 
286
        i = 0;
 
287
 
 
288
        PR_ASSERT((out - data->output_buffer + 3) <= data->output_buflen);
 
289
 
 
290
        /*
 
291
         * Assume we are not at the end; the following function only works
 
292
         * for an internal token (no trailing padding characters) but is
 
293
         * faster that way.  If it hits an invalid character (padding) it
 
294
         * will return an error; we break out of the loop and try again
 
295
         * calling the routine that will handle a final token.
 
296
         * Note that we intentionally do it this way rather than explicitly
 
297
         * add a check for padding here (because that would just slow down
 
298
         * the normal case) nor do we rely on checking whether we have more
 
299
         * input to process (because that would also slow it down but also
 
300
         * because we want to allow trailing garbage, especially white space
 
301
         * and cannot tell that without read-ahead, also a slow proposition).
 
302
         * Whew.  Understand?
 
303
         */
 
304
        n = pl_base64_decode_4to3 (token, out);
 
305
        if (n < 0)
 
306
            break;
 
307
 
 
308
        /* Advance "out" by the number of bytes just written to it. */
 
309
        out += n;
 
310
        n = 0;
 
311
    }
 
312
 
 
313
    /*
 
314
     * See big comment above, before call to pl_base64_decode_4to3.
 
315
     * Here we check if we error'd out of loop, and allow for the case
 
316
     * that we are processing the last interesting token.  If the routine
 
317
     * which should handle padding characters also fails, then we just
 
318
     * have bad input and give up.
 
319
     */
 
320
    if (n < 0) {
 
321
        n = pl_base64_decode_token (token, out);
 
322
        if (n < 0)
 
323
            return PR_FAILURE;
 
324
 
 
325
        out += n;
 
326
    }
 
327
 
 
328
    /*
 
329
     * As explained above, we can get here with more input remaining, but
 
330
     * it should be all characters we do not care about (i.e. would be
 
331
     * ignored when transferring from "in" to "token" in loop above,
 
332
     * except here we choose to ignore extraneous pad characters, too).
 
333
     * Swallow it, performing that check.  If we find more characters that
 
334
     * we would expect to decode, something is wrong.
 
335
     */
 
336
    while (length > 0) {
 
337
        if (base64_codetovaluep1[*in] > 0)
 
338
            return PR_FAILURE;
 
339
        in++;
 
340
        length--;
 
341
    }
 
342
 
 
343
    /* Record the length of decoded data we have left in output_buffer. */
 
344
    data->output_length = (PRUint32) (out - data->output_buffer);
 
345
    return PR_SUCCESS;
 
346
}
 
347
 
 
348
/*
 
349
 * Flush any remaining buffered characters.  Given well-formed input,
 
350
 * this will have nothing to do.  If the input was missing the padding
 
351
 * characters at the end, though, there could be 1-3 characters left
 
352
 * behind -- we will tolerate that by adding the padding for them.
 
353
 */
 
354
static PRStatus
 
355
pl_base64_decode_flush (PLBase64Decoder *data)
 
356
{
 
357
    int count;
 
358
 
 
359
    /*
 
360
     * If no remaining characters, or all are padding (also not well-formed
 
361
     * input, but again, be tolerant), then nothing more to do.  (And, that
 
362
     * is considered successful.)
 
363
     */
 
364
    if (data->token_size == 0 || data->token[0] == B64_PAD)
 
365
        return PR_SUCCESS;
 
366
 
 
367
    /*
 
368
     * Assume we have all the interesting input except for some expected
 
369
     * padding characters.  Add them and decode the resulting token.
 
370
     */
 
371
    while (data->token_size < 4)
 
372
        data->token[data->token_size++] = B64_PAD;
 
373
 
 
374
    data->token_size = 0;       /* so a subsequent flush call is a no-op */
 
375
 
 
376
    count = pl_base64_decode_token (data->token,
 
377
                                    data->output_buffer + data->output_length);
 
378
    if (count < 0)
 
379
        return PR_FAILURE;
 
380
 
 
381
    /*
 
382
     * If there is an output function, call it with this last bit of data.
 
383
     * Otherwise we are doing all buffered output, and the decoded bytes
 
384
     * are now there, we just need to reflect that in the length.
 
385
     */
 
386
    if (data->output_fn != NULL) {
 
387
        PRInt32 output_result;
 
388
 
 
389
        PR_ASSERT(data->output_length == 0);
 
390
        output_result = data->output_fn (data->output_arg,
 
391
                                         data->output_buffer,
 
392
                                         (PRInt32) count);
 
393
        if (output_result < 0)
 
394
            return  PR_FAILURE;
 
395
    } else {
 
396
        data->output_length += count;
 
397
    }
 
398
 
 
399
    return PR_SUCCESS;
 
400
}
 
401
 
 
402
 
 
403
/*
 
404
 * The maximum space needed to hold the output of the decoder given
 
405
 * input data of length "size".
 
406
 */
 
407
static PRUint32
 
408
PL_Base64MaxDecodedLength (PRUint32 size)
 
409
{
 
410
    return ((size * 3) / 4);
 
411
}
 
412
 
 
413
 
 
414
/*
 
415
 * A distinct internal creation function for the buffer version to use.
 
416
 * (It does not want to specify an output_fn, and we want the normal
 
417
 * Create function to require that.)  If more common initialization
 
418
 * of the decoding context needs to be done, it should be done *here*.
 
419
 */
 
420
static PLBase64Decoder *
 
421
pl_base64_create_decoder (void)
 
422
{
 
423
    return PR_NEWZAP(PLBase64Decoder);
 
424
}
 
425
 
 
426
/*
 
427
 * Function to start a base64 decoding context.
 
428
 * An "output_fn" is required; the "output_arg" parameter to that is optional.
 
429
 */
 
430
static PLBase64Decoder *
 
431
PL_CreateBase64Decoder (PRInt32 (*output_fn) (void *, const unsigned char *,
 
432
                                              PRInt32),
 
433
                        void *output_arg)
 
434
{
 
435
    PLBase64Decoder *data;
 
436
 
 
437
    if (output_fn == NULL) {
 
438
        PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
 
439
        return NULL;
 
440
    }
 
441
 
 
442
    data = pl_base64_create_decoder ();
 
443
    if (data != NULL) {
 
444
        data->output_fn = output_fn;
 
445
        data->output_arg = output_arg;
 
446
    }
 
447
    return data;
 
448
}
 
449
 
 
450
 
 
451
/*
 
452
 * Push data through the decoder, causing the output_fn (provided to Create)
 
453
 * to be called with the decoded data.
 
454
 */
 
455
static PRStatus
 
456
PL_UpdateBase64Decoder (PLBase64Decoder *data, const char *buffer,
 
457
                        PRUint32 size)
 
458
{
 
459
    PRUint32 need_length;
 
460
    PRStatus status;
 
461
 
 
462
    /* XXX Should we do argument checking only in debug build? */
 
463
    if (data == NULL || buffer == NULL || size == 0) {
 
464
        PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
 
465
        return PR_FAILURE;
 
466
    }
 
467
 
 
468
    /*
 
469
     * How much space could this update need for decoding?
 
470
     */
 
471
    need_length = PL_Base64MaxDecodedLength (size + data->token_size);
 
472
 
 
473
    /*
 
474
     * Make sure we have at least that much.  If not, (re-)allocate.
 
475
     */
 
476
    if (need_length > data->output_buflen) {
 
477
        unsigned char *output_buffer = data->output_buffer;
 
478
 
 
479
        if (output_buffer != NULL)
 
480
            output_buffer = (unsigned char *) PR_Realloc(output_buffer,
 
481
                                                         need_length);
 
482
        else
 
483
            output_buffer = (unsigned char *) PR_Malloc(need_length);
 
484
 
 
485
        if (output_buffer == NULL)
 
486
            return PR_FAILURE;
 
487
 
 
488
        data->output_buffer = output_buffer;
 
489
        data->output_buflen = need_length;
 
490
    }
 
491
 
 
492
    /* There should not have been any leftover output data in the buffer. */
 
493
    PR_ASSERT(data->output_length == 0);
 
494
    data->output_length = 0;
 
495
 
 
496
    status = pl_base64_decode_buffer (data, (const unsigned char *) buffer,
 
497
                                      size);
 
498
 
 
499
    /* Now that we have some decoded data, write it. */
 
500
    if (status == PR_SUCCESS && data->output_length > 0) {
 
501
        PRInt32 output_result;
 
502
 
 
503
        PR_ASSERT(data->output_fn != NULL);
 
504
        output_result = data->output_fn (data->output_arg,
 
505
                                         data->output_buffer,
 
506
                                         (PRInt32) data->output_length);
 
507
        if (output_result < 0)
 
508
            status = PR_FAILURE;
 
509
    }
 
510
 
 
511
    data->output_length = 0;
 
512
    return status;
 
513
}
 
514
 
 
515
 
 
516
/*
 
517
 * When you're done decoding, call this to free the data.  If "abort_p"
 
518
 * is false, then calling this may cause the output_fn to be called
 
519
 * one last time (as the last buffered data is flushed out).
 
520
 */
 
521
static PRStatus
 
522
PL_DestroyBase64Decoder (PLBase64Decoder *data, PRBool abort_p)
 
523
{
 
524
    PRStatus status = PR_SUCCESS;
 
525
 
 
526
    /* XXX Should we do argument checking only in debug build? */
 
527
    if (data == NULL) {
 
528
        PR_SetError (PR_INVALID_ARGUMENT_ERROR, 0);
 
529
        return PR_FAILURE;
 
530
    }
 
531
 
 
532
    /* Flush out the last few buffered characters. */
 
533
    if (!abort_p)
 
534
        status = pl_base64_decode_flush (data);
 
535
 
 
536
    if (data->output_buffer != NULL)
 
537
        PR_Free(data->output_buffer);
 
538
    PR_Free(data);
 
539
 
 
540
    return status;
 
541
}
 
542
 
 
543
 
 
544
/*
 
545
 * Perform base64 decoding from an input buffer to an output buffer.
 
546
 * The output buffer can be provided (as "dest"); you can also pass in
 
547
 * a NULL and this function will allocate a buffer large enough for you,
 
548
 * and return it.  If you do provide the output buffer, you must also
 
549
 * provide the maximum length of that buffer (as "maxdestlen").
 
550
 * The actual decoded length of output will be returned to you in
 
551
 * "output_destlen".
 
552
 *
 
553
 * Return value is NULL on error, the output buffer (allocated or provided)
 
554
 * otherwise.
 
555
 */
 
556
static unsigned char *
 
557
PL_Base64DecodeBuffer (const char *src, PRUint32 srclen, unsigned char *dest,
 
558
                       PRUint32 maxdestlen, PRUint32 *output_destlen)
 
559
{
 
560
    PRUint32 need_length;
 
561
    unsigned char *output_buffer = NULL;
 
562
    PLBase64Decoder *data = NULL;
 
563
    PRStatus status;
 
564
 
 
565
    PR_ASSERT(srclen > 0);
 
566
    if (srclen == 0)
 
567
        return dest;
 
568
 
 
569
    /*
 
570
     * How much space could we possibly need for decoding this input?
 
571
     */
 
572
    need_length = PL_Base64MaxDecodedLength (srclen);
 
573
 
 
574
    /*
 
575
     * Make sure we have at least that much, if output buffer provided.
 
576
     * If no output buffer provided, then we allocate that much.
 
577
     */
 
578
    if (dest != NULL) {
 
579
        PR_ASSERT(maxdestlen >= need_length);
 
580
        if (maxdestlen < need_length) {
 
581
            PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
 
582
            goto loser;
 
583
        }
 
584
        output_buffer = dest;
 
585
    } else {
 
586
        output_buffer = (unsigned char *) PR_Malloc(need_length);
 
587
        if (output_buffer == NULL)
 
588
            goto loser;
 
589
        maxdestlen = need_length;
 
590
    }
 
591
 
 
592
    data = pl_base64_create_decoder();
 
593
    if (data == NULL)
 
594
        goto loser;
 
595
 
 
596
    data->output_buflen = maxdestlen;
 
597
    data->output_buffer = output_buffer;
 
598
 
 
599
    status = pl_base64_decode_buffer (data, (const unsigned char *) src,
 
600
                                      srclen);
 
601
 
 
602
    /*
 
603
     * We do not wait for Destroy to flush, because Destroy will also
 
604
     * get rid of our decoder context, which we need to look at first!
 
605
     */
 
606
    if (status == PR_SUCCESS)
 
607
        status = pl_base64_decode_flush (data);
 
608
 
 
609
    /* Must clear this or Destroy will free it. */
 
610
    data->output_buffer = NULL;
 
611
 
 
612
    if (status == PR_SUCCESS) {
 
613
        *output_destlen = data->output_length;
 
614
        status = PL_DestroyBase64Decoder (data, PR_FALSE);
 
615
        data = NULL;
 
616
        if (status == PR_FAILURE)
 
617
            goto loser;
 
618
        return output_buffer;
 
619
    }
 
620
 
 
621
loser:
 
622
    if (dest == NULL && output_buffer != NULL)
 
623
        PR_Free(output_buffer);
 
624
    if (data != NULL)
 
625
        (void) PL_DestroyBase64Decoder (data, PR_TRUE);
 
626
    return NULL;
 
627
}
 
628
 
 
629
 
 
630
/*
 
631
 * XXX End of base64 decoding code to be moved into NSPR.
 
632
 ********************************************************
 
633
 */
 
634
 
 
635
/*
 
636
 * This is the beginning of the NSS cover functions.  These will
 
637
 * provide the interface we want to expose as NSS-ish.  For example,
 
638
 * they will operate on our Items, do any special handling or checking
 
639
 * we want to do, etc.
 
640
 */
 
641
 
 
642
 
 
643
PR_BEGIN_EXTERN_C
 
644
 
 
645
/*
 
646
 * A boring cover structure for now.  Perhaps someday it will include
 
647
 * some more interesting fields.
 
648
 */
 
649
struct NSSBase64DecoderStr {
 
650
    PLBase64Decoder *pl_data;
 
651
};
 
652
 
 
653
PR_END_EXTERN_C
 
654
 
 
655
 
 
656
/*
 
657
 * Function to start a base64 decoding context.
 
658
 */
 
659
NSSBase64Decoder *
 
660
NSSBase64Decoder_Create (PRInt32 (*output_fn) (void *, const unsigned char *,
 
661
                                               PRInt32),
 
662
                         void *output_arg)
 
663
{
 
664
    PLBase64Decoder *pl_data;
 
665
    NSSBase64Decoder *nss_data;
 
666
 
 
667
    nss_data = PORT_ZNew(NSSBase64Decoder);
 
668
    if (nss_data == NULL)
 
669
        return NULL;
 
670
 
 
671
    pl_data = PL_CreateBase64Decoder (output_fn, output_arg);
 
672
    if (pl_data == NULL) {
 
673
        PORT_Free(nss_data);
 
674
        return NULL;
 
675
    }
 
676
 
 
677
    nss_data->pl_data = pl_data;
 
678
    return nss_data;
 
679
}
 
680
 
 
681
 
 
682
/*
 
683
 * Push data through the decoder, causing the output_fn (provided to Create)
 
684
 * to be called with the decoded data.
 
685
 */
 
686
SECStatus
 
687
NSSBase64Decoder_Update (NSSBase64Decoder *data, const char *buffer,
 
688
                         PRUint32 size)
 
689
{
 
690
    PRStatus pr_status;
 
691
 
 
692
    /* XXX Should we do argument checking only in debug build? */
 
693
    if (data == NULL) {
 
694
        PORT_SetError (SEC_ERROR_INVALID_ARGS);
 
695
        return SECFailure;
 
696
    }
 
697
 
 
698
    pr_status = PL_UpdateBase64Decoder (data->pl_data, buffer, size);
 
699
    if (pr_status == PR_FAILURE)
 
700
        return SECFailure;
 
701
 
 
702
    return SECSuccess;
 
703
}
 
704
 
 
705
 
 
706
/*
 
707
 * When you're done decoding, call this to free the data.  If "abort_p"
 
708
 * is false, then calling this may cause the output_fn to be called
 
709
 * one last time (as the last buffered data is flushed out).
 
710
 */
 
711
SECStatus
 
712
NSSBase64Decoder_Destroy (NSSBase64Decoder *data, PRBool abort_p)
 
713
{
 
714
    PRStatus pr_status;
 
715
 
 
716
    /* XXX Should we do argument checking only in debug build? */
 
717
    if (data == NULL) {
 
718
        PORT_SetError (SEC_ERROR_INVALID_ARGS);
 
719
        return SECFailure;
 
720
    }
 
721
 
 
722
    pr_status = PL_DestroyBase64Decoder (data->pl_data, abort_p);
 
723
 
 
724
    PORT_Free(data);
 
725
 
 
726
    if (pr_status == PR_FAILURE)
 
727
        return SECFailure;
 
728
 
 
729
    return SECSuccess;
 
730
}
 
731
 
 
732
 
 
733
/*
 
734
 * Perform base64 decoding from an ascii string "inStr" to an Item.
 
735
 * The length of the input must be provided as "inLen".  The Item
 
736
 * may be provided (as "outItemOpt"); you can also pass in a NULL
 
737
 * and the Item will be allocated for you.
 
738
 *
 
739
 * In any case, the data within the Item will be allocated for you.
 
740
 * All allocation will happen out of the passed-in "arenaOpt", if non-NULL.
 
741
 * If "arenaOpt" is NULL, standard allocation (heap) will be used and
 
742
 * you will want to free the result via SECITEM_FreeItem.
 
743
 *
 
744
 * Return value is NULL on error, the Item (allocated or provided) otherwise.
 
745
 */
 
746
SECItem *
 
747
NSSBase64_DecodeBuffer (PRArenaPool *arenaOpt, SECItem *outItemOpt,
 
748
                        const char *inStr, unsigned int inLen)
 
749
{
 
750
    SECItem *out_item = outItemOpt;
 
751
    PRUint32 max_out_len = PL_Base64MaxDecodedLength (inLen);
 
752
    PRUint32 out_len;
 
753
    void *mark = NULL;
 
754
    unsigned char *dummy;
 
755
 
 
756
    PORT_Assert(outItemOpt == NULL || outItemOpt->data == NULL);
 
757
 
 
758
    if (arenaOpt != NULL)
 
759
        mark = PORT_ArenaMark (arenaOpt);
 
760
 
 
761
    out_item = SECITEM_AllocItem (arenaOpt, outItemOpt, max_out_len);
 
762
    if (out_item == NULL) {
 
763
        if (arenaOpt != NULL)
 
764
            PORT_ArenaRelease (arenaOpt, mark);
 
765
        return NULL;
 
766
    }
 
767
 
 
768
    dummy = PL_Base64DecodeBuffer (inStr, inLen, out_item->data,
 
769
                                   max_out_len, &out_len);
 
770
    if (dummy == NULL) {
 
771
        if (arenaOpt != NULL) {
 
772
            PORT_ArenaRelease (arenaOpt, mark);
 
773
            if (outItemOpt != NULL) {
 
774
                outItemOpt->data = NULL;
 
775
                outItemOpt->len = 0;
 
776
            }
 
777
        } else {
 
778
            SECITEM_FreeItem (out_item,
 
779
                              (outItemOpt == NULL) ? PR_TRUE : PR_FALSE);
 
780
        }
 
781
        return NULL;
 
782
    }
 
783
 
 
784
    if (arenaOpt != NULL)
 
785
        PORT_ArenaUnmark (arenaOpt, mark);
 
786
    out_item->len = out_len;
 
787
    return out_item;
 
788
}
 
789
 
 
790
 
 
791
/*
 
792
 * XXX Everything below is deprecated.  If you add new stuff, put it
 
793
 * *above*, not below.
 
794
 */
 
795
 
 
796
/*
 
797
 * XXX The following "ATOB" functions are provided for backward compatibility
 
798
 * with current code.  They should be considered strongly deprecated.
 
799
 * When we can convert all our code over to using the new NSSBase64Decoder_
 
800
 * functions defined above, we should get rid of these altogether.  (Remove
 
801
 * protoypes from base64.h as well -- actually, remove that file completely).
 
802
 * If someone thinks either of these functions provides such a very useful
 
803
 * interface (though, as shown, the same functionality can already be
 
804
 * obtained by calling NSSBase64_DecodeBuffer directly), fine -- but then
 
805
 * that API should be provided with a nice new NSSFoo name and using
 
806
 * appropriate types, etc.
 
807
 */
 
808
 
 
809
#include "base64.h"
 
810
 
 
811
/*
 
812
** Return an PORT_Alloc'd string which is the base64 decoded version
 
813
** of the input string; set *lenp to the length of the returned data.
 
814
*/
 
815
unsigned char *
 
816
ATOB_AsciiToData(const char *string, unsigned int *lenp)
 
817
{
 
818
    SECItem binary_item, *dummy;
 
819
 
 
820
    binary_item.data = NULL;
 
821
    binary_item.len = 0;
 
822
 
 
823
    dummy = NSSBase64_DecodeBuffer (NULL, &binary_item, string,
 
824
                                    (PRUint32) PORT_Strlen(string));
 
825
    if (dummy == NULL)
 
826
        return NULL;
 
827
 
 
828
    PORT_Assert(dummy == &binary_item);
 
829
 
 
830
    *lenp = dummy->len;
 
831
    return dummy->data;
 
832
}
 
833
 
 
834
/*
 
835
** Convert from ascii to binary encoding of an item.
 
836
*/
 
837
SECStatus
 
838
ATOB_ConvertAsciiToItem(SECItem *binary_item, char *ascii)
 
839
{
 
840
    SECItem *dummy;
 
841
 
 
842
    if (binary_item == NULL) {
 
843
        PORT_SetError (SEC_ERROR_INVALID_ARGS);
 
844
        return SECFailure;
 
845
    }
 
846
 
 
847
    /*
 
848
     * XXX Would prefer to assert here if data is non-null (actually,
 
849
     * don't need to, just let NSSBase64_DecodeBuffer do it), so as to
 
850
     * to catch unintended memory leaks, but callers are not clean in
 
851
     * this respect so we need to explicitly clear here to avoid the
 
852
     * assert in NSSBase64_DecodeBuffer.
 
853
     */
 
854
    binary_item->data = NULL;
 
855
    binary_item->len = 0;
 
856
 
 
857
    dummy = NSSBase64_DecodeBuffer (NULL, binary_item, ascii,
 
858
                                    (PRUint32) PORT_Strlen(ascii));
 
859
 
 
860
    if (dummy == NULL)
 
861
        return SECFailure;
 
862
 
 
863
    return SECSuccess;
 
864
}