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