Support encrypted backup files

Also includes features merged from:

Update twrpTar by kokotas

Revised function entryExists().
Added function to get archive's uncompressed size.
Added option to exclude item(s) from the archive.
Revised forks()

http://review.teamw.in/#/c/590/

Change-Id: I01fa2c81643161984eff2625247af75990684bd9
diff --git a/openaes/src/oaes.c b/openaes/src/oaes.c
new file mode 100644
index 0000000..9a5d268
--- /dev/null
+++ b/openaes/src/oaes.c
@@ -0,0 +1,317 @@
+/* 
+ * ---------------------------------------------------------------------------
+ * OpenAES License
+ * ---------------------------------------------------------------------------
+ * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ *   - Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   - Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * ---------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define OAES_DEBUG 1
+#include "../inc/oaes_lib.h"
+
+#if defined(_WIN32) && !defined(__SYMBIAN32__)
+#include <io.h>
+#else
+__inline static int setmode(int a, int b)
+{
+	return 0;
+}
+#endif
+
+#ifndef __max
+	#define __max(a,b)  (((a) > (b)) ? (a) : (b))
+#endif // __max
+
+#ifndef __min
+	#define __min(a,b)  (((a) < (b)) ? (a) : (b))
+#endif // __min
+
+#define OAES_BUF_LEN_ENC 4096 - 2 * OAES_BLOCK_SIZE
+#define OAES_BUF_LEN_DEC 4096
+
+static void usage( const char * exe_name )
+{
+	if( NULL == exe_name )
+		return;
+	
+	fprintf( stderr,
+			"Usage:\n"
+			"  %s <command> --key <key_data> [options]\n"
+			"\n"
+			"    command:\n"
+			"      enc: encrypt\n"
+			"      dec:  decrypt\n"
+			"\n"
+			"    options:\n"
+			"      --ecb: use ecb mode instead of cbc\n"
+			"      --in <path_in>\n"
+			"      --out <path_out>\n"
+			"\n",
+			exe_name
+	);
+}
+
+int main(int argc, char** argv)
+{
+	size_t _i = 0, _j = 0;
+	OAES_CTX * ctx = NULL;
+	uint8_t _buf_in[OAES_BUF_LEN_DEC];
+	uint8_t *_buf_out = NULL, _key_data[32] = "";
+	size_t _buf_in_len = 0, _buf_out_len = 0, _read_len = 0;
+	size_t _key_data_len = 0;
+	short _is_ecb = 0;
+	char *_file_in = NULL, *_file_out = NULL;
+	int _op = 0;
+	FILE *_f_in = stdin, *_f_out = stdout;
+	
+	fprintf( stderr, "\n"
+		"*******************************************************************************\n"
+		"* OpenAES %-10s                                                          *\n"
+		"* Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com                     *\n"
+		"*******************************************************************************\n\n",
+		OAES_VERSION );
+
+	// pad the key
+	for( _j = 0; _j < 32; _j++ )
+		_key_data[_j] = _j + 1;
+
+	if( argc < 2 )
+	{
+		usage( argv[0] );
+		return EXIT_FAILURE;
+	}
+
+	if( 0 == strcmp( argv[1], "enc" ) )
+	{
+		_op = 0;
+		_read_len = OAES_BUF_LEN_ENC;
+	}
+	else if( 0 == strcmp( argv[1], "dec" ) )
+	{
+		_op = 1;
+		_read_len = OAES_BUF_LEN_DEC;
+	}
+	else
+	{
+		fprintf(stderr, "Error: Unknown command '%s'.", argv[1]);
+		usage( argv[0] );
+		return EXIT_FAILURE;
+	}
+
+	for( _i = 2; _i < argc; _i++ )
+	{
+		int _found = 0;
+
+		if( 0 == strcmp( argv[_i], "--ecb" ) )
+		{
+			_found = 1;
+			_is_ecb = 1;
+		}
+		
+		if( 0 == strcmp( argv[_i], "--key" ) )
+		{
+			_found = 1;
+			_i++; // key_data
+			if( _i >= argc )
+			{
+				fprintf(stderr, "Error: No value specified for '%s'.\n",
+						"--key");
+				usage( argv[0] );
+				return EXIT_FAILURE;
+			}
+			_key_data_len = strlen(argv[_i]);
+			if( 16 >= _key_data_len )
+				_key_data_len = 16;
+			else if( 24 >= _key_data_len )
+				_key_data_len = 24;
+			else
+				_key_data_len = 32;
+			memcpy(_key_data, argv[_i], __min(32, strlen(argv[_i])));
+		}
+		
+		if( 0 == strcmp( argv[_i], "--in" ) )
+		{
+			_found = 1;
+			_i++; // path_in
+			if( _i >= argc )
+			{
+				fprintf(stderr, "Error: No value specified for '%s'.\n",
+						"--in");
+				usage( argv[0] );
+				return EXIT_FAILURE;
+			}
+			_file_in = argv[_i];
+		}
+		
+		if( 0 == strcmp( argv[_i], "--out" ) )
+		{
+			_found = 1;
+			_i++; // path_out
+			if( _i >= argc )
+			{
+				fprintf(stderr, "Error: No value specified for '%s'.\n",
+						"--out");
+				usage( argv[0] );
+				return EXIT_FAILURE;
+			}
+			_file_out = argv[_i];
+		}
+		
+		if( 0 == _found )
+		{
+			fprintf(stderr, "Error: Invalid option '%s'.\n", argv[_i]);
+			usage( argv[0] );
+			return EXIT_FAILURE;
+		}			
+	}
+
+	if( 0 == _key_data_len )
+	{
+		fprintf(stderr, "Error: --key must be specified.\n");
+		return EXIT_FAILURE;
+	}
+
+	if( _file_in )
+	{
+		_f_in = fopen(_file_in, "rb");
+		if( NULL == _f_in )
+		{
+			fprintf(stderr,
+				"Error: Failed to open '-%s' for reading.\n", _file_in);
+			return EXIT_FAILURE;
+		}
+	}
+	else
+	{
+		if( setmode(fileno(stdin), 0x8000) < 0 )
+			fprintf(stderr,"Error: Failed in setmode().\n");
+		_f_in = stdin;
+	}
+
+	if( _file_out )
+	{
+		_f_out = fopen(_file_out, "wb");
+		if( NULL == _f_out )
+		{
+			fprintf(stderr,
+				"Error: Failed to open '-%s' for writing.\n", _file_out);
+			if( _file_in )
+				fclose(_f_in);
+			return EXIT_FAILURE;
+		}
+	}
+	else
+	{
+		if( setmode(fileno(stdout), 0x8000) < 0 )
+			fprintf(stderr, "Error: Failed in setmode().\n");
+		_f_out = stdout;
+	}
+
+	ctx = oaes_alloc();
+	if( NULL == ctx )
+	{
+		fprintf(stderr, "Error: Failed to initialize OAES.\n");
+		if( _file_in )
+			fclose(_f_in);
+		if( _file_out )
+			fclose(_f_out);
+		return EXIT_FAILURE;
+	}
+	if( _is_ecb )
+		if( OAES_RET_SUCCESS != oaes_set_option( ctx, OAES_OPTION_ECB, NULL ) )
+			fprintf(stderr, "Error: Failed to set OAES options.\n");
+
+	oaes_key_import_data( ctx, _key_data, _key_data_len );
+
+	while( _buf_in_len =
+		fread(_buf_in, sizeof(uint8_t), _read_len, _f_in) )
+	{
+		switch(_op)
+		{
+		case 0:
+			if( OAES_RET_SUCCESS != oaes_encrypt( ctx,
+					_buf_in, _buf_in_len, NULL, &_buf_out_len ) )
+				fprintf( stderr,
+					"Error: Failed to retrieve required buffer size for "
+					"encryption.\n" );
+			_buf_out = (uint8_t *) calloc( _buf_out_len, sizeof( char ) );
+			if( NULL == _buf_out )
+			{
+				fprintf(stderr,  "Error: Failed to allocate memory.\n" );
+				if( _file_in )
+					fclose(_f_in);
+				if( _file_out )
+					fclose(_f_out);
+				return EXIT_FAILURE;
+			}
+			if( OAES_RET_SUCCESS != oaes_encrypt( ctx,
+					_buf_in, _buf_in_len, _buf_out, &_buf_out_len ) )
+				fprintf(stderr, "Error: Encryption failed.\n");
+			fwrite(_buf_out, sizeof(uint8_t), _buf_out_len, _f_out);
+			free(_buf_out);
+			break;
+		case 1:
+			if( OAES_RET_SUCCESS != oaes_decrypt( ctx,
+					_buf_in, _buf_in_len, NULL, &_buf_out_len ) )
+				fprintf( stderr,
+					"Error: Failed to retrieve required buffer size for "
+					"encryption.\n" );
+			_buf_out = (uint8_t *) calloc( _buf_out_len, sizeof( char ) );
+			if( NULL == _buf_out )
+			{
+				fprintf(stderr,  "Error: Failed to allocate memory.\n" );
+				free( _buf_out );
+				if( _file_in )
+					fclose(_f_in);
+				if( _file_out )
+					fclose(_f_out);
+				return EXIT_FAILURE;
+			}
+			if( OAES_RET_SUCCESS != oaes_decrypt( ctx,
+					_buf_in, _buf_in_len, _buf_out, &_buf_out_len ) )
+				fprintf(stderr, "Error: Decryption failed.\n");
+			fwrite(_buf_out, sizeof(uint8_t), _buf_out_len, _f_out);
+			free(_buf_out);
+			break;
+		default:
+			break;
+		}
+	}
+
+
+	if( OAES_RET_SUCCESS !=  oaes_free( &ctx ) )
+		fprintf(stderr, "Error: Failed to uninitialize OAES.\n");
+	
+	if( _file_in )
+		fclose(_f_in);
+	if( _file_out )
+		fclose(_f_out);
+
+	return (EXIT_SUCCESS);
+}