2 * Copyright (C) 2000,2001 Nikos Mavroyanopoulos <nmav@hellug.gr>
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_errors.h"
25 const static uint8 b64table
[64] =
26 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27 const static uint8 asciitable
[128] = {
28 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
29 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
30 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
31 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
36 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
37 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
38 0xff, 0xf1, 0xff, 0xff, 0xff, 0x00, /* 0xf1 for '=' */
39 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
40 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
41 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
42 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
43 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
44 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
45 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
46 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a,
47 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
48 0x31, 0x32, 0x33, 0xff, 0xff, 0xff,
52 inline static int encode(uint8
* result
, const uint8
* data
, int left
)
64 result
[0] = b64table
[(data
[0] >> 2)];
66 b64table
[(((((data
[0] & 0x03) & 0xff) << 4) & 0xff) |
69 b64table
[((((data
[1] & 0x0f) << 2) & 0xff) |
71 result
[3] = b64table
[(((data
[2] << 2) & 0xff) >> 2)];
74 result
[0] = b64table
[(data
[0] >> 2)];
76 b64table
[(((((data
[0] & 0x03) & 0xff) << 4) & 0xff) |
78 result
[2] = b64table
[(((data
[1] << 4) & 0xff) >> 2)];
82 result
[0] = b64table
[(data
[0] >> 2)];
84 b64table
[(((((data
[0] & 0x03) & 0xff) << 4) & 0xff))];
96 /* data must be 4 bytes
97 * result should be 3 bytes
99 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
100 inline static int decode(uint8
* result
, const uint8
* data
)
105 a1
= TOASCII(data
[0]);
106 a2
= TOASCII(data
[1]);
107 if (a1
== 0xff || a2
== 0xff)
109 result
[0] = ((a1
<< 2) & 0xff) | ((a2
>> 4) & 0xff);
112 a2
= TOASCII(data
[2]);
115 result
[1] = ((a1
<< 4) & 0xff) | ((a2
>> 2) & 0xff);
118 a2
= TOASCII(data
[3]);
121 result
[2] = ((a1
<< 6) & 0xff) | (a2
& 0xff);
131 /* encodes data and puts the result into result (localy alocated)
132 * The result_size is the return value
134 int _gnutls_base64_encode(const uint8
* data
, int data_size
, uint8
** result
)
145 ret
+= (data_size
/ 3) * 4;
147 (*result
) = gnutls_malloc(ret
+ 1);
148 if ((*result
) == NULL
)
151 for (i
= j
= 0; i
< data_size
; i
+= 3, j
+= 4) {
152 tmp
= encode(tmpres
, &data
[i
], data_size
- i
);
154 gnutls_free( (*result
));
157 memcpy(&(*result
)[j
], tmpres
, tmp
);
159 (*result
)[ret
] = 0; /* null terminated */
164 /* encodes data and puts the result into result (localy alocated)
165 * The result_size is the return value
167 int _gnutls_fbase64_encode(const char *msg
, const uint8
* data
, int data_size
,
177 memset(bottom
, 0, sizeof(bottom
));
178 memset(top
, 0, sizeof(top
));
180 if (strlen(msg
) > 50)
183 strcat(top
, "-----BEGIN "); /* Flawfinder: ignore */
184 strcat(top
, msg
); /* Flawfinder: ignore */
185 strcat(top
, "-----"); /* Flawfinder: ignore */
187 strcat(bottom
, "\n-----END "); /* Flawfinder: ignore */
188 strcat(bottom
, msg
); /* Flawfinder: ignore */
189 strcat(bottom
, "-----\n"); /* Flawfinder: ignore */
197 ret
+= strlen(top
) + strlen(bottom
);
199 tmp
= (data_size
/ 3) * 4;
200 ret
+= (tmp
/ 64) + (tmp
% 64 > 0 ? 1 : 0); /* add new lines */
203 (*result
) = gnutls_calloc(1, ret
+ 1);
204 if ((*result
) == NULL
)
207 strcat(*result
, top
); /* Flawfinder: ignore */
210 for (i
= j
= 0; i
< data_size
; i
+= 3, j
+= 4) {
211 tmp
= encode(tmpres
, &data
[i
], data_size
- i
);
213 gnutls_free( (*result
));
216 ptr
= &(*result
)[j
+ pos
];
224 if ((j
+ 1) % 64 == 0) {
230 if ((j
+ 2) % 64 == 0) {
236 if ((j
+ 3) % 64 == 0) {
243 strcat(*result
, bottom
); /* Flawfinder: ignore */
248 * gnutls_b64_encode_fmt - This function will convert raw data to Base64 encoded
249 * @msg: is a message to be put in the header
250 * @data: contain the raw data
251 * @result: the place where base64 data will be copied
252 * @result_size: holds the size of the result
254 * This function will convert the given data to printable data, using the base64
255 * encoding. This is the encoding used in PEM messages. If the provided
256 * buffer is not long enough GNUTLS_E_INVALID_REQUEST is returned.
260 int gnutls_b64_encode_fmt( const char* msg
, const gnutls_datum
*data
, char* result
, int* result_size
) {
264 size
= _gnutls_fbase64_encode( msg
, data
->data
, data
->size
, &ret
);
268 if (result
==NULL
|| *result_size
< size
) {
271 return GNUTLS_E_INVALID_REQUEST
;
273 memcpy( result
, ret
, size
);
282 /* decodes data and puts the result into result (localy alocated)
283 * The result_size is the return value
285 int _gnutls_base64_decode(const uint8
* data
, int data_size
, uint8
** result
)
293 ret
= data_size
/ 4 * 3;
294 (*result
) = gnutls_malloc(ret
+1);
295 if ((*result
) == NULL
)
298 for (i
= j
= 0; i
< data_size
; i
+= 4) {
299 tmp
= decode(tmpres
, &data
[i
]);
301 gnutls_free( *result
);
304 memcpy(&(*result
)[j
], tmpres
, tmp
);
312 /* copies data to result but removes newlines and <CR>
313 * returns the size of the data copied.
315 inline static int cpydata(const uint8
* data
, int data_size
, uint8
** result
)
319 (*result
) = gnutls_malloc(data_size
);
323 for (j
= i
= 0; i
< data_size
; i
++) {
324 if (data
[i
] == '\n' || data
[i
] == '\r')
326 (*result
)[j
] = data
[i
];
332 /* Searches the given string for ONE PEM encoded certificate, and
333 * stores it in the result.
335 * The result_size is the return value
337 #define ENDSTR "-----\n"
338 int _gnutls_fbase64_decode( const uint8
* data
, int data_size
,
342 char top
[] = "-----BEGIN ";
343 char bottom
[] = "\n-----END ";
349 rdata
= strstr( data
, top
);
354 data_size
-= (unsigned long int)rdata
-(unsigned long int)data
;
356 if (data_size
< 4 + strlen(bottom
)) {
361 kdata
= strstr( rdata
, ENDSTR
);
366 data_size
-= strlen(ENDSTR
);
367 data_size
-= (unsigned long int)kdata
-(unsigned long int)rdata
;
369 rdata
= kdata
+ strlen(ENDSTR
);
371 /* position is now after the ---BEGIN--- headers */
373 kdata
= strstr( rdata
, bottom
);
378 /* position of kdata is before the ----END--- footer
380 rdata_size
= (unsigned long int)kdata
-(unsigned long int)rdata
;
382 if (rdata_size
< 4) {
387 kdata_size
= cpydata(rdata
, rdata_size
, &kdata
);
389 if (kdata_size
< 4) {
394 if ((ret
= _gnutls_base64_decode( kdata
, kdata_size
, result
)) < 0) {
397 return GNUTLS_E_PARSING_ERROR
;
405 * gnutls_b64_decode_fmt - This function will decode base64 encoded data
406 * @b64_data: contain the encoded data
407 * @result: the place where decoded data will be copied
408 * @result_size: holds the size of the result
410 * This function will decode the given encoded data.
413 int gnutls_b64_decode_fmt( const gnutls_datum
*b64_data
, char* result
, int* result_size
) {
417 size
= _gnutls_fbase64_decode( b64_data
->data
, b64_data
->size
, &ret
);
421 if (result
==NULL
|| *result_size
< size
) {
424 return GNUTLS_E_INVALID_REQUEST
;
426 memcpy( result
, ret
, size
);
442 /* for (i = 0; i < 128; i++) {
444 fprintf(stdout, "\n");
445 if (strchr(b64table, i) == NULL)
446 fprintf(stdout, "0x%.2x, ", 0xff);
448 fprintf(stdout, "0x%.2x, ",
449 (int) ((int) index(b64table, i) -
455 siz
= fread(x
, 1, sizeof(x
), stdin
);
457 // siz = _gnutls_fbase64_encode("CERTIFICATE", x, siz, &b64);
458 siz
= _gnutls_base64_encode(x
, siz
, &b64
);
459 // siz = _gnutls_base64_decode(x, siz, &b64);
460 // siz = _gnutls_fbase64_decode("CERTIFICATE", x, siz, &b64);
464 _gnutls_log( "ERROR %d\n", siz
);
467 fwrite(b64
, siz
, 1, stdout
);