content.h pt1
[voxelands-alt.git] / src / crypto_base64.c
bloba47d5e88d94ee05f483487582f41af6032254394
1 /************************************************************************
2 * crypto_base64.c
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program 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 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the 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, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
20 #include "crypto.h"
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
26 static const char* b64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
28 /* encode three bytes using base64 */
29 static void s_base64_encode_triple(unsigned char triple[3], unsigned char result[4])
31 int tripleValue;
32 int i;
33 int v;
35 tripleValue = triple[0];
36 tripleValue *= 256;
37 tripleValue += triple[1];
38 tripleValue *= 256;
39 tripleValue += triple[2];
41 for (i=0; i<4; i++) {
42 v = tripleValue%64;
43 if (v < 0) {
44 v *= -1;
46 if (v > 63) {
47 result[3-i] = '=';
48 }else{
49 result[3-i] = b64_chars[v];
51 tripleValue /= 64;
55 /* get the value of a base64 encoding character */
56 static int s_base64_char_value(unsigned char c)
58 if (c >= 'A' && c <= 'Z')
59 return c-'A';
60 if (c >= 'a' && c <= 'z')
61 return c-'a'+26;
62 if (c >= '0' && c <= '9')
63 return c-'0'+2*26;
64 if (c == '+')
65 return 2*26+10;
66 if (c == '/')
67 return 2*26+11;
68 return -1;
71 /* decode a 4 char base64 encoded byte triple */
72 static int s_base64_decode_triple(unsigned char quadruple[4], unsigned char *result)
74 int i, triple_value, bytes_to_decode = 3, only_equals_yet = 1;
75 int char_value[4];
77 for (i=0; i<4; i++) {
78 char_value[i] = s_base64_char_value(quadruple[i]);
81 /* check if the characters are valid */
82 for (i=3; i>=0; i--) {
83 if (char_value[i]<0) {
84 if (only_equals_yet && quadruple[i]=='=') {
85 /* we will ignore this character anyway, make it something
86 * that does not break our calculations */
87 char_value[i]=0;
88 bytes_to_decode--;
89 continue;
91 return 0;
93 /* after we got a real character, no other '=' are allowed anymore */
94 only_equals_yet = 0;
97 /* if we got "====" as input, bytes_to_decode is -1 */
98 if (bytes_to_decode < 0)
99 bytes_to_decode = 0;
101 /* make one big value out of the partial values */
102 triple_value = char_value[0];
103 triple_value *= 64;
104 triple_value += char_value[1];
105 triple_value *= 64;
106 triple_value += char_value[2];
107 triple_value *= 64;
108 triple_value += char_value[3];
110 /* break the big value into bytes */
111 for (i=bytes_to_decode; i<3; i++) {
112 triple_value /= 256;
115 for (i=bytes_to_decode-1; i>=0; i--) {
116 result[i] = triple_value%256;
117 triple_value /= 256;
120 return bytes_to_decode;
123 /* encode an array of bytes using base64 */
124 int base64_lencode(char *source, size_t sourcelen, char *target, size_t targetlen)
126 /* check if the result will fit in the target buffer */
127 if ((sourcelen+2)/3*4 > targetlen-1)
128 return 0;
130 /* encode all full triples */
131 while (sourcelen >= 3) {
132 s_base64_encode_triple((unsigned char*)source, (unsigned char*)target);
133 sourcelen -= 3;
134 source += 3;
135 target += 4;
138 /* encode the last one or two characters */
139 if (sourcelen > 0) {
140 unsigned char temp[3];
141 memset(temp, 0, sizeof(temp));
142 memcpy(temp, source, sourcelen);
143 s_base64_encode_triple((unsigned char*)temp, (unsigned char*)target);
144 target[3] = '=';
145 if (sourcelen == 1)
146 target[2] = '=';
148 target += 4;
151 /* terminate the string */
152 target[0] = 0;
154 return 1;
157 /* decode base64 encoded data */
158 size_t base64_ldecode(char *source, char *target, size_t targetlen)
160 char *src, *tmpptr;
161 char quadruple[4], tmpresult[3];
162 int i, tmplen = 3;
163 size_t converted = 0;
165 /* concatinate '===' to the source to handle unpadded base64 data */
166 src = (char *)malloc(strlen(source)+5);
167 if (src == NULL)
168 return -1;
169 strcpy(src, source);
170 strcat(src, "====");
171 tmpptr = src;
173 /* convert as long as we get a full result */
174 while (tmplen == 3) {
175 /* get 4 characters to convert */
176 for (i=0; i<4; i++) {
177 /* skip invalid characters - we won't reach the end */
178 while (*tmpptr != '=' && s_base64_char_value(*tmpptr)<0) {
179 tmpptr++;
182 quadruple[i] = *(tmpptr++);
185 /* convert the characters */
186 tmplen = s_base64_decode_triple((unsigned char*)quadruple, (unsigned char*)tmpresult);
188 /* check if the fit in the result buffer */
189 if (targetlen < tmplen) {
190 free(src);
191 return -1;
194 /* put the partial result in the result buffer */
195 memcpy(target, tmpresult, tmplen);
196 target += tmplen;
197 targetlen -= tmplen;
198 converted += tmplen;
201 free(src);
202 return converted;