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 encoding (binary to ascii).
7  */
8 
9 #include "nssb64.h"
10 #include <nspr.h>
11 #include "secitem.h"
12 #include "secerr.h"
13 
14 /*
15  * XXX See the big comment at the top of nssb64d.c about moving the
16  * bulk of this code over into NSPR (the PL part).  It all applies
17  * here but I didn't want to duplicate it, to avoid divergence problems.
18  */
19 
20 /*
21  **************************************************************
22  * XXX Beginning of base64 encoding code to be moved into NSPR.
23  */
24 
25 struct PLBase64EncodeStateStr {
26     unsigned chunks;
27     unsigned saved;
28     unsigned char buf[3];
29 };
30 
31 /*
32  * This typedef would belong in the NSPR header file (i.e. plbase64.h).
33  */
34 typedef struct PLBase64EncoderStr PLBase64Encoder;
35 
36 /*
37  * The following implementation of base64 encoding was based on code
38  * found in libmime (specifically, in mimeenc.c).  It has been adapted to
39  * use PR types and naming as well as to provide other necessary semantics
40  * (like buffer-in/buffer-out in addition to "streaming" without undue
41  * performance hit of extra copying if you made the buffer versions
42  * use the output_fn).  It also incorporates some aspects of the current
43  * NSPR base64 encoding code.  As such, you may find similarities to
44  * both of those implementations.  I tried to use names that reflected
45  * the original code when possible.  For this reason you may find some
46  * inconsistencies -- libmime used lots of "in" and "out" whereas the
47  * NSPR version uses "src" and "dest"; sometimes I changed one to the other
48  * and sometimes I left them when I thought the subroutines were at least
49  * self-consistent.
50  */
51 
52 PR_BEGIN_EXTERN_C
53 
54 /*
55  * Opaque object used by the encoder to store state.
56  */
57 struct PLBase64EncoderStr {
58     /*
59      * The one or two bytes pending.  (We need 3 to create a "token",
60      * and hold the leftovers here.  in_buffer_count is *only* ever
61      * 0, 1, or 2.
62      */
63     unsigned char in_buffer[2];
64     int in_buffer_count;
65 
66     /*
67      * If the caller wants linebreaks added, line_length specifies
68      * where they come out.  It must be a multiple of 4; if the caller
69      * provides one that isn't, we round it down to the nearest
70      * multiple of 4.
71      *
72      * The value of current_column counts how many characters have been
73      * added since the last linebreaks (or since the beginning, on the
74      * first line).  It is also always a multiple of 4; it is unused when
75      * line_length is 0.
76      */
77     PRUint32 line_length;
78     PRUint32 current_column;
79 
80     /*
81      * Where to write the encoded data (used when streaming, not when
82      * doing all in-memory (buffer) operations).
83      *
84      * Note that this definition is chosen to be compatible with PR_Write.
85      */
86     PRInt32 (*output_fn)(void *output_arg, const char *buf, PRInt32 size);
87     void *output_arg;
88 
89     /*
90      * Where the encoded output goes -- either temporarily (in the streaming
91      * case, staged here before it goes to the output function) or what will
92      * be the entire buffered result for users of the buffer version.
93      */
94     char *output_buffer;
95     PRUint32 output_buflen; /* the total length of allocated buffer */
96     PRUint32 output_length; /* the length that is currently populated */
97 };
98 
99 PR_END_EXTERN_C
100 
101 /*
102  * Table to convert a binary value to its corresponding ascii "code".
103  */
104 static unsigned char base64_valuetocode[64] =
105     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
106 
107 #define B64_PAD '='
108 #define B64_CR '\r'
109 #define B64_LF '\n'
110 
111 static PRStatus
pl_base64_encode_buffer(PLBase64Encoder * data,const unsigned char * in,PRUint32 size)112 pl_base64_encode_buffer(PLBase64Encoder *data, const unsigned char *in,
113                         PRUint32 size)
114 {
115     const unsigned char *end = in + size;
116     char *out = data->output_buffer + data->output_length;
117     unsigned int i = data->in_buffer_count;
118     PRUint32 n = 0;
119     int off;
120     PRUint32 output_threshold;
121 
122     /* If this input buffer is too small, wait until next time. */
123     if (size < (3 - i)) {
124         data->in_buffer[i++] = in[0];
125         if (size > 1)
126             data->in_buffer[i++] = in[1];
127         PR_ASSERT(i < 3);
128         data->in_buffer_count = i;
129         return PR_SUCCESS;
130     }
131 
132     /* If there are bytes that were put back last time, take them now. */
133     if (i > 0) {
134         n = data->in_buffer[0];
135         if (i > 1)
136             n = (n << 8) | data->in_buffer[1];
137         data->in_buffer_count = 0;
138     }
139 
140     /* If our total is not a multiple of three, put one or two bytes back. */
141     off = (size + i) % 3;
142     if (off > 0) {
143         size -= off;
144         data->in_buffer[0] = in[size];
145         if (off > 1)
146             data->in_buffer[1] = in[size + 1];
147         data->in_buffer_count = off;
148         end -= off;
149     }
150 
151     output_threshold = data->output_buflen - 3;
152 
153     /*
154      * Populate the output buffer with base64 data, one line (or buffer)
155      * at a time.
156      */
157     while (in < end) {
158         int j, k;
159 
160         while (i < 3) {
161             n = (n << 8) | *in++;
162             i++;
163         }
164         i = 0;
165 
166         if (data->line_length > 0) {
167             if (data->current_column >= data->line_length) {
168                 data->current_column = 0;
169                 *out++ = B64_CR;
170                 *out++ = B64_LF;
171                 data->output_length += 2;
172             }
173             data->current_column += 4; /* the bytes we are about to add */
174         }
175 
176         for (j = 18; j >= 0; j -= 6) {
177             k = (n >> j) & 0x3F;
178             *out++ = base64_valuetocode[k];
179         }
180         n = 0;
181         data->output_length += 4;
182 
183         if (data->output_length >= output_threshold) {
184             PR_ASSERT(data->output_length <= data->output_buflen);
185             if (data->output_fn != NULL) {
186                 PRInt32 output_result;
187 
188                 output_result = data->output_fn(data->output_arg,
189                                                 data->output_buffer,
190                                                 (PRInt32)data->output_length);
191                 if (output_result < 0)
192                     return PR_FAILURE;
193 
194                 out = data->output_buffer;
195                 data->output_length = 0;
196             } else {
197                 /*
198                  * Check that we are about to exit the loop.  (Since we
199                  * are over the threshold, there isn't enough room in the
200                  * output buffer for another trip around.)
201                  */
202                 PR_ASSERT(in == end);
203                 if (in < end) {
204                     PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
205                     return PR_FAILURE;
206                 }
207             }
208         }
209     }
210 
211     return PR_SUCCESS;
212 }
213 
214 static PRStatus
pl_base64_encode_flush(PLBase64Encoder * data)215 pl_base64_encode_flush(PLBase64Encoder *data)
216 {
217     int i = data->in_buffer_count;
218 
219     if (i == 0 && data->output_length == 0)
220         return PR_SUCCESS;
221 
222     if (i > 0) {
223         char *out = data->output_buffer + data->output_length;
224         PRUint32 n;
225         int j, k;
226 
227         n = ((PRUint32)data->in_buffer[0]) << 16;
228         if (i > 1)
229             n |= ((PRUint32)data->in_buffer[1] << 8);
230 
231         data->in_buffer_count = 0;
232 
233         if (data->line_length > 0) {
234             if (data->current_column >= data->line_length) {
235                 data->current_column = 0;
236                 *out++ = B64_CR;
237                 *out++ = B64_LF;
238                 data->output_length += 2;
239             }
240         }
241 
242         /*
243          * This will fill in more than we really have data for, but the
244          * valid parts will end up in the correct position and the extras
245          * will be over-written with pad characters below.
246          */
247         for (j = 18; j >= 0; j -= 6) {
248             k = (n >> j) & 0x3F;
249             *out++ = base64_valuetocode[k];
250         }
251 
252         /* Pad with equal-signs. */
253         if (i == 1)
254             out[-2] = B64_PAD;
255         out[-1] = B64_PAD;
256 
257         data->output_length += 4;
258     }
259 
260     if (data->output_fn != NULL) {
261         PRInt32 output_result;
262 
263         output_result = data->output_fn(data->output_arg, data->output_buffer,
264                                         (PRInt32)data->output_length);
265         data->output_length = 0;
266 
267         if (output_result < 0)
268             return PR_FAILURE;
269     }
270 
271     return PR_SUCCESS;
272 }
273 
274 /*
275  * The maximum space needed to hold the output of the encoder given input
276  * data of length "size", and allowing for CRLF added at least every
277  * line_length bytes (we will add it at nearest lower multiple of 4).
278  * There is no trailing CRLF.
279  */
280 static PRUint32
PL_Base64MaxEncodedLength(PRUint32 size,PRUint32 line_length)281 PL_Base64MaxEncodedLength(PRUint32 size, PRUint32 line_length)
282 {
283     PRUint32 tokens, tokens_per_line, full_lines, line_break_chars, remainder;
284 
285     /* This is the maximum length we support. */
286     if (size > 0x3fffffff) {
287         return 0;
288     }
289 
290     tokens = (size + 2) / 3;
291 
292     if (line_length == 0) {
293         return tokens * 4;
294     }
295 
296     if (line_length < 4) { /* too small! */
297         line_length = 4;
298     }
299 
300     tokens_per_line = line_length / 4;
301     full_lines = tokens / tokens_per_line;
302     remainder = (tokens - (full_lines * tokens_per_line)) * 4;
303     line_break_chars = full_lines * 2;
304     if (remainder == 0) {
305         line_break_chars -= 2;
306     }
307 
308     return (full_lines * tokens_per_line * 4) + line_break_chars + remainder;
309 }
310 
311 /*
312  * A distinct internal creation function for the buffer version to use.
313  * (It does not want to specify an output_fn, and we want the normal
314  * Create function to require that.)  All common initialization of the
315  * encoding context should be done *here*.
316  *
317  * Save "line_length", rounded down to nearest multiple of 4 (if not
318  * already even multiple).  Allocate output_buffer, if not provided --
319  * based on given size if specified, otherwise based on line_length.
320  */
321 static PLBase64Encoder *
pl_base64_create_encoder(PRUint32 line_length,char * output_buffer,PRUint32 output_buflen)322 pl_base64_create_encoder(PRUint32 line_length, char *output_buffer,
323                          PRUint32 output_buflen)
324 {
325     PLBase64Encoder *data;
326     PRUint32 line_tokens;
327 
328     data = PR_NEWZAP(PLBase64Encoder);
329     if (data == NULL)
330         return NULL;
331 
332     if (line_length > 0 && line_length < 4) /* too small! */
333         line_length = 4;
334 
335     line_tokens = line_length / 4;
336     data->line_length = line_tokens * 4;
337 
338     if (output_buffer == NULL) {
339         if (output_buflen == 0) {
340             if (data->line_length > 0) /* need to include room for CRLF */
341                 output_buflen = data->line_length + 2;
342             else
343                 output_buflen = 64; /* XXX what is a good size? */
344         }
345 
346         output_buffer = (char *)PR_Malloc(output_buflen);
347         if (output_buffer == NULL) {
348             PR_Free(data);
349             return NULL;
350         }
351     }
352 
353     data->output_buffer = output_buffer;
354     data->output_buflen = output_buflen;
355     return data;
356 }
357 
358 /*
359  * Function to start a base64 encoding context.
360  * An "output_fn" is required; the "output_arg" parameter to that is optional.
361  * If linebreaks in the encoded output are desired, "line_length" specifies
362  * where to place them -- it will be rounded down to the nearest multiple of 4
363  * (if it is not already an even multiple of 4).  If it is zero, no linebreaks
364  * will be added.  (FYI, a linebreak is CRLF -- two characters.)
365  */
366 static PLBase64Encoder *
PL_CreateBase64Encoder(PRInt32 (* output_fn)(void *,const char *,PRInt32),void * output_arg,PRUint32 line_length)367 PL_CreateBase64Encoder(PRInt32 (*output_fn)(void *, const char *, PRInt32),
368                        void *output_arg, PRUint32 line_length)
369 {
370     PLBase64Encoder *data;
371 
372     if (output_fn == NULL) {
373         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
374         return NULL;
375     }
376 
377     data = pl_base64_create_encoder(line_length, NULL, 0);
378     if (data == NULL)
379         return NULL;
380 
381     data->output_fn = output_fn;
382     data->output_arg = output_arg;
383 
384     return data;
385 }
386 
387 /*
388  * Push data through the encoder, causing the output_fn (provided to Create)
389  * to be called with the encoded data.
390  */
391 static PRStatus
PL_UpdateBase64Encoder(PLBase64Encoder * data,const unsigned char * buffer,PRUint32 size)392 PL_UpdateBase64Encoder(PLBase64Encoder *data, const unsigned char *buffer,
393                        PRUint32 size)
394 {
395     /* XXX Should we do argument checking only in debug build? */
396     if (data == NULL || buffer == NULL || size == 0) {
397         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
398         return PR_FAILURE;
399     }
400 
401     return pl_base64_encode_buffer(data, buffer, size);
402 }
403 
404 /*
405  * When you're done encoding, call this to free the data.  If "abort_p"
406  * is false, then calling this may cause the output_fn to be called
407  * one last time (as the last buffered data is flushed out).
408  */
409 static PRStatus
PL_DestroyBase64Encoder(PLBase64Encoder * data,PRBool abort_p)410 PL_DestroyBase64Encoder(PLBase64Encoder *data, PRBool abort_p)
411 {
412     PRStatus status = PR_SUCCESS;
413 
414     /* XXX Should we do argument checking only in debug build? */
415     if (data == NULL) {
416         PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
417         return PR_FAILURE;
418     }
419 
420     /* Flush out the last few buffered characters. */
421     if (!abort_p)
422         status = pl_base64_encode_flush(data);
423 
424     if (data->output_buffer != NULL)
425         PR_Free(data->output_buffer);
426     PR_Free(data);
427 
428     return status;
429 }
430 
431 /*
432  * Perform base64 encoding from an input buffer to an output buffer.
433  * The output buffer can be provided (as "dest"); you can also pass in
434  * a NULL and this function will allocate a buffer large enough for you,
435  * and return it.  If you do provide the output buffer, you must also
436  * provide the maximum length of that buffer (as "maxdestlen").
437  * The actual encoded length of output will be returned to you in
438  * "output_destlen".
439  *
440  * If linebreaks in the encoded output are desired, "line_length" specifies
441  * where to place them -- it will be rounded down to the nearest multiple of 4
442  * (if it is not already an even multiple of 4).  If it is zero, no linebreaks
443  * will be added.  (FYI, a linebreak is CRLF -- two characters.)
444  *
445  * Return value is NULL on error, the output buffer (allocated or provided)
446  * otherwise.
447  */
448 static char *
PL_Base64EncodeBuffer(const unsigned char * src,PRUint32 srclen,PRUint32 line_length,char * dest,PRUint32 maxdestlen,PRUint32 * output_destlen)449 PL_Base64EncodeBuffer(const unsigned char *src, PRUint32 srclen,
450                       PRUint32 line_length, char *dest, PRUint32 maxdestlen,
451                       PRUint32 *output_destlen)
452 {
453     PRUint32 need_length;
454     PLBase64Encoder *data = NULL;
455     PRStatus status;
456 
457     PR_ASSERT(srclen > 0);
458     if (srclen == 0) {
459         return dest;
460     }
461 
462     /*
463      * How much space could we possibly need for encoding this input?
464      */
465     need_length = PL_Base64MaxEncodedLength(srclen, line_length);
466     if (need_length == 0) {
467         PORT_SetError(SEC_ERROR_INVALID_ARGS);
468         return NULL;
469     }
470 
471     /*
472      * Make sure we have at least that much, if output buffer provided.
473      */
474     if (dest != NULL) {
475         PR_ASSERT(maxdestlen >= need_length);
476         if (maxdestlen < need_length) {
477             PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
478             return NULL;
479         }
480     } else {
481         maxdestlen = need_length;
482     }
483 
484     data = pl_base64_create_encoder(line_length, dest, maxdestlen);
485     if (data == NULL)
486         return NULL;
487 
488     status = pl_base64_encode_buffer(data, src, srclen);
489 
490     /*
491      * We do not wait for Destroy to flush, because Destroy will also
492      * get rid of our encoder context, which we need to look at first!
493      */
494     if (status == PR_SUCCESS)
495         status = pl_base64_encode_flush(data);
496 
497     if (status != PR_SUCCESS) {
498         (void)PL_DestroyBase64Encoder(data, PR_TRUE);
499         return NULL;
500     }
501 
502     dest = data->output_buffer;
503 
504     /* Must clear this or Destroy will free it. */
505     data->output_buffer = NULL;
506 
507     *output_destlen = data->output_length;
508     status = PL_DestroyBase64Encoder(data, PR_FALSE);
509     if (status == PR_FAILURE) {
510         PR_Free(dest);
511         return NULL;
512     }
513 
514     return dest;
515 }
516 
517 /*
518  * XXX End of base64 encoding code to be moved into NSPR.
519  ********************************************************
520  */
521 
522 /*
523  * This is the beginning of the NSS cover functions.  These will
524  * provide the interface we want to expose as NSS-ish.  For example,
525  * they will operate on our Items, do any special handling or checking
526  * we want to do, etc.
527  */
528 
529 PR_BEGIN_EXTERN_C
530 
531 /*
532  * A boring cover structure for now.  Perhaps someday it will include
533  * some more interesting fields.
534  */
535 struct NSSBase64EncoderStr {
536     PLBase64Encoder *pl_data;
537 };
538 
539 PR_END_EXTERN_C
540 
541 /*
542  * Function to start a base64 encoding context.
543  */
544 NSSBase64Encoder *
NSSBase64Encoder_Create(PRInt32 (* output_fn)(void *,const char *,PRInt32),void * output_arg)545 NSSBase64Encoder_Create(PRInt32 (*output_fn)(void *, const char *, PRInt32),
546                         void *output_arg)
547 {
548     PLBase64Encoder *pl_data;
549     NSSBase64Encoder *nss_data;
550 
551     nss_data = PORT_ZNew(NSSBase64Encoder);
552     if (nss_data == NULL)
553         return NULL;
554 
555     pl_data = PL_CreateBase64Encoder(output_fn, output_arg, 64);
556     if (pl_data == NULL) {
557         PORT_Free(nss_data);
558         return NULL;
559     }
560 
561     nss_data->pl_data = pl_data;
562     return nss_data;
563 }
564 
565 /*
566  * Push data through the encoder, causing the output_fn (provided to Create)
567  * to be called with the encoded data.
568  */
569 SECStatus
NSSBase64Encoder_Update(NSSBase64Encoder * data,const unsigned char * buffer,PRUint32 size)570 NSSBase64Encoder_Update(NSSBase64Encoder *data, const unsigned char *buffer,
571                         PRUint32 size)
572 {
573     PRStatus pr_status;
574 
575     /* XXX Should we do argument checking only in debug build? */
576     if (data == NULL) {
577         PORT_SetError(SEC_ERROR_INVALID_ARGS);
578         return SECFailure;
579     }
580 
581     pr_status = PL_UpdateBase64Encoder(data->pl_data, buffer, size);
582     if (pr_status == PR_FAILURE)
583         return SECFailure;
584 
585     return SECSuccess;
586 }
587 
588 /*
589  * When you're done encoding, call this to free the data.  If "abort_p"
590  * is false, then calling this may cause the output_fn to be called
591  * one last time (as the last buffered data is flushed out).
592  */
593 SECStatus
NSSBase64Encoder_Destroy(NSSBase64Encoder * data,PRBool abort_p)594 NSSBase64Encoder_Destroy(NSSBase64Encoder *data, PRBool abort_p)
595 {
596     PRStatus pr_status;
597 
598     /* XXX Should we do argument checking only in debug build? */
599     if (data == NULL) {
600         PORT_SetError(SEC_ERROR_INVALID_ARGS);
601         return SECFailure;
602     }
603 
604     pr_status = PL_DestroyBase64Encoder(data->pl_data, abort_p);
605 
606     PORT_Free(data);
607 
608     if (pr_status == PR_FAILURE)
609         return SECFailure;
610 
611     return SECSuccess;
612 }
613 
614 /*
615  * Perform base64 encoding of binary data "inItem" to an ascii string.
616  * The output buffer may be provided (as "outStrOpt"); you can also pass
617  * in a NULL and the buffer will be allocated for you.  The result will
618  * be null-terminated, and if the buffer is provided, "maxOutLen" must
619  * specify the maximum length of the buffer and will be checked to
620  * supply sufficient space space for the encoded result.  (If "outStrOpt"
621  * is NULL, "maxOutLen" is ignored.)
622  *
623  * If "outStrOpt" is NULL, allocation will happen out of the passed-in
624  * "arenaOpt", if *it* is non-NULL, otherwise standard allocation (heap)
625  * will be used.
626  *
627  * Return value is NULL on error, the output buffer (allocated or provided)
628  * otherwise.
629  */
630 char *
NSSBase64_EncodeItem(PLArenaPool * arenaOpt,char * outStrOpt,unsigned int maxOutLen,SECItem * inItem)631 NSSBase64_EncodeItem(PLArenaPool *arenaOpt, char *outStrOpt,
632                      unsigned int maxOutLen, SECItem *inItem)
633 {
634     char *out_string = outStrOpt;
635     PRUint32 max_out_len;
636     PRUint32 out_len = 0;
637     void *mark = NULL;
638     char *dummy;
639 
640     PORT_Assert(inItem != NULL && inItem->data != NULL && inItem->len != 0);
641     if (inItem == NULL || inItem->data == NULL || inItem->len == 0) {
642         PORT_SetError(SEC_ERROR_INVALID_ARGS);
643         return NULL;
644     }
645 
646     max_out_len = PL_Base64MaxEncodedLength(inItem->len, 64);
647     if (max_out_len == 0) {
648         PORT_SetError(SEC_ERROR_INVALID_ARGS);
649         return NULL;
650     }
651 
652     if (arenaOpt != NULL)
653         mark = PORT_ArenaMark(arenaOpt);
654 
655     if (out_string == NULL) {
656         if (arenaOpt != NULL)
657             out_string = PORT_ArenaAlloc(arenaOpt, max_out_len + 1);
658         else
659             out_string = PORT_Alloc(max_out_len + 1);
660 
661         if (out_string == NULL) {
662             if (arenaOpt != NULL)
663                 PORT_ArenaRelease(arenaOpt, mark);
664             return NULL;
665         }
666     } else {
667         if ((max_out_len + 1) > maxOutLen) {
668             PORT_SetError(SEC_ERROR_OUTPUT_LEN);
669             return NULL;
670         }
671         max_out_len = maxOutLen;
672     }
673 
674     dummy = PL_Base64EncodeBuffer(inItem->data, inItem->len, 64,
675                                   out_string, max_out_len, &out_len);
676     if (dummy == NULL) {
677         if (arenaOpt != NULL) {
678             PORT_ArenaRelease(arenaOpt, mark);
679         } else {
680             PORT_Free(out_string);
681         }
682         return NULL;
683     }
684 
685     if (arenaOpt != NULL)
686         PORT_ArenaUnmark(arenaOpt, mark);
687 
688     out_string[out_len] = '\0';
689     return out_string;
690 }
691 
692 /*
693  * XXX Everything below is deprecated.  If you add new stuff, put it
694  * *above*, not below.
695  */
696 
697 /*
698  * XXX The following "BTOA" functions are provided for backward compatibility
699  * with current code.  They should be considered strongly deprecated.
700  * When we can convert all our code over to using the new NSSBase64Encoder_
701  * functions defined above, we should get rid of these altogether.  (Remove
702  * protoypes from base64.h as well -- actually, remove that file completely).
703  * If someone thinks either of these functions provides such a very useful
704  * interface (though, as shown, the same functionality can already be
705  * obtained by calling NSSBase64_EncodeItem directly), fine -- but then
706  * that API should be provided with a nice new NSSFoo name and using
707  * appropriate types, etc.
708  */
709 
710 #include "base64.h"
711 
712 /*
713 ** Return an PORT_Alloc'd ascii string which is the base64 encoded
714 ** version of the input string.
715 */
716 char *
BTOA_DataToAscii(const unsigned char * data,unsigned int len)717 BTOA_DataToAscii(const unsigned char *data, unsigned int len)
718 {
719     SECItem binary_item;
720 
721     binary_item.data = (unsigned char *)data;
722     binary_item.len = len;
723 
724     return NSSBase64_EncodeItem(NULL, NULL, 0, &binary_item);
725 }
726 
727 /*
728 ** Convert from binary encoding of an item to ascii.
729 */
730 char *
BTOA_ConvertItemToAscii(SECItem * binary_item)731 BTOA_ConvertItemToAscii(SECItem *binary_item)
732 {
733     return NSSBase64_EncodeItem(NULL, NULL, 0, binary_item);
734 }
735