nssb64e.c 21 KB

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