1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
/*
Copyright (C) 2008- The University of Notre Dame
This software is distributed under the GNU General Public License.
See the file COPYING for details.
*/
#include "b64.h"
#include "buffer.h"
#include "catch.h"
#include "debug.h"
#include <assert.h>
#include <stddef.h>
int b64_encode(const void *blob, size_t bloblen, buffer_t *Bb64)
{
static const char e_base64[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
int rc;
const unsigned char *i = blob;
char o[4];
size_t l;
for (l = bloblen; l >= 3; l -= 3, i += 3) {
o[0] = e_base64[(i[0]>>2)&0x3f];
o[1] = e_base64[(((i[0]<<4)&0x30)|((i[1]>>4)&0xf))&0x3f];
o[2] = e_base64[(((i[1]<<2)&0x3c)|((i[2]>>6)&0x3))&0x3f];
o[3] = e_base64[i[2]&0x3f];
CATCHUNIX(buffer_putlstring(Bb64, o, sizeof(o)));
}
if (l > 0) {
assert(l == 1 || l == 2);
o[0] = e_base64[(i[0]>>2)&0x3f];
if (l == 1) {
o[1] = e_base64[(((i[0]<<4)&0x30)|((0>>4)&0xf))&0x3f];
o[2] = '=';
} else {
o[1] = e_base64[(((i[0]<<4)&0x30)|((i[1]>>4)&0xf))&0x3f];
o[2] = e_base64[(((i[1]<<2)&0x3c)|(0&0x3))&0x3f];
}
o[3] = '=';
CATCHUNIX(buffer_putlstring(Bb64, o, sizeof(o)));
}
rc = 0;
goto out;
out:
return RCUNIX(rc);
}
int b64_decode (const char *b64, buffer_t *Bblob)
{
static const int d_base64[256] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 0x3e, -1, -1, -1, 0x3f,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
0x3c, 0x3d, -1, -1, -1, -1, -1, -1,
-1, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
0x17, 0x18, 0x19, -1, -1, -1, -1, -1,
-1, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
0x31, 0x32, 0x33, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1
};
int rc;
for (; b64[0]; b64 += 4) {
char o[3];
unsigned char i[4] = {(unsigned char)b64[0], (unsigned char)b64[1], 0, 0};
size_t l = 3;
if (d_base64[i[0]] == -1 || d_base64[i[1]] == -1)
return errno = EINVAL, -1;
if (b64[2] == 0 || b64[3] == 0)
return errno = EINVAL, -1;
i[3] = b64[3] == '=' ? (l = 2, 'A') : b64[3];
i[2] = b64[2] == '=' ? (l = 1, 'A') : b64[2];
if (d_base64[i[2]] == -1 || d_base64[i[3]] == -1)
return errno = EINVAL, -1;
o[0] = ((d_base64[i[0]]<<2)&0xfc) | ((d_base64[i[1]]>>4)&0x03);
o[1] = ((d_base64[i[1]]<<4)&0xf0) | ((d_base64[i[2]]>>2)&0x0f);
o[2] = ((d_base64[i[2]]<<6)&0xc0) | ((d_base64[i[3]])&0x3f);
CATCHUNIX(buffer_putlstring(Bblob, o, l));
if (l < 3)
break; /* end of b64 */
}
rc = 0;
goto out;
out:
return RCUNIX(rc);
}
/* vim: set noexpandtab tabstop=4: */
|