mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 15:15:34 +02:00
696 lines
17 KiB
C
696 lines
17 KiB
C
/******************************************************
|
|
Copyright (c) 2013 Percona LLC and/or its affiliates.
|
|
|
|
The xbcrypt utility: decrypt files in the XBCRYPT format.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*******************************************************/
|
|
|
|
#include <my_base.h>
|
|
#include <my_getopt.h>
|
|
#include "common.h"
|
|
#include "xbcrypt.h"
|
|
#include "xbcrypt_common.h"
|
|
#include "crc_glue.h"
|
|
|
|
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
|
GCRY_THREAD_OPTION_PTHREAD_IMPL;
|
|
#endif
|
|
|
|
#define XBCRYPT_VERSION "1.1"
|
|
|
|
typedef enum {
|
|
RUN_MODE_NONE,
|
|
RUN_MODE_ENCRYPT,
|
|
RUN_MODE_DECRYPT
|
|
} run_mode_t;
|
|
|
|
const char *xbcrypt_encrypt_algo_names[] =
|
|
{ "NONE", "AES128", "AES192", "AES256", NullS};
|
|
TYPELIB xbcrypt_encrypt_algo_typelib=
|
|
{array_elements(xbcrypt_encrypt_algo_names)-1,"",
|
|
xbcrypt_encrypt_algo_names, NULL};
|
|
|
|
static run_mode_t opt_run_mode = RUN_MODE_ENCRYPT;
|
|
static char *opt_input_file = NULL;
|
|
static char *opt_output_file = NULL;
|
|
static ulong opt_encrypt_algo;
|
|
static char *opt_encrypt_key_file = NULL;
|
|
static void *opt_encrypt_key = NULL;
|
|
static ulonglong opt_encrypt_chunk_size = 0;
|
|
static my_bool opt_verbose = FALSE;
|
|
|
|
static uint encrypt_algos[] = { GCRY_CIPHER_NONE,
|
|
GCRY_CIPHER_AES128,
|
|
GCRY_CIPHER_AES192,
|
|
GCRY_CIPHER_AES256 };
|
|
static int encrypt_algo = 0;
|
|
static int encrypt_mode = GCRY_CIPHER_MODE_CTR;
|
|
static uint encrypt_key_len = 0;
|
|
static size_t encrypt_iv_len = 0;
|
|
|
|
static struct my_option my_long_options[] =
|
|
{
|
|
{"help", '?', "Display this help and exit.",
|
|
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"decrypt", 'd', "Decrypt data input to output.",
|
|
0, 0, 0,
|
|
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"input", 'i', "Optional input file. If not specified, input"
|
|
" will be read from standard input.",
|
|
&opt_input_file, &opt_input_file, 0,
|
|
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"output", 'o', "Optional output file. If not specified, output"
|
|
" will be written to standard output.",
|
|
&opt_output_file, &opt_output_file, 0,
|
|
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"encrypt-algo", 'a', "Encryption algorithm.",
|
|
&opt_encrypt_algo, &opt_encrypt_algo, &xbcrypt_encrypt_algo_typelib,
|
|
GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"encrypt-key", 'k', "Encryption key.",
|
|
&opt_encrypt_key, &opt_encrypt_key, 0,
|
|
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"encrypt-key-file", 'f', "File which contains encryption key.",
|
|
&opt_encrypt_key_file, &opt_encrypt_key_file, 0,
|
|
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
|
|
|
{"encrypt-chunk-size", 's', "Size of working buffer for encryption in"
|
|
" bytes. The default value is 64K.",
|
|
&opt_encrypt_chunk_size, &opt_encrypt_chunk_size, 0,
|
|
GET_ULL, REQUIRED_ARG, (1 << 16), 1024, ULONGLONG_MAX, 0, 0, 0},
|
|
|
|
{"verbose", 'v', "Display verbose status output.",
|
|
&opt_verbose, &opt_verbose,
|
|
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
|
|
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
|
};
|
|
|
|
static
|
|
int
|
|
get_options(int *argc, char ***argv);
|
|
|
|
static
|
|
my_bool
|
|
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|
char *argument __attribute__((unused)));
|
|
|
|
static
|
|
void
|
|
print_version(void);
|
|
|
|
static
|
|
void
|
|
usage(void);
|
|
|
|
static
|
|
int
|
|
mode_decrypt(File filein, File fileout);
|
|
|
|
static
|
|
int
|
|
mode_encrypt(File filein, File fileout);
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
|
gcry_error_t gcry_error;
|
|
#endif
|
|
File filein = 0;
|
|
File fileout = 0;
|
|
|
|
MY_INIT(argv[0]);
|
|
|
|
crc_init();
|
|
|
|
if (get_options(&argc, &argv)) {
|
|
goto err;
|
|
}
|
|
|
|
/* Acording to gcrypt docs (and my testing), setting up the threading
|
|
callbacks must be done first, so, lets give it a shot */
|
|
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
|
gcry_error = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
|
|
if (gcry_error) {
|
|
msg("%s: unable to set libgcrypt thread cbs - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
/* Version check should be the very first call because it
|
|
makes sure that important subsystems are intialized. */
|
|
if (!gcry_control(GCRYCTL_ANY_INITIALIZATION_P)) {
|
|
const char *gcrypt_version;
|
|
gcrypt_version = gcry_check_version(NULL);
|
|
/* No other library has already initialized libgcrypt. */
|
|
if (!gcrypt_version) {
|
|
msg("%s: failed to initialize libgcrypt\n",
|
|
my_progname);
|
|
return 1;
|
|
} else if (opt_verbose) {
|
|
msg("%s: using gcrypt %s\n", my_progname,
|
|
gcrypt_version);
|
|
}
|
|
}
|
|
gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
|
|
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
|
|
|
/* Determine the algorithm */
|
|
encrypt_algo = encrypt_algos[opt_encrypt_algo];
|
|
|
|
/* Set up the iv length */
|
|
encrypt_iv_len = gcry_cipher_get_algo_blklen(encrypt_algo);
|
|
|
|
/* Now set up the key */
|
|
if (opt_encrypt_key == NULL && opt_encrypt_key_file == NULL) {
|
|
msg("%s: no encryption key or key file specified.\n",
|
|
my_progname);
|
|
return 1;
|
|
} else if (opt_encrypt_key && opt_encrypt_key_file) {
|
|
msg("%s: both encryption key and key file specified.\n",
|
|
my_progname);
|
|
return 1;
|
|
} else if (opt_encrypt_key_file) {
|
|
if (!xb_crypt_read_key_file(opt_encrypt_key_file,
|
|
&opt_encrypt_key,
|
|
&encrypt_key_len)) {
|
|
msg("%s: unable to read encryption key file \"%s\".\n",
|
|
opt_encrypt_key_file, my_progname);
|
|
return 1;
|
|
}
|
|
} else {
|
|
encrypt_key_len = strlen(opt_encrypt_key);
|
|
}
|
|
|
|
if (opt_input_file) {
|
|
MY_STAT mystat;
|
|
|
|
if (opt_verbose)
|
|
msg("%s: input file \"%s\".\n", my_progname,
|
|
opt_input_file);
|
|
|
|
if (my_stat(opt_input_file, &mystat, MYF(MY_WME)) == NULL) {
|
|
goto err;
|
|
}
|
|
if (!MY_S_ISREG(mystat.st_mode)) {
|
|
msg("%s: \"%s\" is not a regular file, exiting.\n",
|
|
my_progname, opt_input_file);
|
|
goto err;
|
|
}
|
|
if ((filein = my_open(opt_input_file, O_RDONLY, MYF(MY_WME)))
|
|
< 0) {
|
|
msg("%s: failed to open \"%s\".\n", my_progname,
|
|
opt_input_file);
|
|
goto err;
|
|
}
|
|
} else {
|
|
if (opt_verbose)
|
|
msg("%s: input from standard input.\n", my_progname);
|
|
filein = fileno(stdin);
|
|
}
|
|
|
|
if (opt_output_file) {
|
|
if (opt_verbose)
|
|
msg("%s: output file \"%s\".\n", my_progname,
|
|
opt_output_file);
|
|
|
|
if ((fileout = my_create(opt_output_file, 0,
|
|
O_WRONLY|O_BINARY|O_EXCL|O_NOFOLLOW,
|
|
MYF(MY_WME))) < 0) {
|
|
msg("%s: failed to create output file \"%s\".\n",
|
|
my_progname, opt_output_file);
|
|
goto err;
|
|
}
|
|
} else {
|
|
if (opt_verbose)
|
|
msg("%s: output to standard output.\n", my_progname);
|
|
fileout = fileno(stdout);
|
|
}
|
|
|
|
if (opt_run_mode == RUN_MODE_DECRYPT
|
|
&& mode_decrypt(filein, fileout)) {
|
|
goto err;
|
|
} else if (opt_run_mode == RUN_MODE_ENCRYPT
|
|
&& mode_encrypt(filein, fileout)) {
|
|
goto err;
|
|
}
|
|
|
|
if (opt_input_file && filein) {
|
|
my_close(filein, MYF(MY_WME));
|
|
}
|
|
if (opt_output_file && fileout) {
|
|
my_close(fileout, MYF(MY_WME));
|
|
}
|
|
|
|
my_cleanup_options(my_long_options);
|
|
|
|
my_end(0);
|
|
|
|
return EXIT_SUCCESS;
|
|
err:
|
|
if (opt_input_file && filein) {
|
|
my_close(filein, MYF(MY_WME));
|
|
}
|
|
if (opt_output_file && fileout) {
|
|
my_close(fileout, MYF(MY_WME));
|
|
}
|
|
|
|
my_cleanup_options(my_long_options);
|
|
|
|
my_end(0);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
static
|
|
size_t
|
|
my_xb_crypt_read_callback(void *userdata, void *buf, size_t len)
|
|
{
|
|
File* file = (File *) userdata;
|
|
return xb_read_full(*file, buf, len);
|
|
}
|
|
|
|
static
|
|
int
|
|
mode_decrypt(File filein, File fileout)
|
|
{
|
|
xb_rcrypt_t *xbcrypt_file = NULL;
|
|
void *chunkbuf = NULL;
|
|
size_t chunksize;
|
|
size_t originalsize;
|
|
void *ivbuf = NULL;
|
|
size_t ivsize;
|
|
void *decryptbuf = NULL;
|
|
size_t decryptbufsize = 0;
|
|
ulonglong ttlchunksread = 0;
|
|
ulonglong ttlbytesread = 0;
|
|
xb_rcrypt_result_t result;
|
|
gcry_cipher_hd_t cipher_handle;
|
|
gcry_error_t gcry_error;
|
|
my_bool hash_appended;
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
|
gcry_error = gcry_cipher_open(&cipher_handle,
|
|
encrypt_algo,
|
|
encrypt_mode, 0);
|
|
if (gcry_error) {
|
|
msg("%s:decrypt: unable to open libgcrypt"
|
|
" cipher - %s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
return 1;
|
|
}
|
|
|
|
gcry_error = gcry_cipher_setkey(cipher_handle,
|
|
opt_encrypt_key,
|
|
encrypt_key_len);
|
|
if (gcry_error) {
|
|
msg("%s:decrypt: unable to set libgcrypt cipher"
|
|
"key - %s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
/* Initialize the xb_crypt format reader */
|
|
xbcrypt_file = xb_crypt_read_open(&filein, my_xb_crypt_read_callback);
|
|
if (xbcrypt_file == NULL) {
|
|
msg("%s:decrypt: xb_crypt_read_open() failed.\n", my_progname);
|
|
goto err;
|
|
}
|
|
|
|
/* Walk the encrypted chunks, decrypting them and writing out */
|
|
while ((result = xb_crypt_read_chunk(xbcrypt_file, &chunkbuf,
|
|
&originalsize, &chunksize,
|
|
&ivbuf, &ivsize, &hash_appended))
|
|
== XB_CRYPT_READ_CHUNK) {
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
|
gcry_error = gcry_cipher_reset(cipher_handle);
|
|
if (gcry_error) {
|
|
msg("%s:decrypt: unable to reset libgcrypt"
|
|
" cipher - %s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
goto err;
|
|
}
|
|
|
|
if (ivsize) {
|
|
gcry_error = gcry_cipher_setctr(cipher_handle,
|
|
ivbuf,
|
|
ivsize);
|
|
}
|
|
if (gcry_error) {
|
|
msg("%s:decrypt: unable to set cipher iv - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
continue;
|
|
}
|
|
|
|
if (decryptbufsize < originalsize) {
|
|
decryptbuf = my_realloc(decryptbuf,
|
|
originalsize,
|
|
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
|
decryptbufsize = originalsize;
|
|
}
|
|
|
|
/* Try to decrypt it */
|
|
gcry_error = gcry_cipher_decrypt(cipher_handle,
|
|
decryptbuf,
|
|
originalsize,
|
|
chunkbuf,
|
|
chunksize);
|
|
if (gcry_error) {
|
|
msg("%s:decrypt: unable to decrypt chunk - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
gcry_cipher_close(cipher_handle);
|
|
goto err;
|
|
}
|
|
|
|
} else {
|
|
decryptbuf = chunkbuf;
|
|
}
|
|
|
|
if (hash_appended) {
|
|
uchar hash[XB_CRYPT_HASH_LEN];
|
|
|
|
originalsize -= XB_CRYPT_HASH_LEN;
|
|
|
|
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
|
of XB_CRYPT_HASH hashing algorithm output */
|
|
xb_a(gcry_md_get_algo_dlen(XB_CRYPT_HASH) ==
|
|
XB_CRYPT_HASH_LEN);
|
|
gcry_md_hash_buffer(XB_CRYPT_HASH, hash, decryptbuf,
|
|
originalsize);
|
|
if (memcmp(hash, (char *) decryptbuf + originalsize,
|
|
XB_CRYPT_HASH_LEN) != 0) {
|
|
msg("%s:%s invalid plaintext hash. "
|
|
"Wrong encrytion key specified?\n",
|
|
my_progname, __FUNCTION__);
|
|
result = XB_CRYPT_READ_ERROR;
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
/* Write it out */
|
|
if (my_write(fileout, (const uchar *) decryptbuf, originalsize,
|
|
MYF(MY_WME | MY_NABP))) {
|
|
msg("%s:decrypt: unable to write output chunk.\n",
|
|
my_progname);
|
|
goto err;
|
|
}
|
|
ttlchunksread++;
|
|
ttlbytesread += chunksize;
|
|
if (opt_verbose)
|
|
msg("%s:decrypt: %llu chunks read, %llu bytes read\n.",
|
|
my_progname, ttlchunksread, ttlbytesread);
|
|
}
|
|
|
|
xb_crypt_read_close(xbcrypt_file);
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE)
|
|
gcry_cipher_close(cipher_handle);
|
|
|
|
if (decryptbuf && decryptbufsize)
|
|
my_free(decryptbuf);
|
|
|
|
if (opt_verbose)
|
|
msg("\n%s:decrypt: done\n", my_progname);
|
|
|
|
return 0;
|
|
err:
|
|
if (xbcrypt_file)
|
|
xb_crypt_read_close(xbcrypt_file);
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE)
|
|
gcry_cipher_close(cipher_handle);
|
|
|
|
if (decryptbuf && decryptbufsize)
|
|
my_free(decryptbuf);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static
|
|
ssize_t
|
|
my_xb_crypt_write_callback(void *userdata, const void *buf, size_t len)
|
|
{
|
|
File* file = (File *) userdata;
|
|
|
|
ssize_t ret = my_write(*file, buf, len, MYF(MY_WME));
|
|
posix_fadvise(*file, 0, 0, POSIX_FADV_DONTNEED);
|
|
return ret;
|
|
}
|
|
|
|
static
|
|
int
|
|
mode_encrypt(File filein, File fileout)
|
|
{
|
|
size_t bytesread;
|
|
size_t chunkbuflen;
|
|
uchar *chunkbuf = NULL;
|
|
void *ivbuf = NULL;
|
|
size_t encryptbuflen = 0;
|
|
size_t encryptedlen = 0;
|
|
void *encryptbuf = NULL;
|
|
ulonglong ttlchunkswritten = 0;
|
|
ulonglong ttlbyteswritten = 0;
|
|
xb_wcrypt_t *xbcrypt_file = NULL;
|
|
gcry_cipher_hd_t cipher_handle;
|
|
gcry_error_t gcry_error;
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
|
gcry_error = gcry_cipher_open(&cipher_handle,
|
|
encrypt_algo,
|
|
encrypt_mode, 0);
|
|
if (gcry_error) {
|
|
msg("%s:encrypt: unable to open libgcrypt cipher - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
return 1;
|
|
}
|
|
|
|
gcry_error = gcry_cipher_setkey(cipher_handle,
|
|
opt_encrypt_key,
|
|
encrypt_key_len);
|
|
if (gcry_error) {
|
|
msg("%s:encrypt: unable to set libgcrypt cipher key - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
goto err;
|
|
}
|
|
}
|
|
|
|
posix_fadvise(filein, 0, 0, POSIX_FADV_SEQUENTIAL);
|
|
|
|
xbcrypt_file = xb_crypt_write_open(&fileout,
|
|
my_xb_crypt_write_callback);
|
|
if (xbcrypt_file == NULL) {
|
|
msg("%s:encrypt: xb_crypt_write_open() failed.\n",
|
|
my_progname);
|
|
goto err;
|
|
}
|
|
|
|
ivbuf = my_malloc(encrypt_iv_len, MYF(MY_FAE));
|
|
|
|
/* now read in data in chunk size, encrypt and write out */
|
|
chunkbuflen = opt_encrypt_chunk_size + XB_CRYPT_HASH_LEN;
|
|
chunkbuf = (uchar *) my_malloc(chunkbuflen, MYF(MY_FAE));
|
|
while ((bytesread = my_read(filein, chunkbuf, opt_encrypt_chunk_size,
|
|
MYF(MY_WME))) > 0) {
|
|
|
|
size_t origbuflen = bytesread + XB_CRYPT_HASH_LEN;
|
|
|
|
/* ensure that XB_CRYPT_HASH_LEN is the correct length
|
|
of XB_CRYPT_HASH hashing algorithm output */
|
|
xb_a(XB_CRYPT_HASH_LEN == gcry_md_get_algo_dlen(XB_CRYPT_HASH));
|
|
gcry_md_hash_buffer(XB_CRYPT_HASH, chunkbuf + bytesread,
|
|
chunkbuf, bytesread);
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE) {
|
|
gcry_error = gcry_cipher_reset(cipher_handle);
|
|
|
|
if (gcry_error) {
|
|
msg("%s:encrypt: unable to reset cipher - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
goto err;
|
|
}
|
|
|
|
xb_crypt_create_iv(ivbuf, encrypt_iv_len);
|
|
gcry_error = gcry_cipher_setctr(cipher_handle,
|
|
ivbuf,
|
|
encrypt_iv_len);
|
|
|
|
if (gcry_error) {
|
|
msg("%s:encrypt: unable to set cipher iv - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
continue;
|
|
}
|
|
|
|
if (encryptbuflen < origbuflen) {
|
|
encryptbuf = my_realloc(encryptbuf, origbuflen,
|
|
MYF(MY_WME | MY_ALLOW_ZERO_PTR));
|
|
encryptbuflen = origbuflen;
|
|
}
|
|
|
|
gcry_error = gcry_cipher_encrypt(cipher_handle,
|
|
encryptbuf,
|
|
encryptbuflen,
|
|
chunkbuf,
|
|
origbuflen);
|
|
|
|
encryptedlen = origbuflen;
|
|
|
|
if (gcry_error) {
|
|
msg("%s:encrypt: unable to encrypt chunk - "
|
|
"%s : %s\n", my_progname,
|
|
gcry_strsource(gcry_error),
|
|
gcry_strerror(gcry_error));
|
|
gcry_cipher_close(cipher_handle);
|
|
goto err;
|
|
}
|
|
} else {
|
|
encryptedlen = origbuflen;
|
|
encryptbuf = chunkbuf;
|
|
}
|
|
|
|
if (xb_crypt_write_chunk(xbcrypt_file, encryptbuf,
|
|
bytesread + XB_CRYPT_HASH_LEN,
|
|
encryptedlen, ivbuf, encrypt_iv_len)) {
|
|
msg("%s:encrypt: abcrypt_write_chunk() failed.\n",
|
|
my_progname);
|
|
goto err;
|
|
}
|
|
|
|
ttlchunkswritten++;
|
|
ttlbyteswritten += encryptedlen;
|
|
|
|
if (opt_verbose)
|
|
msg("%s:encrypt: %llu chunks written, %llu bytes "
|
|
"written\n.", my_progname, ttlchunkswritten,
|
|
ttlbyteswritten);
|
|
}
|
|
|
|
my_free(ivbuf);
|
|
my_free(chunkbuf);
|
|
|
|
if (encryptbuf && encryptbuflen)
|
|
my_free(encryptbuf);
|
|
|
|
xb_crypt_write_close(xbcrypt_file);
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE)
|
|
gcry_cipher_close(cipher_handle);
|
|
|
|
if (opt_verbose)
|
|
msg("\n%s:encrypt: done\n", my_progname);
|
|
|
|
return 0;
|
|
err:
|
|
if (chunkbuf)
|
|
my_free(chunkbuf);
|
|
|
|
if (encryptbuf && encryptbuflen)
|
|
my_free(encryptbuf);
|
|
|
|
if (xbcrypt_file)
|
|
xb_crypt_write_close(xbcrypt_file);
|
|
|
|
if (encrypt_algo != GCRY_CIPHER_NONE)
|
|
gcry_cipher_close(cipher_handle);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static
|
|
int
|
|
get_options(int *argc, char ***argv)
|
|
{
|
|
int ho_error;
|
|
|
|
if ((ho_error= handle_options(argc, argv, my_long_options,
|
|
get_one_option))) {
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static
|
|
my_bool
|
|
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|
char *argument __attribute__((unused)))
|
|
{
|
|
switch (optid) {
|
|
case 'd':
|
|
opt_run_mode = RUN_MODE_DECRYPT;
|
|
break;
|
|
case '?':
|
|
usage();
|
|
exit(0);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static
|
|
void
|
|
print_version(void)
|
|
{
|
|
printf("%s Ver %s for %s (%s)\n", my_progname, XBCRYPT_VERSION,
|
|
SYSTEM_TYPE, MACHINE_TYPE);
|
|
}
|
|
|
|
static
|
|
void
|
|
usage(void)
|
|
{
|
|
print_version();
|
|
puts("Copyright (C) 2011 Percona Inc.");
|
|
puts("This software comes with ABSOLUTELY NO WARRANTY. "
|
|
"This is free software,\nand you are welcome to modify and "
|
|
"redistribute it under the GPL license.\n");
|
|
|
|
puts("Encrypt or decrypt files in the XBCRYPT format.\n");
|
|
|
|
puts("Usage: ");
|
|
printf(" %s [OPTIONS...]"
|
|
" # read data from specified input, encrypting or decrypting "
|
|
" and writing the result to the specified output.\n",
|
|
my_progname);
|
|
puts("\nOptions:");
|
|
my_print_help(my_long_options);
|
|
}
|