1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier
4*8ccd4a63SDavid du Colombier enum {
5*8ccd4a63SDavid du Colombier INVAL= 255
6*8ccd4a63SDavid du Colombier };
7*8ccd4a63SDavid du Colombier
8*8ccd4a63SDavid du Colombier static uchar t64d[256] = {
9*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
10*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
11*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL, 62,INVAL,INVAL,INVAL, 63,
12*8ccd4a63SDavid du Colombier 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
13*8ccd4a63SDavid du Colombier INVAL, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
14*8ccd4a63SDavid du Colombier 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,INVAL,INVAL,INVAL,INVAL,INVAL,
15*8ccd4a63SDavid du Colombier INVAL, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
16*8ccd4a63SDavid du Colombier 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,INVAL,INVAL,INVAL,INVAL,INVAL,
17*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
18*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
19*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
20*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
21*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
22*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
23*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,
24*8ccd4a63SDavid du Colombier INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL,INVAL
25*8ccd4a63SDavid du Colombier };
26*8ccd4a63SDavid du Colombier static char t64e[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27*8ccd4a63SDavid du Colombier
28*8ccd4a63SDavid du Colombier int
dec64(uchar * out,int lim,char * in,int n)29*8ccd4a63SDavid du Colombier dec64(uchar *out, int lim, char *in, int n)
30*8ccd4a63SDavid du Colombier {
31*8ccd4a63SDavid du Colombier ulong b24;
32*8ccd4a63SDavid du Colombier uchar *start = out;
33*8ccd4a63SDavid du Colombier uchar *e = out + lim;
34*8ccd4a63SDavid du Colombier int i, c;
35*8ccd4a63SDavid du Colombier
36*8ccd4a63SDavid du Colombier b24 = 0;
37*8ccd4a63SDavid du Colombier i = 0;
38*8ccd4a63SDavid du Colombier while(n-- > 0){
39*8ccd4a63SDavid du Colombier
40*8ccd4a63SDavid du Colombier c = t64d[*(uchar*)in++];
41*8ccd4a63SDavid du Colombier if(c == INVAL)
42*8ccd4a63SDavid du Colombier continue;
43*8ccd4a63SDavid du Colombier switch(i){
44*8ccd4a63SDavid du Colombier case 0:
45*8ccd4a63SDavid du Colombier b24 = c<<18;
46*8ccd4a63SDavid du Colombier break;
47*8ccd4a63SDavid du Colombier case 1:
48*8ccd4a63SDavid du Colombier b24 |= c<<12;
49*8ccd4a63SDavid du Colombier break;
50*8ccd4a63SDavid du Colombier case 2:
51*8ccd4a63SDavid du Colombier b24 |= c<<6;
52*8ccd4a63SDavid du Colombier break;
53*8ccd4a63SDavid du Colombier case 3:
54*8ccd4a63SDavid du Colombier if(out + 3 > e)
55*8ccd4a63SDavid du Colombier goto exhausted;
56*8ccd4a63SDavid du Colombier
57*8ccd4a63SDavid du Colombier b24 |= c;
58*8ccd4a63SDavid du Colombier *out++ = b24>>16;
59*8ccd4a63SDavid du Colombier *out++ = b24>>8;
60*8ccd4a63SDavid du Colombier *out++ = b24;
61*8ccd4a63SDavid du Colombier i = -1;
62*8ccd4a63SDavid du Colombier break;
63*8ccd4a63SDavid du Colombier }
64*8ccd4a63SDavid du Colombier i++;
65*8ccd4a63SDavid du Colombier }
66*8ccd4a63SDavid du Colombier switch(i){
67*8ccd4a63SDavid du Colombier case 2:
68*8ccd4a63SDavid du Colombier if(out + 1 > e)
69*8ccd4a63SDavid du Colombier goto exhausted;
70*8ccd4a63SDavid du Colombier *out++ = b24>>16;
71*8ccd4a63SDavid du Colombier break;
72*8ccd4a63SDavid du Colombier case 3:
73*8ccd4a63SDavid du Colombier if(out + 2 > e)
74*8ccd4a63SDavid du Colombier goto exhausted;
75*8ccd4a63SDavid du Colombier *out++ = b24>>16;
76*8ccd4a63SDavid du Colombier *out++ = b24>>8;
77*8ccd4a63SDavid du Colombier break;
78*8ccd4a63SDavid du Colombier }
79*8ccd4a63SDavid du Colombier exhausted:
80*8ccd4a63SDavid du Colombier return out - start;
81*8ccd4a63SDavid du Colombier }
82*8ccd4a63SDavid du Colombier
83*8ccd4a63SDavid du Colombier int
enc64(char * out,int lim,uchar * in,int n)84*8ccd4a63SDavid du Colombier enc64(char *out, int lim, uchar *in, int n)
85*8ccd4a63SDavid du Colombier {
86*8ccd4a63SDavid du Colombier int i;
87*8ccd4a63SDavid du Colombier ulong b24;
88*8ccd4a63SDavid du Colombier char *start = out;
89*8ccd4a63SDavid du Colombier char *e = out + lim;
90*8ccd4a63SDavid du Colombier
91*8ccd4a63SDavid du Colombier for(i = n/3; i > 0; i--){
92*8ccd4a63SDavid du Colombier b24 = (*in++)<<16;
93*8ccd4a63SDavid du Colombier b24 |= (*in++)<<8;
94*8ccd4a63SDavid du Colombier b24 |= *in++;
95*8ccd4a63SDavid du Colombier if(out + 4 >= e)
96*8ccd4a63SDavid du Colombier goto exhausted;
97*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>18)];
98*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>12)&0x3f];
99*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>6)&0x3f];
100*8ccd4a63SDavid du Colombier *out++ = t64e[(b24)&0x3f];
101*8ccd4a63SDavid du Colombier }
102*8ccd4a63SDavid du Colombier
103*8ccd4a63SDavid du Colombier switch(n%3){
104*8ccd4a63SDavid du Colombier case 2:
105*8ccd4a63SDavid du Colombier b24 = (*in++)<<16;
106*8ccd4a63SDavid du Colombier b24 |= (*in)<<8;
107*8ccd4a63SDavid du Colombier if(out + 4 >= e)
108*8ccd4a63SDavid du Colombier goto exhausted;
109*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>18)];
110*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>12)&0x3f];
111*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>6)&0x3f];
112*8ccd4a63SDavid du Colombier *out++ = '=';
113*8ccd4a63SDavid du Colombier break;
114*8ccd4a63SDavid du Colombier case 1:
115*8ccd4a63SDavid du Colombier b24 = (*in)<<16;
116*8ccd4a63SDavid du Colombier if(out + 4 >= e)
117*8ccd4a63SDavid du Colombier goto exhausted;
118*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>18)];
119*8ccd4a63SDavid du Colombier *out++ = t64e[(b24>>12)&0x3f];
120*8ccd4a63SDavid du Colombier *out++ = '=';
121*8ccd4a63SDavid du Colombier *out++ = '=';
122*8ccd4a63SDavid du Colombier break;
123*8ccd4a63SDavid du Colombier }
124*8ccd4a63SDavid du Colombier exhausted:
125*8ccd4a63SDavid du Colombier *out = 0;
126*8ccd4a63SDavid du Colombier return out - start;
127*8ccd4a63SDavid du Colombier }
128