base64.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /*
  2. * Base64 encoding/decoding (RFC1341)
  3. * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. */
  13. #include "base64.h"
  14. #include <string.h>
  15. static const uint8_t dtable[] = {0x3e, 0x80, 0x80, 0x80, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38,
  16. 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x0, 0x80,
  17. 0x80, 0x80, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
  18. 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11,
  19. 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80,
  20. 0x80, 0x80, 0x80, 0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
  21. 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
  22. 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33};
  23. static uint8_t get_dtable_value(uint8_t index) {
  24. return (index < 43 || index > 122) ? 0x80 : dtable[index - 43];
  25. }
  26. uint8_t* base64_decode(const uint8_t* src, size_t len, size_t* out_len, size_t* out_size) {
  27. uint8_t* out;
  28. uint8_t* pos;
  29. uint8_t in[4];
  30. uint8_t block[4];
  31. uint8_t tmp;
  32. size_t i;
  33. size_t count;
  34. size_t olen;
  35. count = 0;
  36. for(i = 0; i < len; i++) {
  37. if(get_dtable_value(src[i]) != 0x80) count++;
  38. }
  39. if(count == 0 || count % 4) return NULL;
  40. olen = count / 4 * 3;
  41. pos = out = malloc(olen);
  42. *out_size = olen;
  43. if(out == NULL) return NULL;
  44. count = 0;
  45. for(i = 0; i < len; i++) {
  46. tmp = get_dtable_value(src[i]);
  47. if(tmp == 0x80) continue;
  48. in[count] = src[i];
  49. block[count] = tmp;
  50. count++;
  51. if(count == 4) {
  52. *pos++ = (block[0] << 2) | (block[1] >> 4);
  53. *pos++ = (block[1] << 4) | (block[2] >> 2);
  54. *pos++ = (block[2] << 6) | block[3];
  55. count = 0;
  56. }
  57. }
  58. if(pos > out) {
  59. if(in[2] == '=')
  60. pos -= 2;
  61. else if(in[3] == '=')
  62. pos--;
  63. }
  64. *out_len = pos - out;
  65. return out;
  66. }