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