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 #elif defined(_MSC_VER)
37 #include "config-msvc.h"
38 #endif
39 
40 #include "syshead.h"
41 
42 #include "base64.h"
43 
44 #include "memdbg.h"
45 
46 static char base64_chars[] =
47  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
48 /*
49  * base64 encode input data of length size to malloced
50  * buffer which is returned as *str. Returns string
51  * length of *str.
52  */
53 int
54 openvpn_base64_encode(const void *data, int size, char **str)
55 {
56  char *s, *p;
57  int i;
58  int c;
59  const unsigned char *q;
60 
61  if (size < 0)
62  {
63  return -1;
64  }
65  p = s = (char *) malloc(size * 4 / 3 + 4);
66  if (p == NULL)
67  {
68  return -1;
69  }
70  q = (const unsigned char *) data;
71  i = 0;
72  for (i = 0; i < size; )
73  {
74  c = q[i++];
75  c *= 256;
76  if (i < size)
77  {
78  c += q[i];
79  }
80  i++;
81  c *= 256;
82  if (i < size)
83  {
84  c += q[i];
85  }
86  i++;
87  p[0] = base64_chars[(c & 0x00fc0000) >> 18];
88  p[1] = base64_chars[(c & 0x0003f000) >> 12];
89  p[2] = base64_chars[(c & 0x00000fc0) >> 6];
90  p[3] = base64_chars[(c & 0x0000003f) >> 0];
91  if (i > size)
92  {
93  p[3] = '=';
94  }
95  if (i > size + 1)
96  {
97  p[2] = '=';
98  }
99  p += 4;
100  }
101  *p = 0;
102  *str = s;
103  return strlen(s);
104 }
105 
106 static int
107 pos(char c)
108 {
109  char *p;
110  for (p = base64_chars; *p; p++)
111  {
112  if (*p == c)
113  {
114  return p - base64_chars;
115  }
116  }
117  return -1;
118 }
119 
120 #define DECODE_ERROR 0xffffffff
121 
122 static unsigned int
123 token_decode(const char *token)
124 {
125  int i;
126  unsigned int val = 0;
127  int marker = 0;
128  if (!token[0] || !token[1] || !token[2] || !token[3])
129  {
130  return DECODE_ERROR;
131  }
132  for (i = 0; i < 4; i++)
133  {
134  val *= 64;
135  if (token[i] == '=')
136  {
137  marker++;
138  }
139  else if (marker > 0)
140  {
141  return DECODE_ERROR;
142  }
143  else
144  {
145  val += pos(token[i]);
146  }
147  }
148  if (marker > 2)
149  {
150  return DECODE_ERROR;
151  }
152  return (marker << 24) | val;
153 }
154 /*
155  * Decode base64 str, outputting data to buffer
156  * at data of length size. Return length of
157  * decoded data written or -1 on error or overflow.
158  */
159 int
160 openvpn_base64_decode(const char *str, void *data, int size)
161 {
162  const char *p;
163  unsigned char *q;
164  unsigned char *e = NULL;
165 
166  q = data;
167  if (size >= 0)
168  {
169  e = q + size;
170  }
171  for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4)
172  {
173  unsigned int val = token_decode(p);
174  unsigned int marker = (val >> 24) & 0xff;
175  if (val == DECODE_ERROR)
176  {
177  return -1;
178  }
179  if (e && q >= e)
180  {
181  return -1;
182  }
183  *q++ = (val >> 16) & 0xff;
184  if (marker < 2)
185  {
186  if (e && q >= e)
187  {
188  return -1;
189  }
190  *q++ = (val >> 8) & 0xff;
191  }
192  if (marker < 1)
193  {
194  if (e && q >= e)
195  {
196  return -1;
197  }
198  *q++ = val & 0xff;
199  }
200  }
201  return q - (unsigned char *) data;
202 }
static char base64_chars[]
Definition: base64.c:46
#define DECODE_ERROR
Definition: base64.c:120
#define malloc
Definition: cmocka.c:1795
int openvpn_base64_decode(const char *str, void *data, int size)
Definition: base64.c:160
static int pos(char c)
Definition: base64.c:107
int openvpn_base64_encode(const void *data, int size, char **str)
Definition: base64.c:54
static unsigned int token_decode(const char *token)
Definition: base64.c:123