security/nss/lib/util/nssb64e.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial