2 * ntfsdecrypt - Decrypt ntfs encrypted files. Part of the Linux-NTFS project.
4 * Copyright (c) 2005 Yuval Fledel
5 * Copyright (c) 2005-2007 Anton Altaparmakov
6 * Copyright (c) 2007 Yura Pakhuchiy
8 * This utility will decrypt files and print the decrypted data on the standard
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (in the main directory of the Linux-NTFS
23 * distribution in the file COPYING); if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
32 #ifdef HAVE_SYS_STAT_H
57 #include <gnutls/pkcs12.h>
66 /* #include "version.h" */
68 typedef gcry_sexp_t ntfs_rsa_private_key
;
70 #define NTFS_SHA1_THUMBPRINT_SIZE 0x14
72 #define NTFS_CRED_TYPE_CERT_THUMBPRINT const_cpu_to_le32(3)
74 #define NTFS_EFS_CERT_PURPOSE_OID_DDF "1.3.6.1.4.1.311.10.3.4"
75 #define NTFS_EFS_CERT_PURPOSE_OID_DRF "1.3.6.1.4.1.311.10.3.4.1"
84 * enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit)
86 * To choose which one is used in Windows, create or set the REG_DWORD registry
87 * key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\
88 * AlgorithmID to the value of your chosen crypto algorithm, e.g. to use DesX,
89 * set AlgorithmID to 0x6604.
91 * Note that the Windows versions I have tried so far (all are high crypto
92 * enabled) ignore the AlgorithmID value if it is not one of CALG_3DES,
93 * CALG_DESX, or CALG_AES_256, i.e. you cannot select CALG_DES at all using
94 * this registry key. It would be interesting to check out encryption on one
95 * of the "crippled" crypto Windows versions...
98 CALG_DES
= const_cpu_to_le32(0x6601),
99 /* If not one of the below three, fall back to standard Des. */
100 CALG_3DES
= const_cpu_to_le32(0x6603),
101 CALG_DESX
= const_cpu_to_le32(0x6604),
102 CALG_AES_256
= const_cpu_to_le32(0x6610),
103 } NTFS_CRYPTO_ALGORITHMS
;
106 * struct ntfs_fek - Decrypted, in-memory file encryption key.
109 gcry_cipher_hd_t gcry_cipher_hd
;
112 gcry_cipher_hd_t
*des_gcry_cipher_hd_ptr
;
115 /* DESX-MS128 implementation for libgcrypt. */
116 static gcry_module_t ntfs_desx_module
;
117 static int ntfs_desx_algorithm_id
= -1;
120 u64 in_whitening
, out_whitening
;
121 gcry_cipher_hd_t gcry_cipher_hd
;
125 char *keyfile
; /* .pfx file containing the user's private key. */
126 char *device
; /* Device/File to work with */
127 char *file
; /* File to display */
128 s64 inode
; /* Inode to work with */
129 ATTR_TYPES attr
; /* Attribute type to display */
130 int force
; /* Override common sense */
131 int quiet
; /* Less output */
132 int verbose
; /* Extra output */
135 static const char *EXEC_NAME
= "ntfsdecrypt";
136 static struct options opts
;
138 static ntfschar EFS
[5] = {
139 const_cpu_to_le16('$'), const_cpu_to_le16('E'), const_cpu_to_le16('F'),
140 const_cpu_to_le16('S'), const_cpu_to_le16('\0')
144 * version - Print version information about the program
146 * Print a copyright statement and a brief description of the program.
150 static void version(void)
152 ntfs_log_info("\n%s v%s (libntfs-3g) - Decrypt files and print on the "
153 "standard output.\n\n", EXEC_NAME
, VERSION
);
154 ntfs_log_info("Copyright (c) 2005 Yuval Fledel\n");
155 ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
156 ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl
, ntfs_bugs
, ntfs_home
);
160 * usage - Print a list of the parameters to the program
162 * Print a list of the parameters and options for the program.
166 static void usage(void)
168 ntfs_log_info("\nUsage: %s [options] -k name.pfx device [file]\n\n"
169 " -i, --inode num Display this inode\n\n"
170 " -k --keyfile name.pfx Use file name as the user's private key file.\n"
171 " -f --force Use less caution\n"
172 " -h --help Print this help\n"
173 " -q --quiet Less output\n"
174 " -V --version Version information\n"
175 " -v --verbose More output\n\n",
177 ntfs_log_info("%s%s\n", ntfs_bugs
, ntfs_home
);
181 * parse_options - Read and validate the programs command line
183 * Read the command line, verify the syntax and parse the options.
184 * This function is very long, but quite simple.
187 * 0 Error, one or more problems
189 static int parse_options(int argc
, char **argv
)
191 static const char *sopt
= "-fh?i:k:qVv";
192 static const struct option lopt
[] = {
193 {"force", no_argument
, NULL
, 'f'},
194 {"help", no_argument
, NULL
, 'h'},
195 {"inode", required_argument
, NULL
, 'i'},
196 {"keyfile", required_argument
, NULL
, 'k'},
197 {"quiet", no_argument
, NULL
, 'q'},
198 {"version", no_argument
, NULL
, 'V'},
199 {"verbose", no_argument
, NULL
, 'v'},
208 opterr
= 0; /* We'll handle the errors, thank you. */
212 while ((c
= getopt_long(argc
, argv
, sopt
, lopt
, NULL
)) != -1) {
214 case 1: /* A non-option argument */
216 opts
.device
= argv
[optind
- 1];
218 opts
.file
= argv
[optind
- 1];
220 ntfs_log_error("You must specify exactly one "
234 opts
.keyfile
= argv
[optind
- 1];
236 ntfs_log_error("You must specify exactly one "
242 if (opts
.inode
!= -1)
243 ntfs_log_error("You must specify exactly one "
245 else if (utils_parse_size(optarg
, &opts
.inode
, FALSE
))
248 ntfs_log_error("Couldn't parse inode number.\n");
253 ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET
);
260 ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE
);
263 ntfs_log_error("Unknown option '%s'.\n",
272 ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET
);
275 ntfs_log_error("You must specify a key file.\n");
277 } else if (opts
.device
== NULL
) {
278 ntfs_log_error("You must specify a device.\n");
280 } else if (opts
.file
== NULL
&& opts
.inode
== -1) {
281 ntfs_log_error("You must specify a file or inode with "
284 } else if (opts
.file
!= NULL
&& opts
.inode
!= -1) {
285 ntfs_log_error("You can't specify both a file and "
289 if (opts
.quiet
&& opts
.verbose
) {
290 ntfs_log_error("You may not use --quiet and --verbose "
291 "at the same time.\n");
301 return (!err
&& !help
&& !ver
);
305 * ntfs_pkcs12_load_pfxfile
307 static int ntfs_pkcs12_load_pfxfile(const char *keyfile
, u8
**pfx
,
310 int f
, to_read
, total
, attempts
, br
;
311 struct stat key_stat
;
313 if (!keyfile
|| !pfx
|| !pfx_size
) {
314 ntfs_log_error("You have to specify the key file, a pointer "
315 "to hold the key file contents, and a pointer "
316 "to hold the size of the key file contents.\n");
319 f
= open(keyfile
, O_RDONLY
);
321 ntfs_log_perror("Failed to open key file");
324 if (fstat(f
, &key_stat
) == -1) {
325 ntfs_log_perror("Failed to stat key file");
328 if (!S_ISREG(key_stat
.st_mode
)) {
329 ntfs_log_error("Key file is not a regular file, cannot read "
333 if (!key_stat
.st_size
) {
334 ntfs_log_error("Key file has zero size.\n");
337 *pfx
= malloc(key_stat
.st_size
+ 1);
339 ntfs_log_perror("Failed to allocate buffer for key file "
343 to_read
= key_stat
.st_size
;
344 total
= attempts
= 0;
346 br
= read(f
, *pfx
+ total
, to_read
);
348 ntfs_log_perror("Failed to read from key file");
355 } while (to_read
> 0 && attempts
< 3);
357 /* Make sure it is zero terminated. */
358 (*pfx
)[key_stat
.st_size
] = 0;
359 *pfx_size
= key_stat
.st_size
;
371 static int ntfs_crypto_init(void)
375 /* Initialize gcrypt library. Note: Must come before GNU TLS init. */
376 if (gcry_control(GCRYCTL_DISABLE_SECMEM
, 0) != GPG_ERR_NO_ERROR
) {
377 ntfs_log_error("Failed to initialize the gcrypt library.\n");
380 /* Initialize GNU TLS library. Note: Must come after libgcrypt init. */
381 err
= gnutls_global_init();
383 ntfs_log_error("Failed to initialize GNU TLS library: %s\n",
384 gnutls_strerror(err
));
393 static void ntfs_crypto_deinit(void)
395 gnutls_global_deinit();
396 if (ntfs_desx_module
) {
397 gcry_cipher_unregister(ntfs_desx_module
);
398 ntfs_desx_module
= NULL
;
399 ntfs_desx_algorithm_id
= -1;
404 * ntfs_rsa_private_key_import_from_gnutls
406 static ntfs_rsa_private_key
ntfs_rsa_private_key_import_from_gnutls(
407 gnutls_x509_privkey_t priv_key
)
411 gnutls_datum_t rd
[6];
415 /* Extract the RSA parameters from the GNU TLS private key. */
416 if (gnutls_x509_privkey_export_rsa_raw(priv_key
, &rd
[0], &rd
[1],
417 &rd
[2], &rd
[3], &rd
[4], &rd
[5])) {
418 ntfs_log_error("Failed to export rsa parameters. (Is the "
419 "key an RSA private key?)\n");
422 /* Convert each RSA parameter to mpi format. */
423 for (i
= 0; i
< 6; i
++) {
424 if (gcry_mpi_scan(&rm
[i
], GCRYMPI_FMT_USG
, rd
[i
].data
,
425 rd
[i
].size
, &tmp_size
) != GPG_ERR_NO_ERROR
) {
426 ntfs_log_error("Failed to convert RSA parameter %i "
427 "to mpi format (size %d)\n", i
,
433 /* Release the no longer needed datum values. */
434 for (j
= 0; j
< 6; j
++) {
435 if (rd
[j
].data
&& rd
[j
].size
)
436 gnutls_free(rd
[j
].data
);
439 * Build the gcrypt private key, note libgcrypt uses p and q inversed
440 * to what gnutls uses.
442 if (i
== 6 && gcry_sexp_build(&rsa_key
, NULL
,
443 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
444 rm
[0], rm
[1], rm
[2], rm
[4], rm
[3], rm
[5]) !=
446 ntfs_log_error("Failed to build RSA private key s-exp.\n");
449 /* Release the no longer needed mpi values. */
450 for (j
= 0; j
< i
; j
++)
451 gcry_mpi_release(rm
[j
]);
452 return (ntfs_rsa_private_key
)rsa_key
;
456 * ntfs_rsa_private_key_release
458 static void ntfs_rsa_private_key_release(ntfs_rsa_private_key rsa_key
)
460 gcry_sexp_release((gcry_sexp_t
)rsa_key
);
464 * ntfs_pkcs12_extract_rsa_key
466 static ntfs_rsa_private_key
ntfs_pkcs12_extract_rsa_key(u8
*pfx
, int pfx_size
,
467 char *password
, char *thumbprint
, int thumbprint_size
,
468 NTFS_DF_TYPES
*df_type
)
470 int err
, bag_index
, flags
;
471 gnutls_datum_t dpfx
, dkey
;
472 gnutls_pkcs12_t pkcs12
= NULL
;
473 gnutls_pkcs12_bag_t bag
= NULL
;
474 gnutls_x509_privkey_t pkey
= NULL
;
475 gnutls_x509_crt_t crt
= NULL
;
476 ntfs_rsa_private_key rsa_key
= NULL
;
477 char purpose_oid
[100];
478 size_t purpose_oid_size
= sizeof(purpose_oid
);
479 size_t tp_size
= thumbprint_size
;
480 BOOL have_thumbprint
= FALSE
;
482 *df_type
= DF_TYPE_UNKNOWN
;
483 /* Create a pkcs12 structure. */
484 err
= gnutls_pkcs12_init(&pkcs12
);
486 ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n",
487 gnutls_strerror(err
));
490 /* Convert the PFX file (DER format) to native pkcs12 format. */
492 dpfx
.size
= pfx_size
;
493 err
= gnutls_pkcs12_import(pkcs12
, &dpfx
, GNUTLS_X509_FMT_DER
, 0);
495 ntfs_log_error("Failed to convert the PFX file from DER to "
496 "native PKCS#12 format: %s\n",
497 gnutls_strerror(err
));
501 * Verify that the password is correct and that the key file has not
502 * been tampered with. Note if the password has zero length and the
503 * verification fails, retry with password set to NULL. This is needed
504 * to get passwordless .pfx files generated with Windows XP SP1 (and
505 * probably earlier versions of Windows) to work.
508 err
= gnutls_pkcs12_verify_mac(pkcs12
, password
);
510 if (err
== GNUTLS_E_MAC_VERIFY_FAILED
&&
511 password
&& !strlen(password
)) {
515 ntfs_log_error("Failed to verify the MAC: %s Is the "
516 "password correct?\n", gnutls_strerror(err
));
519 for (bag_index
= 0; ; bag_index
++) {
520 err
= gnutls_pkcs12_bag_init(&bag
);
522 ntfs_log_error("Failed to initialize PKCS#12 Bag "
524 gnutls_strerror(err
));
527 err
= gnutls_pkcs12_get_bag(pkcs12
, bag_index
, bag
);
529 if (err
== GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
) {
533 ntfs_log_error("Failed to obtain Bag from PKCS#12 "
535 gnutls_strerror(err
));
539 err
= gnutls_pkcs12_bag_get_count(bag
);
541 ntfs_log_error("Failed to obtain Bag count: %s\n",
542 gnutls_strerror(err
));
545 err
= gnutls_pkcs12_bag_get_type(bag
, 0);
547 ntfs_log_error("Failed to determine Bag type: %s\n",
548 gnutls_strerror(err
));
553 case GNUTLS_BAG_PKCS8_KEY
:
554 flags
= GNUTLS_PKCS_PLAIN
;
555 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY
:
556 err
= gnutls_pkcs12_bag_get_data(bag
, 0, &dkey
);
558 ntfs_log_error("Failed to obtain Bag data: "
559 "%s\n", gnutls_strerror(err
));
562 err
= gnutls_x509_privkey_init(&pkey
);
564 ntfs_log_error("Failed to initialized "
565 "private key structure: %s\n",
566 gnutls_strerror(err
));
569 /* Decrypt the private key into GNU TLS format. */
570 err
= gnutls_x509_privkey_import_pkcs8(pkey
, &dkey
,
571 GNUTLS_X509_FMT_DER
, password
, flags
);
573 ntfs_log_error("Failed to convert private "
574 "key from DER to GNU TLS "
576 gnutls_strerror(err
));
581 * Export the key again, but unencrypted, and output it
582 * to stderr. Note the output has an RSA header so to
583 * compare to openssl pkcs12 -nodes -in myfile.pfx
584 * output need to ignore the part of the key between
585 * the first "MII..." up to the second "MII...". The
586 * actual RSA private key begins at the second "MII..."
587 * and in my testing at least was identical to openssl
588 * output and was also identical both on big and little
589 * endian so gnutls should be endianness safe.
591 char *buf
= malloc(8192);
592 size_t bufsize
= 8192;
593 err
= gnutls_x509_privkey_export_pkcs8(pkey
,
594 GNUTLS_X509_FMT_PEM
, "", GNUTLS_PKCS_PLAIN
, buf
,
597 ntfs_log_error("eek1\n");
600 ntfs_log_error("%s\n", buf
);
603 /* Convert the private key to our internal format. */
604 rsa_key
= ntfs_rsa_private_key_import_from_gnutls(pkey
);
608 case GNUTLS_BAG_ENCRYPTED
:
609 err
= gnutls_pkcs12_bag_decrypt(bag
, password
);
611 ntfs_log_error("Failed to decrypt Bag: %s\n",
612 gnutls_strerror(err
));
616 case GNUTLS_BAG_CERTIFICATE
:
617 err
= gnutls_pkcs12_bag_get_data(bag
, 0, &dkey
);
619 ntfs_log_error("Failed to obtain Bag data: "
620 "%s\n", gnutls_strerror(err
));
623 err
= gnutls_x509_crt_init(&crt
);
625 ntfs_log_error("Failed to initialize "
626 "certificate structure: %s\n",
627 gnutls_strerror(err
));
630 err
= gnutls_x509_crt_import(crt
, &dkey
,
631 GNUTLS_X509_FMT_DER
);
633 ntfs_log_error("Failed to convert certificate "
634 "from DER to GNU TLS format: "
635 "%s\n", gnutls_strerror(err
));
638 err
= gnutls_x509_crt_get_key_purpose_oid(crt
, 0,
639 purpose_oid
, &purpose_oid_size
, NULL
);
641 ntfs_log_error("Failed to get key purpose "
643 gnutls_strerror(err
));
646 purpose_oid
[purpose_oid_size
- 1] = '\0';
647 if (!strcmp(purpose_oid
,
648 NTFS_EFS_CERT_PURPOSE_OID_DRF
))
649 *df_type
= DF_TYPE_DRF
;
650 else if (!strcmp(purpose_oid
,
651 NTFS_EFS_CERT_PURPOSE_OID_DDF
))
652 *df_type
= DF_TYPE_DDF
;
654 ntfs_log_error("Certificate has unknown "
660 /* Return the thumbprint to the caller. */
661 err
= gnutls_x509_crt_get_fingerprint(crt
,
662 GNUTLS_DIG_SHA1
, thumbprint
, &tp_size
);
664 ntfs_log_error("Failed to get thumbprint: "
665 "%s\n", gnutls_strerror(err
));
668 if (tp_size
!= NTFS_SHA1_THUMBPRINT_SIZE
) {
669 ntfs_log_error("Invalid thumbprint size %zd. "
670 "Should be %d.\n", tp_size
,
675 have_thumbprint
= TRUE
;
676 gnutls_x509_crt_deinit(crt
);
680 /* We do not care about other types. */
683 gnutls_pkcs12_bag_deinit(bag
);
686 if (rsa_key
&& (err
|| *df_type
== DF_TYPE_UNKNOWN
||
689 ntfs_log_error("Key type or thumbprint not found, "
691 ntfs_rsa_private_key_release(rsa_key
);
695 gnutls_x509_crt_deinit(crt
);
697 gnutls_x509_privkey_deinit(pkey
);
699 gnutls_pkcs12_bag_deinit(bag
);
701 gnutls_pkcs12_deinit(pkcs12
);
706 * ntfs_buffer_reverse -
708 * This is a utility function for reversing the order of a buffer in place.
709 * Users of this function should be very careful not to sweep byte order
710 * problems under the rug.
712 static inline void ntfs_buffer_reverse(u8
*buf
, unsigned buf_size
)
717 for (i
= 0; i
< buf_size
/ 2; i
++) {
719 buf
[i
] = buf
[buf_size
- i
- 1];
720 buf
[buf_size
- i
- 1] = t
;
726 * strnlen - strnlen is a gnu extension so emulate it if not present
728 static size_t strnlen(const char *s
, size_t maxlen
)
732 /* Look for a '\0' character. */
733 for (p
= s
, end
= s
+ maxlen
; p
< end
&& *p
; p
++)
737 #endif /* ! HAVE_STRNLEN */
740 * ntfs_raw_fek_decrypt -
742 * Note: decrypting into the input buffer.
744 static unsigned ntfs_raw_fek_decrypt(u8
*fek
, u32 fek_size
,
745 ntfs_rsa_private_key rsa_key
)
748 gcry_sexp_t fek_sexp
, fek_sexp2
;
750 size_t size
, padding
;
752 /* Reverse the raw FEK. */
753 ntfs_buffer_reverse(fek
, fek_size
);
754 /* Convert the FEK to internal MPI format. */
755 err
= gcry_mpi_scan(&fek_mpi
, GCRYMPI_FMT_USG
, fek
, fek_size
, NULL
);
756 if (err
!= GPG_ERR_NO_ERROR
) {
757 ntfs_log_error("Failed to convert file encryption key to "
758 "internal MPI format: %s\n",
762 /* Create an internal S-expression from the FEK. */
763 err
= gcry_sexp_build(&fek_sexp
, NULL
,
764 "(enc-val (flags) (rsa (a %m)))", fek_mpi
);
765 gcry_mpi_release(fek_mpi
);
766 if (err
!= GPG_ERR_NO_ERROR
) {
767 ntfs_log_error("Failed to create internal S-expression of "
768 "the file encryption key: %s\n",
772 /* Decrypt the FEK. */
773 err
= gcry_pk_decrypt(&fek_sexp2
, fek_sexp
, (gcry_sexp_t
)rsa_key
);
774 gcry_sexp_release(fek_sexp
);
775 if (err
!= GPG_ERR_NO_ERROR
) {
776 ntfs_log_error("Failed to decrypt the file encryption key: "
777 "%s\n", gcry_strerror(err
));
780 /* Extract the actual FEK from the decrypted raw S-expression. */
781 fek_sexp
= gcry_sexp_find_token(fek_sexp2
, "value", 0);
782 gcry_sexp_release(fek_sexp2
);
784 ntfs_log_error("Failed to find the decrypted file encryption "
785 "key in the internal S-expression.\n");
788 /* Convert the decrypted FEK S-expression into MPI format. */
789 fek_mpi
= gcry_sexp_nth_mpi(fek_sexp
, 1, GCRYMPI_FMT_USG
);
790 gcry_sexp_release(fek_sexp
);
792 ntfs_log_error("Failed to convert the decrypted file "
793 "encryption key S-expression to internal MPI "
797 /* Convert the decrypted FEK from MPI format to binary data. */
798 err
= gcry_mpi_print(GCRYMPI_FMT_USG
, fek
, fek_size
, &size
, fek_mpi
);
799 gcry_mpi_release(fek_mpi
);
800 if (err
!= GPG_ERR_NO_ERROR
|| !size
) {
801 ntfs_log_error("Failed to convert decrypted file encryption "
802 "key from internal MPI format to binary data: "
803 "%s\n", gcry_strerror(err
));
807 * Finally, remove the PKCS#1 padding and return the size of the
810 padding
= strnlen((char *)fek
, size
) + 1;
811 if (padding
> size
) {
812 ntfs_log_error("Failed to remove PKCS#1 padding from "
813 "decrypted file encryption key.\n");
817 memmove(fek
, fek
+ padding
, size
);
822 * ntfs_desx_key_expand - expand a 128-bit desx key to the needed 192-bit key
823 * @src: source buffer containing 128-bit key
825 * Expands the on-disk 128-bit desx key to the needed des key, the in-, and the
826 * out-whitening keys required to perform desx {de,en}cryption.
828 static gcry_error_t
ntfs_desx_key_expand(const u8
*src
, u32
*des_key
,
829 u64
*out_whitening
, u64
*in_whitening
)
831 static const u8
*salt1
= (const u8
*)"Dan Simon ";
832 static const u8
*salt2
= (const u8
*)"Scott Field";
833 static const int salt_len
= 12;
834 gcry_md_hd_t hd1
, hd2
;
838 err
= gcry_md_open(&hd1
, GCRY_MD_MD5
, 0);
839 if (err
!= GPG_ERR_NO_ERROR
) {
840 ntfs_log_error("Failed to open MD5 digest.\n");
843 /* Hash the on-disk key. */
844 gcry_md_write(hd1
, src
, 128 / 8);
845 /* Copy the current hash for efficiency. */
846 err
= gcry_md_copy(&hd2
, hd1
);
847 if (err
!= GPG_ERR_NO_ERROR
) {
848 ntfs_log_error("Failed to copy MD5 digest object.\n");
851 /* Hash with the first salt and store the result. */
852 gcry_md_write(hd1
, salt1
, salt_len
);
853 md
= (u32
*)gcry_md_read(hd1
, 0);
854 des_key
[0] = md
[0] ^ md
[1];
855 des_key
[1] = md
[2] ^ md
[3];
856 /* Hash with the second salt and store the result. */
857 gcry_md_write(hd2
, salt2
, salt_len
);
858 md
= (u32
*)gcry_md_read(hd2
, 0);
859 *out_whitening
= *(u64
*)md
;
860 *in_whitening
= *(u64
*)(md
+ 2);
868 * ntfs_desx_setkey - libgcrypt set_key implementation for DES-X-MS128
869 * @context: pointer to a variable of type ntfs_desx_ctx
870 * @key: the 128 bit DES-X-MS128 key, concated with the DES handle
871 * @keylen: must always be 16
873 * This is the libgcrypt set_key implementation for DES-X-MS128.
875 static gcry_err_code_t
ntfs_desx_setkey(void *context
, const u8
*key
,
878 ntfs_desx_ctx
*ctx
= context
;
883 ntfs_log_error("Key length for desx must be 16.\n");
884 return GPG_ERR_INV_KEYLEN
;
886 err
= gcry_cipher_open(&ctx
->gcry_cipher_hd
, GCRY_CIPHER_DES
,
887 GCRY_CIPHER_MODE_ECB
, 0);
888 if (err
!= GPG_ERR_NO_ERROR
) {
889 ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
893 err
= ntfs_desx_key_expand(key
, (u32
*)des_key
, &ctx
->out_whitening
,
895 if (err
!= GPG_ERR_NO_ERROR
) {
896 ntfs_log_error("Failed to expand desx key (error 0x%x).\n",
898 gcry_cipher_close(ctx
->gcry_cipher_hd
);
901 err
= gcry_cipher_setkey(ctx
->gcry_cipher_hd
, des_key
, sizeof(des_key
));
902 if (err
!= GPG_ERR_NO_ERROR
) {
903 ntfs_log_error("Failed to set des key (error 0x%x).\n", err
);
904 gcry_cipher_close(ctx
->gcry_cipher_hd
);
908 * Take a note of the ctx->gcry_cipher_hd since we need to close it at
909 * ntfs_decrypt_data_key_close() time.
911 **(gcry_cipher_hd_t
***)(key
+ ((keylen
+ 7) & ~7)) =
912 &ctx
->gcry_cipher_hd
;
913 return GPG_ERR_NO_ERROR
;
919 static void ntfs_desx_decrypt(void *context
, u8
*outbuf
, const u8
*inbuf
)
921 ntfs_desx_ctx
*ctx
= context
;
924 err
= gcry_cipher_reset(ctx
->gcry_cipher_hd
);
925 if (err
!= GPG_ERR_NO_ERROR
)
926 ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
928 *(u64
*)outbuf
= *(const u64
*)inbuf
^ ctx
->out_whitening
;
929 err
= gcry_cipher_encrypt(ctx
->gcry_cipher_hd
, outbuf
, 8, NULL
, 0);
930 if (err
!= GPG_ERR_NO_ERROR
)
931 ntfs_log_error("Des decryption failed (error 0x%x).\n", err
);
932 *(u64
*)outbuf
^= ctx
->in_whitening
;
935 static gcry_cipher_spec_t ntfs_desx_cipher
= {
936 .name
= "DES-X-MS128",
939 .contextsize
= sizeof(ntfs_desx_ctx
),
940 .setkey
= ntfs_desx_setkey
,
941 .decrypt
= ntfs_desx_decrypt
,
944 //#define DO_CRYPTO_TESTS 1
946 #ifdef DO_CRYPTO_TESTS
948 /* Do not remove this test code from this file! AIA */
950 * ntfs_desx_key_expand_test
952 static BOOL
ntfs_desx_key_expand_test(void)
954 const u8 known_desx_on_disk_key
[16] = {
955 0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f,
956 0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30
958 const u8 known_des_key
[8] = {
959 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f,
961 const u8 known_out_whitening
[8] = {
962 0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d,
964 const u8 known_in_whitening
[8] = {
965 0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e
967 u64 test_out_whitening
, test_in_whitening
;
975 err
= ntfs_desx_key_expand(known_desx_on_disk_key
, test_des_key
.u32
,
976 &test_out_whitening
, &test_in_whitening
);
977 if (err
!= GPG_ERR_NO_ERROR
)
980 res
= test_des_key
.u64
== *(u64
*)known_des_key
&&
981 test_out_whitening
==
982 *(u64
*)known_out_whitening
&&
984 *(u64
*)known_in_whitening
;
985 ntfs_log_error("Testing whether ntfs_desx_key_expand() works: %s\n",
986 res
? "SUCCESS" : "FAILED");
993 static BOOL
ntfs_des_test(void)
995 const u8 known_des_key
[8] = {
996 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f
998 const u8 known_des_encrypted_data
[8] = {
999 0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f
1001 const u8 known_decrypted_data
[8] = {
1002 0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09
1004 u8 test_decrypted_data
[8];
1007 gcry_cipher_hd_t gcry_cipher_hd
;
1009 err
= gcry_cipher_open(&gcry_cipher_hd
, GCRY_CIPHER_DES
,
1010 GCRY_CIPHER_MODE_ECB
, 0);
1011 if (err
!= GPG_ERR_NO_ERROR
) {
1012 ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
1016 err
= gcry_cipher_setkey(gcry_cipher_hd
, known_des_key
,
1017 sizeof(known_des_key
));
1018 if (err
!= GPG_ERR_NO_ERROR
) {
1019 ntfs_log_error("Failed to set des key (error 0x%x.\n", err
);
1020 gcry_cipher_close(gcry_cipher_hd
);
1024 * Apply DES decryption (ntfs actually uses encryption when decrypting).
1026 err
= gcry_cipher_encrypt(gcry_cipher_hd
, test_decrypted_data
,
1027 sizeof(test_decrypted_data
), known_des_encrypted_data
,
1028 sizeof(known_des_encrypted_data
));
1029 gcry_cipher_close(gcry_cipher_hd
);
1031 ntfs_log_error("Failed to des decrypt test data (error "
1035 res
= !memcmp(test_decrypted_data
, known_decrypted_data
,
1036 sizeof(known_decrypted_data
));
1037 ntfs_log_error("Testing whether des decryption works: %s\n",
1038 res
? "SUCCESS" : "FAILED");
1042 #else /* !defined(DO_CRYPTO_TESTS) */
1045 * ntfs_desx_key_expand_test
1047 static inline BOOL
ntfs_desx_key_expand_test(void)
1055 static inline BOOL
ntfs_des_test(void)
1060 #endif /* !defined(DO_CRYPTO_TESTS) */
1063 * ntfs_fek_import_from_raw
1065 static ntfs_fek
*ntfs_fek_import_from_raw(u8
*fek_buf
, unsigned fek_size
)
1068 u32 key_size
, wanted_key_size
, gcry_algo
;
1071 key_size
= le32_to_cpup(fek_buf
);
1072 ntfs_log_debug("key_size 0x%x\n", key_size
);
1073 if (key_size
+ 16 > fek_size
) {
1074 ntfs_log_debug("Invalid FEK. It was probably decrypted with "
1075 "the incorrect RSA key.");
1079 fek
= malloc(((((sizeof(*fek
) + 7) & ~7) + key_size
+ 7) & ~7) +
1080 sizeof(gcry_cipher_hd_t
));
1085 fek
->alg_id
= *(le32
*)(fek_buf
+ 8);
1086 //ntfs_log_debug("alg_id 0x%x\n", le32_to_cpu(fek->alg_id));
1087 fek
->key_data
= (u8
*)fek
+ ((sizeof(*fek
) + 7) & ~7);
1088 memcpy(fek
->key_data
, fek_buf
+ 16, key_size
);
1089 fek
->des_gcry_cipher_hd_ptr
= NULL
;
1090 *(gcry_cipher_hd_t
***)(fek
->key_data
+ ((key_size
+ 7) & ~7)) =
1091 &fek
->des_gcry_cipher_hd_ptr
;
1092 switch (fek
->alg_id
) {
1094 if (!ntfs_desx_module
) {
1095 if (!ntfs_desx_key_expand_test() || !ntfs_des_test()) {
1099 err
= gcry_cipher_register(&ntfs_desx_cipher
,
1100 &ntfs_desx_algorithm_id
,
1102 if (err
!= GPG_ERR_NO_ERROR
) {
1103 ntfs_log_error("Failed to register desx "
1105 gcry_strerror(err
));
1110 wanted_key_size
= 16;
1111 gcry_algo
= ntfs_desx_algorithm_id
;
1114 wanted_key_size
= 24;
1115 gcry_algo
= GCRY_CIPHER_3DES
;
1118 wanted_key_size
= 32;
1119 gcry_algo
= GCRY_CIPHER_AES256
;
1122 wanted_key_size
= 8;
1123 gcry_algo
= GCRY_CIPHER_DES
;
1124 if (fek
->alg_id
== CALG_DES
)
1125 ntfs_log_error("DES is not supported at present\n");
1127 ntfs_log_error("Unknown crypto algorithm 0x%x\n",
1128 le32_to_cpu(fek
->alg_id
));
1129 ntfs_log_error(". Please email %s and say that you saw this "
1130 "message. We will then try to implement "
1131 "support for this algorithm.\n", NTFS_DEV_LIST
);
1135 if (key_size
!= wanted_key_size
) {
1136 ntfs_log_error("%s key of %u bytes but needed size is %u "
1137 "bytes, assuming corrupt or incorrect key. "
1139 gcry_cipher_algo_name(gcry_algo
),
1140 (unsigned)key_size
, (unsigned)wanted_key_size
);
1144 err
= gcry_cipher_open(&fek
->gcry_cipher_hd
, gcry_algo
,
1145 GCRY_CIPHER_MODE_CBC
, 0);
1146 if (err
!= GPG_ERR_NO_ERROR
) {
1147 ntfs_log_error("gcry_cipher_open() failed: %s\n",
1148 gcry_strerror(err
));
1152 err
= gcry_cipher_setkey(fek
->gcry_cipher_hd
, fek
->key_data
, key_size
);
1153 if (err
!= GPG_ERR_NO_ERROR
) {
1154 ntfs_log_error("gcry_cipher_setkey() failed: %s\n",
1155 gcry_strerror(err
));
1156 gcry_cipher_close(fek
->gcry_cipher_hd
);
1170 static void ntfs_fek_release(ntfs_fek
*fek
)
1172 if (fek
->des_gcry_cipher_hd_ptr
)
1173 gcry_cipher_close(*fek
->des_gcry_cipher_hd_ptr
);
1174 gcry_cipher_close(fek
->gcry_cipher_hd
);
1179 * ntfs_df_array_fek_get
1181 static ntfs_fek
*ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER
*df_array
,
1182 ntfs_rsa_private_key rsa_key
, char *thumbprint
,
1183 int thumbprint_size
)
1185 EFS_DF_HEADER
*df_header
;
1186 EFS_DF_CREDENTIAL_HEADER
*df_cred
;
1187 EFS_DF_CERT_THUMBPRINT_HEADER
*df_cert
;
1190 u32 df_count
, fek_size
;
1193 df_count
= le32_to_cpu(df_array
->df_count
);
1195 ntfs_log_error("There are no elements in the DF array.\n");
1196 df_header
= (EFS_DF_HEADER
*)(df_array
+ 1);
1197 for (i
= 0; i
< df_count
; i
++, df_header
= (EFS_DF_HEADER
*)(
1198 (u8
*)df_header
+ le32_to_cpu(df_header
->df_length
))) {
1199 df_cred
= (EFS_DF_CREDENTIAL_HEADER
*)((u8
*)df_header
+
1200 le32_to_cpu(df_header
->cred_header_offset
));
1201 if (df_cred
->type
!= NTFS_CRED_TYPE_CERT_THUMBPRINT
) {
1202 ntfs_log_debug("Credential type is not certificate "
1203 "thumbprint, skipping DF entry.\n");
1206 df_cert
= (EFS_DF_CERT_THUMBPRINT_HEADER
*)((u8
*)df_cred
+
1208 df_cred
->cert_thumbprint_header_offset
));
1209 if (le32_to_cpu(df_cert
->thumbprint_size
) != thumbprint_size
) {
1210 ntfs_log_error("Thumbprint size %d is not valid "
1211 "(should be %d), skipping this DF "
1213 le32_to_cpu(df_cert
->thumbprint_size
),
1217 if (memcmp((u8
*)df_cert
+
1218 le32_to_cpu(df_cert
->thumbprint_offset
),
1219 thumbprint
, thumbprint_size
)) {
1220 ntfs_log_debug("Thumbprints do not match, skipping "
1221 "this DF entry.\n");
1225 * The thumbprints match so this is probably the DF entry
1226 * matching the RSA key. Try to decrypt the FEK with it.
1228 fek_size
= le32_to_cpu(df_header
->fek_size
);
1229 fek_buf
= (u8
*)df_header
+ le32_to_cpu(df_header
->fek_offset
);
1230 /* Decrypt the FEK. Note: This is done in place. */
1231 fek_size
= ntfs_raw_fek_decrypt(fek_buf
, fek_size
, rsa_key
);
1233 /* Convert the FEK to our internal format. */
1234 fek
= ntfs_fek_import_from_raw(fek_buf
, fek_size
);
1237 ntfs_log_error("Failed to convert the decrypted file "
1238 "encryption key to internal format.\n");
1240 ntfs_log_error("Failed to decrypt the file "
1241 "encryption key.\n");
1247 * ntfs_inode_fek_get -
1249 static ntfs_fek
*ntfs_inode_fek_get(ntfs_inode
*inode
,
1250 ntfs_rsa_private_key rsa_key
, char *thumbprint
,
1251 int thumbprint_size
, NTFS_DF_TYPES df_type
)
1253 EFS_ATTR_HEADER
*efs
;
1254 EFS_DF_ARRAY_HEADER
*df_array
= NULL
;
1255 ntfs_fek
*fek
= NULL
;
1257 /* Obtain the $EFS contents. */
1258 efs
= ntfs_attr_readall(inode
, AT_LOGGED_UTILITY_STREAM
, EFS
, 4, NULL
);
1260 ntfs_log_perror("Failed to read $EFS attribute");
1264 * Depending on whether the key is a normal key or a data recovery key,
1265 * iterate through the DDF or DRF array, respectively.
1267 if (df_type
== DF_TYPE_DDF
) {
1268 if (efs
->offset_to_ddf_array
)
1269 df_array
= (EFS_DF_ARRAY_HEADER
*)((u8
*)efs
+
1270 le32_to_cpu(efs
->offset_to_ddf_array
));
1272 ntfs_log_error("There are no entries in the DDF "
1274 } else if (df_type
== DF_TYPE_DRF
) {
1275 if (efs
->offset_to_drf_array
)
1276 df_array
= (EFS_DF_ARRAY_HEADER
*)((u8
*)efs
+
1277 le32_to_cpu(efs
->offset_to_drf_array
));
1279 ntfs_log_error("There are no entries in the DRF "
1282 ntfs_log_error("Invalid DF type.\n");
1284 fek
= ntfs_df_array_fek_get(df_array
, rsa_key
, thumbprint
,
1291 * ntfs_fek_decrypt_sector
1293 static int ntfs_fek_decrypt_sector(ntfs_fek
*fek
, u8
*data
, const u64 offset
)
1297 err
= gcry_cipher_reset(fek
->gcry_cipher_hd
);
1298 if (err
!= GPG_ERR_NO_ERROR
) {
1299 ntfs_log_error("Failed to reset cipher: %s\n",
1300 gcry_strerror(err
));
1304 * Note: You may wonder why we are not calling gcry_cipher_setiv() here
1305 * instead of doing it by hand after the decryption. The answer is
1306 * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
1307 * it a length of 16 for AES256 so it does not like it.
1309 err
= gcry_cipher_decrypt(fek
->gcry_cipher_hd
, data
, 512, NULL
, 0);
1310 if (err
!= GPG_ERR_NO_ERROR
) {
1311 ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err
));
1315 if (fek
->alg_id
== CALG_AES_256
) {
1316 ((le64
*)data
)[0] ^= cpu_to_le64(0x5816657be9161312ULL
+ offset
);
1317 ((le64
*)data
)[1] ^= cpu_to_le64(0x1989adbe44918961ULL
+ offset
);
1319 /* All other algos (Des, 3Des, DesX) use the same IV. */
1320 ((le64
*)data
)[0] ^= cpu_to_le64(0x169119629891ad13ULL
+ offset
);
1326 * ntfs_cat_decrypt - Decrypt the contents of an encrypted file to stdout.
1327 * @inode: An encrypted file's inode structure, as obtained by
1328 * ntfs_inode_open().
1329 * @fek: A file encryption key. As obtained by ntfs_inode_fek_get().
1331 static int ntfs_cat_decrypt(ntfs_inode
*inode
, ntfs_fek
*fek
)
1334 unsigned char *buffer
;
1336 s64 bytes_read
, written
, offset
, total
;
1337 s64 old_data_size
, old_initialized_size
;
1340 buffer
= malloc(bufsize
);
1343 attr
= ntfs_attr_open(inode
, AT_DATA
, NULL
, 0);
1345 ntfs_log_error("Cannot cat a directory.\n");
1349 total
= attr
->data_size
;
1351 // hack: make sure attr will not be commited to disk if you use this.
1352 // clear the encrypted bit, otherwise the library won't allow reading.
1353 NAttrClearEncrypted(attr
);
1354 // extend the size, we may need to read past the end of the stream.
1355 old_data_size
= attr
->data_size
;
1356 old_initialized_size
= attr
->initialized_size
;
1357 attr
->data_size
= attr
->initialized_size
= attr
->allocated_size
;
1361 bytes_read
= ntfs_attr_pread(attr
, offset
, 512, buffer
);
1362 if (bytes_read
== -1) {
1363 ntfs_log_perror("ERROR: Couldn't read file");
1368 if ((i
= ntfs_fek_decrypt_sector(fek
, buffer
, offset
)) <
1370 ntfs_log_perror("ERROR: Couldn't decrypt all data!");
1371 ntfs_log_error("%u/%lld/%lld/%lld\n", i
,
1372 (long long)bytes_read
, (long long)offset
,
1376 if (bytes_read
> total
)
1378 written
= fwrite(buffer
, 1, bytes_read
, stdout
);
1379 if (written
!= bytes_read
) {
1380 ntfs_log_perror("ERROR: Couldn't output all data!");
1383 offset
+= bytes_read
;
1384 total
-= bytes_read
;
1386 attr
->data_size
= old_data_size
;
1387 attr
->initialized_size
= old_initialized_size
;
1388 NAttrSetEncrypted(attr
);
1389 ntfs_attr_close(attr
);
1399 * Return: 0 Success, the program worked
1400 * 1 Error, something went wrong
1402 int main(int argc
, char *argv
[])
1406 ntfs_rsa_private_key rsa_key
;
1412 NTFS_DF_TYPES df_type
;
1413 char thumbprint
[NTFS_SHA1_THUMBPRINT_SIZE
];
1415 ntfs_log_set_handler(ntfs_log_handler_stderr
);
1417 if (!parse_options(argc
, argv
))
1421 /* Initialize crypto in ntfs. */
1422 if (ntfs_crypto_init()) {
1423 ntfs_log_error("Failed to initialize crypto. Aborting.\n");
1426 /* Load the PKCS#12 (.pfx) file containing the user's private key. */
1427 if (ntfs_pkcs12_load_pfxfile(opts
.keyfile
, &pfx_buf
, &pfx_size
)) {
1428 ntfs_log_error("Failed to load key file. Aborting.\n");
1429 ntfs_crypto_deinit();
1432 /* Ask the user for their password. */
1433 password
= getpass("Enter the password with which the private key was "
1436 ntfs_log_perror("Failed to obtain user password");
1438 ntfs_crypto_deinit();
1441 /* Obtain the user's private RSA key from the key file. */
1442 rsa_key
= ntfs_pkcs12_extract_rsa_key(pfx_buf
, pfx_size
, password
,
1443 thumbprint
, sizeof(thumbprint
), &df_type
);
1444 /* Destroy the password. */
1445 memset(password
, 0, strlen(password
));
1446 /* No longer need the pfx file contents. */
1449 ntfs_log_error("Failed to extract the private RSA key.\n");
1450 ntfs_crypto_deinit();
1453 /* Mount the ntfs volume. */
1454 vol
= utils_mount_volume(opts
.device
, NTFS_MNT_RDONLY
|
1455 (opts
.force
? NTFS_MNT_RECOVER
: 0));
1457 ntfs_log_error("Failed to mount ntfs volume. Aborting.\n");
1458 ntfs_rsa_private_key_release(rsa_key
);
1459 ntfs_crypto_deinit();
1462 /* Open the encrypted ntfs file. */
1463 if (opts
.inode
!= -1)
1464 inode
= ntfs_inode_open(vol
, opts
.inode
);
1466 inode
= ntfs_pathname_to_inode(vol
, NULL
, opts
.file
);
1468 ntfs_log_error("Failed to open encrypted file. Aborting.\n");
1469 ntfs_umount(vol
, FALSE
);
1470 ntfs_rsa_private_key_release(rsa_key
);
1471 ntfs_crypto_deinit();
1474 /* Obtain the file encryption key of the encrypted file. */
1475 fek
= ntfs_inode_fek_get(inode
, rsa_key
, thumbprint
,
1476 sizeof(thumbprint
), df_type
);
1477 ntfs_rsa_private_key_release(rsa_key
);
1479 res
= ntfs_cat_decrypt(inode
, fek
);
1480 ntfs_fek_release(fek
);
1482 ntfs_log_error("Failed to obtain file encryption key. "
1486 ntfs_inode_close(inode
);
1487 ntfs_umount(vol
, FALSE
);
1488 ntfs_crypto_deinit();