nssb64d.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:25k
源码类别:

CA认证

开发平台:

WINDOWS

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