base64.c 2.4 KB

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