kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

b64.c (2100B)


      1 #include "b64.h"
      2 
      3 #include "dist.h"
      4 
      5 static const char B64_ENC[] =
      6     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
      7 
      8 size_t dist_b64_encode(char* out, const uint8_t* in, size_t n) {
      9   size_t i = 0, o = 0;
     10   while (i + 3 <= n) {
     11     uint32_t v = ((uint32_t)in[i] << 16) | ((uint32_t)in[i + 1] << 8) |
     12                  (uint32_t)in[i + 2];
     13     out[o++] = B64_ENC[(v >> 18) & 0x3f];
     14     out[o++] = B64_ENC[(v >> 12) & 0x3f];
     15     out[o++] = B64_ENC[(v >> 6) & 0x3f];
     16     out[o++] = B64_ENC[v & 0x3f];
     17     i += 3;
     18   }
     19   if (n - i == 1) {
     20     uint32_t v = (uint32_t)in[i] << 16;
     21     out[o++] = B64_ENC[(v >> 18) & 0x3f];
     22     out[o++] = B64_ENC[(v >> 12) & 0x3f];
     23     out[o++] = '=';
     24     out[o++] = '=';
     25   } else if (n - i == 2) {
     26     uint32_t v = ((uint32_t)in[i] << 16) | ((uint32_t)in[i + 1] << 8);
     27     out[o++] = B64_ENC[(v >> 18) & 0x3f];
     28     out[o++] = B64_ENC[(v >> 12) & 0x3f];
     29     out[o++] = B64_ENC[(v >> 6) & 0x3f];
     30     out[o++] = '=';
     31   }
     32   out[o] = '\0';
     33   return o;
     34 }
     35 
     36 /* Map a base64 character to its 6-bit value, or 64 for '=' / -1 on error. */
     37 static int b64_val(char c) {
     38   if (c >= 'A' && c <= 'Z') return c - 'A';
     39   if (c >= 'a' && c <= 'z') return c - 'a' + 26;
     40   if (c >= '0' && c <= '9') return c - '0' + 52;
     41   if (c == '+') return 62;
     42   if (c == '/') return 63;
     43   if (c == '=') return 64;
     44   return -1;
     45 }
     46 
     47 int dist_b64_decode(uint8_t* out, size_t* outlen, const char* in,
     48                     size_t inlen) {
     49   size_t i = 0, o = 0;
     50   if (inlen % 4u != 0u) return DIST_ERR;
     51   while (i < inlen) {
     52     int a = b64_val(in[i]);
     53     int b = b64_val(in[i + 1]);
     54     int c = b64_val(in[i + 2]);
     55     int d = b64_val(in[i + 3]);
     56     if (a < 0 || b < 0 || c < 0 || d < 0) return DIST_ERR;
     57     if (a == 64 || b == 64) return DIST_ERR; /* pad only in last two slots */
     58     out[o++] = (uint8_t)((a << 2) | (b >> 4));
     59     if (c != 64) {
     60       out[o++] = (uint8_t)((b << 4) | (c >> 2));
     61       if (d != 64) out[o++] = (uint8_t)((c << 6) | d);
     62     } else if (d != 64) {
     63       return DIST_ERR; /* '=' followed by non-'=' */
     64     }
     65     i += 4;
     66   }
     67   *outlen = o;
     68   return DIST_OK;
     69 }