1 /**
2 * crypto.c - Routines for dealing with encrypted files. Part of the
3 * Linux-NTFS project.
4 *
5 * Copyright (c) 2005 Yuval Fledel
6 * Copyright (c) 2005-2007 Anton Altaparmakov
7 * Copyright (c) 2007 Yura Pakhuchiy
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the Linux-NTFS
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * TODO: Cleanup this file. Write nice descriptions for non-exported functions
25 * and maybe clean up namespace (not necessary for all functions to belong to
26 * ntfs_crypto, we can have ntfs_fek, ntfs_rsa, etc.., but there should be
27 * maximum 2-3 namespaces, not every function begins with it own namespace
28 * like now).
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #ifdef HAVE_SYS_TYPES_H
36 #include <sys/types.h>
37 #endif
38 #ifdef HAVE_SYS_STAT_H
39 #include <sys/stat.h>
40 #endif
41 #ifdef HAVE_FCNTL_H
42 #include <fcntl.h>
43 #endif
44 #ifdef HAVE_STDIO_H
45 #include <stdio.h>
46 #endif
47 #ifdef HAVE_STDLIB_H
48 #include <stdlib.h>
49 #endif
50 #ifdef HAVE_STRING_H
51 #include <string.h>
52 #endif
53 #ifdef HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #ifdef HAVE_ERRNO_H
57 #include <errno.h>
58 #endif
59
60 #include "compat.h"
61 #include "attrib.h"
62 #include "types.h"
63 #include "volume.h"
64 #include "debug.h"
65 #include "dir.h"
66 #include "layout.h"
67 #include "crypto.h"
68
69 #ifdef ENABLE_CRYPTO
70
71 #include <gcrypt.h>
72 #include <gnutls/pkcs12.h>
73 #include <gnutls/x509.h>
74
75 #include <libconfig.h>
76
77 #define NTFS_CONFIG_PATH_SYSTEM "/etc/libntfs/config"
78 #define NTFS_CONFIG_PATH_USER ".libntfs/config"
79
80 #define NTFS_SHA1_THUMBPRINT_SIZE 0x14
81
82 #define NTFS_CRED_TYPE_CERT_THUMBPRINT const_cpu_to_le32(3)
83
84 #define NTFS_EFS_CERT_PURPOSE_OID_DDF "1.3.6.1.4.1.311.10.3.4"
85 #define NTFS_EFS_CERT_PURPOSE_OID_DRF "1.3.6.1.4.1.311.10.3.4.1"
86
87 #define NTFS_EFS_SECTOR_SIZE 512
88
89 typedef enum {
90 DF_TYPE_UNKNOWN,
91 DF_TYPE_DDF,
92 DF_TYPE_DRF,
93 } NTFS_DF_TYPES;
94
95 /**
96 * enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit)
97 *
98 * To choose which one is used in Windows, create or set the REG_DWORD registry
99 * key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\
100 * AlgorithmID to the value of your chosen crypto algorithm, e.g. to use DesX,
101 * set AlgorithmID to 0x6604.
102 *
103 * Note that the Windows versions I have tried so far (all are high crypto
104 * enabled) ignore the AlgorithmID value if it is not one of CALG_3DES,
105 * CALG_DESX, or CALG_AES_256, i.e. you cannot select CALG_DES at all using
106 * this registry key. It would be interesting to check out encryption on one
107 * of the "crippled" crypto Windows versions...
108 */
109 typedef enum {
110 CALG_DES = const_cpu_to_le32(0x6601),
111 /* If not one of the below three, fall back to standard Des. */
112 CALG_3DES = const_cpu_to_le32(0x6603),
113 CALG_DESX = const_cpu_to_le32(0x6604),
114 CALG_AES_256 = const_cpu_to_le32(0x6610),
115 } NTFS_CRYPTO_ALGORITHMS;
116
117 /**
118 * struct ntfs_fek - Decrypted, in-memory file encryption key.
119 */
120 struct _ntfs_fek {
121 gcry_cipher_hd_t gcry_cipher_hd;
122 le32 alg_id;
123 u8 *key_data;
124 gcry_cipher_hd_t *des_gcry_cipher_hd_ptr;
125 };
126
127 typedef struct _ntfs_fek ntfs_fek;
128
129 struct _ntfs_crypto_attr {
130 ntfs_fek *fek;
131 };
132
133 typedef struct {
134 u64 in_whitening, out_whitening;
135 gcry_cipher_hd_t gcry_cipher_hd;
136 } ntfs_desx_ctx;
137
138 ntfschar NTFS_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)
141 };
142
143 typedef struct {
144 gcry_sexp_t key;
145 NTFS_DF_TYPES df_type;
146 char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE];
147 } ntfs_rsa_private_key_t;
148
149 /*
150 * Yes, global variables sucks, but we need to keep whether we performed
151 * gcrypt/gnutls global initialization and keep user's RSA keys.
152 */
153 typedef struct {
154 int initialized;
155 int desx_alg_id;
156 gcry_module_t desx_module;
157 ntfs_rsa_private_key_t **rsa_key;
158 int nr_rsa_keys;
159 } ntfs_crypto_ctx_t;
160
161 static ntfs_crypto_ctx_t ntfs_crypto_ctx = {
162 .desx_alg_id = -1,
163 .desx_module = NULL,
164 };
165
166 /**
167 * ntfs_pkcs12_load_pfxfile
168 */
169 static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx,
170 unsigned *pfx_size)
171 {
172 int f, to_read, total, attempts, br;
173 struct stat key_stat;
174
175 if (!keyfile || !pfx || !pfx_size) {
176 ntfs_log_error("You have to specify the key file, a pointer "
177 "to hold the key file contents, and a pointer "
178 "to hold the size of the key file contents.\n");
179 return -1;
180 }
181 f = open(keyfile, O_RDONLY);
182 if (f == -1) {
183 ntfs_log_perror("Failed to open key file");
184 return -1;
185 }
186 if (fstat(f, &key_stat) == -1) {
187 ntfs_log_perror("Failed to stat key file");
188 goto file_out;
189 }
190 if (!S_ISREG(key_stat.st_mode)) {
191 ntfs_log_error("Key file is not a regular file, cannot read "
192 "it.\n");
193 goto file_out;
194 }
195 if (!key_stat.st_size) {
196 ntfs_log_error("Key file has zero size.\n");
197 goto file_out;
198 }
199 *pfx = malloc(key_stat.st_size + 1);
200 if (!*pfx) {
201 ntfs_log_perror("Failed to allocate buffer for key file "
202 "contents");
203 goto file_out;
204 }
205 to_read = key_stat.st_size;
206 total = attempts = 0;
207 do {
208 br = read(f, *pfx + total, to_read);
209 if (br == -1) {
210 ntfs_log_perror("Failed to read from key file");
211 goto free_out;
212 }
213 if (!br)
214 attempts++;
215 to_read -= br;
216 total += br;
217 } while (to_read > 0 && attempts < 3);
218 close(f);
219 /* Make sure it is zero terminated. */
220 (*pfx)[key_stat.st_size] = 0;
221 *pfx_size = key_stat.st_size;
222 return 0;
223 free_out:
224 free(*pfx);
225 file_out:
226 close(f);
227 return -1;
228 }
229
230 /**
231 * ntfs_rsa_private_key_import_from_gnutls
232 */
233 static gcry_sexp_t ntfs_rsa_private_key_import_from_gnutls(
234 gnutls_x509_privkey_t priv_key)
235 {
236 int i, j;
237 size_t tmp_size;
238 gnutls_datum_t rd[6];
239 gcry_mpi_t rm[6];
240 gcry_sexp_t rsa_key;
241
242 /* Extract the RSA parameters from the GNU TLS private key. */
243 if (gnutls_x509_privkey_export_rsa_raw(priv_key, &rd[0], &rd[1],
244 &rd[2], &rd[3], &rd[4], &rd[5])) {
245 ntfs_log_error("Failed to export rsa parameters. (Is the "
246 "key an RSA private key?)\n");
247 return NULL;
248 }
249 /* Convert each RSA parameter to MPI format. */
250 for (i = 0; i < 6; i++) {
251 if (gcry_mpi_scan(&rm[i], GCRYMPI_FMT_USG, rd[i].data,
252 rd[i].size, &tmp_size) != GPG_ERR_NO_ERROR) {
253 ntfs_log_error("Failed to convert RSA parameter %i "
254 "to mpi format (size %d)\n", i,
255 rd[i].size);
256 rsa_key = NULL;
257 break;
258 }
259 }
260 /* Release the no longer needed datum values. */
261 for (j = 0; j < 6; j++) {
262 if (rd[j].data && rd[j].size)
263 gnutls_free(rd[j].data);
264 }
265 /*
266 * Build the gcrypt private key, note libgcrypt uses p and q inversed
267 * to what gnutls uses.
268 */
269 if (i == 6 && gcry_sexp_build(&rsa_key, NULL,
270 "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
271 rm[0], rm[1], rm[2], rm[4], rm[3], rm[5]) !=
272 GPG_ERR_NO_ERROR) {
273 ntfs_log_error("Failed to build RSA private key s-exp.\n");
274 rsa_key = NULL;
275 }
276 /* Release the no longer needed MPI values. */
277 for (j = 0; j < i; j++)
278 gcry_mpi_release(rm[j]);
279 return rsa_key;
280 }
281
282 /**
283 * ntfs_rsa_private_key_release
284 */
285 static void ntfs_rsa_private_key_release(ntfs_rsa_private_key_t *rsa_key)
286 {
287 if (rsa_key) {
288 if (rsa_key->key)
289 gcry_sexp_release(rsa_key->key);
290 free(rsa_key);
291 }
292 }
293
294 /**
295 * ntfs_pkcs12_extract_rsa_key
296 */
297 static ntfs_rsa_private_key_t *ntfs_pkcs12_extract_rsa_key(u8 *pfx,
298 int pfx_size, const char *password)
299 {
300 int err, bag_index, flags;
301 gnutls_datum_t dpfx, dkey;
302 gnutls_pkcs12_t pkcs12 = NULL;
303 gnutls_pkcs12_bag_t bag = NULL;
304 gnutls_x509_privkey_t pkey = NULL;
305 gnutls_x509_crt_t crt = NULL;
306 ntfs_rsa_private_key_t *rsa_key = NULL;
307 char purpose_oid[100];
308 size_t purpose_oid_size = sizeof(purpose_oid);
309 size_t tp_size;
310 BOOL have_thumbprint = FALSE;
311
312 rsa_key = malloc(sizeof(ntfs_rsa_private_key_t));
313 if (!rsa_key) {
314 ntfs_log_perror("%s", "ntfs_pkcs12_extract_rsa_key");
315 return NULL;
316 }
317 rsa_key->df_type = DF_TYPE_UNKNOWN;
318 rsa_key->key = NULL;
319 tp_size = sizeof(rsa_key->thumbprint);
320 /* Create a pkcs12 structure. */
321 err = gnutls_pkcs12_init(&pkcs12);
322 if (err) {
323 ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n",
324 gnutls_strerror(err));
325 goto err;
326 }
327 /* Convert the PFX file (DER format) to native pkcs12 format. */
328 dpfx.data = pfx;
329 dpfx.size = pfx_size;
330 err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0);
331 if (err) {
332 ntfs_log_error("Failed to convert the PFX file from DER to "
333 "native PKCS#12 format: %s\n",
334 gnutls_strerror(err));
335 goto err;
336 }
337 /*
338 * Verify that the password is correct and that the key file has not
339 * been tampered with. Note if the password has zero length and the
340 * verification fails, retry with password set to NULL. This is needed
341 * to get password less .pfx files generated with Windows XP SP1 (and
342 * probably earlier versions of Windows) to work.
343 */
344 retry_verify:
345 err = gnutls_pkcs12_verify_mac(pkcs12, password);
346 if (err) {
347 if (err == GNUTLS_E_MAC_VERIFY_FAILED &&
348 password && !strlen(password)) {
349 password = NULL;
350 goto retry_verify;
351 }
352 ntfs_log_error("You are probably misspelled password to PFX "
353 "file.\n");
354 goto err;
355 }
356 for (bag_index = 0; ; bag_index++) {
357 err = gnutls_pkcs12_bag_init(&bag);
358 if (err) {
359 ntfs_log_error("Failed to initialize PKCS#12 Bag "
360 "structure: %s\n",
361 gnutls_strerror(err));
362 goto err;
363 }
364 err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag);
365 if (err) {
366 if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
367 err = 0;
368 break;
369 }
370 ntfs_log_error("Failed to obtain Bag from PKCS#12 "
371 "structure: %s\n",
372 gnutls_strerror(err));
373 goto err;
374 }
375 check_again:
376 err = gnutls_pkcs12_bag_get_count(bag);
377 if (err < 0) {
378 ntfs_log_error("Failed to obtain Bag count: %s\n",
379 gnutls_strerror(err));
380 goto err;
381 }
382 err = gnutls_pkcs12_bag_get_type(bag, 0);
383 if (err < 0) {
384 ntfs_log_error("Failed to determine Bag type: %s\n",
385 gnutls_strerror(err));
386 goto err;
387 }
388 flags = 0;
389 switch (err) {
390 case GNUTLS_BAG_PKCS8_KEY:
391 flags = GNUTLS_PKCS_PLAIN;
392 case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
393 err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
394 if (err < 0) {
395 ntfs_log_error("Failed to obtain Bag data: "
396 "%s\n", gnutls_strerror(err));
397 goto err;
398 }
399 err = gnutls_x509_privkey_init(&pkey);
400 if (err) {
401 ntfs_log_error("Failed to initialized "
402 "private key structure: %s\n",
403 gnutls_strerror(err));
404 goto err;
405 }
406 /* Decrypt the private key into GNU TLS format. */
407 err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey,
408 GNUTLS_X509_FMT_DER, password, flags);
409 if (err) {
410 ntfs_log_error("Failed to convert private "
411 "key from DER to GNU TLS "
412 "format: %s\n",
413 gnutls_strerror(err));
414 goto err;
415 }
416 #if 0
417 /*
418 * Export the key again, but unencrypted, and output it
419 * to stderr. Note the output has an RSA header so to
420 * compare to openssl pkcs12 -nodes -in myfile.pfx
421 * output need to ignore the part of the key between
422 * the first "MII..." up to the second "MII...". The
423 * actual RSA private key begins at the second "MII..."
424 * and in my testing at least was identical to openssl
425 * output and was also identical both on big and little
426 * endian so gnutls should be endianness safe.
427 */
428 char *buf = malloc(8192);
429 size_t bufsize = 8192;
430 err = gnutls_x509_privkey_export_pkcs8(pkey,
431 GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf,
432 &bufsize);
433 if (err) {
434 ntfs_log_error("eek1\n");
435 exit(1);
436 }
437 ntfs_log_error("%s\n", buf);
438 free(buf);
439 #endif
440 /* Convert the private key to our internal format. */
441 rsa_key->key =
442 ntfs_rsa_private_key_import_from_gnutls(pkey);
443 if (!rsa_key->key)
444 goto err;
445 break;
446 case GNUTLS_BAG_ENCRYPTED:
447 err = gnutls_pkcs12_bag_decrypt(bag, password);
448 if (err) {
449 ntfs_log_error("Failed to decrypt Bag: %s\n",
450 gnutls_strerror(err));
451 goto err;
452 }
453 goto check_again;
454 case GNUTLS_BAG_CERTIFICATE:
455 err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey);
456 if (err < 0) {
457 ntfs_log_error("Failed to obtain Bag data: "
458 "%s\n", gnutls_strerror(err));
459 goto err;
460 }
461 err = gnutls_x509_crt_init(&crt);
462 if (err) {
463 ntfs_log_error("Failed to initialize "
464 "certificate structure: %s\n",
465 gnutls_strerror(err));
466 goto err;
467 }
468 err = gnutls_x509_crt_import(crt, &dkey,
469 GNUTLS_X509_FMT_DER);
470 if (err) {
471 ntfs_log_error("Failed to convert certificate "
472 "from DER to GNU TLS format: "
473 "%s\n", gnutls_strerror(err));
474 goto err;
475 }
476 err = gnutls_x509_crt_get_key_purpose_oid(crt, 0,
477 purpose_oid, &purpose_oid_size, NULL);
478 if (err) {
479 ntfs_log_error("Failed to get key purpose "
480 "OID: %s\n",
481 gnutls_strerror(err));
482 goto err;
483 }
484 purpose_oid[purpose_oid_size - 1] = 0;
485 if (!strcmp(purpose_oid,
486 NTFS_EFS_CERT_PURPOSE_OID_DRF))
487 rsa_key->df_type = DF_TYPE_DRF;
488 else if (!strcmp(purpose_oid,
489 NTFS_EFS_CERT_PURPOSE_OID_DDF))
490 rsa_key->df_type = DF_TYPE_DDF;
491 else {
492 ntfs_log_error("Certificate has unknown "
493 "purpose OID %s.\n",
494 purpose_oid);
495 err = EINVAL;
496 goto err;
497 }
498 /* Return the thumbprint to the caller. */
499 err = gnutls_x509_crt_get_fingerprint(crt,
500 GNUTLS_DIG_SHA1, rsa_key->thumbprint,
501 &tp_size);
502 if (err) {
503 ntfs_log_error("Failed to get thumbprint: "
504 "%s\n", gnutls_strerror(err));
505 goto err;
506 }
507 if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) {
508 ntfs_log_error("Invalid thumbprint size %zd. "
509 "Should be %d.\n", tp_size,
510 sizeof(rsa_key->thumbprint));
511 err = EINVAL;
512 goto err;
513 }
514 have_thumbprint = TRUE;
515 gnutls_x509_crt_deinit(crt);
516 crt = NULL;
517 break;
518 default:
519 /* We do not care about other types. */
520 break;
521 }
522 gnutls_pkcs12_bag_deinit(bag);
523 }
524 err:
525 if (err || !rsa_key->key || rsa_key->df_type == DF_TYPE_UNKNOWN ||
526 !have_thumbprint) {
527 if (!err)
528 ntfs_log_error("Key type or thumbprint not found, "
529 "aborting.\n");
530 ntfs_rsa_private_key_release(rsa_key);
531 rsa_key = NULL;
532 }
533 if (crt)
534 gnutls_x509_crt_deinit(crt);
535 if (pkey)
536 gnutls_x509_privkey_deinit(pkey);
537 if (bag)
538 gnutls_pkcs12_bag_deinit(bag);
539 if (pkcs12)
540 gnutls_pkcs12_deinit(pkcs12);
541 return rsa_key;
542 }
543
544 /**
545 * ntfs_buffer_reverse -
546 *
547 * This is a utility function for reversing the order of a buffer in place.
548 * Users of this function should be very careful not to sweep byte order
549 * problems under the rug.
550 */
551 static inline void ntfs_buffer_reverse(u8 *buf, unsigned buf_size)
552 {
553 unsigned i;
554 u8 t;
555
556 for (i = 0; i < buf_size / 2; i++) {
557 t = buf[i];
558 buf[i] = buf[buf_size - i - 1];
559 buf[buf_size - i - 1] = t;
560 }
561 }
562
563 #ifndef HAVE_STRNLEN
564 /**
565 * strnlen - strnlen is a gnu extension so emulate it if not present
566 */
567 static size_t strnlen(const char *s, size_t maxlen)
568 {
569 const char *p, *end;
570
571 /* Look for a '\0' character. */
572 for (p = s, end = s + maxlen; p < end && *p; p++)
573 ;
574 return p - s;
575 }
576 #endif /* ! HAVE_STRNLEN */
577
578 /**
579 * ntfs_raw_fek_decrypt -
580 *
581 * Note: decrypting into the input buffer.
582 */
583 static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
584 ntfs_rsa_private_key_t *rsa_key)
585 {
586 gcry_mpi_t fek_mpi;
587 gcry_sexp_t fek_sexp, fek_sexp2;
588 gcry_error_t err;
589 size_t size, padding;
590
591 /* Reverse the raw FEK. */
592 ntfs_buffer_reverse(fek, fek_size);
593 /* Convert the FEK to internal MPI format. */
594 err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL);
595 if (err != GPG_ERR_NO_ERROR) {
596 ntfs_log_error("Failed to convert file encryption key to "
597 "internal MPI format: %s\n",
598 gcry_strerror(err));
599 return 0;
600 }
601 /* Create an internal S-expression from the FEK. */
602 err = gcry_sexp_build(&fek_sexp, NULL,
603 "(enc-val (flags) (rsa (a %m)))", fek_mpi);
604 gcry_mpi_release(fek_mpi);
605 if (err != GPG_ERR_NO_ERROR) {
606 ntfs_log_error("Failed to create internal S-expression of "
607 "the file encryption key: %s\n",
608 gcry_strerror(err));
609 return 0;
610 }
611 /* Decrypt the FEK. */
612 err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, rsa_key->key);
613 gcry_sexp_release(fek_sexp);
614 if (err != GPG_ERR_NO_ERROR) {
615 ntfs_log_error("Failed to decrypt the file encryption key: "
616 "%s\n", gcry_strerror(err));
617 return 0;
618 }
619 /* Extract the actual FEK from the decrypted raw S-expression. */
620 fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0);
621 gcry_sexp_release(fek_sexp2);
622 if (!fek_sexp) {
623 ntfs_log_error("Failed to find the decrypted file encryption "
624 "key in the internal S-expression.\n");
625 return 0;
626 }
627 /* Convert the decrypted FEK S-expression into MPI format. */
628 fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG);
629 gcry_sexp_release(fek_sexp);
630 if (!fek_mpi) {
631 ntfs_log_error("Failed to convert the decrypted file "
632 "encryption key S-expression to internal MPI "
633 "format.\n");
634 return 0;
635 }
636 /* Convert the decrypted FEK from MPI format to binary data. */
637 err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi);
638 gcry_mpi_release(fek_mpi);
639 if (err != GPG_ERR_NO_ERROR || !size) {
640 ntfs_log_error("Failed to convert decrypted file encryption "
641 "key from internal MPI format to binary data: "
642 "%s\n", gcry_strerror(err));
643 return 0;
644 }
645 /*
646 * Finally, remove the PKCS#1 padding and return the size of the
647 * decrypted FEK.
648 */
649 padding = strnlen((char *)fek, size) + 1;
650 if (padding > size) {
651 ntfs_log_error("Failed to remove PKCS#1 padding from "
652 "decrypted file encryption key.\n");
653 return 0;
654 }
655 size -= padding;
656 memmove(fek, fek + padding, size);
657 return size;
658 }
659
660 /**
661 * ntfs_desx_key_expand - expand a 128-bit desx key to the needed 192-bit key
662 * @src: source buffer containing 128-bit key
663 *
664 * Expands the on-disk 128-bit desx key to the needed des key, the in-, and the
665 * out-whitening keys required to perform desx {de,en}cryption.
666 */
667 static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key,
668 u64 *out_whitening, u64 *in_whitening)
669 {
670 static const u8 *salt1 = (const u8*)"Dan Simon ";
671 static const u8 *salt2 = (const u8*)"Scott Field";
672 static const int salt_len = 12;
673 gcry_md_hd_t hd1, hd2;
674 u32 *md;
675 gcry_error_t err;
676
677 err = gcry_md_open(&hd1, GCRY_MD_MD5, 0);
678 if (err != GPG_ERR_NO_ERROR) {
679 ntfs_log_error("Failed to open MD5 digest.\n");
680 return err;
681 }
682 /* Hash the on-disk key. */
683 gcry_md_write(hd1, src, 128 / 8);
684 /* Copy the current hash for efficiency. */
685 err = gcry_md_copy(&hd2, hd1);
686 if (err != GPG_ERR_NO_ERROR) {
687 ntfs_log_error("Failed to copy MD5 digest object.\n");
688 goto out;
689 }
690 /* Hash with the first salt and store the result. */
691 gcry_md_write(hd1, salt1, salt_len);
692 md = (u32*)gcry_md_read(hd1, 0);
693 des_key[0] = md[0] ^ md[1];
694 des_key[1] = md[2] ^ md[3];
695 /* Hash with the second salt and store the result. */
696 gcry_md_write(hd2, salt2, salt_len);
697 md = (u32*)gcry_md_read(hd2, 0);
698 *out_whitening = *(u64*)md;
699 *in_whitening = *(u64*)(md + 2);
700 gcry_md_close(hd2);
701 out:
702 gcry_md_close(hd1);
703 return err;
704 }
705
706 /**
707 * ntfs_desx_setkey - libgcrypt set_key implementation for DES-X-MS128
708 * @context: pointer to a variable of type ntfs_desx_ctx
709 * @key: the 128 bit DES-X-MS128 key, concated with the DES handle
710 * @keylen: must always be 16
711 *
712 * This is the libgcrypt set_key implementation for DES-X-MS128.
713 */
714 static gcry_err_code_t ntfs_desx_setkey(void *context, const u8 *key,
715 unsigned keylen)
716 {
717 ntfs_desx_ctx *ctx = context;
718 gcry_error_t err;
719 u8 des_key[8];
720
721 if (keylen != 16) {
722 ntfs_log_error("Key length for desx must be 16.\n");
723 return GPG_ERR_INV_KEYLEN;
724 }
725 err = gcry_cipher_open(&ctx->gcry_cipher_hd, GCRY_CIPHER_DES,
726 GCRY_CIPHER_MODE_ECB, 0);
727 if (err != GPG_ERR_NO_ERROR) {
728 ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
729 err);
730 return err;
731 }
732 err = ntfs_desx_key_expand(key, (u32*)des_key, &ctx->out_whitening,
733 &ctx->in_whitening);
734 if (err != GPG_ERR_NO_ERROR) {
735 ntfs_log_error("Failed to expand desx key (error 0x%x).\n",
736 err);
737 gcry_cipher_close(ctx->gcry_cipher_hd);
738 return err;
739 }
740 err = gcry_cipher_setkey(ctx->gcry_cipher_hd, des_key, sizeof(des_key));
741 if (err != GPG_ERR_NO_ERROR) {
742 ntfs_log_error("Failed to set des key (error 0x%x).\n", err);
743 gcry_cipher_close(ctx->gcry_cipher_hd);
744 return err;
745 }
746 /*
747 * Take a note of the ctx->gcry_cipher_hd since we need to close it at
748 * ntfs_decrypt_data_key_close() time.
749 */
750 **(gcry_cipher_hd_t***)(key + ((keylen + 7) & ~7)) =
751 &ctx->gcry_cipher_hd;
752 return GPG_ERR_NO_ERROR;
753 }
754
755 /**
756 * ntfs_desx_decrypt
757 */
758 static void ntfs_desx_decrypt(void *context, u8 *outbuf, const u8 *inbuf)
759 {
760 ntfs_desx_ctx *ctx = context;
761 gcry_error_t err;
762
763 err = gcry_cipher_reset(ctx->gcry_cipher_hd);
764 if (err != GPG_ERR_NO_ERROR)
765 ntfs_log_error("Failed to reset des cipher (error 0x%x).\n",
766 err);
767 *(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening;
768 err = gcry_cipher_encrypt(ctx->gcry_cipher_hd, outbuf, 8, NULL, 0);
769 if (err != GPG_ERR_NO_ERROR)
770 ntfs_log_error("Des decryption failed (error 0x%x).\n", err);
771 *(u64*)outbuf ^= ctx->in_whitening;
772 }
773
774 static gcry_cipher_spec_t ntfs_desx_cipher = {
775 .name = "DES-X-MS128",
776 .blocksize = 8,
777 .keylen = 128,
778 .contextsize = sizeof(ntfs_desx_ctx),
779 .setkey = ntfs_desx_setkey,
780 .decrypt = ntfs_desx_decrypt,
781 };
782
783 #ifdef NTFS_TEST
784 /*
785 * Do not remove this test code from this file! (AIA)
786 * It would be nice to move all tests (these and runlist) out of the library
787 * (at least, into the separate file{,s}), so they would not annoy eyes. (Yura)
788 */
789
790 /**
791 * ntfs_desx_key_expand_test
792 */
793 static BOOL ntfs_desx_key_expand_test(void)
794 {
795 const u8 known_desx_on_disk_key[16] = {
796 0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f,
797 0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30
798 };
799 const u8 known_des_key[8] = {
800 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f,
801 };
802 const u8 known_out_whitening[8] = {
803 0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d,
804 };
805 const u8 known_in_whitening[8] = {
806 0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e
807 };
808 u64 test_out_whitening, test_in_whitening;
809 union {
810 u64 u64;
811 u32 u32[2];
812 } test_des_key;
813 gcry_error_t err;
814 BOOL res;
815
816 err = ntfs_desx_key_expand(known_desx_on_disk_key, test_des_key.u32,
817 &test_out_whitening, &test_in_whitening);
818 if (err != GPG_ERR_NO_ERROR)
819 res = FALSE;
820 else
821 res = test_des_key.u64 == *(u64*)known_des_key &&
822 test_out_whitening ==
823 *(u64*)known_out_whitening &&
824 test_in_whitening ==
825 *(u64*)known_in_whitening;
826 ntfs_log_error("Testing whether ntfs_desx_key_expand() works: %s\n",
827 res ? "SUCCESS" : "FAILED");
828 return res;
829 }
830
831 /**
832 * ntfs_des_test
833 */
834 static BOOL ntfs_des_test(void)
835 {
836 const u8 known_des_key[8] = {
837 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f
838 };
839 const u8 known_des_encrypted_data[8] = {
840 0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f
841 };
842 const u8 known_decrypted_data[8] = {
843 0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09
844 };
845 u8 test_decrypted_data[8];
846 int res;
847 gcry_error_t err;
848 gcry_cipher_hd_t gcry_cipher_hd;
849
850 err = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_DES,
851 GCRY_CIPHER_MODE_ECB, 0);
852 if (err != GPG_ERR_NO_ERROR) {
853 ntfs_log_error("Failed to open des cipher (error 0x%x).\n",
854 err);
855 return FALSE;
856 }
857 err = gcry_cipher_setkey(gcry_cipher_hd, known_des_key,
858 sizeof(known_des_key));
859 if (err != GPG_ERR_NO_ERROR) {
860 ntfs_log_error("Failed to set des key (error 0x%x.\n", err);
861 gcry_cipher_close(gcry_cipher_hd);
862 return FALSE;
863 }
864 /*
865 * Apply DES decryption (ntfs actually uses encryption when decrypting).
866 */
867 err = gcry_cipher_encrypt(gcry_cipher_hd, test_decrypted_data,
868 sizeof(test_decrypted_data), known_des_encrypted_data,
869 sizeof(known_des_encrypted_data));
870 gcry_cipher_close(gcry_cipher_hd);
871 if (err) {
872 ntfs_log_error("Failed to des decrypt test data (error "
873 "0x%x).\n", err);
874 return FALSE;
875 }
876 res = !memcmp(test_decrypted_data, known_decrypted_data,
877 sizeof(known_decrypted_data));
878 ntfs_log_error("Testing whether des decryption works: %s\n",
879 res ? "SUCCESS" : "FAILED");
880 return res;
881 }
882
883 #else /* !defined(NTFS_TEST) */
884
885 /**
886 * ntfs_desx_key_expand_test
887 */
888 static inline BOOL ntfs_desx_key_expand_test(void)
889 {
890 return TRUE;
891 }
892
893 /**
894 * ntfs_des_test
895 */
896 static inline BOOL ntfs_des_test(void)
897 {
898 return TRUE;
899 }
900
901 #endif /* !defined(NTFS_TEST) */
902
903 /**
904 * ntfs_fek_import_from_raw
905 */
906 static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
907 unsigned fek_size)
908 {
909 ntfs_fek *fek;
910 u32 key_size, wanted_key_size, gcry_algo;
911 gcry_error_t err;
912
913 key_size = le32_to_cpup(fek_buf);
914 ntfs_log_debug("key_size 0x%x\n", key_size);
915 if (key_size + 16 > fek_size) {
916 ntfs_log_debug("Invalid FEK. It was probably decrypted with "
917 "the incorrect RSA key.");
918 errno = EINVAL;
919 return NULL;
920 }
921 fek = malloc(((((sizeof(*fek) + 7) & ~7) + key_size + 7) & ~7) +
922 sizeof(gcry_cipher_hd_t));
923 if (!fek) {
924 errno = ENOMEM;
925 return NULL;
926 }
927 fek->alg_id = *(le32*)(fek_buf + 8);
928 ntfs_log_debug("algorithm_id 0x%x\n", le32_to_cpu(fek->alg_id));
929 fek->key_data = (u8*)fek + ((sizeof(*fek) + 7) & ~7);
930 memcpy(fek->key_data, fek_buf + 16, key_size);
931 fek->des_gcry_cipher_hd_ptr = NULL;
932 *(gcry_cipher_hd_t***)(fek->key_data + ((key_size + 7) & ~7)) =
933 &fek->des_gcry_cipher_hd_ptr;
934 switch (fek->alg_id) {
935 case CALG_DESX:
936 if (!ntfs_crypto_ctx.desx_module) {
937 if (!ntfs_desx_key_expand_test() || !ntfs_des_test()) {
938 err = EINVAL;
939 goto out;
940 }
941 err = gcry_cipher_register(&ntfs_desx_cipher,
942 &ntfs_crypto_ctx.desx_alg_id,
943 &ntfs_crypto_ctx.desx_module);
944 if (err != GPG_ERR_NO_ERROR) {
945 ntfs_log_error("Failed to register desx "
946 "cipher: %s\n",
947 gcry_strerror(err));
948 err = EINVAL;
949 goto out;
950 }
951 }
952 wanted_key_size = 16;
953 gcry_algo = ntfs_crypto_ctx.desx_alg_id;
954 break;
955 case CALG_3DES:
956 wanted_key_size = 24;
957 gcry_algo = GCRY_CIPHER_3DES;
958 break;
959 case CALG_AES_256:
960 wanted_key_size = 32;
961 gcry_algo = GCRY_CIPHER_AES256;
962 break;
963 default:
964 wanted_key_size = 8;
965 gcry_algo = GCRY_CIPHER_DES;
966 if (fek->alg_id == CALG_DES)
967 ntfs_log_error("DES is not supported at present\n");
968 else
969 ntfs_log_error("Unknown crypto algorithm 0x%x\n",
970 le32_to_cpu(fek->alg_id));
971 ntfs_log_error(". Please email %s and say that you saw this "
972 "message. We will then try to implement "
973 "support for this algorithm.\n", NTFS_DEV_LIST);
974 err = EOPNOTSUPP;
975 goto out;
976 }
977 if (key_size != wanted_key_size) {
978 ntfs_log_error("%s key of %u bytes but needed size is %u "
979 "bytes, assuming corrupt or incorrect key. "
980 "Aborting.\n",
981 gcry_cipher_algo_name(gcry_algo),
982 (unsigned)key_size, (unsigned)wanted_key_size);
983 err = EIO;
984 goto out;
985 }
986 err = gcry_cipher_open(&fek->gcry_cipher_hd, gcry_algo,
987 GCRY_CIPHER_MODE_CBC, 0);
988 if (err != GPG_ERR_NO_ERROR) {
989 ntfs_log_error("gcry_cipher_open() failed: %s\n",
990 gcry_strerror(err));
991 err = EINVAL;
992 goto out;
993 }
994 err = gcry_cipher_setkey(fek->gcry_cipher_hd, fek->key_data, key_size);
995 if (err != GPG_ERR_NO_ERROR) {
996 ntfs_log_error("gcry_cipher_setkey() failed: %s\n",
997 gcry_strerror(err));
998 gcry_cipher_close(fek->gcry_cipher_hd);
999 err = EINVAL;
1000 goto out;
1001 }
1002 return fek;
1003 out:
1004 free(fek);
1005 errno = err;
1006 return NULL;
1007 }
1008
1009 /**
1010 * ntfs_fek_release
1011 */
1012 static void ntfs_fek_release(ntfs_fek *fek)
1013 {
1014 if (fek->des_gcry_cipher_hd_ptr)
1015 gcry_cipher_close(*fek->des_gcry_cipher_hd_ptr);
1016 gcry_cipher_close(fek->gcry_cipher_hd);
1017 free(fek);
1018 }
1019
1020 /**
1021 * ntfs_df_array_fek_get
1022 */
1023 static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
1024 ntfs_rsa_private_key_t *rsa_key)
1025 {
1026 EFS_DF_HEADER *df_header;
1027 EFS_DF_CREDENTIAL_HEADER *df_cred;
1028 EFS_DF_CERT_THUMBPRINT_HEADER *df_cert;
1029 u8 *fek_buf;
1030 ntfs_fek *fek;
1031 u32 df_count, fek_size;
1032 unsigned i, thumbprint_size = sizeof(rsa_key->thumbprint);
1033
1034 df_count = le32_to_cpu(df_array->df_count);
1035 if (!df_count)
1036 ntfs_log_error("There are no elements in the DF array.\n");
1037 df_header = (EFS_DF_HEADER*)(df_array + 1);
1038 for (i = 0; i < df_count; i++, df_header = (EFS_DF_HEADER*)(
1039 (u8*)df_header + le32_to_cpu(df_header->df_length))) {
1040 df_cred = (EFS_DF_CREDENTIAL_HEADER*)((u8*)df_header +
1041 le32_to_cpu(df_header->cred_header_offset));
1042 if (df_cred->type != NTFS_CRED_TYPE_CERT_THUMBPRINT) {
1043 ntfs_log_debug("Credential type is not certificate "
1044 "thumbprint, skipping DF entry.\n");
1045 continue;
1046 }
1047 df_cert = (EFS_DF_CERT_THUMBPRINT_HEADER*)((u8*)df_cred +
1048 le32_to_cpu(
1049 df_cred->cert_thumbprint_header_offset));
1050 if (le32_to_cpu(df_cert->thumbprint_size) != thumbprint_size) {
1051 ntfs_log_error("Thumbprint size %d is not valid "
1052 "(should be %d), skipping this DF "
1053 "entry.\n",
1054 le32_to_cpu(df_cert->thumbprint_size),
1055 thumbprint_size);
1056 continue;
1057 }
1058 if (memcmp((u8*)df_cert +
1059 le32_to_cpu(df_cert->thumbprint_offset),
1060 rsa_key->thumbprint, thumbprint_size)) {
1061 ntfs_log_debug("Thumbprints do not match, skipping "
1062 "this DF entry.\n");
1063 continue;
1064 }
1065 /*
1066 * The thumbprints match so this is probably the DF entry
1067 * matching the RSA key. Try to decrypt the FEK with it.
1068 */
1069 fek_size = le32_to_cpu(df_header->fek_size);
1070 fek_buf = (u8*)df_header + le32_to_cpu(df_header->fek_offset);
1071 /* Decrypt the FEK. Note: This is done in place. */
1072 fek_size = ntfs_raw_fek_decrypt(fek_buf, fek_size, rsa_key);
1073 if (fek_size) {
1074 /* Convert the FEK to our internal format. */
1075 fek = ntfs_fek_import_from_raw(fek_buf, fek_size);
1076 if (fek)
1077 return fek;
1078 ntfs_log_error("Failed to convert the decrypted file "
1079 "encryption key to internal format.\n");
1080 } else
1081 ntfs_log_error("Failed to decrypt the file "
1082 "encryption key.\n");
1083 }
1084 return NULL;
1085 }
1086
1087 /**
1088 * ntfs_inode_fek_get -
1089 */
1090 static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
1091 ntfs_rsa_private_key_t *rsa_key)
1092 {
1093 EFS_ATTR_HEADER *efs;
1094 EFS_DF_ARRAY_HEADER *df_array = NULL;
1095 ntfs_fek *fek = NULL;
1096
1097 /* Obtain the $EFS contents. */
1098 efs = ntfs_attr_readall(inode, AT_LOGGED_UTILITY_STREAM, NTFS_EFS, 4,
1099 NULL);
1100 if (!efs) {
1101 ntfs_log_perror("Failed to read $EFS attribute");
1102 return NULL;
1103 }
1104 /*
1105 * Depending on whether the key is a normal key or a data recovery key,
1106 * iterate through the DDF or DRF array, respectively.
1107 */
1108 if (rsa_key->df_type == DF_TYPE_DDF) {
1109 if (efs->offset_to_ddf_array)
1110 df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
1111 le32_to_cpu(efs->offset_to_ddf_array));
1112 else
1113 ntfs_log_error("There are no entries in the DDF "
1114 "array.\n");
1115 } else if (rsa_key->df_type == DF_TYPE_DRF) {
1116 if (efs->offset_to_drf_array)
1117 df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
1118 le32_to_cpu(efs->offset_to_drf_array));
1119 else
1120 ntfs_log_error("There are no entries in the DRF "
1121 "array.\n");
1122 } else
1123 ntfs_log_error("Invalid DF type.\n");
1124 if (df_array)
1125 fek = ntfs_df_array_fek_get(df_array, rsa_key);
1126 free(efs);
1127 return fek;
1128 }
1129
1130 /**
1131 * ntfs_fek_decrypt_sector
1132 */
1133 static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
1134 {
1135 gcry_error_t err;
1136
1137 err = gcry_cipher_reset(fek->gcry_cipher_hd);
1138 if (err != GPG_ERR_NO_ERROR) {
1139 ntfs_log_error("Failed to reset cipher: %s\n",
1140 gcry_strerror(err));
1141 return -1;
1142 }
1143 /*
1144 * Note: You may wonder why we are not calling gcry_cipher_setiv() here
1145 * instead of doing it by hand after the decryption. The answer is
1146 * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give
1147 * it a length of 16 for AES256 so it does not like it.
1148 */
1149 err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0);
1150 if (err != GPG_ERR_NO_ERROR) {
1151 ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err));
1152 return -1;
1153 }
1154 /* Apply the IV. */
1155 if (fek->alg_id == CALG_AES_256) {
1156 ((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
1157 ((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
1158 } else {
1159 /* All other algorithms (Des, 3Des, DesX) use the same IV. */
1160 ((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
1161 }
1162 return 512;
1163 }
1164
1165 /**
1166 * ntfs_crypto_deinit - perform library-wide crypto deinitialization
1167 */
1168 static void ntfs_crypto_deinit(void)
1169 {
1170 int i;
1171
1172 if (!ntfs_crypto_ctx.initialized)
1173 return;
1174
1175 for (i = 0; i < ntfs_crypto_ctx.nr_rsa_keys; i++)
1176 ntfs_rsa_private_key_release(ntfs_crypto_ctx.rsa_key[i]);
1177 free(ntfs_crypto_ctx.rsa_key);
1178 ntfs_crypto_ctx.rsa_key = NULL;
1179 ntfs_crypto_ctx.nr_rsa_keys = 0;
1180 gnutls_global_deinit();
1181 if (ntfs_crypto_ctx.desx_module) {
1182 gcry_cipher_unregister(ntfs_crypto_ctx.desx_module);
1183 ntfs_crypto_ctx.desx_module = NULL;
1184 ntfs_crypto_ctx.desx_alg_id = -1;
1185 }
1186 ntfs_crypto_ctx.initialized = 0;
1187 }
1188
1189
1190 static void ntfs_crypto_parse_config(struct config_t *cfg)
1191 {
1192 ntfs_crypto_ctx_t *ctx = &ntfs_crypto_ctx;
1193 config_setting_t *cfg_keys, *cfg_key;
1194 const char *pfx_file, *pfx_pwd;
1195 ntfs_rsa_private_key_t *key;
1196 u8 *pfx_buf;
1197 unsigned pfx_size;
1198 int i;
1199
1200 /* Search for crypto.keys list. */
1201 cfg_keys = config_lookup(cfg, "crypto.keys");
1202 if (!cfg_keys) {
1203 ntfs_log_error("Unable to find crypto.keys in config file.\n");
1204 return;
1205 }
1206 /* Iterate trough list of records about keys. */
1207 for (i = 0; (cfg_key = config_setting_get_elem(cfg_keys, i)); i++) {
1208 /* Get path and password to key. */
1209 pfx_file = config_setting_get_string_elem(cfg_key, 0);
1210 pfx_pwd = config_setting_get_string_elem(cfg_key, 1);
1211 if (!pfx_file) {
1212 ntfs_log_error("Entry number %d in section crypto.keys "
1213 "of configuration file formed "
1214 "incorrectly.\n", i + 1);
1215 continue;
1216 }
1217 if (!pfx_pwd)
1218 pfx_pwd = "";
1219 /* Load the PKCS#12 file containing the user's private key. */
1220 if (ntfs_pkcs12_load_pfxfile(pfx_file, &pfx_buf, &pfx_size)) {
1221 ntfs_log_error("Failed to load key file %s.\n",
1222 pfx_file);
1223 continue;
1224 }
1225 /*
1226 * Check whether we need to allocate memory for new key pointer.
1227 * If yes, allocate memory for it and for 3 more pointers.
1228 */
1229 if (!(ctx->nr_rsa_keys % 4)) {
1230 ntfs_rsa_private_key_t **new;
1231
1232 new = realloc(ctx->rsa_key,
1233 sizeof(ntfs_rsa_private_key_t *) *
1234 (ctx->nr_rsa_keys + 4));
1235 if (!new) {
1236 ntfs_log_perror("Unable to store all keys");
1237 break;
1238 }
1239 ctx->rsa_key = new;
1240 }
1241 /* Obtain the user's private RSA key from the key file. */
1242 key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, pfx_pwd);
1243 if (key)
1244 ctx->rsa_key[ctx->nr_rsa_keys++] = key;
1245 else
1246 ntfs_log_error("Failed to obtain RSA key from %s\n",
1247 pfx_file);
1248 /* No longer need the pfx file contents. */
1249 free(pfx_buf);
1250 }
1251 }
1252
1253
1254 static void ntfs_crypto_read_configs(void)
1255 {
1256 struct config_t cfg;
1257 char *home;
1258 int fd = -1;
1259
1260 config_init(&cfg);
1261 /* Load system configuration file. */
1262 if (config_read_file(&cfg, NTFS_CONFIG_PATH_SYSTEM))
1263 ntfs_crypto_parse_config(&cfg);
1264 else
1265 if (config_error_line(&cfg)) /* Do not cry if file absent. */
1266 ntfs_log_error("Failed to read system configuration "
1267 "file: %s (line %d).\n",
1268 config_error_text(&cfg),
1269 config_error_line(&cfg));
1270 /* Load user configuration file. */
1271 fd = open(".", O_RDONLY); /* Save current working directory. */
1272 if (fd == -1) {
1273 ntfs_log_error("Failed to open working directory.\n");
1274 goto out;
1275 }
1276 home = getenv("HOME");
1277 if (!home) {
1278 ntfs_log_error("Environment variable HOME is not set.\n");
1279 goto out;
1280 }
1281 if (chdir(home) == -1) {
1282 ntfs_log_perror("chdir() to home directory failed");
1283 goto out;
1284 }
1285 if (config_read_file(&cfg, NTFS_CONFIG_PATH_USER))
1286 ntfs_crypto_parse_config(&cfg);
1287 else
1288 if (config_error_line(&cfg)) /* Do not cry if file absent. */
1289 ntfs_log_error("Failed to read user configuration "
1290 "file: %s (line %d).\n",
1291 config_error_text(&cfg),
1292 config_error_line(&cfg));
1293 if (fchdir(fd) == -1)
1294 ntfs_log_error("Failed to restore original working "
1295 "directory.\n");
1296 out:
1297 if (fd != -1)
1298 close(fd);
1299 config_destroy(&cfg);
1300 }
1301
1302 /**
1303 * ntfs_crypto_init - perform library-wide crypto initializations
1304 *
1305 * This function is called during first call of ntfs_crypto_attr_open and
1306 * performs gcrypt and GNU TLS initializations, then read list of PFX files
1307 * from configuration files and load RSA keys from them.
1308 */
1309 static int ntfs_crypto_init(void)
1310 {
1311 int err;
1312
1313 if (ntfs_crypto_ctx.initialized)
1314 return 0;
1315
1316 /* Initialize gcrypt library. Note: Must come before GNU TLS init. */
1317 if (gcry_control(GCRYCTL_DISABLE_SECMEM, 0) != GPG_ERR_NO_ERROR) {
1318 ntfs_log_error("Failed to initialize the gcrypt library.\n");
1319 return -1;
1320 }
1321 /* Initialize GNU TLS library. Note: Must come after libgcrypt init. */
1322 err = gnutls_global_init();
1323 if (err < 0) {
1324 ntfs_log_error("Failed to initialize GNU TLS library: %s\n",
1325 gnutls_strerror(err));
1326 return -1;
1327 }
1328 /* Read crypto related sections of libntfs configuration files. */
1329 ntfs_crypto_read_configs();
1330
1331 ntfs_crypto_ctx.initialized = 1;
1332 atexit(ntfs_crypto_deinit);
1333 return 0;
1334 }
1335
1336
1337 /**
1338 * ntfs_crypto_attr_open - perform crypto related initialization for attribute
1339 * @na: ntfs attribute to perform initialization for
1340 *
1341 * This function is called from ntfs_attr_open for encrypted attributes and
1342 * tries to decrypt FEK enumerating all user submitted RSA keys. If we
1343 * successfully obtained FEK, then @na->crypto is allocated and FEK stored
1344 * inside. In the other case @na->crypto is set to NULL.
1345 *
1346 * Return 0 on success and -1 on error with errno set to the error code.
1347 */
1348 int ntfs_crypto_attr_open(ntfs_attr *na)
1349 {
1350 ntfs_fek *fek;
1351 int i;
1352
1353 na->crypto = NULL;
1354 if (!na || !NAttrEncrypted(na)) {
1355 errno = EINVAL;
1356 return -1;
1357 }
1358 if (ntfs_crypto_init()) {
1359 errno = EACCES;
1360 return -1;
1361 }
1362
1363 for (i = 0; i < ntfs_crypto_ctx.nr_rsa_keys; i++) {
1364 fek = ntfs_inode_fek_get(na->ni, ntfs_crypto_ctx.rsa_key[i]);
1365 if (fek) {
1366 na->crypto = ntfs_malloc(sizeof(ntfs_crypto_attr));
1367 if (!na->crypto)
1368 return -1;
1369 na->crypto->fek = fek;
1370 return 0;
1371 }
1372 }
1373
1374 errno = EACCES;
1375 return -1;
1376 }
1377
1378
1379 /**
1380 * ntfs_crypto_attr_close - perform crypto related deinit for attribute
1381 * @na: ntfs attribute to perform deinitialization for
1382 *
1383 * This function is called from ntfs_attr_close for encrypted attributes and
1384 * frees memory that were allocated for it handling.
1385 */
1386 void ntfs_crypto_attr_close(ntfs_attr *na)
1387 {
1388 if (!na || !NAttrEncrypted(na))
1389 return;
1390
1391 if (na->crypto) {
1392 ntfs_fek_release(na->crypto->fek);
1393 free(na->crypto);
1394 }
1395 }
1396
1397
1398 /**
1399 * ntfs_crypto_attr_pread - read from an encrypted attribute
1400 * @na: ntfs attribute to read from
1401 * @pos: byte position in the attribute to begin reading from
1402 * @count: number of bytes to read
1403 * @b: output data buffer
1404 *
1405 * This function is called from ntfs_attr_pread for encrypted attributes and
1406 * should behave as described in ntfs_attr_pread description.
1407 */
1408 s64 ntfs_crypto_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b)
1409 {
1410 unsigned char *buffer;
1411 s64 bytes_read, offset, total, length;
1412 int i;
1413
1414 if (!na || pos < 0 || count < 0 || !b || !NAttrEncrypted(na)) {
1415 errno = EINVAL;
1416 return -1;
1417 }
1418 if (!count)
1419 return 0;
1420
1421 if (!na->crypto) {
1422 errno = EACCES;
1423 return -1;
1424 }
1425
1426 buffer = malloc(NTFS_EFS_SECTOR_SIZE);
1427 if (!buffer)
1428 return -1;
1429
1430 ntfs_attr_map_runlist_range(na, pos >> na->ni->vol->cluster_size_bits,
1431 (pos + count - 1) >> na->ni->vol->cluster_size_bits);
1432
1433 total = 0;
1434 offset = ROUND_DOWN(pos, 9);
1435 while (total < count && offset < na->data_size) {
1436 /* Calculate number of bytes we actually want. */
1437 length = NTFS_EFS_SECTOR_SIZE;
1438 if (offset + length > pos + count)
1439 length = pos + count - offset;
1440 if (offset + length > na->data_size)
1441 length = na->data_size - offset;
1442
1443 if (length < 0) {
1444 total = -1;
1445 errno = EIO;
1446 ntfs_log_error("LIBRARY BUG!!! Please report that you "
1447 "saw this message to %s. Thanks!",
1448 NTFS_DEV_LIST);
1449 break;
1450 }
1451
1452 /* Just write zeros if @offset fully beyond initialized size. */
1453 if (offset >= na->initialized_size) {
1454 memset(b + total, 0, length);
1455 total += length;
1456 continue;
1457 }
1458
1459 bytes_read = ntfs_rl_pread(na->ni->vol, na->rl, offset,
1460 NTFS_EFS_SECTOR_SIZE, buffer);
1461 if (!bytes_read)
1462 break;
1463 if (bytes_read != NTFS_EFS_SECTOR_SIZE) {
1464 ntfs_log_perror("%s(): ntfs_rl_pread returned %lld "
1465 "bytes", "ntfs_crypto_attr_pread", bytes_read);
1466 break;
1467 }
1468 if ((i = ntfs_fek_decrypt_sector(na->crypto->fek, buffer,
1469 offset)) < bytes_read) {
1470 ntfs_log_error("%s(): Couldn't decrypt all data "
1471 "(%u/%lld/%lld/%lld)!", "ntfs_crypto_attr_pread",
1472 i, (long long)bytes_read,
1473 (long long)offset, (long long)total);
1474 break;
1475 }
1476
1477 /* Handle partially in initialized size situation. */
1478 if (offset + length > na->initialized_size)
1479 memset(buffer + (na->initialized_size - offset), 0,
1480 offset + length - na->initialized_size);
1481
1482 if (offset >= pos)
1483 memcpy(b + total, buffer, length);
1484 else {
1485 length -= (pos - offset);
1486 memcpy(b + total, buffer + (pos - offset), length);
1487 }
1488 total += length;
1489 offset += bytes_read;
1490 }
1491
1492 free(buffer);
1493 return total;
1494 }
1495
1496 #else /* !ENABLE_CRYPTO */
1497
1498 /* Stubs for crypto-disabled version of libntfs. */
1499
1500 int ntfs_crypto_attr_open(ntfs_attr *na)
1501 {
1502 na->crypto = NULL;
1503 errno = EACCES;
1504 return -1;
1505 }
1506
1507 void ntfs_crypto_attr_close(ntfs_attr *na)
1508 {
1509 }
1510
1511 s64 ntfs_crypto_attr_pread(ntfs_attr *na, const s64 pos, s64 count,
1512 void *b)
1513 {
1514 errno = EACCES;
1515 return -1;
1516 }
1517
1518 #endif /* !ENABLE_CRYPTO */
1519