00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "gnutls_int.h"
00029 #include "gnutls_errors.h"
00030 #include <gnutls_datum.h>
00031 #include <x509_b64.h>
00032
00033 static const uint8_t b64table[] =
00034 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00035
00036 static const uint8_t asciitable[128] = {
00037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00040 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00041 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00042 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00043 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00044 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
00045 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
00046 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
00047 0xff, 0xf1, 0xff, 0xff, 0xff, 0x00,
00048 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
00049 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
00050 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
00051 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
00052 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
00053 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
00054 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
00055 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
00056 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
00057 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
00058 0xff, 0xff
00059 };
00060
00061 #define INCR(what, size) \
00062 do { \
00063 what+=size; \
00064 if (what > ret) { \
00065 MHD_gnutls_assert(); \
00066 MHD_gnutls_free( (*result)); *result = NULL; \
00067 return GNUTLS_E_INTERNAL_ERROR; \
00068 } \
00069 } while(0)
00070
00071
00072 inline static int
00073 encode (char *result, const uint8_t * data, int left)
00074 {
00075
00076 int data_len;
00077
00078 if (left > 3)
00079 data_len = 3;
00080 else
00081 data_len = left;
00082
00083 switch (data_len)
00084 {
00085 case 3:
00086 result[0] = b64table[(data[0] >> 2)];
00087 result[1] =
00088 b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
00089 (data[1] >> 4))];
00090 result[2] =
00091 b64table[((((data[1] & 0x0f) << 2) & 0xff) | (data[2] >> 6))];
00092 result[3] = b64table[(((data[2] << 2) & 0xff) >> 2)];
00093 break;
00094 case 2:
00095 result[0] = b64table[(data[0] >> 2)];
00096 result[1] =
00097 b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff) |
00098 (data[1] >> 4))];
00099 result[2] = b64table[(((data[1] << 4) & 0xff) >> 2)];
00100 result[3] = '=';
00101 break;
00102 case 1:
00103 result[0] = b64table[(data[0] >> 2)];
00104 result[1] = b64table[(((((data[0] & 0x03) & 0xff) << 4) & 0xff))];
00105 result[2] = '=';
00106 result[3] = '=';
00107 break;
00108 default:
00109 return -1;
00110 }
00111
00112 return 4;
00113
00114 }
00115
00116
00117
00118
00119 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
00120 inline static int
00121 decode (uint8_t * result, const opaque * data)
00122 {
00123 uint8_t a1, a2;
00124 int ret = 3;
00125
00126 a1 = TOASCII (data[0]);
00127 a2 = TOASCII (data[1]);
00128 if (a1 == 0xff || a2 == 0xff)
00129 return -1;
00130 result[0] = ((a1 << 2) & 0xff) | ((a2 >> 4) & 0xff);
00131
00132 a1 = a2;
00133 a2 = TOASCII (data[2]);
00134 if (a2 == 0xff)
00135 return -1;
00136 result[1] = ((a1 << 4) & 0xff) | ((a2 >> 2) & 0xff);
00137
00138 a1 = a2;
00139 a2 = TOASCII (data[3]);
00140 if (a2 == 0xff)
00141 return -1;
00142 result[2] = ((a1 << 6) & 0xff) | (a2 & 0xff);
00143
00144 if (data[2] == '=')
00145 ret--;
00146
00147 if (data[3] == '=')
00148 ret--;
00149 return ret;
00150 }
00151
00152
00153
00154
00155 int
00156 MHD__gnutls_fbase64_encode (const char *msg, const uint8_t * data,
00157 int data_size, uint8_t ** result)
00158 {
00159 int i, ret, tmp, j;
00160 char tmpres[4];
00161 uint8_t *ptr;
00162 uint8_t top[80];
00163 uint8_t bottom[80];
00164 int pos, bytes, top_len, bottom_len;
00165 size_t msglen = strlen (msg);
00166
00167 if (msglen > 50)
00168 {
00169 MHD_gnutls_assert ();
00170 return GNUTLS_E_BASE64_ENCODING_ERROR;
00171 }
00172
00173 memset (bottom, 0, sizeof (bottom));
00174 memset (top, 0, sizeof (top));
00175
00176 strcat ((char *) top, "-----BEGIN ");
00177 strcat ((char *) top, msg);
00178 strcat ((char *) top, "-----");
00179
00180 strcat ((char *) bottom, "\n-----END ");
00181 strcat ((char *) bottom, msg);
00182 strcat ((char *) bottom, "-----\n");
00183
00184 top_len = strlen ((char *) top);
00185 bottom_len = strlen ((char *) bottom);
00186
00187 ret = B64FSIZE (msglen, data_size);
00188
00189 (*result) = MHD_gnutls_calloc (1, ret + 1);
00190 if ((*result) == NULL)
00191 {
00192 MHD_gnutls_assert ();
00193 return GNUTLS_E_MEMORY_ERROR;
00194 }
00195
00196 bytes = pos = 0;
00197 INCR (bytes, top_len);
00198 pos = top_len;
00199
00200 strcpy ((char *) *result, (char *) top);
00201
00202 for (i = j = 0; i < data_size; i += 3, j += 4)
00203 {
00204
00205 tmp = encode (tmpres, &data[i], data_size - i);
00206 if (tmp == -1)
00207 {
00208 MHD_gnutls_assert ();
00209 MHD_gnutls_free ((*result));
00210 *result = NULL;
00211 return GNUTLS_E_BASE64_ENCODING_ERROR;
00212 }
00213
00214 INCR (bytes, 4);
00215 ptr = &(*result)[j + pos];
00216
00217 if ((j) % 64 == 0)
00218 {
00219 INCR (bytes, 1);
00220 pos++;
00221 *ptr++ = '\n';
00222 }
00223 *ptr++ = tmpres[0];
00224
00225 if ((j + 1) % 64 == 0)
00226 {
00227 INCR (bytes, 1);
00228 pos++;
00229 *ptr++ = '\n';
00230 }
00231 *ptr++ = tmpres[1];
00232
00233 if ((j + 2) % 64 == 0)
00234 {
00235 INCR (bytes, 1);
00236 pos++;
00237 *ptr++ = '\n';
00238 }
00239 *ptr++ = tmpres[2];
00240
00241 if ((j + 3) % 64 == 0)
00242 {
00243 INCR (bytes, 1);
00244 pos++;
00245 *ptr++ = '\n';
00246 }
00247 *ptr++ = tmpres[3];
00248 }
00249
00250 INCR (bytes, bottom_len);
00251
00252 memcpy (&(*result)[bytes - bottom_len], bottom, bottom_len);
00253 (*result)[bytes] = 0;
00254
00255 return ret + 1;
00256 }
00257
00258
00259
00260
00261 int
00262 MHD__gnutls_base64_decode (const uint8_t * data, size_t data_size,
00263 uint8_t ** result)
00264 {
00265 unsigned int i, j;
00266 int ret, tmp, est;
00267 uint8_t tmpres[3];
00268
00269 est = ((data_size * 3) / 4) + 1;
00270 (*result) = MHD_gnutls_malloc (est);
00271 if ((*result) == NULL)
00272 return GNUTLS_E_MEMORY_ERROR;
00273
00274 ret = 0;
00275 for (i = j = 0; i < data_size; i += 4, j += 3)
00276 {
00277 tmp = decode (tmpres, &data[i]);
00278 if (tmp < 0)
00279 {
00280 MHD_gnutls_free (*result);
00281 *result = NULL;
00282 return tmp;
00283 }
00284 memcpy (&(*result)[j], tmpres, tmp);
00285 ret += tmp;
00286 }
00287 return ret;
00288 }
00289
00290
00291
00292
00293 inline static int
00294 cpydata (const uint8_t * data, int data_size, uint8_t ** result)
00295 {
00296 int i, j;
00297
00298 (*result) = MHD_gnutls_malloc (data_size);
00299 if (*result == NULL)
00300 return GNUTLS_E_MEMORY_ERROR;
00301
00302 for (j = i = 0; i < data_size; i++)
00303 {
00304 if (data[i] == '\n' || data[i] == '\r')
00305 continue;
00306 (*result)[j] = data[i];
00307 j++;
00308 }
00309 return j;
00310 }
00311
00312
00313
00314
00315
00316
00317 #define ENDSTR "-----\n"
00318 #define ENDSTR2 "-----\r"
00319 int
00320 MHD__gnutls_fbase64_decode (const char *header, const opaque * data,
00321 size_t data_size, uint8_t ** result)
00322 {
00323 int ret;
00324 static const char top[] = "-----BEGIN ";
00325 static const char bottom[] = "\n-----END ";
00326 uint8_t *rdata;
00327 int rdata_size;
00328 uint8_t *kdata;
00329 int kdata_size;
00330 char pem_header[128];
00331
00332 MHD_gtls_str_cpy (pem_header, sizeof (pem_header), top);
00333 if (header != NULL)
00334 MHD_gtls_str_cat (pem_header, sizeof (pem_header), header);
00335
00336 rdata = memmem (data, data_size, pem_header, strlen (pem_header));
00337
00338 if (rdata == NULL)
00339 {
00340 MHD_gnutls_assert ();
00341 MHD__gnutls_debug_log ("Could not find '%s'\n", pem_header);
00342 return GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR;
00343 }
00344
00345 data_size -= (unsigned long int) rdata - (unsigned long int) data;
00346
00347 if (data_size < 4 + strlen (bottom))
00348 {
00349 MHD_gnutls_assert ();
00350 return GNUTLS_E_BASE64_DECODING_ERROR;
00351 }
00352
00353 kdata = memmem (rdata, data_size, ENDSTR, sizeof (ENDSTR) - 1);
00354
00355
00356 if (kdata == NULL)
00357 kdata = memmem (rdata, data_size, ENDSTR2, sizeof (ENDSTR2) - 1);
00358
00359 if (kdata == NULL)
00360 {
00361 MHD_gnutls_assert ();
00362 MHD__gnutls_x509_log ("Could not find '%s'\n", ENDSTR);
00363 return GNUTLS_E_BASE64_DECODING_ERROR;
00364 }
00365 data_size -= strlen (ENDSTR);
00366 data_size -= (unsigned long int) kdata - (unsigned long int) rdata;
00367
00368 rdata = kdata + strlen (ENDSTR);
00369
00370
00371
00372 kdata = memmem (rdata, data_size, bottom, strlen (bottom));
00373 if (kdata == NULL)
00374 {
00375 MHD_gnutls_assert ();
00376 return GNUTLS_E_BASE64_DECODING_ERROR;
00377 }
00378
00379
00380
00381 rdata_size = (unsigned long int) kdata - (unsigned long int) rdata;
00382
00383 if (rdata_size < 4)
00384 {
00385 MHD_gnutls_assert ();
00386 return GNUTLS_E_BASE64_DECODING_ERROR;
00387 }
00388
00389 kdata_size = cpydata (rdata, rdata_size, &kdata);
00390
00391 if (kdata_size < 0)
00392 {
00393 MHD_gnutls_assert ();
00394 return kdata_size;
00395 }
00396
00397 if (kdata_size < 4)
00398 {
00399 MHD_gnutls_assert ();
00400 MHD_gnutls_free (kdata);
00401 return GNUTLS_E_BASE64_DECODING_ERROR;
00402 }
00403
00404 if ((ret = MHD__gnutls_base64_decode (kdata, kdata_size, result)) < 0)
00405 {
00406 MHD_gnutls_free (kdata);
00407 MHD_gnutls_assert ();
00408 return GNUTLS_E_BASE64_DECODING_ERROR;
00409 }
00410 MHD_gnutls_free (kdata);
00411
00412 return ret;
00413 }