OpenVPN
base64.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#include "syshead.h"
39
40#include "base64.h"
41
42#include "memdbg.h"
43
44static char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
45/*
46 * base64 encode input data of length size to malloced
47 * buffer which is returned as *str. Returns string
48 * length of *str.
49 */
50int
51openvpn_base64_encode(const void *data, int size, char **str)
52{
53 char *s, *p;
54 int i;
55 int c;
56 const unsigned char *q;
57
58 if (size < 0)
59 {
60 return -1;
61 }
62 p = s = (char *)malloc(size * 4 / 3 + 4);
63 if (p == NULL)
64 {
65 return -1;
66 }
67 q = (const unsigned char *)data;
68 i = 0;
69 for (i = 0; i < size;)
70 {
71 c = q[i++];
72 c *= 256;
73 if (i < size)
74 {
75 c += q[i];
76 }
77 i++;
78 c *= 256;
79 if (i < size)
80 {
81 c += q[i];
82 }
83 i++;
84 p[0] = base64_chars[(c & 0x00fc0000) >> 18];
85 p[1] = base64_chars[(c & 0x0003f000) >> 12];
86 p[2] = base64_chars[(c & 0x00000fc0) >> 6];
87 p[3] = base64_chars[(c & 0x0000003f) >> 0];
88 if (i > size)
89 {
90 p[3] = '=';
91 }
92 if (i > size + 1)
93 {
94 p[2] = '=';
95 }
96 p += 4;
97 }
98 *p = 0;
99 *str = s;
100 return strlen(s);
101}
102
103static int
104pos(char c)
105{
106 char *p;
107 for (p = base64_chars; *p; p++)
108 {
109 if (*p == c)
110 {
111 return p - base64_chars;
112 }
113 }
114 return -1;
115}
116
117#define DECODE_ERROR 0xffffffff
118
119static unsigned int
120token_decode(const char *token)
121{
122 int i;
123 unsigned int val = 0;
124 int marker = 0;
125 if (!token[0] || !token[1] || !token[2] || !token[3])
126 {
127 return DECODE_ERROR;
128 }
129 for (i = 0; i < 4; i++)
130 {
131 val *= 64;
132 if (token[i] == '=')
133 {
134 marker++;
135 }
136 else if (marker > 0)
137 {
138 return DECODE_ERROR;
139 }
140 else
141 {
142 val += pos(token[i]);
143 }
144 }
145 if (marker > 2)
146 {
147 return DECODE_ERROR;
148 }
149 return (marker << 24) | val;
150}
151/*
152 * Decode base64 str, outputting data to buffer
153 * at data of length size. Return length of
154 * decoded data written or -1 on error or overflow.
155 */
156int
157openvpn_base64_decode(const char *str, void *data, int size)
158{
159 const char *p;
160 unsigned char *q;
161 unsigned char *e = NULL;
162
163 q = data;
164 if (size >= 0)
165 {
166 e = q + size;
167 }
168 for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4)
169 {
170 unsigned int val = token_decode(p);
171 unsigned int marker = (val >> 24) & 0xff;
172 if (val == DECODE_ERROR)
173 {
174 return -1;
175 }
176 if (e && q >= e)
177 {
178 return -1;
179 }
180 *q++ = (val >> 16) & 0xff;
181 if (marker < 2)
182 {
183 if (e && q >= e)
184 {
185 return -1;
186 }
187 *q++ = (val >> 8) & 0xff;
188 }
189 if (marker < 1)
190 {
191 if (e && q >= e)
192 {
193 return -1;
194 }
195 *q++ = val & 0xff;
196 }
197 }
198 return q - (unsigned char *)data;
199}
static int pos(char c)
Definition base64.c:104
int openvpn_base64_decode(const char *str, void *data, int size)
Definition base64.c:157
static char base64_chars[]
Definition base64.c:44
int openvpn_base64_encode(const void *data, int size, char **str)
Definition base64.c:51
static unsigned int token_decode(const char *token)
Definition base64.c:120
#define DECODE_ERROR
Definition base64.c:117