Base64.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2018, 2019 Wind River Systems, Inc. All Rights Reserved.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  * https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  * http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  * Keith Holman - initial implementation and documentation
15  *******************************************************************************/
16 
17 #include "Base64.h"
18 
19 #if defined(_WIN32) || defined(_WIN64)
20 #pragma comment(lib, "crypt32.lib")
21 #include <windows.h>
22 #include <wincrypt.h>
23 b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
24 {
25  b64_size_t ret = 0u;
26  DWORD dw_out_len = (DWORD)out_len;
27  if ( CryptStringToBinaryA( in, in_len, CRYPT_STRING_BASE64, out, &dw_out_len, NULL, NULL ) )
28  ret = (b64_size_t)dw_out_len;
29  return ret;
30 }
31 
32 b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
33 {
34  b64_size_t ret = 0u;
35  DWORD dw_out_len = (DWORD)out_len;
36  if ( CryptBinaryToStringA( in, in_len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, out, &dw_out_len ) )
37  ret = (b64_size_t)dw_out_len;
38  return ret;
39 }
40 #else /* if defined(_WIN32) || defined(_WIN64) */
41 
42 #if defined(OPENSSL)
43 #include <openssl/bio.h>
44 #include <openssl/evp.h>
45 static b64_size_t Base64_encodeDecode(
46  char *out, b64_size_t out_len, const char *in, b64_size_t in_len, int encode )
47 {
48  b64_size_t ret = 0u;
49  if ( in_len > 0u )
50  {
51  int rv;
52  BIO *bio, *b64, *b_in, *b_out;
53 
54  b64 = BIO_new(BIO_f_base64());
55  bio = BIO_new(BIO_s_mem());
56  b64 = BIO_push(b64, bio);
57  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); /* ignore new-lines */
58 
59  if ( encode )
60  {
61  b_in = bio;
62  b_out = b64;
63  }
64  else
65  {
66  b_in = b64;
67  b_out = bio;
68  }
69 
70  rv = BIO_write(b_out, in, (int)in_len);
71  BIO_flush(b_out); /* indicate end of encoding */
72 
73  if ( rv > 0 )
74  {
75  rv = BIO_read(b_in, out, (int)out_len);
76  if ( rv > 0 )
77  {
78  ret = (b64_size_t)rv;
79  if ( out_len > ret )
80  out[ret] = '\0';
81  }
82  }
83 
84  BIO_free_all(b64); /* free all used memory */
85  }
86  return ret;
87 }
88 
89 b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
90 {
91  return Base64_encodeDecode( (char*)out, out_len, in, in_len, 0 );
92 }
93 
94 b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
95 {
96  return Base64_encodeDecode( out, out_len, (const char*)in, in_len, 1 );
97 }
98 
99 #else /* if defined(OPENSSL) */
100 b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
101 {
102 #define NV 64
103  static const unsigned char BASE64_DECODE_TABLE[] =
104  {
105  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 0-15 */
106  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 16-31 */
107  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, 62, NV, NV, NV, 63, /* 32-47 */
108  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NV, NV, NV, NV, NV, NV, /* 48-63 */
109  NV, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64-79 */
110  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NV, NV, NV, NV, NV, /* 80-95 */
111  NV, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 96-111 */
112  41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NV, NV, NV, NV, NV, /* 112-127 */
113  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 128-143 */
114  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 144-159 */
115  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 160-175 */
116  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 176-191 */
117  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 192-207 */
118  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 208-223 */
119  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 224-239 */
120  NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV /* 240-255 */
121  };
122 
123  b64_size_t ret = 0u;
124  b64_size_t out_count = 0u;
125 
126  /* in valid base64, length must be multiple of 4's: 0, 4, 8, 12, etc */
127  while ( in_len > 3u && out_count < out_len )
128  {
129  int i;
130  unsigned char c[4];
131  for ( i = 0; i < 4; ++i, ++in )
132  c[i] = BASE64_DECODE_TABLE[(int)(*in)];
133  in_len -= 4u;
134 
135  /* first byte */
136  *out = c[0] << 2;
137  *out |= (c[1] & ~0xF) >> 4;
138  ++out;
139  ++out_count;
140 
141  if ( out_count < out_len )
142  {
143  /* second byte */
144  *out = (c[1] & 0xF) << 4;
145  if ( c[2] < NV )
146  {
147  *out |= (c[2] & ~0x3) >> 2;
148  ++out;
149  ++out_count;
150 
151  if ( out_count < out_len )
152  {
153  /* third byte */
154  *out = (c[2] & 0x3) << 6;
155  if ( c[3] < NV )
156  {
157  *out |= c[3];
158  ++out;
159  ++out_count;
160  }
161  else
162  in_len = 0u;
163  }
164  }
165  else
166  in_len = 0u;
167  }
168  }
169 
170  if ( out_count <= out_len )
171  {
172  ret = out_count;
173  if ( out_count < out_len )
174  *out = '\0';
175  }
176  return ret;
177 }
178 
179 b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
180 {
181  static const char BASE64_ENCODE_TABLE[] =
182  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
183  "abcdefghijklmnopqrstuvwxyz"
184  "0123456789+/=";
185  b64_size_t ret = 0u;
186  b64_size_t out_count = 0u;
187 
188  while ( in_len > 0u && out_count < out_len )
189  {
190  int i;
191  unsigned char c[] = { 0, 0, 64, 64 }; /* index of '=' char */
192 
193  /* first character */
194  i = *in;
195  c[0] = (i & ~0x3) >> 2;
196 
197  /* second character */
198  c[1] = (i & 0x3) << 4;
199  --in_len;
200  if ( in_len > 0u )
201  {
202  ++in;
203  i = *in;
204  c[1] |= (i & ~0xF) >> 4;
205 
206  /* third character */
207  c[2] = (i & 0xF) << 2;
208  --in_len;
209  if ( in_len > 0u )
210  {
211  ++in;
212  i = *in;
213  c[2] |= (i & ~0x3F) >> 6;
214 
215  /* fourth character */
216  c[3] = (i & 0x3F);
217  --in_len;
218  ++in;
219  }
220  }
221 
222  /* encode the characters */
223  out_count += 4u;
224  for ( i = 0; i < 4 && out_count <= out_len; ++i, ++out )
225  *out = BASE64_ENCODE_TABLE[c[i]];
226  }
227 
228  if ( out_count <= out_len )
229  {
230  if ( out_count < out_len )
231  *out = '\0';
232  ret = out_count;
233  }
234  return ret;
235 }
236 #endif /* else if defined(OPENSSL) */
237 #endif /* if else defined(_WIN32) || defined(_WIN64) */
238 
239 b64_size_t Base64_decodeLength( const char *in, b64_size_t in_len )
240 {
241  b64_size_t pad = 0u;
242 
243  if ( in && in_len > 1u )
244  pad += ( in[in_len - 2u] == '=' ? 1u : 0u );
245  if ( in && in_len > 0u )
246  pad += ( in[in_len - 1u] == '=' ? 1u : 0u );
247  return (in_len / 4u * 3u) - pad;
248 }
249 
251 {
252  return ((4u * in_len / 3u) + 3u) & ~0x3;
253 }
254 
255 #if defined(BASE64_TEST)
256 #include <stdio.h>
257 #include <string.h>
258 
259 #define TEST_EXPECT(i,x) if (!(x)) {fprintf( stderr, "failed test: %s (for i == %d)\n", #x, i ); ++fails;}
260 
261 int main(int argc, char *argv[])
262 {
263  struct _td
264  {
265  const char *in;
266  const char *out;
267  };
268 
269  int i;
270  unsigned int fails = 0u;
271  struct _td test_data[] = {
272  { "", "" },
273  { "p", "cA==" },
274  { "pa", "cGE=" },
275  { "pah", "cGFo" },
276  { "paho", "cGFobw==" },
277  { "paho ", "cGFobyA=" },
278  { "paho w", "cGFobyB3" },
279  { "paho wi", "cGFobyB3aQ==" },
280  { "paho wit", "cGFobyB3aXQ=" },
281  { "paho with", "cGFobyB3aXRo" },
282  { "paho with ", "cGFobyB3aXRoIA==" },
283  { "paho with w", "cGFobyB3aXRoIHc=" },
284  { "paho with we", "cGFobyB3aXRoIHdl" },
285  { "paho with web", "cGFobyB3aXRoIHdlYg==" },
286  { "paho with webs", "cGFobyB3aXRoIHdlYnM=" },
287  { "paho with webso", "cGFobyB3aXRoIHdlYnNv" },
288  { "paho with websoc", "cGFobyB3aXRoIHdlYnNvYw==" },
289  { "paho with websock", "cGFobyB3aXRoIHdlYnNvY2s=" },
290  { "paho with websocke", "cGFobyB3aXRoIHdlYnNvY2tl" },
291  { "paho with websocket", "cGFobyB3aXRoIHdlYnNvY2tldA==" },
292  { "paho with websockets", "cGFobyB3aXRoIHdlYnNvY2tldHM=" },
293  { "paho with websockets.", "cGFobyB3aXRoIHdlYnNvY2tldHMu" },
294  { "The quick brown fox jumps over the lazy dog",
295  "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==" },
296  { "Man is distinguished, not only by his reason, but by this singular passion from\n"
297  "other animals, which is a lust of the mind, that by a perseverance of delight\n"
298  "in the continued and indefatigable generation of knowledge, exceeds the short\n"
299  "vehemence of any carnal pleasure.",
300  "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
301  "IHNpbmd1bGFyIHBhc3Npb24gZnJvbQpvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
302  "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodAppbiB0aGUgY29udGlu"
303  "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
304  "ZSBzaG9ydAp2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" },
305  { NULL, NULL }
306  };
307 
308  /* decode tests */
309  i = 0;
310  while ( test_data[i].in != NULL )
311  {
312  int r;
313  char out[512u];
314  r = Base64_decode( out, sizeof(out), test_data[i].out, strlen(test_data[i].out) );
315  TEST_EXPECT( i, r == strlen(test_data[i].in) && strncmp(out, test_data[i].in, strlen(test_data[i].in)) == 0 );
316  ++i;
317  }
318 
319  /* decode length tests */
320  i = 0;
321  while ( test_data[i].in != NULL )
322  {
323  TEST_EXPECT( i, Base64_decodeLength(test_data[i].out, strlen(test_data[i].out)) == strlen(test_data[i].in));
324  ++i;
325  }
326 
327  /* encode tests */
328  i = 0;
329  while ( test_data[i].in != NULL )
330  {
331  int r;
332  char out[512u];
333  r = Base64_encode( out, sizeof(out), test_data[i].in, strlen(test_data[i].in) );
334  TEST_EXPECT( i, r == strlen(test_data[i].out) && strncmp(out, test_data[i].out, strlen(test_data[i].out)) == 0 );
335  ++i;
336  }
337 
338  /* encode length tests */
339  i = 0;
340  while ( test_data[i].in != NULL )
341  {
342  TEST_EXPECT( i, Base64_encodeLength(test_data[i].in, strlen(test_data[i].in)) == strlen(test_data[i].out) );
343  ++i;
344  }
345 
346  if ( fails )
347  printf( "%u test failed!\n", fails );
348  else
349  printf( "all tests passed\n" );
350  return fails;
351 }
352 #endif /* if defined(BASE64_TEST) */
static unsigned char pad[64]
Definition: SHA1.c:66
b64_size_t Base64_decode(b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len)
Definition: Base64.c:100
b64_size_t Base64_decodeLength(const char *in, b64_size_t in_len)
Definition: Base64.c:239
def encode(x)
Definition: MQTTV5.py:229
b64_size_t Base64_encodeLength(const b64_data_t *in, b64_size_t in_len)
Definition: Base64.c:250
b64_size_t Base64_encode(char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len)
Definition: Base64.c:179
MQTTClient c
Definition: test10.c:1656
unsigned char b64_data_t
Definition: Base64.h:23
unsigned int b64_size_t
Definition: Base64.h:21
int main(int argc, char **argv)
Definition: lua.c:619
#define NV


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:47:33