base64_c.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "base64.h"
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <assert.h>
  6. /* Encoding table as described in RFC1113. */
  7. const static uint8_t b64_encode_table[] =
  8. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  9. "abcdefghijklmnopqrstuvwxyz0123456789+/";
  10. /* Decoding table. */
  11. const static int8_t b64_decode_table[256] = {
  12. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 00-0F */
  13. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10-1F */
  14. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 20-2F */
  15. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 30-3F */
  16. -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 40-4F */
  17. 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 50-5F */
  18. -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 60-6F */
  19. 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, /* 70-7F */
  20. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80-8F */
  21. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90-9F */
  22. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A0-AF */
  23. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* B0-BF */
  24. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* C0-CF */
  25. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0-DF */
  26. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0-EF */
  27. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 /* F0-FF */
  28. };
  29. uint8_t *base64decode(const uint8_t *src, const size_t buflen, size_t *retlen)
  30. {
  31. int8_t digit, lastdigit;
  32. size_t i, j;
  33. uint8_t *decoded;
  34. const size_t maxlen = ((buflen + 3) / 4) * 3;
  35. /* Sanity check */
  36. assert(src != NULL);
  37. digit = lastdigit = j = 0;
  38. decoded = malloc(maxlen + 1);
  39. if (decoded == NULL) return NULL;
  40. for (i = 0; i < buflen; ++i) {
  41. if ((digit = b64_decode_table[src[i]]) != -1) {
  42. /* Decode block */
  43. switch (i % 4) {
  44. case 1:
  45. decoded[j++] = ((lastdigit << 2) | ((digit & 0x30) >> 4));
  46. break;
  47. case 2:
  48. decoded[j++] = (((lastdigit & 0xF) << 4) | ((digit & 0x3C) >> 2));
  49. break;
  50. case 3:
  51. decoded[j++] = (((lastdigit & 0x03) << 6) | digit);
  52. break;
  53. }
  54. lastdigit = digit;
  55. }
  56. }
  57. if (retlen != NULL) *retlen = j;
  58. decoded[j] = '\0';
  59. return decoded; /* Must be free()'d by caller */
  60. }
  61. uint8_t *base64encode(const uint8_t *src, const size_t buflen, size_t *retlen)
  62. {
  63. size_t i, j;
  64. const size_t maxlen = (((buflen + 3) & ~3)) * 4;
  65. uint8_t *encoded = malloc(maxlen + 1);
  66. if (encoded == NULL) return NULL;
  67. /* Sanity check */
  68. assert(src != NULL);
  69. assert(buflen > 0);
  70. j = 0;
  71. for (i = 0; i < buflen + 1; ++i) {
  72. /* Encode block */
  73. switch (i % 3) {
  74. case 0:
  75. encoded[j++] = b64_encode_table[src[i] >> 2];
  76. encoded[j++] = b64_encode_table[((src[i] & 0x03) << 4) |
  77. ((src[i + 1] & 0xF0) >> 4)];
  78. break;
  79. case 1:
  80. encoded[j++] = b64_encode_table[((src[i] & 0x0F) << 2) |
  81. ((src[i + 1] & 0xC0) >> 6)];
  82. break;
  83. case 2:
  84. encoded[j++] = b64_encode_table[(src[i] & 0x3F)];
  85. break;
  86. }
  87. }
  88. /* Add padding if necessary */
  89. if ((j % 4) != 0) {
  90. const size_t with_padding = ((j + 3) & ~3); /* Align to 4 bytes */
  91. do {
  92. encoded[j++] = '=';
  93. } while (j < with_padding);
  94. }
  95. assert(j <= maxlen);
  96. if (retlen != NULL) *retlen = j;
  97. encoded[j] = '\0';
  98. return encoded; /* Must be free()'d by caller */
  99. }