Add.
[gnutls.git] / lib / auth_srp_sb64.c
blob2834fba7b5b94c2ddb0ac6b084a9a1d33fdd7220
1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
4 * Author: Nikos Mavroyanopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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.
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.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_datum.h>
29 #ifdef ENABLE_SRP
31 /* this a modified base64 for srp !!!
32 * It seems that everybody makes an own base64 conversion.
34 static const uint8_t b64table[] =
35 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
37 static const uint8_t asciitable[128] = {
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, 0xff, 0xff,
45 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f,
46 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
47 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
48 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a,
49 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
50 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
51 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
52 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
53 0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
54 0xff, 0x24, 0x25, 0x26, 0x27, 0x28,
55 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
56 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
57 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
58 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff,
59 0xff, 0xff
62 inline static int
63 encode (uint8_t * result, const uint8_t * rdata, int left)
66 int data_len;
67 int c, ret = 4;
68 uint8_t data[3];
70 if (left > 3)
71 data_len = 3;
72 else
73 data_len = left;
75 data[0] = data[1] = data[2] = 0;
76 memcpy (data, rdata, data_len);
78 switch (data_len)
80 case 3:
81 result[0] = b64table[((data[0] & 0xfc) >> 2)];
82 result[1] =
83 b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
84 ((data[1] & 0xf0) >> 4))];
85 result[2] =
86 b64table[((((data[1] & 0x0f) << 2) & 0xff) |
87 ((data[2] & 0xc0) >> 6))];
88 result[3] = b64table[(data[2] & 0x3f) & 0xff];
89 break;
90 case 2:
91 if ((c = ((data[0] & 0xf0) >> 4)) != 0)
93 result[0] = b64table[c];
94 result[1] =
95 b64table[((((data[0] & 0x0f) << 2) & 0xff) |
96 ((data[1] & 0xc0) >> 6))];
97 result[2] = b64table[(data[1] & 0x3f) & 0xff];
98 result[3] = '\0';
99 ret -= 1;
101 else
103 if ((c = ((data[0] & 0x0f) << 2) | ((data[1] & 0xc0) >> 6)) != 0)
105 result[0] = b64table[c];
106 result[1] = b64table[data[1] & 0x3f];
107 result[2] = '\0';
108 result[3] = '\0';
109 ret -= 2;
111 else
113 result[0] = b64table[data[0] & 0x3f];
114 result[1] = '\0';
115 result[2] = '\0';
116 result[3] = '\0';
117 ret -= 3;
120 break;
121 case 1:
122 if ((c = ((data[0] & 0xc0) >> 6)) != 0)
124 result[0] = b64table[c];
125 result[1] = b64table[(data[0] & 0x3f) & 0xff];
126 result[2] = '\0';
127 result[3] = '\0';
128 ret -= 2;
130 else
132 result[0] = b64table[(data[0] & 0x3f) & 0xff];
133 result[1] = '\0';
134 result[2] = '\0';
135 result[3] = '\0';
136 ret -= 3;
138 break;
139 default:
140 return -1;
143 return ret;
147 /* encodes data and puts the result into result (locally allocated)
148 * The result_size is the return value
151 _gnutls_sbase64_encode (uint8_t * data, size_t data_size, uint8_t ** result)
153 unsigned i, j;
154 int ret, tmp;
155 opaque tmpres[4];
156 int mod = data_size % 3;
158 ret = mod;
159 if (ret != 0)
160 ret = 4;
161 else
162 ret = 0;
164 ret += (data_size * 4) / 3;
166 (*result) = gnutls_calloc (1, ret + 1);
167 if ((*result) == NULL)
168 return -1;
170 i = j = 0;
171 /* encode the bytes that are not a multiple of 3
173 if (mod > 0)
175 tmp = encode (tmpres, &data[0], mod);
176 if (tmp < 0)
178 gnutls_free ((*result));
179 return tmp;
182 memcpy (&(*result)[0], tmpres, tmp);
183 i = mod;
184 j = tmp;
187 /* encode the rest
189 for (; i < data_size; i += 3, j += 4)
191 tmp = encode (tmpres, &data[i], data_size - i);
192 if (tmp < 0)
194 gnutls_free ((*result));
195 return tmp;
197 memcpy (&(*result)[j], tmpres, tmp);
200 return strlen (*result);
204 /* data must be 4 bytes
205 * result should be 3 bytes
207 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
208 inline static int
209 decode (uint8_t * result, const uint8_t * data)
211 uint8_t a1, a2;
212 int ret = 3;
214 memset (result, 0, 3);
216 a1 = TOASCII (data[3]);
217 a2 = TOASCII (data[2]);
218 if (a1 != 0xff)
219 result[2] = a1 & 0xff;
220 else
221 return -1;
222 if (a2 != 0xff)
223 result[2] |= ((a2 & 0x03) << 6) & 0xff;
225 a1 = a2;
226 a2 = TOASCII (data[1]);
227 if (a1 != 0xff)
228 result[1] = ((a1 & 0x3c) >> 2);
229 if (a2 != 0xff)
230 result[1] |= ((a2 & 0x0f) << 4);
231 else if (a1 == 0xff || result[1] == 0)
232 ret--;
234 a1 = a2;
235 a2 = TOASCII (data[0]);
236 if (a1 != 0xff)
237 result[0] = (((a1 & 0x30) >> 4) & 0xff);
238 if (a2 != 0xff)
239 result[0] |= ((a2 << 2) & 0xff);
240 else if (a1 == 0xff || result[0] == 0)
241 ret--;
243 return ret;
246 /* decodes data and puts the result into result (locally allocated)
247 * The result_size is the return value.
248 * That function does not ignore newlines tabs etc. You should remove them
249 * before calling it.
252 _gnutls_sbase64_decode (uint8_t * data, size_t idata_size, uint8_t ** result)
254 unsigned i, j;
255 int ret, left;
256 int data_size, tmp;
257 uint8_t datrev[4];
258 uint8_t tmpres[3];
260 data_size = (idata_size / 4) * 4;
261 left = idata_size % 4;
263 ret = (data_size / 4) * 3;
265 if (left > 0)
266 ret += 3;
268 (*result) = gnutls_malloc (ret + 1);
269 if ((*result) == NULL)
270 return -1;
272 /* the first "block" is treated with special care */
273 tmp = 0;
274 if (left > 0)
276 memset (datrev, 0, 4);
277 memcpy (&datrev[4 - left], data, left);
279 tmp = decode (tmpres, datrev);
280 if (tmp < 0)
282 gnutls_free ((*result));
283 *result = NULL;
284 return tmp;
287 memcpy (*result, &tmpres[3 - tmp], tmp);
288 if (tmp < 3)
289 ret -= (3 - tmp);
292 /* rest data */
293 for (i = left, j = tmp; i < idata_size; i += 4)
295 tmp = decode (tmpres, &data[i]);
296 if (tmp < 0)
298 gnutls_free ((*result));
299 *result = NULL;
300 return tmp;
302 memcpy (&(*result)[j], tmpres, tmp);
303 if (tmp < 3)
304 ret -= (3 - tmp);
305 j += 3;
308 return ret;
312 * gnutls_srp_base64_encode - This function will convert raw data to base64 encoded
313 * @data: contain the raw data
314 * @result: the place where base64 data will be copied
315 * @result_size: holds the size of the result
317 * This function will convert the given data to printable data, using the base64
318 * encoding, as used in the libsrp. This is the encoding used in SRP password files.
319 * If the provided buffer is not long enough GNUTLS_E_SHORT_MEMORY_BUFFER is returned.
323 gnutls_srp_base64_encode (const gnutls_datum_t * data, char *result,
324 size_t * result_size)
326 opaque *ret;
327 int size;
329 size = _gnutls_sbase64_encode (data->data, data->size, &ret);
330 if (size < 0)
331 return size;
333 if (result == NULL || *result_size < (size_t) size)
335 gnutls_free (ret);
336 *result_size = size;
337 return GNUTLS_E_SHORT_MEMORY_BUFFER;
339 else
341 memcpy (result, ret, size);
342 gnutls_free (ret);
343 *result_size = size;
346 return 0;
350 * gnutls_srp_base64_encode_alloc - This function will convert raw data to Base64 encoded
351 * @data: contains the raw data
352 * @result: will hold the newly allocated encoded data
354 * This function will convert the given data to printable data, using the base64
355 * encoding. This is the encoding used in SRP password files. This function will
356 * allocate the required memory to hold the encoded data.
358 * You should use gnutls_free() to free the returned data.
362 gnutls_srp_base64_encode_alloc (const gnutls_datum_t * data,
363 gnutls_datum_t * result)
365 opaque *ret;
366 int size;
368 size = _gnutls_sbase64_encode (data->data, data->size, &ret);
369 if (size < 0)
370 return size;
372 if (result == NULL)
374 gnutls_free (ret);
375 return GNUTLS_E_INVALID_REQUEST;
377 else
379 result->data = ret;
380 result->size = size;
383 return 0;
387 * gnutls_srp_base64_decode - This function will decode base64 encoded data
388 * @b64_data: contain the encoded data
389 * @result: the place where decoded data will be copied
390 * @result_size: holds the size of the result
392 * This function will decode the given encoded data, using the base64 encoding
393 * found in libsrp.
395 * Note that b64_data should be null terminated.
397 * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not long enough,
398 * or 0 on success.
401 gnutls_srp_base64_decode (const gnutls_datum_t * b64_data, char *result,
402 size_t * result_size)
404 opaque *ret;
405 int size;
407 size = _gnutls_sbase64_decode (b64_data->data, b64_data->size, &ret);
408 if (size < 0)
409 return size;
411 if (result == NULL || *result_size < (size_t) size)
413 gnutls_free (ret);
414 *result_size = size;
415 return GNUTLS_E_SHORT_MEMORY_BUFFER;
417 else
419 memcpy (result, ret, size);
420 gnutls_free (ret);
421 *result_size = size;
424 return 0;
428 * gnutls_srp_base64_decode_alloc - This function will decode base64 encoded data
429 * @b64_data: contains the encoded data
430 * @result: the place where decoded data lie
432 * This function will decode the given encoded data. The decoded data
433 * will be allocated, and stored into result.
434 * It will decode using the base64 algorithm found in libsrp.
436 * You should use gnutls_free() to free the returned data.
440 gnutls_srp_base64_decode_alloc (const gnutls_datum_t * b64_data,
441 gnutls_datum_t * result)
443 opaque *ret;
444 int size;
446 size = _gnutls_sbase64_decode (b64_data->data, b64_data->size, &ret);
447 if (size < 0)
448 return size;
450 if (result == NULL)
452 gnutls_free (ret);
453 return GNUTLS_E_INVALID_REQUEST;
455 else
457 result->data = ret;
458 result->size = size;
461 return 0;
464 #endif /* ENABLE_SRP */