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