123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352 |
- /*******************************************************************************
- * Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- *
- * The Eclipse Public License is available at
- * http://www.eclipse.org/legal/epl-v10.html
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Keith Holman - initial implementation and documentation
- *******************************************************************************/
- #include "Base64.h"
- #if defined(WIN32) || defined(WIN64)
- #pragma comment(lib, "crypt32.lib")
- #include <Windows.h>
- #include <WinCrypt.h>
- b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
- {
- b64_size_t ret = 0u;
- DWORD dw_out_len = (DWORD)out_len;
- if ( CryptStringToBinaryA( in, in_len, CRYPT_STRING_BASE64, out, &dw_out_len, NULL, NULL ) )
- ret = (b64_size_t)dw_out_len;
- return ret;
- }
- b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
- {
- b64_size_t ret = 0u;
- DWORD dw_out_len = (DWORD)out_len;
- if ( CryptBinaryToStringA( in, in_len, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF, out, &dw_out_len ) )
- ret = (b64_size_t)dw_out_len;
- return ret;
- }
- #else /* if defined(WIN32) || defined(WIN64) */
- #if defined(OPENSSL)
- #include <openssl/bio.h>
- #include <openssl/evp.h>
- static b64_size_t Base64_encodeDecode(
- char *out, b64_size_t out_len, const char *in, b64_size_t in_len, int encode )
- {
- b64_size_t ret = 0u;
- if ( in_len > 0u )
- {
- int rv;
- BIO *bio, *b64, *b_in, *b_out;
- b64 = BIO_new(BIO_f_base64());
- bio = BIO_new(BIO_s_mem());
- b64 = BIO_push(b64, bio);
- BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); /* ignore new-lines */
- if ( encode )
- {
- b_in = bio;
- b_out = b64;
- }
- else
- {
- b_in = b64;
- b_out = bio;
- }
- rv = BIO_write(b_out, in, (int)in_len);
- BIO_flush(b_out); /* indicate end of encoding */
- if ( rv > 0 )
- {
- rv = BIO_read(b_in, out, (int)out_len);
- if ( rv > 0 )
- {
- ret = (b64_size_t)rv;
- if ( out_len > ret )
- out[ret] = '\0';
- }
- }
- BIO_free_all(b64); /* free all used memory */
- }
- return ret;
- }
- b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
- {
- return Base64_encodeDecode( (char*)out, out_len, in, in_len, 0 );
- }
- b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
- {
- return Base64_encodeDecode( out, out_len, (const char*)in, in_len, 1 );
- }
- #else /* if defined(OPENSSL) */
- b64_size_t Base64_decode( b64_data_t *out, b64_size_t out_len, const char *in, b64_size_t in_len )
- {
- #define NV 64
- static const unsigned char BASE64_DECODE_TABLE[] =
- {
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 0-15 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 16-31 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, 62, NV, NV, NV, 63, /* 32-47 */
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, NV, NV, NV, NV, NV, NV, /* 48-63 */
- NV, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 64-79 */
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, NV, NV, NV, NV, NV, /* 80-95 */
- NV, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 96-111 */
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, NV, NV, NV, NV, NV, /* 112-127 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 128-143 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 144-159 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 160-175 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 176-191 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 192-207 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 208-223 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, /* 224-239 */
- NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV, NV /* 240-255 */
- };
- b64_size_t ret = 0u;
- b64_size_t out_count = 0u;
- /* in valid base64, length must be multiple of 4's: 0, 4, 8, 12, etc */
- while ( in_len > 3u && out_count < out_len )
- {
- int i;
- unsigned char c[4];
- for ( i = 0; i < 4; ++i, ++in )
- c[i] = BASE64_DECODE_TABLE[(int)(*in)];
- in_len -= 4u;
- /* first byte */
- *out = c[0] << 2;
- *out |= (c[1] & ~0xF) >> 4;
- ++out;
- ++out_count;
- if ( out_count < out_len )
- {
- /* second byte */
- *out = (c[1] & 0xF) << 4;
- if ( c[2] < NV )
- {
- *out |= (c[2] & ~0x3) >> 2;
- ++out;
- ++out_count;
- if ( out_count < out_len )
- {
- /* third byte */
- *out = (c[2] & 0x3) << 6;
- if ( c[3] < NV )
- {
- *out |= c[3];
- ++out;
- ++out_count;
- }
- else
- in_len = 0u;
- }
- }
- else
- in_len = 0u;
- }
- }
- if ( out_count <= out_len )
- {
- ret = out_count;
- if ( out_count < out_len )
- *out = '\0';
- }
- return ret;
- }
- b64_size_t Base64_encode( char *out, b64_size_t out_len, const b64_data_t *in, b64_size_t in_len )
- {
- static const char BASE64_ENCODE_TABLE[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789+/=";
- b64_size_t ret = 0u;
- b64_size_t out_count = 0u;
- while ( in_len > 0u && out_count < out_len )
- {
- int i;
- unsigned char c[] = { 0, 0, 64, 64 }; /* index of '=' char */
- /* first character */
- i = *in;
- c[0] = (i & ~0x3) >> 2;
- /* second character */
- c[1] = (i & 0x3) << 4;
- --in_len;
- if ( in_len > 0u )
- {
- ++in;
- i = *in;
- c[1] |= (i & ~0xF) >> 4;
- /* third character */
- c[2] = (i & 0xF) << 2;
- --in_len;
- if ( in_len > 0u )
- {
- ++in;
- i = *in;
- c[2] |= (i & ~0x3F) >> 6;
- /* fourth character */
- c[3] = (i & 0x3F);
- --in_len;
- ++in;
- }
- }
- /* encode the characters */
- out_count += 4u;
- for ( i = 0; i < 4 && out_count <= out_len; ++i, ++out )
- *out = BASE64_ENCODE_TABLE[c[i]];
- }
- if ( out_count <= out_len )
- {
- if ( out_count < out_len )
- *out = '\0';
- ret = out_count;
- }
- return ret;
- }
- #endif /* else if defined(OPENSSL) */
- #endif /* if else defined(WIN32) || defined(WIN64) */
- b64_size_t Base64_decodeLength( const char *in, b64_size_t in_len )
- {
- b64_size_t pad = 0u;
- if ( in && in_len > 1u )
- pad += ( in[in_len - 2u] == '=' ? 1u : 0u );
- if ( in && in_len > 0u )
- pad += ( in[in_len - 1u] == '=' ? 1u : 0u );
- return (in_len / 4u * 3u) - pad;
- }
- b64_size_t Base64_encodeLength( const b64_data_t *in, b64_size_t in_len )
- {
- return ((4u * in_len / 3u) + 3u) & ~0x3;
- }
- #if defined(BASE64_TEST)
- #include <stdio.h>
- #include <string.h>
- #define TEST_EXPECT(i,x) if (!(x)) {fprintf( stderr, "failed test: %s (for i == %d)\n", #x, i ); ++fails;}
- int main(int argc, char *argv[])
- {
- struct _td
- {
- const char *in;
- const char *out;
- };
- int i;
- unsigned int fails = 0u;
- struct _td test_data[] = {
- { "", "" },
- { "p", "cA==" },
- { "pa", "cGE=" },
- { "pah", "cGFo" },
- { "paho", "cGFobw==" },
- { "paho ", "cGFobyA=" },
- { "paho w", "cGFobyB3" },
- { "paho wi", "cGFobyB3aQ==" },
- { "paho wit", "cGFobyB3aXQ=" },
- { "paho with", "cGFobyB3aXRo" },
- { "paho with ", "cGFobyB3aXRoIA==" },
- { "paho with w", "cGFobyB3aXRoIHc=" },
- { "paho with we", "cGFobyB3aXRoIHdl" },
- { "paho with web", "cGFobyB3aXRoIHdlYg==" },
- { "paho with webs", "cGFobyB3aXRoIHdlYnM=" },
- { "paho with webso", "cGFobyB3aXRoIHdlYnNv" },
- { "paho with websoc", "cGFobyB3aXRoIHdlYnNvYw==" },
- { "paho with websock", "cGFobyB3aXRoIHdlYnNvY2s=" },
- { "paho with websocke", "cGFobyB3aXRoIHdlYnNvY2tl" },
- { "paho with websocket", "cGFobyB3aXRoIHdlYnNvY2tldA==" },
- { "paho with websockets", "cGFobyB3aXRoIHdlYnNvY2tldHM=" },
- { "paho with websockets.", "cGFobyB3aXRoIHdlYnNvY2tldHMu" },
- { "The quick brown fox jumps over the lazy dog",
- "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw==" },
- { "Man is distinguished, not only by his reason, but by this singular passion from\n"
- "other animals, which is a lust of the mind, that by a perseverance of delight\n"
- "in the continued and indefatigable generation of knowledge, exceeds the short\n"
- "vehemence of any carnal pleasure.",
- "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"
- "IHNpbmd1bGFyIHBhc3Npb24gZnJvbQpvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg"
- "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodAppbiB0aGUgY29udGlu"
- "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo"
- "ZSBzaG9ydAp2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" },
- { NULL, NULL }
- };
- /* decode tests */
- i = 0;
- while ( test_data[i].in != NULL )
- {
- int r;
- char out[512u];
- r = Base64_decode( out, sizeof(out), test_data[i].out, strlen(test_data[i].out) );
- TEST_EXPECT( i, r == strlen(test_data[i].in) && strncmp(out, test_data[i].in, strlen(test_data[i].in)) == 0 );
- ++i;
- }
- /* decode length tests */
- i = 0;
- while ( test_data[i].in != NULL )
- {
- TEST_EXPECT( i, Base64_decodeLength(test_data[i].out, strlen(test_data[i].out)) == strlen(test_data[i].in));
- ++i;
- }
- /* encode tests */
- i = 0;
- while ( test_data[i].in != NULL )
- {
- int r;
- char out[512u];
- r = Base64_encode( out, sizeof(out), test_data[i].in, strlen(test_data[i].in) );
- TEST_EXPECT( i, r == strlen(test_data[i].out) && strncmp(out, test_data[i].out, strlen(test_data[i].out)) == 0 );
- ++i;
- }
- /* encode length tests */
- i = 0;
- while ( test_data[i].in != NULL )
- {
- TEST_EXPECT( i, Base64_encodeLength(test_data[i].in, strlen(test_data[i].in)) == strlen(test_data[i].out) );
- ++i;
- }
- if ( fails )
- printf( "%u test failed!\n", fails );
- else
- printf( "all tests passed\n" );
- return fails;
- }
- #endif /* if defined(BASE64_TEST) */
|