1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Base64 Encoding & Decoding
4 *
5 * Copyright 2011-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <winpr/crt.h>
25
26 #include <freerdp/crypto/crypto.h>
27
28 static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
29
crypto_base64_encode(const BYTE * data,int length)30 char* crypto_base64_encode(const BYTE* data, int length)
31 {
32 int c;
33 const BYTE* q;
34 char* p;
35 char* ret;
36 int i = 0;
37 int blocks;
38
39 q = data;
40 p = ret = (char*)malloc((length + 3) * 4 / 3 + 1);
41 if (!p)
42 return NULL;
43
44 /* b1, b2, b3 are input bytes
45 *
46 * 0 1 2
47 * 012345678901234567890123
48 * | b1 | b2 | b3 |
49 *
50 * [ c1 ] [ c3 ]
51 * [ c2 ] [ c4 ]
52 *
53 * c1, c2, c3, c4 are output chars in base64
54 */
55
56 /* first treat complete blocks */
57 blocks = length - (length % 3);
58 for (i = 0; i < blocks; i += 3, q += 3)
59 {
60 c = (q[0] << 16) + (q[1] << 8) + q[2];
61
62 *p++ = base64[(c & 0x00FC0000) >> 18];
63 *p++ = base64[(c & 0x0003F000) >> 12];
64 *p++ = base64[(c & 0x00000FC0) >> 6];
65 *p++ = base64[c & 0x0000003F];
66 }
67
68 /* then remainder */
69 switch (length % 3)
70 {
71 case 0:
72 break;
73 case 1:
74 c = (q[0] << 16);
75 *p++ = base64[(c & 0x00FC0000) >> 18];
76 *p++ = base64[(c & 0x0003F000) >> 12];
77 *p++ = '=';
78 *p++ = '=';
79 break;
80 case 2:
81 c = (q[0] << 16) + (q[1] << 8);
82 *p++ = base64[(c & 0x00FC0000) >> 18];
83 *p++ = base64[(c & 0x0003F000) >> 12];
84 *p++ = base64[(c & 0x00000FC0) >> 6];
85 *p++ = '=';
86 break;
87 }
88
89 *p = 0;
90
91 return ret;
92 }
93
base64_decode_char(char c)94 static int base64_decode_char(char c)
95 {
96 if (c >= 'A' && c <= 'Z')
97 return c - 'A';
98
99 if (c >= 'a' && c <= 'z')
100 return c - 'a' + 26;
101
102 if (c >= '0' && c <= '9')
103 return c - '0' + 52;
104
105 if (c == '+')
106 return 62;
107
108 if (c == '/')
109 return 63;
110
111 if (c == '=')
112 return -1;
113
114 return -1;
115 }
116
base64_decode(const char * s,int length,int * data_len)117 static void* base64_decode(const char* s, int length, int* data_len)
118 {
119 int n[4];
120 BYTE* q;
121 BYTE* data;
122 int nBlocks, i, outputLen;
123
124 if (length % 4)
125 return NULL;
126
127 q = data = (BYTE*)malloc(length / 4 * 3 + 1);
128 if (!q)
129 return NULL;
130
131 /* first treat complete blocks */
132 nBlocks = (length / 4);
133 outputLen = 0;
134
135 for (i = 0; i < nBlocks - 1; i++, q += 3)
136 {
137 n[0] = base64_decode_char(*s++);
138 n[1] = base64_decode_char(*s++);
139 n[2] = base64_decode_char(*s++);
140 n[3] = base64_decode_char(*s++);
141
142 if ((n[0] == -1) || (n[1] == -1) || (n[2] == -1) || (n[3] == -1))
143 goto out_free;
144
145 q[0] = (n[0] << 2) + (n[1] >> 4);
146 q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
147 q[2] = ((n[2] & 3) << 6) + n[3];
148 outputLen += 3;
149 }
150
151 /* treat last block */
152 n[0] = base64_decode_char(*s++);
153 n[1] = base64_decode_char(*s++);
154 if ((n[0] == -1) || (n[1] == -1))
155 goto out_free;
156
157 n[2] = base64_decode_char(*s++);
158 n[3] = base64_decode_char(*s++);
159
160 q[0] = (n[0] << 2) + (n[1] >> 4);
161 if (n[2] == -1)
162 {
163 /* XX== */
164 outputLen += 1;
165 if (n[3] != -1)
166 goto out_free;
167
168 q[1] = ((n[1] & 15) << 4);
169 }
170 else if (n[3] == -1)
171 {
172 /* yyy= */
173 outputLen += 2;
174 q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
175 q[2] = ((n[2] & 3) << 6);
176 }
177 else
178 {
179 /* XXXX */
180 outputLen += 3;
181 q[0] = (n[0] << 2) + (n[1] >> 4);
182 q[1] = ((n[1] & 15) << 4) + (n[2] >> 2);
183 q[2] = ((n[2] & 3) << 6) + n[3];
184 }
185
186 *data_len = outputLen;
187 data[outputLen] = '\0';
188
189 return data;
190 out_free:
191 free(data);
192 return NULL;
193 }
194
crypto_base64_decode(const char * enc_data,int length,BYTE ** dec_data,int * res_length)195 void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length)
196 {
197 *dec_data = base64_decode(enc_data, length, res_length);
198 }
199