parent
f1a50e9bd8
commit
71c5c068b5
|
@ -74,8 +74,8 @@
|
|||
|
||||
typedef gcry_sexp_t ntfs_rsa_private_key;
|
||||
|
||||
/*
|
||||
* List of crypto algorithms used by EFS (32-bit values).
|
||||
/**
|
||||
* enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit)
|
||||
*
|
||||
* To choose which one is used in Windows, create or set the REG_DWORD registry
|
||||
* key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\
|
||||
|
@ -96,7 +96,9 @@ typedef enum {
|
|||
CALG_AES_256 = const_cpu_to_le32(0x6610),
|
||||
} NTFS_CRYPTO_ALGORITHMS;
|
||||
|
||||
/* Decrypted, in-memory file encryption key. */
|
||||
/**
|
||||
* struct ntfs_fek - Decrypted, in-memory file encryption key.
|
||||
*/
|
||||
typedef struct {
|
||||
gcry_cipher_hd_t gcry_cipher_hd;
|
||||
u32 alg_id;
|
||||
|
@ -127,11 +129,6 @@ struct options {
|
|||
static const char *EXEC_NAME = "ntfsdecrypt";
|
||||
static struct options opts;
|
||||
|
||||
GEN_PRINTF(Eprintf, stderr, NULL, FALSE)
|
||||
GEN_PRINTF(Vprintf, stderr, &opts.verbose, TRUE)
|
||||
GEN_PRINTF(Qprintf, stderr, &opts.quiet, FALSE)
|
||||
static GEN_PRINTF(Printf, stderr, NULL, FALSE)
|
||||
|
||||
static ntfschar EFS[5] = {
|
||||
const_cpu_to_le16('$'), const_cpu_to_le16('E'), const_cpu_to_le16('F'),
|
||||
const_cpu_to_le16('S'), const_cpu_to_le16('\0')
|
||||
|
@ -146,12 +143,12 @@ static ntfschar EFS[5] = {
|
|||
*/
|
||||
static void version(void)
|
||||
{
|
||||
Printf("\n%s v%s (libntfs %s) - Decrypt files and print on the "
|
||||
ntfs_log_info("\n%s v%s (libntfs %s) - Decrypt files and print on the "
|
||||
"standard output.\n\n", EXEC_NAME, VERSION,
|
||||
ntfs_libntfs_version());
|
||||
Printf("Copyright (c) 2005 Yuval Fledel\n");
|
||||
Printf("Copyright (c) 2005 Anton Altaparmakov\n");
|
||||
Printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
|
||||
ntfs_log_info("Copyright (c) 2005 Yuval Fledel\n");
|
||||
ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
|
||||
ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,7 +160,7 @@ static void version(void)
|
|||
*/
|
||||
static void usage(void)
|
||||
{
|
||||
Printf("\nUsage: %s [options] -k name.pfx device [file]\n\n"
|
||||
ntfs_log_info("\nUsage: %s [options] -k name.pfx device [file]\n\n"
|
||||
" -i, --inode num Display this inode\n\n"
|
||||
" -k --keyfile name.pfx Use file name as the user's private key file.\n"
|
||||
" -f --force Use less caution\n"
|
||||
|
@ -172,7 +169,7 @@ static void usage(void)
|
|||
" -V --version Version information\n"
|
||||
" -v --verbose More output\n\n",
|
||||
EXEC_NAME);
|
||||
Printf("%s%s\n", ntfs_bugs, ntfs_home);
|
||||
ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,7 +212,8 @@ static int parse_options(int argc, char **argv)
|
|||
else if (!opts.file)
|
||||
opts.file = argv[optind - 1];
|
||||
else {
|
||||
Eprintf("You must specify exactly one file.\n");
|
||||
ntfs_log_error("You must specify exactly one "
|
||||
"file.\n");
|
||||
err++;
|
||||
}
|
||||
break;
|
||||
|
@ -230,32 +228,35 @@ static int parse_options(int argc, char **argv)
|
|||
if (!opts.keyfile)
|
||||
opts.keyfile = argv[optind - 1];
|
||||
else {
|
||||
Eprintf("You must specify exactly one "
|
||||
ntfs_log_error("You must specify exactly one "
|
||||
"key file.\n");
|
||||
err++;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (opts.inode != -1)
|
||||
Eprintf("You must specify exactly one "
|
||||
ntfs_log_error("You must specify exactly one "
|
||||
"inode.\n");
|
||||
else if (utils_parse_size(optarg, &opts.inode, FALSE))
|
||||
break;
|
||||
else
|
||||
Eprintf("Couldn't parse inode number.\n");
|
||||
ntfs_log_error("Couldn't parse inode number.\n");
|
||||
err++;
|
||||
break;
|
||||
case 'q':
|
||||
opts.quiet++;
|
||||
ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
|
||||
break;
|
||||
case 'V':
|
||||
ver++;
|
||||
break;
|
||||
case 'v':
|
||||
opts.verbose++;
|
||||
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
|
||||
break;
|
||||
default:
|
||||
Eprintf("Unknown option '%s'.\n", argv[optind - 1]);
|
||||
ntfs_log_error("Unknown option '%s'.\n",
|
||||
argv[optind - 1]);
|
||||
err++;
|
||||
break;
|
||||
}
|
||||
|
@ -263,24 +264,26 @@ static int parse_options(int argc, char **argv)
|
|||
|
||||
if (help || ver) {
|
||||
opts.quiet = 0;
|
||||
ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET);
|
||||
} else {
|
||||
if (!opts.keyfile) {
|
||||
Eprintf("You must specify a key file.\n");
|
||||
ntfs_log_error("You must specify a key file.\n");
|
||||
err++;
|
||||
} else if (opts.device == NULL) {
|
||||
Eprintf("You must specify a device.\n");
|
||||
ntfs_log_error("You must specify a device.\n");
|
||||
err++;
|
||||
} else if (opts.file == NULL && opts.inode == -1) {
|
||||
Eprintf("You must specify a file or inode with the -i "
|
||||
"option.\n");
|
||||
ntfs_log_error("You must specify a file or inode with "
|
||||
"the -i option.\n");
|
||||
err++;
|
||||
} else if (opts.file != NULL && opts.inode != -1) {
|
||||
Eprintf("You can't specify both a file and inode.\n");
|
||||
ntfs_log_error("You can't specify both a file and "
|
||||
"inode.\n");
|
||||
err++;
|
||||
}
|
||||
if (opts.quiet && opts.verbose) {
|
||||
Eprintf("You may not use --quiet and --verbose at the "
|
||||
"same time.\n");
|
||||
ntfs_log_error("You may not use --quiet and --verbose "
|
||||
"at the same time.\n");
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
@ -293,6 +296,9 @@ static int parse_options(int argc, char **argv)
|
|||
return (!err && !help && !ver);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_pkcs12_load_pfxfile
|
||||
*/
|
||||
static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
|
||||
unsigned *pfx_size)
|
||||
{
|
||||
|
@ -300,32 +306,33 @@ static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
|
|||
struct stat key_stat;
|
||||
|
||||
if (!keyfile || !pfx || !pfx_size) {
|
||||
fprintf(stderr, "You have to specify the key file, a pointer "
|
||||
ntfs_log_error("You have to specify the key file, a pointer "
|
||||
"to hold the key file contents, and a pointer "
|
||||
"to hold the size of the key file contents.");
|
||||
"to hold the size of the key file contents.\n");
|
||||
return -1;
|
||||
}
|
||||
f = open(keyfile, O_RDONLY);
|
||||
if (f == -1) {
|
||||
perror("Failed to open key file");
|
||||
ntfs_log_perror("Failed to open key file");
|
||||
return -1;
|
||||
}
|
||||
if (fstat(f, &key_stat) == -1) {
|
||||
perror("Failed to stat key file");
|
||||
ntfs_log_perror("Failed to stat key file");
|
||||
goto file_out;
|
||||
}
|
||||
if (!S_ISREG(key_stat.st_mode)) {
|
||||
fprintf(stderr, "Key file is not a regular file, cannot read "
|
||||
"it.");
|
||||
ntfs_log_error("Key file is not a regular file, cannot read "
|
||||
"it.\n");
|
||||
goto file_out;
|
||||
}
|
||||
if (!key_stat.st_size) {
|
||||
fprintf(stderr, "Key file has zero size.");
|
||||
ntfs_log_error("Key file has zero size.\n");
|
||||
goto file_out;
|
||||
}
|
||||
*pfx = malloc(key_stat.st_size + 1);
|
||||
if (!*pfx) {
|
||||
perror("Failed to allocate buffer for key file contents");
|
||||
ntfs_log_perror("Failed to allocate buffer for key file "
|
||||
"contents");
|
||||
goto file_out;
|
||||
}
|
||||
to_read = key_stat.st_size;
|
||||
|
@ -333,7 +340,7 @@ static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
|
|||
do {
|
||||
br = read(f, *pfx + total, to_read);
|
||||
if (br == -1) {
|
||||
perror("Failed to read from key file");
|
||||
ntfs_log_perror("Failed to read from key file");
|
||||
goto free_out;
|
||||
}
|
||||
if (!br)
|
||||
|
@ -353,25 +360,31 @@ file_out:
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_crypto_init
|
||||
*/
|
||||
static int ntfs_crypto_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Initialize gcrypt library. Note: Must come before GNU TLS init. */
|
||||
if (gcry_control(GCRYCTL_DISABLE_SECMEM, 0) != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to initialize the gcrypt library.\n");
|
||||
ntfs_log_error("Failed to initialize the gcrypt library.\n");
|
||||
return -1;
|
||||
}
|
||||
/* Initialize GNU TLS library. Note: Must come after libgcrypt init. */
|
||||
err = gnutls_global_init();
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to initialize GNU TLS library: %s\n",
|
||||
ntfs_log_error("Failed to initialize GNU TLS library: %s\n",
|
||||
gnutls_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_crypto_deinit
|
||||
*/
|
||||
static void ntfs_crypto_deinit(void)
|
||||
{
|
||||
gnutls_global_deinit();
|
||||
|
@ -382,6 +395,9 @@ static void ntfs_crypto_deinit(void)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_rsa_private_key_import_from_gnutls
|
||||
*/
|
||||
static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
|
||||
gnutls_x509_privkey_t priv_key)
|
||||
{
|
||||
|
@ -394,7 +410,7 @@ static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
|
|||
/* Extract the RSA parameters from the GNU TLS private key. */
|
||||
if (gnutls_x509_privkey_export_rsa_raw(priv_key, &rd[0], &rd[1],
|
||||
&rd[2], &rd[3], &rd[4], &rd[5])) {
|
||||
fprintf(stderr, "Failed to export rsa parameters. (Is the "
|
||||
ntfs_log_error("Failed to export rsa parameters. (Is the "
|
||||
"key an RSA private key?)\n");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -402,7 +418,7 @@ static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
|
|||
for (i = 0; i < 6; i++) {
|
||||
if (gcry_mpi_scan(&rm[i], GCRYMPI_FMT_USG, rd[i].data,
|
||||
rd[i].size, &tmp_size) != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to convert RSA parameter %i "
|
||||
ntfs_log_error("Failed to convert RSA parameter %i "
|
||||
"to mpi format (size %d)\n", i,
|
||||
rd[i].size);
|
||||
rsa_key = NULL;
|
||||
|
@ -422,7 +438,7 @@ static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
|
|||
"(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
|
||||
rm[0], rm[1], rm[2], rm[4], rm[3], rm[5]) !=
|
||||
GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to build RSA private key s-exp.\n");
|
||||
ntfs_log_error("Failed to build RSA private key s-exp.\n");
|
||||
rsa_key = NULL;
|
||||
}
|
||||
/* Release the no longer needed mpi values. */
|
||||
|
@ -431,6 +447,9 @@ static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
|
|||
return (ntfs_rsa_private_key)rsa_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_pkcs12_extract_rsa_key
|
||||
*/
|
||||
static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
|
||||
char *password)
|
||||
{
|
||||
|
@ -444,7 +463,7 @@ static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
|
|||
/* Create a pkcs12 structure. */
|
||||
err = gnutls_pkcs12_init(&pkcs12);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to initialize PKCS#12 structure: %s\n",
|
||||
ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n",
|
||||
gnutls_strerror(err));
|
||||
return NULL;
|
||||
}
|
||||
|
@ -453,7 +472,7 @@ static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
|
|||
dpfx.size = pfx_size;
|
||||
err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to convert the PFX file from DER to "
|
||||
ntfs_log_error("Failed to convert the PFX file from DER to "
|
||||
"native PKCS#12 format: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto out;
|
||||
|
@ -473,14 +492,14 @@ retry_verify:
|
|||
password = NULL;
|
||||
goto retry_verify;
|
||||
}
|
||||
fprintf(stderr, "Failed to verify the MAC (%s). Is the "
|
||||
ntfs_log_error("Failed to verify the MAC (%s). Is the "
|
||||
"password correct?\n", gnutls_strerror(err));
|
||||
goto out;
|
||||
}
|
||||
for (bag_index = 0; ; bag_index++) {
|
||||
err = gnutls_pkcs12_bag_init(&bag);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to initialize PKCS#12 Bag "
|
||||
ntfs_log_error("Failed to initialize PKCS#12 Bag "
|
||||
"structure: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto out;
|
||||
|
@ -489,7 +508,7 @@ retry_verify:
|
|||
if (err) {
|
||||
if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
|
||||
break;
|
||||
fprintf(stderr, "Failed to obtain Bag from PKCS#12 "
|
||||
ntfs_log_error("Failed to obtain Bag from PKCS#12 "
|
||||
"structure: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
|
@ -497,13 +516,13 @@ retry_verify:
|
|||
check_again:
|
||||
err = gnutls_pkcs12_bag_get_count(bag);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to obtain Bag count: %s\n",
|
||||
ntfs_log_error("Failed to obtain Bag count: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
}
|
||||
err = gnutls_pkcs12_bag_get_type(bag, 0);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to determine Bag type: %s\n",
|
||||
ntfs_log_error("Failed to determine Bag type: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
}
|
||||
|
@ -514,13 +533,13 @@ check_again:
|
|||
case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
|
||||
err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "Failed to obtain Bag data: "
|
||||
ntfs_log_error("Failed to obtain Bag data: "
|
||||
"%s\n", gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
}
|
||||
err = gnutls_x509_privkey_init(&pkey);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to initialized "
|
||||
ntfs_log_error("Failed to initialized "
|
||||
"private key structure: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
|
@ -529,7 +548,7 @@ check_again:
|
|||
err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey,
|
||||
GNUTLS_X509_FMT_DER, password, flags);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to convert private "
|
||||
ntfs_log_error("Failed to convert private "
|
||||
"key from DER to GNU TLS "
|
||||
"format: %s\n",
|
||||
gnutls_strerror(err));
|
||||
|
@ -549,12 +568,14 @@ check_again:
|
|||
*/
|
||||
char *buf = malloc(8192);
|
||||
size_t bufsize = 8192;
|
||||
err = gnutls_x509_privkey_export_pkcs8(pkey, GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf, &bufsize);
|
||||
err = gnutls_x509_privkey_export_pkcs8(pkey,
|
||||
GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf,
|
||||
&bufsize);
|
||||
if (err) {
|
||||
fprintf(stderr, "eek1\n");
|
||||
ntfs_log_error("eek1\n");
|
||||
exit(1);
|
||||
}
|
||||
fprintf(stderr, "%s\n", buf);
|
||||
ntfs_log_error("%s\n", buf);
|
||||
free(buf);
|
||||
#endif
|
||||
/* Convert the private key to our internal format. */
|
||||
|
@ -563,7 +584,7 @@ check_again:
|
|||
case GNUTLS_BAG_ENCRYPTED:
|
||||
err = gnutls_pkcs12_bag_decrypt(bag, password);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to decrypt Bag: %s\n",
|
||||
ntfs_log_error("Failed to decrypt Bag: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto bag_out;
|
||||
}
|
||||
|
@ -583,6 +604,9 @@ out:
|
|||
return rsa_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_rsa_private_key_release
|
||||
*/
|
||||
static void ntfs_rsa_private_key_release(ntfs_rsa_private_key rsa_key)
|
||||
{
|
||||
gcry_sexp_release((gcry_sexp_t)rsa_key);
|
||||
|
@ -608,11 +632,11 @@ static inline void ntfs_buffer_reverse(u8 *buf, unsigned buf_size)
|
|||
}
|
||||
|
||||
#ifndef HAVE_STRNLEN
|
||||
/**
|
||||
/**
|
||||
* strnlen - strnlen is a gnu extension so emulate it if not present
|
||||
*/
|
||||
*/
|
||||
static size_t strnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
{
|
||||
const char *p, *end;
|
||||
|
||||
/* Look for a '\0' character. */
|
||||
|
@ -640,7 +664,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
/* Convert the FEK to internal MPI format. */
|
||||
err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to convert file encryption key to "
|
||||
ntfs_log_error("Failed to convert file encryption key to "
|
||||
"internal MPI format: %s\n",
|
||||
gcry_strerror(err));
|
||||
return 0;
|
||||
|
@ -650,7 +674,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
"(enc-val (flags) (rsa (a %m)))", fek_mpi);
|
||||
gcry_mpi_release(fek_mpi);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to create internal S-expression of "
|
||||
ntfs_log_error("Failed to create internal S-expression of "
|
||||
"the file encryption key: %s\n",
|
||||
gcry_strerror(err));
|
||||
return 0;
|
||||
|
@ -659,7 +683,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, (gcry_sexp_t)rsa_key);
|
||||
gcry_sexp_release(fek_sexp);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to decrypt the file encryption key: "
|
||||
ntfs_log_error("Failed to decrypt the file encryption key: "
|
||||
"%s\n", gcry_strerror(err));
|
||||
return 0;
|
||||
}
|
||||
|
@ -667,7 +691,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0);
|
||||
gcry_sexp_release(fek_sexp2);
|
||||
if (!fek_sexp) {
|
||||
fprintf(stderr, "Failed to find the decrypted file encryption "
|
||||
ntfs_log_error("Failed to find the decrypted file encryption "
|
||||
"key in the internal S-expression.\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -675,7 +699,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG);
|
||||
gcry_sexp_release(fek_sexp);
|
||||
if (!fek_mpi) {
|
||||
fprintf(stderr, "Failed to convert the decrypted file "
|
||||
ntfs_log_error("Failed to convert the decrypted file "
|
||||
"encryption key S-expression to internal MPI "
|
||||
"format.\n");
|
||||
return 0;
|
||||
|
@ -684,7 +708,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi);
|
||||
gcry_mpi_release(fek_mpi);
|
||||
if (err != GPG_ERR_NO_ERROR || !size) {
|
||||
fprintf(stderr, "Failed to convert decrypted file encryption "
|
||||
ntfs_log_error("Failed to convert decrypted file encryption "
|
||||
"key from internal MPI format to binary data: "
|
||||
"%s\n", gcry_strerror(err));
|
||||
return 0;
|
||||
|
@ -695,7 +719,7 @@ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
|
|||
*/
|
||||
padding = strnlen((char *)fek, size) + 1;
|
||||
if (padding > size) {
|
||||
fprintf(stderr, "Failed to remove PKCS#1 padding from "
|
||||
ntfs_log_error("Failed to remove PKCS#1 padding from "
|
||||
"decrypted file encryption key.\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -723,7 +747,7 @@ static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key,
|
|||
|
||||
err = gcry_md_open(&hd1, GCRY_MD_MD5, 0);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to open MD5 digest.\n");
|
||||
ntfs_log_error("Failed to open MD5 digest.\n");
|
||||
return err;
|
||||
}
|
||||
/* Hash the on-disk key. */
|
||||
|
@ -731,7 +755,7 @@ static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key,
|
|||
/* Copy the current hash for efficiency. */
|
||||
err = gcry_md_copy(&hd2, hd1);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to copy MD5 digest object.\n");
|
||||
ntfs_log_error("Failed to copy MD5 digest object.\n");
|
||||
goto out;
|
||||
}
|
||||
/* Hash with the first salt and store the result. */
|
||||
|
@ -755,7 +779,7 @@ out:
|
|||
* @context: pointer to a variable of type ntfs_desx_ctx
|
||||
* @key: the 128 bit DES-X-MS128 key, concated with the DES handle
|
||||
* @keylen: must always be 16
|
||||
*
|
||||
*
|
||||
* This is the libgcrypt set_key implementation for DES-X-MS128.
|
||||
*/
|
||||
static gcry_err_code_t ntfs_desx_setkey(void *context, const u8 *key,
|
||||
|
@ -766,27 +790,27 @@ static gcry_err_code_t ntfs_desx_setkey(void *context, const u8 *key,
|
|||
u8 des_key[8];
|
||||
|
||||
if (keylen != 16) {
|
||||
fprintf(stderr, "Key length for desx must be 16.\n");
|
||||
ntfs_log_error("Key length for desx must be 16.\n");
|
||||
return GPG_ERR_INV_KEYLEN;
|
||||
}
|
||||
err = gcry_cipher_open(&ctx->gcry_cipher_hd, GCRY_CIPHER_DES,
|
||||
GCRY_CIPHER_MODE_ECB, 0);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to open des cipher (error 0x%x).\n",
|
||||
ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
|
||||
err);
|
||||
return err;
|
||||
}
|
||||
err = ntfs_desx_key_expand(key, (u32*)des_key, &ctx->out_whitening,
|
||||
&ctx->in_whitening);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to expand desx key (error 0x%x).\n",
|
||||
ntfs_log_error("Failed to expand desx key (error 0x%x).\n",
|
||||
err);
|
||||
gcry_cipher_close(ctx->gcry_cipher_hd);
|
||||
return err;
|
||||
}
|
||||
err = gcry_cipher_setkey(ctx->gcry_cipher_hd, des_key, sizeof(des_key));
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to set des key (error 0x%x).\n", err);
|
||||
ntfs_log_error("Failed to set des key (error 0x%x).\n", err);
|
||||
gcry_cipher_close(ctx->gcry_cipher_hd);
|
||||
return err;
|
||||
}
|
||||
|
@ -799,6 +823,9 @@ static gcry_err_code_t ntfs_desx_setkey(void *context, const u8 *key,
|
|||
return GPG_ERR_NO_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_desx_decrypt
|
||||
*/
|
||||
static void ntfs_desx_decrypt(void *context, u8 *outbuf, const u8 *inbuf)
|
||||
{
|
||||
ntfs_desx_ctx *ctx = context;
|
||||
|
@ -806,12 +833,12 @@ static void ntfs_desx_decrypt(void *context, u8 *outbuf, const u8 *inbuf)
|
|||
|
||||
err = gcry_cipher_reset(ctx->gcry_cipher_hd);
|
||||
if (err != GPG_ERR_NO_ERROR)
|
||||
fprintf(stderr, "Failed to reset des cipher (error 0x%x).\n",
|
||||
ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
|
||||
err);
|
||||
*(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening;
|
||||
err = gcry_cipher_encrypt(ctx->gcry_cipher_hd, outbuf, 8, NULL, 0);
|
||||
if (err != GPG_ERR_NO_ERROR)
|
||||
fprintf(stderr, "Des decryption failed (error 0x%x).\n", err);
|
||||
ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
|
||||
*(u64*)outbuf ^= ctx->in_whitening;
|
||||
}
|
||||
|
||||
|
@ -829,6 +856,9 @@ static gcry_cipher_spec_t ntfs_desx_cipher = {
|
|||
#ifdef DO_CRYPTO_TESTS
|
||||
|
||||
/* Do not remove this test code from this file! AIA */
|
||||
/**
|
||||
* ntfs_desx_key_expand_test
|
||||
*/
|
||||
static BOOL ntfs_desx_key_expand_test(void)
|
||||
{
|
||||
const u8 known_desx_on_disk_key[16] = {
|
||||
|
@ -862,11 +892,14 @@ static BOOL ntfs_desx_key_expand_test(void)
|
|||
*(u64*)known_out_whitening &&
|
||||
test_in_whitening ==
|
||||
*(u64*)known_in_whitening;
|
||||
fprintf(stderr, "Testing whether ntfs_desx_key_expand() works: %s\n",
|
||||
ntfs_log_error("Testing whether ntfs_desx_key_expand() works: %s\n",
|
||||
res ? "SUCCESS" : "FAILED");
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_des_test
|
||||
*/
|
||||
static BOOL ntfs_des_test(void)
|
||||
{
|
||||
const u8 known_des_key[8] = {
|
||||
|
@ -886,14 +919,14 @@ static BOOL ntfs_des_test(void)
|
|||
err = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_DES,
|
||||
GCRY_CIPHER_MODE_ECB, 0);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to open des cipher (error 0x%x).\n",
|
||||
ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
|
||||
err);
|
||||
return FALSE;
|
||||
}
|
||||
err = gcry_cipher_setkey(gcry_cipher_hd, known_des_key,
|
||||
sizeof(known_des_key));
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to set des key (error 0x%x.\n", err);
|
||||
ntfs_log_error("Failed to set des key (error 0x%x.\n", err);
|
||||
gcry_cipher_close(gcry_cipher_hd);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -905,24 +938,30 @@ static BOOL ntfs_des_test(void)
|
|||
sizeof(known_des_encrypted_data));
|
||||
gcry_cipher_close(gcry_cipher_hd);
|
||||
if (err) {
|
||||
fprintf(stderr, "Failed to des decrypt test data (error "
|
||||
ntfs_log_error("Failed to des decrypt test data (error "
|
||||
"0x%x).\n", err);
|
||||
return FALSE;
|
||||
}
|
||||
res = !memcmp(test_decrypted_data, known_decrypted_data,
|
||||
sizeof(known_decrypted_data));
|
||||
fprintf(stderr, "Testing whether des decryption works: %s\n",
|
||||
ntfs_log_error("Testing whether des decryption works: %s\n",
|
||||
res ? "SUCCESS" : "FAILED");
|
||||
return res;
|
||||
}
|
||||
|
||||
#else /* !defined(DO_CRYPTO_TESTS) */
|
||||
|
||||
/**
|
||||
* ntfs_desx_key_expand_test
|
||||
*/
|
||||
static inline BOOL ntfs_desx_key_expand_test(void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_des_test
|
||||
*/
|
||||
static inline BOOL ntfs_des_test(void)
|
||||
{
|
||||
return TRUE;
|
||||
|
@ -930,6 +969,9 @@ static inline BOOL ntfs_des_test(void)
|
|||
|
||||
#endif /* !defined(DO_CRYPTO_TESTS) */
|
||||
|
||||
/**
|
||||
* ntfs_fek_import_from_raw
|
||||
*/
|
||||
static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
||||
unsigned fek_size __attribute__((unused)))
|
||||
{
|
||||
|
@ -939,7 +981,7 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
|
||||
// TODO: Sanity checking of sizes and offsets.
|
||||
key_size = le32_to_cpup(fek_buf);
|
||||
//fprintf(stderr, "key_size 0x%x\n", key_size);
|
||||
//ntfs_log_debug("key_size 0x%x\n", key_size);
|
||||
fek = malloc(((((sizeof(*fek) + 7) & ~7) + key_size + 7) & ~7) +
|
||||
sizeof(gcry_cipher_hd_t));
|
||||
if (!fek) {
|
||||
|
@ -947,7 +989,7 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
return NULL;
|
||||
}
|
||||
fek->alg_id = *(u32*)(fek_buf + 8);
|
||||
//fprintf(stderr, "alg_id 0x%x\n", le32_to_cpu(fek->alg_id));
|
||||
//ntfs_log_debug("alg_id 0x%x\n", le32_to_cpu(fek->alg_id));
|
||||
fek->key_data = (u8*)fek + ((sizeof(*fek) + 7) & ~7);
|
||||
memcpy(fek->key_data, fek_buf + 16, key_size);
|
||||
fek->des_gcry_cipher_hd_ptr = NULL;
|
||||
|
@ -964,7 +1006,7 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
&ntfs_desx_algorithm_id,
|
||||
&ntfs_desx_module);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to register desx "
|
||||
ntfs_log_error("Failed to register desx "
|
||||
"cipher: %s\n",
|
||||
gcry_strerror(err));
|
||||
err = EINVAL;
|
||||
|
@ -986,11 +1028,11 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
wanted_key_size = 8;
|
||||
gcry_algo = GCRY_CIPHER_DES;
|
||||
if (fek->alg_id == CALG_DES)
|
||||
fprintf(stderr, "DES is not supported at present");
|
||||
ntfs_log_error("DES is not supported at present\n");
|
||||
else
|
||||
fprintf(stderr, "Unknown crypto algorithm 0x%x",
|
||||
ntfs_log_error("Unknown crypto algorithm 0x%x\n",
|
||||
le32_to_cpu(fek->alg_id));
|
||||
fprintf(stderr, ". Please email linux-ntfs-dev@lists."
|
||||
ntfs_log_error(". Please email linux-ntfs-dev@lists."
|
||||
"sourceforge.net and say that you saw this "
|
||||
"message. We will then try to implement "
|
||||
"support for this algorithm.\n");
|
||||
|
@ -998,7 +1040,7 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
goto out;
|
||||
}
|
||||
if (key_size != wanted_key_size) {
|
||||
fprintf(stderr, "%s key of %u bytes but needed size is %u "
|
||||
ntfs_log_error("%s key of %u bytes but needed size is %u "
|
||||
"bytes, assuming corrupt key. Aborting.\n",
|
||||
gcry_cipher_algo_name(gcry_algo),
|
||||
(unsigned)key_size, (unsigned)wanted_key_size);
|
||||
|
@ -1008,14 +1050,14 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
|
|||
err = gcry_cipher_open(&fek->gcry_cipher_hd, gcry_algo,
|
||||
GCRY_CIPHER_MODE_CBC, 0);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "gcry_cipher_open() failed: %s\n",
|
||||
ntfs_log_error("gcry_cipher_open() failed: %s\n",
|
||||
gcry_strerror(err));
|
||||
err = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
err = gcry_cipher_setkey(fek->gcry_cipher_hd, fek->key_data, key_size);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "gcry_cipher_setkey() failed: %s\n",
|
||||
ntfs_log_error("gcry_cipher_setkey() failed: %s\n",
|
||||
gcry_strerror(err));
|
||||
gcry_cipher_close(fek->gcry_cipher_hd);
|
||||
err = EINVAL;
|
||||
|
@ -1028,6 +1070,9 @@ out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_fek_release
|
||||
*/
|
||||
static void ntfs_fek_release(ntfs_fek *fek)
|
||||
{
|
||||
if (fek->des_gcry_cipher_hd_ptr)
|
||||
|
@ -1036,6 +1081,9 @@ static void ntfs_fek_release(ntfs_fek *fek)
|
|||
free(fek);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_df_array_fek_get
|
||||
*/
|
||||
static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
|
||||
ntfs_rsa_private_key rsa_key)
|
||||
{
|
||||
|
@ -1064,10 +1112,10 @@ static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
|
|||
fek = ntfs_fek_import_from_raw(fek_buf, fek_size);
|
||||
if (fek)
|
||||
return fek;
|
||||
fprintf(stderr, "Failed to convert the decrypted file "
|
||||
ntfs_log_error("Failed to convert the decrypted file "
|
||||
"encryption key to internal format.\n");
|
||||
} else
|
||||
fprintf(stderr, "Failed to decrypt the file "
|
||||
ntfs_log_error("Failed to decrypt the file "
|
||||
"encryption key.\n");
|
||||
df_header = (EFS_DF_HEADER*)((u8*)df_header +
|
||||
le32_to_cpu(df_header->df_length));
|
||||
|
@ -1089,17 +1137,17 @@ static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
|
|||
/* Obtain the $EFS contents. */
|
||||
na = ntfs_attr_open(inode, AT_LOGGED_UTILITY_STREAM, EFS, 4);
|
||||
if (!na) {
|
||||
perror("Failed to open $EFS attribute");
|
||||
ntfs_log_perror("Failed to open $EFS attribute");
|
||||
return NULL;
|
||||
}
|
||||
efs = malloc(na->data_size);
|
||||
if (!efs) {
|
||||
perror("Failed to allocate internal buffer");
|
||||
ntfs_log_perror("Failed to allocate internal buffer");
|
||||
ntfs_attr_close(na);
|
||||
return NULL;
|
||||
}
|
||||
if (ntfs_attr_pread(na, 0, na->data_size, efs) != na->data_size) {
|
||||
perror("Failed to read $EFS attribute");
|
||||
ntfs_log_perror("Failed to read $EFS attribute");
|
||||
free(efs);
|
||||
ntfs_attr_close(na);
|
||||
return NULL;
|
||||
|
@ -1120,13 +1168,16 @@ static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
|
|||
return fek;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_fek_decrypt_sector
|
||||
*/
|
||||
static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
|
||||
{
|
||||
gcry_error_t err;
|
||||
|
||||
err = gcry_cipher_reset(fek->gcry_cipher_hd);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Failed to reset cipher: %s\n",
|
||||
ntfs_log_error("Failed to reset cipher: %s\n",
|
||||
gcry_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
|
@ -1138,7 +1189,7 @@ static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
|
|||
*/
|
||||
err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
|
||||
if (err != GPG_ERR_NO_ERROR) {
|
||||
fprintf(stderr, "Decryption failed: %s\n", gcry_strerror(err));
|
||||
ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err));
|
||||
return -1;
|
||||
}
|
||||
/* Apply the IV. */
|
||||
|
@ -1153,9 +1204,9 @@ static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
|
|||
}
|
||||
|
||||
/**
|
||||
* cat
|
||||
* ntfs_cat_decrypt
|
||||
* TODO:
|
||||
*/
|
||||
// TODO:
|
||||
static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek)
|
||||
{
|
||||
int bufsize = 512;
|
||||
|
@ -1170,7 +1221,7 @@ static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek)
|
|||
return 1;
|
||||
attr = ntfs_attr_open(inode, AT_DATA, NULL, 0);
|
||||
if (!attr) {
|
||||
Eprintf("Cannot cat a directory.\n");
|
||||
ntfs_log_error("Cannot cat a directory.\n");
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1188,23 +1239,24 @@ static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek)
|
|||
while (total > 0) {
|
||||
bytes_read = ntfs_attr_pread(attr, offset, 512, buffer);
|
||||
if (bytes_read == -1) {
|
||||
perror("ERROR: Couldn't read file");
|
||||
ntfs_log_perror("ERROR: Couldn't read file");
|
||||
break;
|
||||
}
|
||||
if (!bytes_read)
|
||||
break;
|
||||
if ((i = ntfs_fek_decrypt_sector(fek, buffer, offset)) <
|
||||
bytes_read) {
|
||||
perror("ERROR: Couldn't decrypt all data!");
|
||||
Eprintf("%u/%lld/%lld/%lld\n", i, (long long)bytes_read,
|
||||
(long long)offset, (long long)total);
|
||||
ntfs_log_perror("ERROR: Couldn't decrypt all data!");
|
||||
ntfs_log_error("%u/%lld/%lld/%lld\n", i,
|
||||
(long long)bytes_read, (long long)offset,
|
||||
(long long)total);
|
||||
break;
|
||||
}
|
||||
if (bytes_read > total)
|
||||
bytes_read = total;
|
||||
written = fwrite(buffer, 1, bytes_read, stdout);
|
||||
if (written != bytes_read) {
|
||||
perror("ERROR: Couldn't output all data!");
|
||||
ntfs_log_perror("ERROR: Couldn't output all data!");
|
||||
break;
|
||||
}
|
||||
offset += bytes_read;
|
||||
|
@ -1237,18 +1289,20 @@ int main(int argc, char *argv[])
|
|||
unsigned pfx_size;
|
||||
int res;
|
||||
|
||||
ntfs_log_set_handler(ntfs_log_handler_stderr);
|
||||
|
||||
if (!parse_options(argc, argv))
|
||||
return 1;
|
||||
utils_set_locale();
|
||||
|
||||
/* Initialize crypto in ntfs. */
|
||||
if (ntfs_crypto_init()) {
|
||||
fprintf(stderr, "Failed to initialize crypto. Aborting.\n");
|
||||
ntfs_log_error("Failed to initialize crypto. Aborting.\n");
|
||||
return 1;
|
||||
}
|
||||
/* Load the PKCS#12 (.pfx) file containing the user's private key. */
|
||||
if (ntfs_pkcs12_load_pfxfile(opts.keyfile, &pfx_buf, &pfx_size)) {
|
||||
fprintf(stderr, "Failed to load key file. Aborting.\n");
|
||||
ntfs_log_error("Failed to load key file. Aborting.\n");
|
||||
ntfs_crypto_deinit();
|
||||
return 1;
|
||||
}
|
||||
|
@ -1256,7 +1310,7 @@ int main(int argc, char *argv[])
|
|||
password = getpass("Enter the password with which the private key was "
|
||||
"encrypted: ");
|
||||
if (!password) {
|
||||
perror("Failed to obtain user password");
|
||||
ntfs_log_perror("Failed to obtain user password");
|
||||
free(pfx_buf);
|
||||
ntfs_crypto_deinit();
|
||||
return 1;
|
||||
|
@ -1268,7 +1322,7 @@ int main(int argc, char *argv[])
|
|||
/* No longer need the pfx file contents. */
|
||||
free(pfx_buf);
|
||||
if (!rsa_key) {
|
||||
fprintf(stderr, "Failed to extract the private RSA key. Did "
|
||||
ntfs_log_error("Failed to extract the private RSA key. Did "
|
||||
"you perhaps mistype the password?\n");
|
||||
ntfs_crypto_deinit();
|
||||
return 1;
|
||||
|
@ -1276,7 +1330,7 @@ int main(int argc, char *argv[])
|
|||
/* Mount the ntfs volume. */
|
||||
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
|
||||
if (!vol) {
|
||||
fprintf(stderr, "Failed to mount ntfs volume. Aborting.\n");
|
||||
ntfs_log_error("Failed to mount ntfs volume. Aborting.\n");
|
||||
ntfs_rsa_private_key_release(rsa_key);
|
||||
ntfs_crypto_deinit();
|
||||
return 1;
|
||||
|
@ -1287,7 +1341,7 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
|
||||
if (!inode) {
|
||||
fprintf(stderr, "Failed to open encrypted file. Aborting.\n");
|
||||
ntfs_log_error("Failed to open encrypted file. Aborting.\n");
|
||||
ntfs_umount(vol, FALSE);
|
||||
ntfs_rsa_private_key_release(rsa_key);
|
||||
ntfs_crypto_deinit();
|
||||
|
@ -1300,7 +1354,7 @@ int main(int argc, char *argv[])
|
|||
res = ntfs_cat_decrypt(inode, fek);
|
||||
ntfs_fek_release(fek);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to obtain file encryption key. "
|
||||
ntfs_log_error("Failed to obtain file encryption key. "
|
||||
"Aborting.\n");
|
||||
res = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue