PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/munge-0.5.10/src/munged/base64.c

#
C | 445 lines | 297 code | 66 blank | 82 comment | 66 complexity | a7857d28c42d88f8ed2c1ab4149f933b MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0
  1. /*****************************************************************************
  2. * $Id: base64.c 890 2011-01-20 01:54:21Z chris.m.dunlap $
  3. *****************************************************************************
  4. * Written by Chris Dunlap <cdunlap@llnl.gov>.
  5. * Copyright (C) 2007-2011 Lawrence Livermore National Security, LLC.
  6. * Copyright (C) 2002-2007 The Regents of the University of California.
  7. * UCRL-CODE-155910.
  8. *
  9. * This file is part of the MUNGE Uid 'N' Gid Emporium (MUNGE).
  10. * For details, see <http://munge.googlecode.com/>.
  11. *
  12. * MUNGE is free software: you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation, either version 3 of the License, or (at your option)
  15. * any later version. Additionally for the MUNGE library (libmunge), you
  16. * can redistribute it and/or modify it under the terms of the GNU Lesser
  17. * General Public License as published by the Free Software Foundation,
  18. * either version 3 of the License, or (at your option) any later version.
  19. *
  20. * MUNGE is distributed in the hope that it will be useful, but WITHOUT
  21. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  22. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  23. * and GNU Lesser General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * and GNU Lesser General Public License along with MUNGE. If not, see
  27. * <http://www.gnu.org/licenses/>.
  28. *****************************************************************************/
  29. #if HAVE_CONFIG_H
  30. # include <config.h>
  31. #endif /* HAVE_CONFIG_H */
  32. #include <assert.h>
  33. #include <string.h>
  34. #include "base64.h"
  35. /*****************************************************************************
  36. * Notes
  37. *****************************************************************************/
  38. /*
  39. * For details on base64 encoding/decoding, refer to
  40. * rfc2440 (OpenPGP Message Format) sections 6.3-6.5.
  41. *
  42. * Why am I not using OpenSSL's base64 encoding/decoding functions?
  43. * Because they have the following fucked functionality:
  44. * For base64-encoding, use of the context results in output that is broken
  45. * into 64-character lines; however, EVP_EncodeBlock() output is not broken.
  46. * For base64-decoding, use of the context returns the correct length of the
  47. * resulting output; however, EVP_DecodeBlock() returns a length that may
  48. * be up to two characters too long.
  49. * Finally, data base64-encoded via a context has to be decoded via a context,
  50. * and data base64-encoded w/o a context has to be decoded w/o a context.
  51. * So fuck it, I wrote my own. :-P
  52. */
  53. /*****************************************************************************
  54. * Constants
  55. *****************************************************************************/
  56. #define BASE64_MAGIC 0xDEADBEEF
  57. #define BASE64_ERR 0xFF
  58. #define BASE64_IGN 0xFE
  59. #define BASE64_PAD 0xFD
  60. #define BASE64_PAD_CHAR '='
  61. /*****************************************************************************
  62. * Static Variables
  63. *****************************************************************************/
  64. static const unsigned char bin2asc[] = \
  65. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  66. static const unsigned char asc2bin[256] = {
  67. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe,
  68. 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  69. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
  70. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
  71. 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
  72. 0xff, 0xfd, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  73. 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
  74. 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
  75. 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
  76. 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
  77. 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  78. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  79. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  80. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  81. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  82. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  83. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  84. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  85. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  86. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  87. 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  88. 0xff, 0xff, 0xff, 0xff
  89. };
  90. /*****************************************************************************
  91. * Extern Functions
  92. *****************************************************************************/
  93. int
  94. base64_init (base64_ctx *x)
  95. {
  96. assert (x != NULL);
  97. x->num = 0;
  98. x->pad = 0;
  99. assert (x->magic = BASE64_MAGIC);
  100. assert (!(x->finalized = 0));
  101. return (0);
  102. }
  103. int
  104. base64_encode_update (base64_ctx *x, void *vdst, int *dstlen,
  105. const void *vsrc, int srclen)
  106. {
  107. int n;
  108. int num_read;
  109. int num_write;
  110. unsigned char *dst = (unsigned char *) vdst;
  111. unsigned char *src = (unsigned char *) vsrc;
  112. assert (x != NULL);
  113. assert (x->magic == BASE64_MAGIC);
  114. assert (x->finalized != 1);
  115. assert (dst != NULL);
  116. assert (dstlen != NULL);
  117. assert (src != NULL);
  118. num_write = 0;
  119. if (srclen <= 0) {
  120. return (0);
  121. }
  122. /* Encode leftover data if context buffer can be filled.
  123. */
  124. if ((x->num > 0) && (srclen >= (num_read = 3 - x->num))) {
  125. memcpy (&x->buf[x->num], src, num_read);
  126. src += num_read;
  127. srclen -= num_read;
  128. base64_encode_block (dst, &n, x->buf, 3);
  129. x->num = 0;
  130. dst += n;
  131. num_write += n;
  132. }
  133. /* Encode maximum amount of data w/o requiring a pad.
  134. */
  135. if (srclen >= 3) {
  136. num_read = (srclen / 3) * 3;
  137. base64_encode_block (dst, &n, src, num_read);
  138. src += num_read;
  139. srclen -= num_read;
  140. num_write += n;
  141. }
  142. /* Save leftover data for the next update() or final().
  143. */
  144. if (srclen > 0) {
  145. memcpy (&x->buf[x->num], src, srclen);
  146. x->num += srclen;
  147. }
  148. *dstlen = num_write;
  149. return (0);
  150. }
  151. int
  152. base64_encode_final (base64_ctx *x, void *dst, int *dstlen)
  153. {
  154. assert (x != NULL);
  155. assert (x->magic == BASE64_MAGIC);
  156. assert (x->finalized != 1);
  157. assert (dst != NULL);
  158. assert (dstlen != NULL);
  159. /* Encode leftover data from the previous update().
  160. */
  161. if (x->num > 0) {
  162. base64_encode_block (dst, dstlen, x->buf, x->num);
  163. x->num = 0;
  164. }
  165. else {
  166. *dstlen = 0;
  167. }
  168. assert (x->finalized = 1);
  169. return (0);
  170. }
  171. int
  172. base64_decode_update (base64_ctx *x, void *dst, int *dstlen,
  173. const void *src, int srclen)
  174. {
  175. /* Context [x] should only be NULL when called via base64_decode_block().
  176. */
  177. int i = 0;
  178. int err = 0;
  179. int pad = 0;
  180. unsigned char *pdst;
  181. const unsigned char *psrc;
  182. const unsigned char *psrc_last;
  183. unsigned char c;
  184. assert ((x == NULL) || (x->magic == BASE64_MAGIC));
  185. assert ((x == NULL) || (x->finalized != 1));
  186. assert (dst != NULL);
  187. assert (dstlen != NULL);
  188. assert (src != NULL);
  189. pdst = dst;
  190. psrc = src;
  191. psrc_last = psrc + srclen;
  192. /* Restore context.
  193. */
  194. if (x != NULL) {
  195. i = x->num;
  196. pad = x->pad;
  197. *pdst = x->buf[0];
  198. }
  199. while (psrc < psrc_last) {
  200. c = asc2bin[*psrc++];
  201. if (c == BASE64_IGN) {
  202. continue;
  203. }
  204. if ((c == BASE64_PAD) && (pad < 2)) {
  205. pad++;
  206. continue;
  207. }
  208. if ((c == BASE64_ERR) || (pad > 0)) {
  209. err++;
  210. break;
  211. }
  212. switch (i) {
  213. case 0:
  214. *pdst = (c << 2) & 0xfc;
  215. break;
  216. case 1:
  217. *pdst++ |= (c >> 4) & 0x03;
  218. *pdst = (c << 4) & 0xf0;
  219. break;
  220. case 2:
  221. *pdst++ |= (c >> 2) & 0x0f;
  222. *pdst = (c << 6) & 0xc0;
  223. break;
  224. case 3:
  225. *pdst++ |= (c ) & 0x3f;
  226. break;
  227. }
  228. i = (i + 1) % 4;
  229. }
  230. /* Save context.
  231. */
  232. if (x != NULL) {
  233. x->num = i;
  234. x->pad = pad;
  235. x->buf[0] = *pdst;
  236. }
  237. /* Check for the correct amount of padding.
  238. */
  239. else if (!err) {
  240. err = (((i + pad) % 4) != 0);
  241. }
  242. *pdst = '\0';
  243. *dstlen = pdst - (unsigned char *) dst;
  244. return (err ? -1 : 0);
  245. }
  246. int
  247. base64_decode_final (base64_ctx *x, void *dst, int *dstlen)
  248. {
  249. int rc = 0;
  250. assert (x != NULL);
  251. assert (x->magic == BASE64_MAGIC);
  252. assert (x->finalized != 1);
  253. if (((x->num + x->pad) % 4) != 0) {
  254. rc = -1;
  255. }
  256. *dstlen = 0;
  257. assert (x->finalized = 1);
  258. return (rc);
  259. }
  260. int
  261. base64_cleanup (base64_ctx *x)
  262. {
  263. assert (x != NULL);
  264. assert (x->magic == BASE64_MAGIC);
  265. memset (x, 0, sizeof (*x));
  266. assert (x->magic = ~BASE64_MAGIC);
  267. return (0);
  268. }
  269. int
  270. base64_encode_block (void *dst, int *dstlen, const void *src, int srclen)
  271. {
  272. unsigned char *pdst;
  273. const unsigned char *psrc;
  274. int n;
  275. pdst = dst;
  276. psrc = src;
  277. n = 0;
  278. while (srclen >= 3) {
  279. *pdst++ = bin2asc[ (psrc[0] >> 2) & 0x3f];
  280. *pdst++ = bin2asc[((psrc[0] << 4) & 0x30) | ((psrc[1] >> 4) & 0x0f)];
  281. *pdst++ = bin2asc[((psrc[1] << 2) & 0x3c) | ((psrc[2] >> 6) & 0x03)];
  282. *pdst++ = bin2asc[ (psrc[2] ) & 0x3f];
  283. psrc += 3;
  284. srclen -= 3;
  285. n += 4;
  286. }
  287. if (srclen == 2) {
  288. *pdst++ = bin2asc[ (psrc[0] >> 2) & 0x3f];
  289. *pdst++ = bin2asc[((psrc[0] << 4) & 0x30) | ((psrc[1] >> 4) & 0x0f)];
  290. *pdst++ = bin2asc[ (psrc[1] << 2) & 0x3c];
  291. *pdst++ = '=';
  292. n += 4;
  293. }
  294. else if (srclen == 1) {
  295. *pdst++ = bin2asc[ (psrc[0] >> 2) & 0x3f];
  296. *pdst++ = bin2asc[ (psrc[0] << 4) & 0x30];
  297. *pdst++ = '=';
  298. *pdst++ = '=';
  299. n += 4;
  300. }
  301. *pdst = '\0';
  302. *dstlen = n;
  303. return (0);
  304. }
  305. int
  306. base64_decode_block (void *dst, int *dstlen, const void *src, int srclen)
  307. {
  308. return (base64_decode_update (NULL, dst, dstlen, src, srclen));
  309. }
  310. int
  311. base64_encode_length (int srclen)
  312. {
  313. /* When encoding, 3 bytes are encoded into 4 characters.
  314. * Add 2 bytes to ensure a partial 3-byte chunk will be accounted for
  315. * during integer division, then add 1 byte for the terminating NUL.
  316. */
  317. return (((srclen + 2) / 3) * 4) + 1;
  318. }
  319. int
  320. base64_decode_length (int srclen)
  321. {
  322. /* When decoding, 4 characters are decoded into 3 bytes.
  323. * Add 3 bytes to ensure a partial 4-byte chunk will be accounted for
  324. * during integer division, then add 1 byte for the terminating NUL.
  325. */
  326. return (((srclen + 3) / 4) * 3) + 1;
  327. }
  328. /*****************************************************************************
  329. * Table Initialization Routines
  330. *****************************************************************************/
  331. #ifdef BASE64_INIT
  332. #include <ctype.h>
  333. #include <stdio.h>
  334. #include <stdlib.h>
  335. #define BASE64_DEF_COLS 12
  336. void base64_build_table (unsigned char *data, int len);
  337. void base64_print_table (unsigned char *data, int len, char *name, int col);
  338. int
  339. main (int argc, char *argv[])
  340. {
  341. int col;
  342. unsigned char a2b[256];
  343. col = (argc > 1) ? atoi (argv[1]) : BASE64_DEF_COLS;
  344. base64_build_table (a2b, sizeof (a2b));
  345. base64_print_table (a2b, sizeof (a2b), "asc2bin", col);
  346. exit (EXIT_SUCCESS);
  347. }
  348. void
  349. base64_build_table (unsigned char *data, int len)
  350. {
  351. int i;
  352. for (i = 0; i < len; i++)
  353. data[i] = (isspace (i)) ? BASE64_IGN : BASE64_ERR;
  354. for (i = strlen (bin2asc) - 1; i >= 0; i--)
  355. data[bin2asc[i]] = i;
  356. data[BASE64_PAD_CHAR] = BASE64_PAD;
  357. return;
  358. }
  359. void
  360. base64_print_table (unsigned char *data, int len, char *name, int col)
  361. {
  362. int i;
  363. int n;
  364. if (col < 1) {
  365. col = BASE64_DEF_COLS;
  366. }
  367. printf ("static const unsigned char %s[%d] = {", name, len);
  368. for (i=0, n=len-1; ; i++) {
  369. if ((i % col) == 0)
  370. printf ("\n ");
  371. printf ("0x%02x", data[i]);
  372. if (i == n)
  373. break;
  374. printf (", ");
  375. }
  376. printf ("\n};\n");
  377. return;
  378. }
  379. #endif /* BASE64_INIT */