Sync with TP.
[gnutls.git] / lib / auth_srp_sb64.c
blobd702c0db9e6d292a976ec180c7ef2c61f474549f
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 * USA
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_datum.h>
29 #include <auth_srp_passwd.h>
31 #ifdef ENABLE_SRP
33 /* this a modified base64 for srp !!!
34 * It seems that everybody makes an own base64 conversion.
36 static const uint8_t b64table[] =
37 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
39 static const uint8_t asciitable[128] = {
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, 0xff, 0xff,
45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
47 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f,
48 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
49 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
50 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a,
51 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
52 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
53 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
54 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
55 0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
56 0xff, 0x24, 0x25, 0x26, 0x27, 0x28,
57 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
58 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
59 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
60 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff,
61 0xff, 0xff
64 inline static int
65 encode (uint8_t * result, const uint8_t * rdata, int left)
68 int data_len;
69 int c, ret = 4;
70 uint8_t data[3];
72 if (left > 3)
73 data_len = 3;
74 else
75 data_len = left;
77 data[0] = data[1] = data[2] = 0;
78 memcpy (data, rdata, data_len);
80 switch (data_len)
82 case 3:
83 result[0] = b64table[((data[0] & 0xfc) >> 2)];
84 result[1] =
85 b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
86 ((data[1] & 0xf0) >> 4))];
87 result[2] =
88 b64table[((((data[1] & 0x0f) << 2) & 0xff) |
89 ((data[2] & 0xc0) >> 6))];
90 result[3] = b64table[(data[2] & 0x3f) & 0xff];
91 break;
92 case 2:
93 if ((c = ((data[0] & 0xf0) >> 4)) != 0)
95 result[0] = b64table[c];
96 result[1] =
97 b64table[((((data[0] & 0x0f) << 2) & 0xff) |
98 ((data[1] & 0xc0) >> 6))];
99 result[2] = b64table[(data[1] & 0x3f) & 0xff];
100 result[3] = '\0';
101 ret -= 1;
103 else
105 if ((c = ((data[0] & 0x0f) << 2) | ((data[1] & 0xc0) >> 6)) != 0)
107 result[0] = b64table[c];
108 result[1] = b64table[data[1] & 0x3f];
109 result[2] = '\0';
110 result[3] = '\0';
111 ret -= 2;
113 else
115 result[0] = b64table[data[0] & 0x3f];
116 result[1] = '\0';
117 result[2] = '\0';
118 result[3] = '\0';
119 ret -= 3;
122 break;
123 case 1:
124 if ((c = ((data[0] & 0xc0) >> 6)) != 0)
126 result[0] = b64table[c];
127 result[1] = b64table[(data[0] & 0x3f) & 0xff];
128 result[2] = '\0';
129 result[3] = '\0';
130 ret -= 2;
132 else
134 result[0] = b64table[(data[0] & 0x3f) & 0xff];
135 result[1] = '\0';
136 result[2] = '\0';
137 result[3] = '\0';
138 ret -= 3;
140 break;
141 default:
142 return -1;
145 return ret;
149 /* encodes data and puts the result into result (locally allocated)
150 * The result_size is the return value
152 static int
153 _gnutls_sbase64_encode (uint8_t * data, size_t data_size, uint8_t ** result)
155 unsigned i, j;
156 int ret, tmp;
157 opaque tmpres[4];
158 int mod = data_size % 3;
160 ret = mod;
161 if (ret != 0)
162 ret = 4;
163 else
164 ret = 0;
166 ret += (data_size * 4) / 3;
168 (*result) = gnutls_calloc (1, ret + 1);
169 if ((*result) == NULL)
170 return -1;
172 i = j = 0;
173 /* encode the bytes that are not a multiple of 3
175 if (mod > 0)
177 tmp = encode (tmpres, &data[0], mod);
178 if (tmp < 0)
180 gnutls_free ((*result));
181 return tmp;
184 memcpy (&(*result)[0], tmpres, tmp);
185 i = mod;
186 j = tmp;
189 /* encode the rest
191 for (; i < data_size; i += 3, j += 4)
193 tmp = encode (tmpres, &data[i], data_size - i);
194 if (tmp < 0)
196 gnutls_free ((*result));
197 return tmp;
199 memcpy (&(*result)[j], tmpres, tmp);
202 return strlen (*result);
206 /* data must be 4 bytes
207 * result should be 3 bytes
209 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
210 inline static int
211 decode (uint8_t * result, const uint8_t * data)
213 uint8_t a1, a2;
214 int ret = 3;
216 memset (result, 0, 3);
218 a1 = TOASCII (data[3]);
219 a2 = TOASCII (data[2]);
220 if (a1 != 0xff)
221 result[2] = a1 & 0xff;
222 else
223 return -1;
224 if (a2 != 0xff)
225 result[2] |= ((a2 & 0x03) << 6) & 0xff;
227 a1 = a2;
228 a2 = TOASCII (data[1]);
229 if (a1 != 0xff)
230 result[1] = ((a1 & 0x3c) >> 2);
231 if (a2 != 0xff)
232 result[1] |= ((a2 & 0x0f) << 4);
233 else if (a1 == 0xff || result[1] == 0)
234 ret--;
236 a1 = a2;
237 a2 = TOASCII (data[0]);
238 if (a1 != 0xff)
239 result[0] = (((a1 & 0x30) >> 4) & 0xff);
240 if (a2 != 0xff)
241 result[0] |= ((a2 << 2) & 0xff);
242 else if (a1 == 0xff || result[0] == 0)
243 ret--;
245 return ret;
248 /* decodes data and puts the result into result (locally allocated)
249 * The result_size is the return value.
250 * That function does not ignore newlines tabs etc. You should remove them
251 * before calling it.
254 _gnutls_sbase64_decode (uint8_t * data, size_t idata_size, uint8_t ** result)
256 unsigned i, j;
257 int ret, left;
258 int data_size, tmp;
259 uint8_t datrev[4];
260 uint8_t tmpres[3];
262 data_size = (idata_size / 4) * 4;
263 left = idata_size % 4;
265 ret = (data_size / 4) * 3;
267 if (left > 0)
268 ret += 3;
270 (*result) = gnutls_malloc (ret + 1);
271 if ((*result) == NULL)
272 return -1;
274 /* the first "block" is treated with special care */
275 tmp = 0;
276 if (left > 0)
278 memset (datrev, 0, 4);
279 memcpy (&datrev[4 - left], data, left);
281 tmp = decode (tmpres, datrev);
282 if (tmp < 0)
284 gnutls_free ((*result));
285 *result = NULL;
286 return tmp;
289 memcpy (*result, &tmpres[3 - tmp], tmp);
290 if (tmp < 3)
291 ret -= (3 - tmp);
294 /* rest data */
295 for (i = left, j = tmp; i < idata_size; i += 4)
297 tmp = decode (tmpres, &data[i]);
298 if (tmp < 0)
300 gnutls_free ((*result));
301 *result = NULL;
302 return tmp;
304 memcpy (&(*result)[j], tmpres, tmp);
305 if (tmp < 3)
306 ret -= (3 - tmp);
307 j += 3;
310 return ret;
314 * gnutls_srp_base64_encode - Encode raw data using SRP-Base64
315 * @data: contain the raw data
316 * @result: the place where base64 data will be copied
317 * @result_size: holds the size of the result
319 * This function will convert the given data to printable data, using
320 * the base64 encoding, as used in the libsrp. This is the encoding
321 * used in SRP password files. If the provided buffer is not long
322 * enough GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
324 * Warning! This base64 encoding is not the "standard" encoding, so
325 * do not use it for non-SRP purposes.
327 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
328 * long enough, or 0 on success.
331 gnutls_srp_base64_encode (const gnutls_datum_t * data, char *result,
332 size_t * result_size)
334 opaque *ret;
335 int size;
337 size = _gnutls_sbase64_encode (data->data, data->size, &ret);
338 if (size < 0)
339 return size;
341 if (result == NULL || *result_size < (size_t) size)
343 gnutls_free (ret);
344 *result_size = size;
345 return GNUTLS_E_SHORT_MEMORY_BUFFER;
347 else
349 memcpy (result, ret, size);
350 gnutls_free (ret);
351 *result_size = size;
354 return 0;
358 * gnutls_srp_base64_encode_alloc - encode raw data using SRP-Base64
359 * @data: contains the raw data
360 * @result: will hold the newly allocated encoded data
362 * This function will convert the given data to printable data, using
363 * the base64 encoding. This is the encoding used in SRP password
364 * files. This function will allocate the required memory to hold
365 * the encoded data.
367 * You should use gnutls_free() to free the returned data.
369 * Warning! This base64 encoding is not the "standard" encoding, so
370 * do not use it for non-SRP purposes.
372 * Returns: 0 on success, or an error code.
375 gnutls_srp_base64_encode_alloc (const gnutls_datum_t * data,
376 gnutls_datum_t * result)
378 opaque *ret;
379 int size;
381 size = _gnutls_sbase64_encode (data->data, data->size, &ret);
382 if (size < 0)
383 return size;
385 if (result == NULL)
387 gnutls_free (ret);
388 return GNUTLS_E_INVALID_REQUEST;
390 else
392 result->data = ret;
393 result->size = size;
396 return 0;
400 * gnutls_srp_base64_decode - decode SRP-base64 encoded data
401 * @b64_data: contain the encoded data
402 * @result: the place where decoded data will be copied
403 * @result_size: holds the size of the result
405 * This function will decode the given encoded data, using the base64
406 * encoding found in libsrp.
408 * Note that b64_data should be null terminated.
410 * Warning! This base64 encoding is not the "standard" encoding, so
411 * do not use it for non-SRP purposes.
413 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
414 * long enough, or 0 on success.
417 gnutls_srp_base64_decode (const gnutls_datum_t * b64_data, char *result,
418 size_t * result_size)
420 opaque *ret;
421 int size;
423 size = _gnutls_sbase64_decode (b64_data->data, b64_data->size, &ret);
424 if (size < 0)
425 return size;
427 if (result == NULL || *result_size < (size_t) size)
429 gnutls_free (ret);
430 *result_size = size;
431 return GNUTLS_E_SHORT_MEMORY_BUFFER;
433 else
435 memcpy (result, ret, size);
436 gnutls_free (ret);
437 *result_size = size;
440 return 0;
444 * gnutls_srp_base64_decode_alloc - decode SRP-base64 encoded data
445 * @b64_data: contains the encoded data
446 * @result: the place where decoded data lie
448 * This function will decode the given encoded data. The decoded data
449 * will be allocated, and stored into result. It will decode using
450 * the base64 algorithm as used in libsrp.
452 * You should use gnutls_free() to free the returned data.
454 * Warning! This base64 encoding is not the "standard" encoding, so
455 * do not use it for non-SRP purposes.
457 * Returns: 0 on success, or an error code.
460 gnutls_srp_base64_decode_alloc (const gnutls_datum_t * b64_data,
461 gnutls_datum_t * result)
463 opaque *ret;
464 int size;
466 size = _gnutls_sbase64_decode (b64_data->data, b64_data->size, &ret);
467 if (size < 0)
468 return size;
470 if (result == NULL)
472 gnutls_free (ret);
473 return GNUTLS_E_INVALID_REQUEST;
475 else
477 result->data = ret;
478 result->size = size;
481 return 0;
484 #endif /* ENABLE_SRP */