1 /*
2 * Copyright (C) 2001-2012 Free Software Foundation, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 #include "gnutls_int.h"
24 #include "errors.h"
25 #include <datum.h>
26 #include <auth/srp_passwd.h>
27
28 #ifdef ENABLE_SRP
29
30 /* this is a modified base64 for srp !!!
31 * It seems that everybody makes their own base64 conversion.
32 */
33 static const uint8_t b64table[] =
34 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
35
36 static const uint8_t asciitable[128] = {
37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f,
45 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
46 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
47 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a,
48 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
49 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
50 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
51 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
52 0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
53 0xff, 0x24, 0x25, 0x26, 0x27, 0x28,
54 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
55 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
56 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
57 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff,
58 0xff, 0xff
59 };
60
encode(uint8_t * result,const uint8_t * rdata,unsigned left)61 inline static int encode(uint8_t * result, const uint8_t * rdata, unsigned left)
62 {
63
64 int data_len;
65 int c, ret = 4;
66 uint8_t data[3];
67
68 if (left > 3)
69 data_len = 3;
70 else
71 data_len = left;
72
73 data[0] = data[1] = data[2] = 0;
74 memcpy(data, rdata, data_len);
75
76 switch (data_len) {
77 case 3:
78 result[0] = b64table[((data[0] & 0xfc) >> 2)];
79 result[1] =
80 b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
81 ((data[1] & 0xf0) >> 4))];
82 result[2] =
83 b64table[((((data[1] & 0x0f) << 2) & 0xff) |
84 ((data[2] & 0xc0) >> 6))];
85 result[3] = b64table[(data[2] & 0x3f) & 0xff];
86 break;
87 case 2:
88 if ((c = ((data[0] & 0xf0) >> 4)) != 0) {
89 result[0] = b64table[c];
90 result[1] =
91 b64table[((((data[0] & 0x0f) << 2) & 0xff) |
92 ((data[1] & 0xc0) >> 6))];
93 result[2] = b64table[(data[1] & 0x3f) & 0xff];
94 result[3] = '\0';
95 ret -= 1;
96 } else {
97 if ((c =
98 ((data[0] & 0x0f) << 2) | ((data[1] & 0xc0) >>
99 6)) != 0) {
100 result[0] = b64table[c];
101 result[1] = b64table[data[1] & 0x3f];
102 result[2] = '\0';
103 result[3] = '\0';
104 ret -= 2;
105 } else {
106 result[0] = b64table[data[0] & 0x3f];
107 result[1] = '\0';
108 result[2] = '\0';
109 result[3] = '\0';
110 ret -= 3;
111 }
112 }
113 break;
114 case 1:
115 if ((c = ((data[0] & 0xc0) >> 6)) != 0) {
116 result[0] = b64table[c];
117 result[1] = b64table[(data[0] & 0x3f) & 0xff];
118 result[2] = '\0';
119 result[3] = '\0';
120 ret -= 2;
121 } else {
122 result[0] = b64table[(data[0] & 0x3f) & 0xff];
123 result[1] = '\0';
124 result[2] = '\0';
125 result[3] = '\0';
126 ret -= 3;
127 }
128 break;
129 default:
130 return GNUTLS_E_BASE64_ENCODING_ERROR;
131 }
132
133 return ret;
134
135 }
136
137 /* encodes data and puts the result into result (locally allocated)
138 * The result_size is the return value
139 */
140 static int
_gnutls_sbase64_encode(uint8_t * data,size_t data_size,char ** result)141 _gnutls_sbase64_encode(uint8_t * data, size_t data_size, char **result)
142 {
143 unsigned i, j;
144 int ret, tmp;
145 uint8_t tmpres[4];
146 unsigned mod = data_size % 3;
147
148 ret = mod;
149 if (ret != 0)
150 ret = 4;
151 else
152 ret = 0;
153
154 ret += (data_size * 4) / 3;
155
156 (*result) = gnutls_calloc(1, ret + 1);
157 if ((*result) == NULL)
158 return GNUTLS_E_MEMORY_ERROR;
159
160 i = j = 0;
161 /* encode the bytes that are not a multiple of 3
162 */
163 if (mod > 0) {
164 tmp = encode(tmpres, &data[0], mod);
165 if (tmp < 0) {
166 gnutls_free((*result));
167 return tmp;
168 }
169
170 memcpy(&(*result)[0], tmpres, tmp);
171 i = mod;
172 j = tmp;
173
174 }
175 /* encode the rest
176 */
177 for (; i < data_size; i += 3, j += 4) {
178 tmp = encode(tmpres, &data[i], data_size - i);
179 if (tmp < 0) {
180 gnutls_free((*result));
181 return tmp;
182 }
183 memcpy(&(*result)[j], tmpres, tmp);
184 }
185
186 return strlen(*result);
187 }
188
189
190 /* data must be 4 bytes
191 * result should be 3 bytes
192 */
193 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
decode(uint8_t * result,const uint8_t * data)194 inline static int decode(uint8_t * result, const uint8_t * data)
195 {
196 uint8_t a1, a2;
197 int ret = 3;
198
199 memset(result, 0, 3);
200
201 a1 = TOASCII(data[3]);
202 a2 = TOASCII(data[2]);
203 if (a1 != 0xff)
204 result[2] = a1 & 0xff;
205 else
206 return GNUTLS_E_BASE64_DECODING_ERROR;
207 if (a2 != 0xff)
208 result[2] |= ((a2 & 0x03) << 6) & 0xff;
209
210 a1 = a2;
211 a2 = TOASCII(data[1]);
212 if (a1 != 0xff)
213 result[1] = ((a1 & 0x3c) >> 2);
214 if (a2 != 0xff)
215 result[1] |= ((a2 & 0x0f) << 4);
216 else if (a1 == 0xff || result[1] == 0)
217 ret--;
218
219 a1 = a2;
220 a2 = TOASCII(data[0]);
221 if (a1 != 0xff)
222 result[0] = (((a1 & 0x30) >> 4) & 0xff);
223 if (a2 != 0xff)
224 result[0] |= ((a2 << 2) & 0xff);
225 else if (a1 == 0xff || result[0] == 0)
226 ret--;
227
228 return ret;
229 }
230
231 /* decodes data and puts the result into result (locally allocated)
232 * The result_size is the return value.
233 * That function does not ignore newlines tabs etc. You should remove them
234 * before calling it.
235 */
236 int
_gnutls_sbase64_decode(char * data,size_t idata_size,uint8_t ** result)237 _gnutls_sbase64_decode(char *data, size_t idata_size, uint8_t ** result)
238 {
239 unsigned i, j;
240 int ret, left;
241 int data_size, tmp;
242 uint8_t datrev[4];
243 uint8_t tmpres[3];
244
245 data_size = (idata_size / 4) * 4;
246 left = idata_size % 4;
247
248 ret = (data_size / 4) * 3;
249
250 if (left > 0)
251 ret += 3;
252
253 (*result) = gnutls_malloc(ret + 1);
254 if ((*result) == NULL)
255 return GNUTLS_E_MEMORY_ERROR;
256
257 /* the first "block" is treated with special care */
258 tmp = 0;
259 if (left > 0) {
260 memset(datrev, 0, 4);
261 memcpy(&datrev[4 - left], data, left);
262
263 tmp = decode(tmpres, datrev);
264 if (tmp < 0) {
265 gnutls_free((*result));
266 return tmp;
267 }
268
269 memcpy(*result, &tmpres[3 - tmp], tmp);
270 if (tmp < 3)
271 ret -= (3 - tmp);
272 }
273
274 /* rest data */
275 for (i = left, j = tmp; i < idata_size; i += 4) {
276 tmp = decode(tmpres, (uint8_t *) & data[i]);
277 if (tmp < 0) {
278 gnutls_free((*result));
279 return tmp;
280 }
281 memcpy(&(*result)[j], tmpres, tmp);
282 if (tmp < 3)
283 ret -= (3 - tmp);
284 j += 3;
285 }
286
287 return ret;
288 }
289
290 /**
291 * gnutls_srp_base64_encode:
292 * @data: contain the raw data
293 * @result: the place where base64 data will be copied
294 * @result_size: holds the size of the result
295 *
296 * This function will convert the given data to printable data, using
297 * the base64 encoding, as used in the libsrp. This is the encoding
298 * used in SRP password files. If the provided buffer is not long
299 * enough GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
300 *
301 * Warning! This base64 encoding is not the "standard" encoding, so
302 * do not use it for non-SRP purposes.
303 *
304 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
305 * long enough, or 0 on success.
306 **/
307 int
gnutls_srp_base64_encode(const gnutls_datum_t * data,char * result,size_t * result_size)308 gnutls_srp_base64_encode(const gnutls_datum_t * data, char *result,
309 size_t * result_size)
310 {
311 char *res;
312 int size;
313
314 size = _gnutls_sbase64_encode(data->data, data->size, &res);
315 if (size < 0)
316 return size;
317
318 if (result == NULL || *result_size < (size_t) size) {
319 gnutls_free(res);
320 *result_size = size;
321 return GNUTLS_E_SHORT_MEMORY_BUFFER;
322 } else {
323 memcpy(result, res, size);
324 gnutls_free(res);
325 *result_size = size;
326 }
327
328 return 0;
329 }
330
331 /**
332 * gnutls_srp_base64_encode2:
333 * @data: contains the raw data
334 * @result: will hold the newly allocated encoded data
335 *
336 * This function will convert the given data to printable data, using
337 * the base64 encoding. This is the encoding used in SRP password
338 * files. This function will allocate the required memory to hold
339 * the encoded data.
340 *
341 * You should use gnutls_free() to free the returned data.
342 *
343 * Warning! This base64 encoding is not the "standard" encoding, so
344 * do not use it for non-SRP purposes.
345 *
346 * Returns: 0 on success, or an error code.
347 **/
348 int
gnutls_srp_base64_encode2(const gnutls_datum_t * data,gnutls_datum_t * result)349 gnutls_srp_base64_encode2(const gnutls_datum_t * data,
350 gnutls_datum_t * result)
351 {
352 char *res;
353 int size;
354
355 size = _gnutls_sbase64_encode(data->data, data->size, &res);
356 if (size < 0)
357 return size;
358
359 if (result == NULL) {
360 gnutls_free(res);
361 return GNUTLS_E_INVALID_REQUEST;
362 } else {
363 result->data = (uint8_t *) res;
364 result->size = size;
365 }
366
367 return 0;
368 }
369
370 /**
371 * gnutls_srp_base64_decode:
372 * @b64_data: contain the encoded data
373 * @result: the place where decoded data will be copied
374 * @result_size: holds the size of the result
375 *
376 * This function will decode the given encoded data, using the base64
377 * encoding found in libsrp.
378 *
379 * Note that @b64_data should be null terminated.
380 *
381 * Warning! This base64 encoding is not the "standard" encoding, so
382 * do not use it for non-SRP purposes.
383 *
384 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
385 * long enough, or 0 on success.
386 **/
387 int
gnutls_srp_base64_decode(const gnutls_datum_t * b64_data,char * result,size_t * result_size)388 gnutls_srp_base64_decode(const gnutls_datum_t * b64_data, char *result,
389 size_t * result_size)
390 {
391 uint8_t *res;
392 int size;
393
394 size =
395 _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size,
396 &res);
397 if (size < 0)
398 return size;
399
400 if (result == NULL || *result_size < (size_t) size) {
401 gnutls_free(res);
402 *result_size = size;
403 return GNUTLS_E_SHORT_MEMORY_BUFFER;
404 } else {
405 memcpy(result, res, size);
406 gnutls_free(res);
407 *result_size = size;
408 }
409
410 return 0;
411 }
412
413 /**
414 * gnutls_srp_base64_decode2:
415 * @b64_data: contains the encoded data
416 * @result: the place where decoded data lie
417 *
418 * This function will decode the given encoded data. The decoded data
419 * will be allocated, and stored into result. It will decode using
420 * the base64 algorithm as used in libsrp.
421 *
422 * You should use gnutls_free() to free the returned data.
423 *
424 * Warning! This base64 encoding is not the "standard" encoding, so
425 * do not use it for non-SRP purposes.
426 *
427 * Returns: 0 on success, or an error code.
428 **/
429 int
gnutls_srp_base64_decode2(const gnutls_datum_t * b64_data,gnutls_datum_t * result)430 gnutls_srp_base64_decode2(const gnutls_datum_t * b64_data,
431 gnutls_datum_t * result)
432 {
433 uint8_t *ret;
434 int size;
435
436 size =
437 _gnutls_sbase64_decode((char *) b64_data->data, b64_data->size,
438 &ret);
439 if (size < 0)
440 return size;
441
442 if (result == NULL) {
443 gnutls_free(ret);
444 return GNUTLS_E_INVALID_REQUEST;
445 } else {
446 result->data = ret;
447 result->size = size;
448 }
449
450 return 0;
451 }
452
453 #endif /* ENABLE_SRP */
454