1 #include "byte.h"
2 #include "dns.h"
3 
4 static const char base32_digits[32] = "0123456789bcdfghjklmnpqrstuvwxyz";
5 
dns_base32_bytessize(long long len)6 long long dns_base32_bytessize(long long len) {
7 
8     if (len < 0) return 0;
9     len = (8 * len + 4) / 5;
10     return len + (len + 49) / 50;
11 }
12 
dns_base32_encodebytes(unsigned char * out,const unsigned char * in,long long len)13 void dns_base32_encodebytes(unsigned char *out, const unsigned char *in, long long len) {
14 
15     unsigned long long i, x, v, vbits;
16 
17     if (len < 0) return;
18 
19     x = v = vbits = 0;
20     for (i = 0; i < len; ++i) {
21         v |= ((unsigned long long)in[i]) << vbits;
22         vbits += 8;
23         do {
24             out[++x] = base32_digits[v & 31];
25             v >>= 5;
26             vbits -= 5;
27             if (x == 50) {
28                 *out = x;
29                 out += 1 + x;
30                 x = 0;
31             }
32         } while (vbits >= 5);
33     }
34 
35     if (vbits) out[++x] = base32_digits[v & 31];
36     if (x) *out = x;
37 }
38 
dns_base32_encodekey(unsigned char * out,const unsigned char * key)39 void dns_base32_encodekey(unsigned char *out, const unsigned char *key) {
40 
41     unsigned long long i, v, vbits;
42 
43     byte_copy(out, 4, "\66x1a");
44     out += 4;
45 
46     v = vbits = 0;
47     for (i = 0; i < 32; ++i) {
48         v |= ((unsigned long long)key[i]) << vbits;
49         vbits += 8;
50         do {
51             *out++ = base32_digits[v & 31];
52             v >>= 5;
53             vbits -= 5;
54         } while (vbits >= 5);
55     }
56 }
57 
58 static const unsigned char val[128] = {
59     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
62     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
66     0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67     0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e,
68     0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff,
69     0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
70     0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff,
71     0xff, 0xff, 0x0a, 0x0b, 0x0c, 0xff, 0x0d, 0x0e,
72     0x0f, 0xff, 0x10, 0x11, 0x12, 0x13, 0x14, 0xff,
73     0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
74     0x1d, 0x1e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff
75 };
76 
77 
78 
base32_decode(unsigned char * out,const unsigned char * in,long long len,int mode)79 long long base32_decode(unsigned char *out, const unsigned char *in, long long len, int mode) {
80 
81     long long i;
82     unsigned long long x, v, vbits;
83     unsigned char *out0 = out;
84 
85     if (len < 0) return 0;
86 
87     v = vbits = 0;
88     for (i = 0; i < len; ++i) {
89         if (in[i] & 0x80) return 0;
90         x = val[in[i]];
91         if (x > 0x1f) return 0;
92         v |= x << vbits;
93         vbits += 5;
94         if (vbits >= 8) {
95             *out++ = v;
96             v >>= 8;
97             vbits -= 8;
98         }
99     }
100 
101     if (mode) {
102         if (vbits)
103             *out++ = v;
104     }
105     else if (vbits >= 5 || v)
106         return 0;
107 
108     return out - out0;
109 }
110