2 * Copyright (C) 2001 Nikos Mavroyanopoulos <nmav@hellug.gr>
4 * This file is part of GNUTLS.
6 * GNUTLS-EXTRA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS-EXTRA 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include "gnutls_int.h"
25 /* this a modified base64 for srp !!!
26 * It seems that everybody makes it's own base64 convertion.
28 const static uint8 b64table
[64] =
29 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
31 const static uint8 asciitable
[128] = {
32 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
33 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
34 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
35 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
36 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
37 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
38 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
39 0xff, 0xff, 0xff, 0xff, 0x3e, 0x3f,
40 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
41 0x06, 0x07, 0x08, 0x09, 0xff, 0xff,
42 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a,
43 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
44 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
45 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c,
46 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
47 0x23, 0xff, 0xff, 0xff, 0xff, 0xff,
48 0xff, 0x24, 0x25, 0x26, 0x27, 0x28,
49 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
50 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
51 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a,
52 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff,
56 inline static int encode(uint8
* result
, const uint8
* rdata
, int left
)
68 data
[0] = data
[1] = data
[2] = 0;
69 memcpy(data
, rdata
, data_len
);
73 result
[0] = b64table
[((data
[0] & 0xfc) >> 2)];
75 b64table
[(((((data
[0] & 0x03) & 0xff) << 4) & 0xff) |
76 ((data
[1] & 0xf0) >> 4))];
78 b64table
[((((data
[1] & 0x0f) << 2) & 0xff) |
79 ((data
[2] & 0xc0) >> 6))];
80 result
[3] = b64table
[(data
[2] & 0x3f) & 0xff];
83 if ((c
= ((data
[0] & 0xf0) >> 4)) != 0) {
84 result
[0] = b64table
[c
];
86 b64table
[((((data
[0] & 0x0f) << 2) & 0xff) |
87 ((data
[1] & 0xc0) >> 6))];
88 result
[2] = b64table
[(data
[1] & 0x3f) & 0xff];
93 ((data
[0] & 0x0f) << 2) | ((data
[1] & 0xc0) >>
95 result
[0] = b64table
[c
];
96 result
[1] = b64table
[data
[1] & 0x3f];
101 result
[0] = b64table
[data
[0] & 0x3f];
110 if ((c
= ((data
[0] & 0xc0) >> 6)) != 0) {
111 result
[0] = b64table
[c
];
112 result
[1] = b64table
[(data
[0] & 0x3f) & 0xff];
117 result
[0] = b64table
[(data
[0] & 0x3f) & 0xff];
132 /* encodes data and puts the result into result (localy alocated)
133 * The result_size is the return value
135 int _gnutls_sbase64_encode(uint8
* data
, int data_size
, uint8
** result
)
139 int mod
= data_size
% 3;
147 ret
+= (data_size
* 4) / 3;
149 (*result
) = gnutls_calloc( 1, ret
+ 1);
150 if ((*result
) == NULL
)
154 /* encode the bytes that are not a multiple of 3
157 tmp
= encode(tmpres
, &data
[0], mod
);
159 gnutls_free( (*result
));
163 memcpy(&(*result
)[0], tmpres
, tmp
);
170 for (; i
< data_size
; i
+= 3, j
+= 4) {
171 tmp
= encode(tmpres
, &data
[i
], data_size
- i
);
173 gnutls_free( (*result
));
176 memcpy(&(*result
)[j
], tmpres
, tmp
);
179 return strlen(*result
);
183 /* data must be 4 bytes
184 * result should be 3 bytes
186 #define TOASCII(c) (c < 127 ? asciitable[c] : 0xff)
187 inline static int decode(uint8
* result
, const uint8
* data
)
192 memset( result
, 0, 3);
194 a1
= TOASCII(data
[3]);
195 a2
= TOASCII(data
[2]);
196 if (a1
!= 0xff) result
[2] = a1
& 0xff;
198 if (a2
!= 0xff) result
[2] |= ((a2
& 0x03) << 6) & 0xff;
201 a2
= TOASCII(data
[1]);
202 if (a1
!= 0xff) result
[1] = ((a1
& 0x3c) >> 2);
203 if (a2
!= 0xff) result
[1] |= ((a2
& 0x0f) << 4);
204 else if (a1
==0xff || result
[1] == 0) ret
--;
207 a2
= TOASCII(data
[0]);
208 if (a1
!= 0xff) result
[0] = (((a1
& 0x30) >> 4) & 0xff);
209 if (a2
!= 0xff) result
[0] |= ((a2
<< 2) & 0xff);
210 else if (a1
==0xff || result
[0] == 0) ret
--;
215 /* decodes data and puts the result into result (localy alocated)
216 * The result_size is the return value.
217 * That function does not ignore newlines tabs etc. You should remove them
220 int _gnutls_sbase64_decode(uint8
* data
, int idata_size
, uint8
** result
)
227 data_size
= (idata_size
/4)*4;
228 left
= idata_size
% 4;
230 ret
= (data_size
/ 4) * 3;
235 (*result
) = gnutls_malloc(ret
+1);
236 if ((*result
) == NULL
)
239 /* the first "block" is treated with special care */
242 memset( datrev
, 0, 4);
243 memcpy( &datrev
[4-left
], data
, left
);
245 tmp
= decode( tmpres
, datrev
);
247 gnutls_free( (*result
));
251 memcpy( *result
, &tmpres
[3-tmp
], tmp
);
257 for (i
= left
, j
= tmp
; i
< idata_size
; i
+= 4) {
258 tmp
= decode(tmpres
, &data
[i
]);
260 gnutls_free( (*result
));
263 memcpy(&(*result
)[j
], tmpres
, tmp
);
279 /* for (i = 0; i < 128; i++) {
281 fprintf(stdout, "\n");
282 if (strchr(b64table, i) == NULL)
283 fprintf(stdout, "0x%.2x, ", 0xff);
285 fprintf(stdout, "0x%.2x, ",
286 (int) ((int) index(b64table, i) -
292 siz
= fread(x
, 1, sizeof(x
), stdin
);
294 // siz = _gnutls_sbase64_encode(x, siz, &b64);
295 siz
= _gnutls_sbase64_decode(x
, siz
, &b64
);
299 _gnutls_log( "ERROR %d\n", siz
);
303 fwrite(b64
, siz
, 1, stdout
);
310 #endif /* ENABLE_SRP */