"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/BootEncryption.cpp" (10 Oct 2018, 168778 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "BootEncryption.cpp" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "Tcdefs.h"
   14 #include "Platform/Finally.h"
   15 #include "Platform/ForEach.h"
   16 #include <devguid.h>
   17 #include <io.h>
   18 #include <shlobj.h>
   19 #include <atlbase.h>
   20 #include "BootEncryption.h"
   21 #include "Boot/Windows/BootCommon.h"
   22 #include "Common/Resource.h"
   23 #include "Crc.h"
   24 #include "Crypto.h"
   25 #include "Dlgcode.h"
   26 #include "Endian.h"
   27 #include "Language.h"
   28 #include "Random.h"
   29 #include "Registry.h"
   30 #include "Volumes.h"
   31 #include "Xml.h"
   32 #include "zip.h"
   33 
   34 #ifdef VOLFORMAT
   35 #include "Format/FormatCom.h"
   36 #elif defined (TCMOUNT)
   37 #include "Mount/MainCom.h"
   38 #endif
   39 
   40 #include <algorithm>
   41 #include <Strsafe.h>
   42 
   43 static unsigned char g_pbEFIDcsPK[1385] = {
   44     0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xA7, 0x4A, 0x87, 0xB5, 0xAB, 0x15,
   45     0x5C, 0x2B, 0xF0, 0x72, 0x69, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   46     0x4D, 0x05, 0x00, 0x00, 0x85, 0xBB, 0x45, 0x82, 0xB6, 0xD2, 0xAD, 0x41,
   47     0x84, 0x8D, 0xDD, 0x3A, 0x83, 0x0F, 0x82, 0x78, 0x30, 0x82, 0x05, 0x39,
   48     0x30, 0x82, 0x03, 0x21, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x32,
   49     0xDC, 0x46, 0x30, 0x87, 0xE5, 0x4F, 0xB1, 0x43, 0x0F, 0x58, 0x9E, 0xC0,
   50     0xDA, 0x58, 0xF8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
   51     0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F,
   52     0x06, 0x03, 0x55, 0x04, 0x03, 0x1E, 0x18, 0x00, 0x44, 0x00, 0x43, 0x00,
   53     0x53, 0x00, 0x5F, 0x00, 0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00,
   54     0x66, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31,
   55     0x36, 0x30, 0x38, 0x30, 0x39, 0x30, 0x38, 0x33, 0x38, 0x31, 0x31, 0x5A,
   56     0x17, 0x0D, 0x33, 0x31, 0x30, 0x38, 0x30, 0x39, 0x30, 0x38, 0x33, 0x38,
   57     0x31, 0x30, 0x5A, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55,
   58     0x04, 0x03, 0x1E, 0x18, 0x00, 0x44, 0x00, 0x43, 0x00, 0x53, 0x00, 0x5F,
   59     0x00, 0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x66, 0x00, 0x6F,
   60     0x00, 0x72, 0x00, 0x6D, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09,
   61     0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
   62     0x82, 0x02, 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01,
   63     0x00, 0xAF, 0x5B, 0x97, 0x06, 0x70, 0x4F, 0x3B, 0x2E, 0x50, 0x6A, 0xD1,
   64     0x47, 0xCB, 0x70, 0x20, 0xF4, 0x77, 0x79, 0x06, 0xCA, 0xA9, 0xA2, 0x13,
   65     0x75, 0xAD, 0x07, 0x66, 0x94, 0xC2, 0xBB, 0xCA, 0x7E, 0xFC, 0x6C, 0x19,
   66     0x16, 0x5D, 0x60, 0x77, 0x6E, 0xCB, 0xF3, 0x8A, 0xC2, 0xF6, 0x53, 0xC7,
   67     0xC2, 0xB1, 0x87, 0x5F, 0x8E, 0xFA, 0x20, 0xDF, 0xBA, 0x00, 0xCE, 0xBA,
   68     0xA7, 0xC8, 0x65, 0x7E, 0xFC, 0xA8, 0xF8, 0x50, 0x9E, 0xD7, 0x7D, 0x8E,
   69     0x4F, 0xB1, 0x1B, 0x60, 0xC0, 0xD2, 0xBC, 0x4A, 0xB4, 0x46, 0xA5, 0x0E,
   70     0x90, 0x38, 0xA5, 0x7B, 0x58, 0xEE, 0x16, 0xD9, 0xBA, 0x73, 0xAD, 0x69,
   71     0x2A, 0xA4, 0xB4, 0x51, 0x0C, 0x21, 0x8C, 0x3D, 0x0E, 0x40, 0x44, 0x20,
   72     0x2E, 0xE2, 0xEF, 0x16, 0x25, 0xE8, 0x1C, 0xE8, 0xD2, 0x76, 0x66, 0x8E,
   73     0xA1, 0xB8, 0x29, 0x28, 0x23, 0xA2, 0x9F, 0xCA, 0xAB, 0x0D, 0x81, 0x4A,
   74     0xE0, 0xF9, 0x87, 0x7B, 0xD6, 0xDA, 0x2E, 0x10, 0x21, 0xBD, 0x69, 0x9C,
   75     0x86, 0x45, 0xD2, 0xE8, 0xCD, 0xA1, 0xF6, 0xC2, 0x09, 0x93, 0x68, 0x06,
   76     0xA0, 0x5D, 0xB7, 0x2C, 0xD7, 0x83, 0x0B, 0xCC, 0xFE, 0x91, 0x90, 0x1E,
   77     0x85, 0x96, 0x72, 0xBC, 0x3E, 0x9C, 0xD4, 0x1C, 0xDF, 0xC4, 0x85, 0xB3,
   78     0xD7, 0x00, 0x43, 0xDD, 0xA8, 0x7C, 0xD1, 0xDE, 0x89, 0xDB, 0x2A, 0x70,
   79     0x27, 0x6F, 0x46, 0xF9, 0x3A, 0x9E, 0x55, 0x10, 0x5A, 0x82, 0x42, 0x72,
   80     0x42, 0xEA, 0x83, 0x0F, 0x39, 0x3A, 0x50, 0x67, 0xFE, 0x4F, 0x9D, 0x91,
   81     0x50, 0x93, 0xB3, 0xC6, 0x12, 0x60, 0xAE, 0x3A, 0x5A, 0xB7, 0xB7, 0x9C,
   82     0x83, 0xA0, 0xD2, 0xFF, 0xFF, 0x23, 0xC3, 0x95, 0x66, 0x79, 0x20, 0xA0,
   83     0x09, 0x02, 0x74, 0x15, 0x34, 0x2A, 0x0A, 0x6E, 0x80, 0x36, 0x13, 0xC7,
   84     0x9B, 0x77, 0x81, 0x35, 0x45, 0xDD, 0xEC, 0x11, 0xC3, 0x43, 0xA6, 0x48,
   85     0xF8, 0xDB, 0xC0, 0x3C, 0x12, 0x86, 0x37, 0x68, 0xF4, 0xEA, 0x70, 0x41,
   86     0x66, 0x6D, 0x56, 0x7C, 0xFC, 0xE8, 0x61, 0xD7, 0x82, 0x02, 0xC6, 0xFD,
   87     0xA5, 0x74, 0xCE, 0xA6, 0x39, 0xFB, 0xD2, 0x21, 0x61, 0x15, 0x6B, 0x6E,
   88     0x0B, 0xD6, 0x65, 0xF5, 0x8C, 0x5A, 0x52, 0x5E, 0x16, 0x96, 0x02, 0x09,
   89     0x81, 0x28, 0x32, 0xBF, 0x2C, 0x1E, 0x0F, 0xAD, 0x1E, 0xE5, 0xAD, 0x3B,
   90     0x19, 0x24, 0xED, 0xC1, 0xA7, 0x60, 0xC9, 0x2D, 0xE4, 0x15, 0xA7, 0xAF,
   91     0x91, 0x35, 0x07, 0x5A, 0x31, 0x39, 0xB1, 0xA5, 0x3C, 0xE3, 0x59, 0x9A,
   92     0x85, 0xC8, 0x6F, 0x83, 0x6F, 0xFF, 0x3C, 0x81, 0xC1, 0x8F, 0xF6, 0x2E,
   93     0x3C, 0x1B, 0xF5, 0x9A, 0x21, 0x5D, 0xAD, 0x3A, 0x9B, 0x7F, 0x18, 0x4F,
   94     0x62, 0x09, 0xEA, 0x2F, 0x5D, 0x15, 0xFD, 0x9D, 0x73, 0x78, 0x95, 0x76,
   95     0x47, 0x15, 0x1C, 0x9A, 0x3F, 0x19, 0xB7, 0xCE, 0x03, 0x46, 0x6C, 0x61,
   96     0xCF, 0xC4, 0xBD, 0x0D, 0x1A, 0x9F, 0xB4, 0xAA, 0x03, 0x84, 0x8D, 0x15,
   97     0x3E, 0x8F, 0xBA, 0x28, 0x94, 0x09, 0x35, 0x28, 0xE5, 0x15, 0xBC, 0xAF,
   98     0x33, 0xBA, 0x67, 0xF2, 0x06, 0x79, 0xEE, 0x50, 0x0F, 0x14, 0x98, 0xFC,
   99     0x95, 0xEC, 0x65, 0x40, 0x88, 0xA8, 0x1A, 0x0C, 0x10, 0x74, 0x79, 0x42,
  100     0x3B, 0xCD, 0xE1, 0xD1, 0xAD, 0x7E, 0x29, 0x41, 0xC4, 0x39, 0x75, 0xC5,
  101     0xCB, 0x0F, 0xB1, 0x6F, 0x30, 0xD3, 0xAE, 0x53, 0x59, 0xD6, 0x86, 0x34,
  102     0x31, 0x8B, 0x96, 0x82, 0xDF, 0xA4, 0x01, 0x32, 0xB4, 0x29, 0xDC, 0x9C,
  103     0x28, 0x53, 0x72, 0xAE, 0x96, 0x37, 0xE3, 0x65, 0x59, 0x91, 0x84, 0x95,
  104     0xB3, 0x2D, 0x3F, 0x84, 0x12, 0xD2, 0x52, 0x85, 0x8D, 0x85, 0xD5, 0x2E,
  105     0x2A, 0x3E, 0xEB, 0x0C, 0x11, 0xA4, 0x4F, 0xED, 0x29, 0x02, 0x03, 0x01,
  106     0x00, 0x01, 0xA3, 0x69, 0x30, 0x67, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D,
  107     0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30,
  108     0x54, 0x06, 0x03, 0x55, 0x1D, 0x01, 0x04, 0x4D, 0x30, 0x4B, 0x80, 0x10,
  109     0x8F, 0x11, 0x13, 0x21, 0xAA, 0xC0, 0xFA, 0xB1, 0x63, 0xD5, 0xE6, 0x00,
  110     0x9B, 0x78, 0x67, 0x40, 0xA1, 0x25, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F,
  111     0x06, 0x03, 0x55, 0x04, 0x03, 0x1E, 0x18, 0x00, 0x44, 0x00, 0x43, 0x00,
  112     0x53, 0x00, 0x5F, 0x00, 0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00,
  113     0x66, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x82, 0x10, 0x32, 0xDC, 0x46,
  114     0x30, 0x87, 0xE5, 0x4F, 0xB1, 0x43, 0x0F, 0x58, 0x9E, 0xC0, 0xDA, 0x58,
  115     0xF8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
  116     0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x7D, 0x03, 0x2A,
  117     0x49, 0x7E, 0x0C, 0x43, 0x4E, 0xAE, 0x45, 0xDD, 0xE2, 0x62, 0xB2, 0x31,
  118     0x55, 0xEB, 0x6C, 0xF8, 0x96, 0xFC, 0x5A, 0x5F, 0xA7, 0xD2, 0x26, 0xA5,
  119     0x10, 0x15, 0x85, 0x1D, 0xDE, 0xCD, 0x97, 0xFB, 0x6D, 0x19, 0xED, 0x03,
  120     0x93, 0x83, 0x94, 0x04, 0x1B, 0xE6, 0x00, 0xBA, 0x41, 0xCF, 0xAB, 0xB7,
  121     0x46, 0x17, 0x3F, 0x8E, 0x3B, 0x2D, 0xC4, 0x54, 0x67, 0x31, 0x11, 0x0D,
  122     0xA4, 0x35, 0x1E, 0xC4, 0x09, 0xC2, 0xCB, 0xFD, 0x19, 0x1B, 0x5B, 0x2A,
  123     0x19, 0x6A, 0xB9, 0x72, 0x3E, 0x27, 0x8A, 0x0A, 0xBD, 0xB4, 0x68, 0x5D,
  124     0xA9, 0x72, 0xC7, 0x0E, 0x28, 0x06, 0xC9, 0x4C, 0xE1, 0x56, 0xEB, 0x15,
  125     0x16, 0xC1, 0xD2, 0x86, 0x63, 0x57, 0xB1, 0xAA, 0x01, 0xF9, 0x26, 0xBC,
  126     0xA7, 0xED, 0x0D, 0x02, 0x80, 0xA7, 0x77, 0x57, 0xE9, 0xA5, 0x3B, 0x72,
  127     0xC2, 0xAA, 0x6D, 0x7B, 0xA8, 0x40, 0xA3, 0x34, 0x7B, 0x73, 0x40, 0x90,
  128     0xFC, 0x43, 0x00, 0x29, 0x97, 0x7C, 0x41, 0xB2, 0xCA, 0x31, 0xA7, 0x86,
  129     0x08, 0xDF, 0x67, 0xCA, 0x1B, 0xEC, 0x0C, 0x53, 0xD4, 0x0B, 0x4A, 0x22,
  130     0x40, 0x44, 0xA8, 0xE9, 0x9D, 0x49, 0x01, 0xC6, 0x77, 0x15, 0x6E, 0x8A,
  131     0x1F, 0xFF, 0x42, 0xF3, 0xDE, 0xF7, 0x93, 0xFA, 0x81, 0x8F, 0x98, 0x6B,
  132     0x75, 0x27, 0xA8, 0xBE, 0xE9, 0x2C, 0x70, 0x0F, 0xE6, 0xA5, 0xDD, 0x5D,
  133     0xA5, 0x33, 0x54, 0xEE, 0xFE, 0x6F, 0x91, 0xE8, 0xB4, 0x1A, 0x55, 0x77,
  134     0xA1, 0x98, 0x56, 0x48, 0x9C, 0xF2, 0xA3, 0x96, 0xD7, 0xB2, 0x86, 0x15,
  135     0xA9, 0xCA, 0xBD, 0x04, 0x1B, 0x14, 0x11, 0xBE, 0x5D, 0xC5, 0x2C, 0x5E,
  136     0x5B, 0x57, 0x87, 0x9B, 0xCA, 0xE8, 0xA1, 0x7F, 0x6D, 0xED, 0x79, 0x2D,
  137     0x89, 0x3E, 0x70, 0x3C, 0x9E, 0x5C, 0x0F, 0x26, 0xCD, 0x2D, 0xE3, 0x47,
  138     0x6E, 0x89, 0x05, 0x5C, 0x73, 0x03, 0x87, 0x8C, 0x44, 0xE5, 0xC5, 0x6C,
  139     0x09, 0x8B, 0x93, 0xBC, 0x1E, 0x0F, 0x56, 0x80, 0x45, 0xDD, 0xDA, 0x96,
  140     0x01, 0x48, 0x7C, 0xD2, 0xC0, 0x86, 0xD1, 0x8D, 0x7C, 0xBF, 0x48, 0x74,
  141     0x97, 0x8F, 0x4A, 0xBE, 0xC2, 0x71, 0x29, 0x91, 0xCF, 0x6A, 0x39, 0xBE,
  142     0xD8, 0x50, 0x75, 0xCF, 0x24, 0x8D, 0x5A, 0x12, 0x16, 0xA8, 0x5C, 0x6C,
  143     0x88, 0x3E, 0x9F, 0x38, 0xDE, 0x04, 0x7F, 0x89, 0xE7, 0x5A, 0x36, 0x6D,
  144     0xAB, 0xF3, 0xC8, 0x32, 0x64, 0x91, 0x95, 0x12, 0x69, 0x7E, 0x71, 0x09,
  145     0xD1, 0xDA, 0xC9, 0x5E, 0xFC, 0xF4, 0x6C, 0x38, 0x71, 0x21, 0x62, 0x50,
  146     0xC8, 0x14, 0x47, 0x25, 0x94, 0x67, 0xD2, 0x20, 0x45, 0xC3, 0x50, 0x43,
  147     0x81, 0x1D, 0x56, 0xAC, 0x2A, 0x02, 0x6E, 0x6D, 0x06, 0xCA, 0x42, 0xC9,
  148     0x65, 0x4C, 0xF7, 0x94, 0xF7, 0x67, 0x9C, 0x24, 0x98, 0x20, 0x55, 0x6A,
  149     0x0D, 0x85, 0x47, 0x2F, 0x3D, 0xFC, 0xA1, 0x28, 0xFE, 0xDF, 0x6F, 0xB1,
  150     0x31, 0x62, 0x22, 0x8F, 0x74, 0x3E, 0x1C, 0xE0, 0x02, 0xEF, 0xF9, 0x6B,
  151     0x10, 0x32, 0xC5, 0xF5, 0x08, 0x51, 0xC7, 0x23, 0xE7, 0x53, 0xEA, 0x89,
  152     0x3A, 0xB2, 0xD9, 0x8A, 0x5E, 0xB0, 0x35, 0x06, 0x0A, 0x4F, 0xEE, 0x48,
  153     0x79, 0x7A, 0xEE, 0xEE, 0xAF, 0x9D, 0xF6, 0x59, 0xD6, 0x25, 0x86, 0xAC,
  154     0x05, 0x9D, 0xA7, 0x61, 0x31, 0xE3, 0xC1, 0xD0, 0x78, 0x9F, 0x83, 0x1F,
  155     0x7C, 0x17, 0x50, 0x05, 0xAD, 0x40, 0x1A, 0x0C, 0x19, 0x9E, 0xE1, 0x5D,
  156     0x83, 0xE2, 0xAB, 0x83, 0x17, 0x84, 0x13, 0x76, 0x4F, 0x29, 0xBC, 0xA6,
  157     0x3F, 0xAE, 0x0D, 0xF9, 0x79, 0x11, 0xF8, 0x04, 0x79, 0x94, 0x88, 0x3F,
  158     0x0D, 0x6C, 0x1F, 0x07, 0x61, 0xF6, 0x51, 0xB2, 0xBC, 0xB8, 0xD3, 0x87,
  159     0xA7, 0x15, 0x12, 0x60, 0x7B
  160 };
  161 
  162 static unsigned char g_pbEFIDcsKEK[1137] = {
  163     0xA1, 0x59, 0xC0, 0xA5, 0xE4, 0x94, 0xA7, 0x4A, 0x87, 0xB5, 0xAB, 0x15,
  164     0x5C, 0x2B, 0xF0, 0x72, 0x71, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  165     0x55, 0x04, 0x00, 0x00, 0x85, 0xBB, 0x45, 0x82, 0xB6, 0xD2, 0xAD, 0x41,
  166     0x84, 0x8D, 0xDD, 0x3A, 0x83, 0x0F, 0x82, 0x78, 0x30, 0x82, 0x04, 0x41,
  167     0x30, 0x82, 0x02, 0x29, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x8D,
  168     0x64, 0x69, 0xE0, 0x25, 0x64, 0x87, 0x89, 0x4A, 0x61, 0x9F, 0xC9, 0xE4,
  169     0x3B, 0xE7, 0x83, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
  170     0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F,
  171     0x06, 0x03, 0x55, 0x04, 0x03, 0x1E, 0x18, 0x00, 0x44, 0x00, 0x43, 0x00,
  172     0x53, 0x00, 0x5F, 0x00, 0x70, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00,
  173     0x66, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31,
  174     0x36, 0x30, 0x38, 0x30, 0x39, 0x30, 0x38, 0x33, 0x38, 0x31, 0x32, 0x5A,
  175     0x17, 0x0D, 0x33, 0x31, 0x30, 0x38, 0x30, 0x39, 0x30, 0x38, 0x33, 0x38,
  176     0x31, 0x31, 0x5A, 0x30, 0x2B, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55,
  177     0x04, 0x03, 0x1E, 0x20, 0x00, 0x44, 0x00, 0x43, 0x00, 0x53, 0x00, 0x5F,
  178     0x00, 0x6B, 0x00, 0x65, 0x00, 0x79, 0x00, 0x5F, 0x00, 0x65, 0x00, 0x78,
  179     0x00, 0x63, 0x00, 0x68, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65,
  180     0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
  181     0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00,
  182     0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC7, 0x63, 0x7F,
  183     0xAF, 0x5D, 0x58, 0x3F, 0xE2, 0x82, 0x9B, 0xD9, 0x09, 0x88, 0x09, 0x0B,
  184     0x3D, 0x7C, 0x78, 0xC9, 0x6B, 0x8F, 0xDD, 0x2D, 0xE4, 0xD7, 0x4F, 0x5C,
  185     0x16, 0x61, 0x08, 0x7C, 0x69, 0x42, 0x63, 0xB7, 0x4F, 0xEC, 0xCD, 0xEE,
  186     0xA0, 0xFC, 0xF6, 0xA8, 0x80, 0x9A, 0x93, 0x8B, 0x2D, 0x67, 0xF3, 0x3F,
  187     0x93, 0xB7, 0xA5, 0x33, 0x2B, 0x15, 0xF7, 0x07, 0xC1, 0xCF, 0x47, 0xE5,
  188     0xB1, 0x9D, 0x6D, 0xF5, 0xBB, 0xC2, 0x74, 0x62, 0x10, 0x91, 0xE7, 0xCE,
  189     0xA3, 0x8F, 0x1B, 0xDA, 0x04, 0xF6, 0x0A, 0x56, 0x32, 0x6B, 0xBC, 0x61,
  190     0x24, 0x5C, 0x16, 0x8F, 0x60, 0xD8, 0x43, 0xEA, 0xF0, 0x2E, 0x0B, 0x71,
  191     0x07, 0x60, 0xC6, 0x41, 0xB5, 0x1B, 0xEE, 0x20, 0x3E, 0xE3, 0xAF, 0xF0,
  192     0xEB, 0x15, 0xE3, 0x0F, 0x49, 0x93, 0x0E, 0x65, 0x0C, 0x44, 0x26, 0x04,
  193     0xF8, 0x0D, 0x14, 0x43, 0x1E, 0xC2, 0x13, 0xC8, 0x79, 0x4D, 0x9A, 0xD1,
  194     0x99, 0xA5, 0xC3, 0x70, 0xEA, 0x98, 0xA8, 0x55, 0x9E, 0x0F, 0x8E, 0x41,
  195     0x1B, 0xFB, 0x32, 0x2D, 0x3D, 0x89, 0x16, 0x8B, 0x81, 0xDA, 0xB0, 0x8D,
  196     0xD5, 0xC4, 0x3B, 0xC5, 0xD1, 0x12, 0x0B, 0x7A, 0x40, 0xFE, 0xDA, 0x53,
  197     0xB9, 0xE1, 0xAE, 0xAD, 0x00, 0x00, 0xA2, 0x4A, 0x5E, 0x00, 0x31, 0x8D,
  198     0x4A, 0xA8, 0x05, 0x83, 0xB7, 0x80, 0x6C, 0xB9, 0x39, 0x17, 0x14, 0x01,
  199     0x44, 0x84, 0x9F, 0x5D, 0x60, 0x73, 0xE5, 0x9F, 0xBE, 0x09, 0x29, 0x04,
  200     0x49, 0xDB, 0x0B, 0xC8, 0xE4, 0x03, 0x01, 0xE8, 0xF8, 0xE8, 0x72, 0x42,
  201     0xE5, 0x68, 0xED, 0x03, 0xB5, 0x4B, 0xB9, 0x59, 0xCE, 0x1F, 0xBE, 0x6E,
  202     0x3E, 0xE6, 0xAE, 0x5C, 0x88, 0xBB, 0x0E, 0x72, 0xDA, 0xA8, 0x0D, 0x3B,
  203     0x23, 0x44, 0xDC, 0xC0, 0xF8, 0x4A, 0x7E, 0xB6, 0xEB, 0xF3, 0x1C, 0x20,
  204     0x39, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x69, 0x30, 0x67, 0x30, 0x0F,
  205     0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03,
  206     0x01, 0x01, 0xFF, 0x30, 0x54, 0x06, 0x03, 0x55, 0x1D, 0x01, 0x04, 0x4D,
  207     0x30, 0x4B, 0x80, 0x10, 0x8F, 0x11, 0x13, 0x21, 0xAA, 0xC0, 0xFA, 0xB1,
  208     0x63, 0xD5, 0xE6, 0x00, 0x9B, 0x78, 0x67, 0x40, 0xA1, 0x25, 0x30, 0x23,
  209     0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1E, 0x18, 0x00,
  210     0x44, 0x00, 0x43, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x70, 0x00, 0x6C, 0x00,
  211     0x61, 0x00, 0x74, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x82,
  212     0x10, 0x32, 0xDC, 0x46, 0x30, 0x87, 0xE5, 0x4F, 0xB1, 0x43, 0x0F, 0x58,
  213     0x9E, 0xC0, 0xDA, 0x58, 0xF8, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
  214     0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
  215     0x00, 0x78, 0x0F, 0xDF, 0x0C, 0x5D, 0x72, 0xE8, 0x37, 0x65, 0xDF, 0xC1,
  216     0x23, 0x2C, 0x01, 0x03, 0xA8, 0x96, 0x15, 0xD5, 0xC4, 0xF9, 0x12, 0x83,
  217     0xF0, 0x5C, 0x5B, 0xD4, 0xF5, 0x9E, 0xF4, 0x0A, 0xAF, 0x2C, 0x31, 0x7E,
  218     0xE2, 0x34, 0x31, 0x66, 0x47, 0xE7, 0x3C, 0x77, 0x28, 0x0A, 0x7B, 0x33,
  219     0x53, 0xBC, 0x92, 0x26, 0xE7, 0xD8, 0xE8, 0x90, 0xDC, 0xC1, 0x30, 0x31,
  220     0xCC, 0x7F, 0xF9, 0x52, 0xAC, 0x9F, 0x3E, 0x1A, 0xCB, 0x56, 0xF7, 0xA3,
  221     0x45, 0x9F, 0x3C, 0xA9, 0xB1, 0x03, 0xFC, 0x63, 0xDF, 0xE1, 0x9E, 0x94,
  222     0x0A, 0x07, 0x9B, 0xB3, 0x6A, 0x74, 0x12, 0x2F, 0xC7, 0xBD, 0x29, 0x5F,
  223     0x03, 0xB7, 0xFA, 0xA8, 0x25, 0xD1, 0x08, 0x57, 0xE5, 0x25, 0xD8, 0xA1,
  224     0x5A, 0xDD, 0x3D, 0xFB, 0x0E, 0x83, 0xBF, 0x5F, 0xA0, 0xFD, 0x0B, 0x2F,
  225     0xE1, 0x9E, 0xF6, 0x5E, 0x2B, 0xF0, 0xC5, 0x1C, 0x72, 0x8B, 0x53, 0x34,
  226     0x28, 0x8F, 0x02, 0xD2, 0xD3, 0x7B, 0x0C, 0x2C, 0xC2, 0x55, 0x28, 0xBD,
  227     0xFB, 0xD2, 0x4C, 0x8A, 0xD6, 0x33, 0x88, 0x54, 0xE7, 0x25, 0x5F, 0x31,
  228     0x59, 0x9E, 0x61, 0x3E, 0xC4, 0x9B, 0xF7, 0x09, 0x3C, 0xC6, 0xAD, 0xD0,
  229     0xD5, 0x65, 0x63, 0x6C, 0x91, 0xA0, 0x66, 0xBA, 0x58, 0x04, 0x6E, 0x26,
  230     0x31, 0x2F, 0xBB, 0x11, 0xEF, 0x4D, 0xAA, 0xF8, 0x5E, 0xA6, 0x25, 0xD9,
  231     0x18, 0x75, 0xB0, 0x1F, 0xBF, 0xEA, 0x7F, 0x4D, 0x56, 0x63, 0x4B, 0x86,
  232     0x8B, 0x5E, 0xFA, 0xAD, 0x47, 0xE7, 0xC5, 0xB2, 0x06, 0xE7, 0x2B, 0x99,
  233     0x40, 0x2A, 0x4E, 0xFF, 0xE0, 0xDE, 0x07, 0xDE, 0x5D, 0x62, 0x79, 0xE8,
  234     0xC8, 0x03, 0x26, 0x23, 0x1D, 0x6B, 0xE1, 0x45, 0x11, 0xE8, 0x8B, 0x8B,
  235     0xF1, 0x08, 0x37, 0x8F, 0xED, 0xB6, 0xE5, 0xAE, 0xE6, 0x28, 0x3F, 0x03,
  236     0x69, 0x09, 0x3E, 0xAE, 0x63, 0xDE, 0x46, 0x86, 0xCF, 0x28, 0x3E, 0x09,
  237     0x50, 0xE2, 0x5C, 0x4F, 0x97, 0x4A, 0xAF, 0x24, 0x73, 0xEC, 0xDD, 0xEE,
  238     0x3D, 0xE8, 0xCD, 0xBC, 0xD7, 0x4B, 0x9F, 0x30, 0x7D, 0xC3, 0x9B, 0xE1,
  239     0x76, 0xD5, 0x43, 0xBD, 0x56, 0xCB, 0x52, 0x38, 0x0A, 0x12, 0xDD, 0x79,
  240     0x46, 0xB3, 0x56, 0x25, 0x10, 0x37, 0x75, 0x01, 0x13, 0xF4, 0x43, 0xE6,
  241     0x7D, 0x63, 0xCA, 0x11, 0xE1, 0xD0, 0xE0, 0x45, 0x4F, 0x55, 0x2C, 0xD0,
  242     0xDE, 0x9F, 0x93, 0x7B, 0x62, 0xE3, 0x1E, 0x9B, 0x27, 0xCA, 0x0A, 0xAE,
  243     0x6D, 0x5A, 0xAC, 0x1A, 0xC7, 0xB5, 0x10, 0xEE, 0x17, 0x42, 0xA3, 0xE4,
  244     0xED, 0x16, 0x27, 0x3F, 0x46, 0xB3, 0x33, 0x83, 0x5B, 0xE7, 0x86, 0xB6,
  245     0xCB, 0xB5, 0xB8, 0x5F, 0x2B, 0x4B, 0x36, 0xEC, 0xEF, 0x41, 0xB5, 0x05,
  246     0x0C, 0xF7, 0x0F, 0xD2, 0x05, 0xE0, 0x20, 0x56, 0x29, 0xC1, 0x43, 0x11,
  247     0x93, 0x62, 0xD3, 0x1D, 0xE5, 0x07, 0x27, 0x26, 0xE3, 0x62, 0x46, 0x1E,
  248     0x0D, 0xC3, 0x9F, 0xEA, 0x37, 0x7B, 0xCB, 0xC3, 0x65, 0x8D, 0x71, 0xBA,
  249     0x97, 0xA8, 0x4F, 0x69, 0x25, 0x36, 0x1D, 0x7F, 0x08, 0x54, 0xB2, 0x9A,
  250     0x56, 0xA0, 0x8B, 0x2F, 0xBC, 0x77, 0x16, 0x89, 0xBF, 0x5C, 0xB0, 0xD2,
  251     0xB1, 0xDA, 0x3C, 0x08, 0xD1, 0x8A, 0xC5, 0xB5, 0xA0, 0xED, 0xD1, 0xDF,
  252     0xB1, 0xAE, 0x5F, 0x82, 0x26, 0xA4, 0x0A, 0x12, 0x1E, 0x1F, 0x18, 0x7D,
  253     0x9E, 0x57, 0xE1, 0xA4, 0xCC, 0x90, 0x15, 0x79, 0xC9, 0x19, 0x95, 0x98,
  254     0xCB, 0x86, 0x75, 0xC1, 0x45, 0x67, 0xD8, 0x1D, 0x02, 0x84, 0xC6, 0xF3,
  255     0x50, 0xD7, 0xB8, 0xAB, 0x92, 0xD2, 0x4E, 0xFB, 0xA0, 0xFF, 0x28, 0xB5,
  256     0x69, 0x17, 0xFD, 0xA9, 0x18, 0x07, 0xAB, 0xD3, 0xCD, 0x3A, 0xE7, 0xE7,
  257     0x54, 0x61, 0x6B, 0x73, 0x88, 0xF0, 0xD9, 0xB9, 0xD6
  258 };
  259 
  260 
  261 
  262 bool ZipAdd (zip_t *z, const char* name, const unsigned char* pbData, DWORD cbData)
  263 {
  264     zip_error_t zerr;
  265     zip_source_t* zin = zip_source_buffer_create (pbData, cbData, 0, &zerr);
  266     if (!zin)
  267         return false;
  268 
  269     if (-1 == zip_file_add (z, name, zin, 0))
  270     {
  271         zip_source_free (zin);
  272         return false;
  273     }
  274 
  275     return true;
  276 }
  277 
  278 namespace VeraCrypt
  279 {
  280 #if !defined (SETUP)
  281 
  282     class Elevator
  283     {
  284     public:
  285         
  286         static void AddReference ()
  287         {
  288             ++ReferenceCount;
  289         }
  290 
  291 
  292         static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
  293         {
  294             Elevate();
  295 
  296             CComBSTR inputBstr;
  297             if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK)
  298                 throw ParameterIncorrect (SRC_POS);
  299 
  300             CComBSTR outputBstr;
  301             if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK)
  302                 throw ParameterIncorrect (SRC_POS);
  303 
  304             DWORD result = ElevatedComInstance->CallDriver (ioctl, inputBstr, &outputBstr);
  305 
  306             if (output)
  307                 memcpy (output, *(void **) &outputBstr, outputSize);
  308 
  309             if (result != ERROR_SUCCESS)
  310             {
  311                 SetLastError (result);
  312                 throw SystemException(SRC_POS);
  313             }
  314         }
  315 
  316         static void CopyFile (const wstring &sourceFile, const wstring &destinationFile)
  317         {
  318             Elevate();
  319             DWORD result;
  320             CComBSTR sourceFileBstr, destinationFileBstr;
  321             BSTR bstr = W2BSTR(sourceFile.c_str());
  322             if (bstr)
  323             {
  324                 sourceFileBstr.Attach (bstr);
  325 
  326                 bstr = W2BSTR(destinationFile.c_str());
  327                 if (bstr)
  328                 {
  329                     destinationFileBstr.Attach (bstr);
  330                     result = ElevatedComInstance->CopyFile (sourceFileBstr, destinationFileBstr);
  331                 }
  332                 else
  333                 {
  334                     result = ERROR_OUTOFMEMORY;
  335                 }
  336             }
  337             else
  338             {
  339                 result = ERROR_OUTOFMEMORY;
  340             }
  341 
  342             if (result != ERROR_SUCCESS)
  343             {
  344                 SetLastError (result);
  345                 throw SystemException(SRC_POS);
  346             }
  347         }
  348 
  349         static void DeleteFile (const wstring &file)
  350         {
  351             Elevate();
  352             CComBSTR fileBstr;
  353             DWORD result;
  354             BSTR bstr = W2BSTR(file.c_str());
  355             if (bstr)
  356             {
  357                 fileBstr.Attach (bstr);
  358                 result = ElevatedComInstance->DeleteFile (fileBstr);
  359             }
  360             else
  361             {
  362                 result = ERROR_OUTOFMEMORY;
  363             }
  364 
  365             if (result != ERROR_SUCCESS)
  366             {
  367                 SetLastError (result);
  368                 throw SystemException(SRC_POS);
  369             }
  370         }
  371 
  372         static void ReadWriteFile (BOOL write, BOOL device, const wstring &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone)
  373         {
  374             Elevate();
  375 
  376             DWORD result;
  377             CComBSTR bufferBstr, fileBstr;
  378             if (bufferBstr.AppendBytes ((const char *) buffer, size) != S_OK)
  379                 throw ParameterIncorrect (SRC_POS);
  380             BSTR bstr = W2BSTR(filePath.c_str());
  381             if (bstr)
  382             {
  383                 fileBstr.Attach (bstr);
  384                 result = ElevatedComInstance->ReadWriteFile (write, device, fileBstr, &bufferBstr, offset, size, sizeDone);
  385             }
  386             else
  387             {
  388                 result = ERROR_OUTOFMEMORY;
  389             }
  390 
  391             if (result != ERROR_SUCCESS)
  392             {
  393                 SetLastError (result);
  394                 throw SystemException(SRC_POS);
  395             }
  396 
  397             if (!write)
  398                 memcpy (buffer, (BYTE *) bufferBstr.m_str, size);
  399         }
  400 
  401         static void GetFileSize (const wstring &filePath, unsigned __int64* pSize)
  402         {
  403             Elevate();
  404 
  405             DWORD result;
  406             CComBSTR fileBstr;
  407             BSTR bstr = W2BSTR(filePath.c_str());
  408             if (bstr)
  409             {
  410                 fileBstr.Attach (bstr);
  411                 result = ElevatedComInstance->GetFileSize (fileBstr, pSize);
  412             }
  413             else
  414             {
  415                 result = ERROR_OUTOFMEMORY;
  416             }
  417 
  418             if (result != ERROR_SUCCESS)
  419             {
  420                 SetLastError (result);
  421                 throw SystemException(SRC_POS);
  422             }
  423         }
  424 
  425         static BOOL DeviceIoControl (BOOL readOnly, BOOL device, const wstring &filePath, DWORD dwIoControlCode, LPVOID input, DWORD inputSize, 
  426                                                 LPVOID output, DWORD outputSize)
  427         {
  428             Elevate();
  429 
  430             DWORD result;
  431 
  432             BSTR bstr = W2BSTR(filePath.c_str());
  433             if (bstr)
  434             {
  435                 CComBSTR inputBstr;
  436                 CComBSTR fileBstr;
  437                 fileBstr.Attach (bstr);
  438 
  439                 if (input && inputBstr.AppendBytes ((const char *) input, inputSize) != S_OK)
  440                 {
  441                     SetLastError (ERROR_INVALID_PARAMETER);
  442                     return FALSE;
  443                 }
  444 
  445                 CComBSTR outputBstr;
  446                 if (output && outputBstr.AppendBytes ((const char *) output, outputSize) != S_OK)
  447                 {
  448                     SetLastError (ERROR_INVALID_PARAMETER);
  449                     return FALSE;
  450                 }
  451 
  452                 result = ElevatedComInstance->DeviceIoControl (readOnly, device, fileBstr, dwIoControlCode, inputBstr, &outputBstr);
  453 
  454                 if (output)
  455                     memcpy (output, *(void **) &outputBstr, outputSize);
  456             }
  457             else
  458             {
  459                 result = ERROR_OUTOFMEMORY;
  460             }
  461 
  462             if (result != ERROR_SUCCESS)
  463             {
  464                 SetLastError (result);
  465                 return FALSE;
  466             }
  467             else
  468                 return TRUE;
  469         }
  470 
  471         static BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly)
  472         {
  473             Elevate();
  474 
  475             return ElevatedComInstance->IsPagingFileActive (checkNonWindowsPartitionsOnly);
  476         }
  477 
  478         static void WriteLocalMachineRegistryDwordValue (wchar_t *keyPath, wchar_t *valueName, DWORD value)
  479         {
  480             Elevate();
  481             DWORD result;
  482             CComBSTR keyPathBstr, valueNameBstr;
  483             BSTR bstr = W2BSTR(keyPath);
  484             if (bstr)
  485             {
  486                 keyPathBstr.Attach (bstr);
  487 
  488                 bstr = W2BSTR(valueName);
  489                 if (bstr)
  490                 {
  491                     valueNameBstr.Attach (bstr);
  492 
  493                     result = ElevatedComInstance->WriteLocalMachineRegistryDwordValue (keyPathBstr, valueNameBstr, value);
  494                 }
  495                 else
  496                 {
  497                     result = ERROR_OUTOFMEMORY;
  498                 }
  499             }
  500             else
  501             {
  502                 result = ERROR_OUTOFMEMORY;
  503             }
  504 
  505             if (result != ERROR_SUCCESS)
  506             {
  507                 SetLastError (result);
  508                 throw SystemException(SRC_POS);
  509             }
  510         }
  511 
  512         static void RegisterFilterDriver (bool registerDriver, BootEncryption::FilterType filterType)
  513         {
  514             Elevate();
  515 
  516             DWORD result = ElevatedComInstance->RegisterFilterDriver (registerDriver ? TRUE : FALSE, filterType);
  517             if (result != ERROR_SUCCESS)
  518             {
  519                 SetLastError (result);
  520                 throw SystemException(SRC_POS);
  521             }
  522         }
  523 
  524         static void RegisterSystemFavoritesService (BOOL registerService)
  525         {
  526             Elevate();
  527 
  528             DWORD result = ElevatedComInstance->RegisterSystemFavoritesService (registerService);
  529             if (result != ERROR_SUCCESS)
  530             {
  531                 SetLastError (result);
  532                 throw SystemException(SRC_POS);
  533             }
  534         }
  535 
  536         static void InstallEfiBootLoader (bool preserveUserConfig, bool hiddenOSCreation, int pim, int hashAlg)
  537         {
  538             Elevate();
  539 
  540             DWORD result = ElevatedComInstance->InstallEfiBootLoader (preserveUserConfig ? TRUE : FALSE, hiddenOSCreation ? TRUE : FALSE, pim, hashAlg);
  541             if (result != ERROR_SUCCESS)
  542             {
  543                 SetLastError (result);
  544                 throw SystemException(SRC_POS);
  545             }
  546         }
  547 
  548         static void BackupEfiSystemLoader ()
  549         {
  550             Elevate();
  551 
  552             DWORD result = ElevatedComInstance->BackupEfiSystemLoader ();
  553             if (result != ERROR_SUCCESS)
  554             {
  555                 if (result == ERROR_CANCELLED)
  556                     throw UserAbort (SRC_POS);
  557                 else
  558                 {
  559                     SetLastError (result);
  560                     throw SystemException(SRC_POS);
  561                 }
  562             }
  563         }
  564 
  565         static void RestoreEfiSystemLoader ()
  566         {
  567             Elevate();
  568 
  569             DWORD result = ElevatedComInstance->RestoreEfiSystemLoader ();
  570             if (result != ERROR_SUCCESS)
  571             {
  572                 SetLastError (result);
  573                 throw SystemException(SRC_POS);
  574             }
  575         }
  576 
  577         static void GetEfiBootDeviceNumber (PSTORAGE_DEVICE_NUMBER pSdn)
  578         {
  579             Elevate();
  580 
  581             CComBSTR outputBstr;
  582             if (pSdn && outputBstr.AppendBytes ((const char *) pSdn, sizeof (STORAGE_DEVICE_NUMBER)) != S_OK)
  583             {
  584                 SetLastError (ERROR_INVALID_PARAMETER);
  585                 throw SystemException(SRC_POS);
  586             }
  587 
  588             DWORD result = ElevatedComInstance->GetEfiBootDeviceNumber (&outputBstr);
  589 
  590             if (pSdn)
  591                 memcpy (pSdn, *(void **) &outputBstr, sizeof (STORAGE_DEVICE_NUMBER));
  592 
  593             if (result != ERROR_SUCCESS)
  594             {
  595                 SetLastError (result);
  596                 throw SystemException(SRC_POS);
  597             }
  598         }
  599 
  600         static void GetSecureBootConfig (BOOL* pSecureBootEnabled, BOOL *pVeraCryptKeysLoaded)
  601         {
  602             Elevate();
  603 
  604             DWORD result = ElevatedComInstance->GetSecureBootConfig (pSecureBootEnabled, pVeraCryptKeysLoaded);
  605 
  606             if (result != ERROR_SUCCESS)
  607             {
  608                 SetLastError (result);
  609                 throw SystemException(SRC_POS);
  610             }
  611         }
  612 
  613         static void WriteEfiBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim, int hashAlg)
  614         {
  615             Elevate();
  616 
  617             DWORD result;
  618             CComBSTR customUserMessageBstr;
  619             BSTR bstr = A2BSTR(customUserMessage.c_str());
  620             if (bstr)
  621             {
  622                 customUserMessageBstr.Attach (bstr);
  623                 result = ElevatedComInstance->WriteEfiBootSectorUserConfig ((DWORD) userConfig, customUserMessageBstr, pim, hashAlg);
  624             }
  625             else
  626             {
  627                 result = ERROR_OUTOFMEMORY;
  628             }
  629 
  630             if (result != ERROR_SUCCESS)
  631             {
  632                 SetLastError (result);
  633                 throw SystemException(SRC_POS);
  634             }
  635         }
  636 
  637         static void UpdateSetupConfigFile (bool bForInstall)
  638         {
  639             Elevate();
  640 
  641             DWORD result = ElevatedComInstance->UpdateSetupConfigFile (bForInstall ? TRUE : FALSE);
  642             if (result != ERROR_SUCCESS)
  643             {
  644                 SetLastError (result);
  645                 throw SystemException(SRC_POS);
  646             }
  647         }
  648 
  649         static void Release ()
  650         {
  651             if (--ReferenceCount == 0 && ElevatedComInstance)
  652             {
  653                 ElevatedComInstance->Release();
  654                 ElevatedComInstance = nullptr;
  655                 CoUninitialize ();
  656             }
  657         }
  658 
  659         static void SetDriverServiceStartType (DWORD startType)
  660         {
  661             Elevate();
  662 
  663             DWORD result = ElevatedComInstance->SetDriverServiceStartType (startType);
  664             if (result != ERROR_SUCCESS)
  665             {
  666                 SetLastError (result);
  667                 throw SystemException(SRC_POS);
  668             }
  669         }
  670 
  671     protected:
  672         static void Elevate ()
  673         {
  674             if (IsAdmin())
  675             {
  676                 SetLastError (ERROR_ACCESS_DENIED);
  677                 throw SystemException(SRC_POS);
  678             }
  679 
  680             if (!ElevatedComInstance || ElevatedComInstanceThreadId != GetCurrentThreadId())
  681             {
  682                 CoInitialize (NULL);
  683                 ElevatedComInstance = GetElevatedInstance (GetActiveWindow() ? GetActiveWindow() : MainDlg);
  684                 ElevatedComInstanceThreadId = GetCurrentThreadId();
  685             }
  686         }
  687 
  688 #if defined (TCMOUNT)
  689         static ITrueCryptMainCom *ElevatedComInstance;
  690 #elif defined (VOLFORMAT)
  691         static ITrueCryptFormatCom *ElevatedComInstance;
  692 #endif
  693         static DWORD ElevatedComInstanceThreadId;
  694         static int ReferenceCount;
  695     };
  696 
  697 #if defined (TCMOUNT)
  698     ITrueCryptMainCom *Elevator::ElevatedComInstance;
  699 #elif defined (VOLFORMAT)
  700     ITrueCryptFormatCom *Elevator::ElevatedComInstance;
  701 #endif
  702     DWORD Elevator::ElevatedComInstanceThreadId;
  703     int Elevator::ReferenceCount = 0;
  704 
  705 #else // SETUP
  706 
  707     class Elevator
  708     {
  709     public:
  710         static void AddReference () { }
  711         static void CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); }
  712         static void ReadWriteFile (BOOL write, BOOL device, const wstring &filePath, byte *buffer, uint64 offset, uint32 size, DWORD *sizeDone) { throw ParameterIncorrect (SRC_POS); }
  713         static void RegisterFilterDriver (bool registerDriver, BootEncryption::FilterType filterType) { throw ParameterIncorrect (SRC_POS); }
  714         static void Release () { }
  715         static void SetDriverServiceStartType (DWORD startType) { throw ParameterIncorrect (SRC_POS); }
  716         static void GetFileSize (const wstring &filePath, unsigned __int64 *pSize) { throw ParameterIncorrect (SRC_POS); }
  717         static BOOL DeviceIoControl (BOOL readOnly, BOOL device, const wstring &filePath, DWORD dwIoControlCode, LPVOID input, DWORD inputSize, LPVOID output, DWORD outputSize) { throw ParameterIncorrect (SRC_POS); }
  718         static void InstallEfiBootLoader (bool preserveUserConfig, bool hiddenOSCreation, int pim, int hashAlg) { throw ParameterIncorrect (SRC_POS); }
  719         static void BackupEfiSystemLoader () { throw ParameterIncorrect (SRC_POS); }
  720         static void RestoreEfiSystemLoader () { throw ParameterIncorrect (SRC_POS); }
  721         static void GetEfiBootDeviceNumber (PSTORAGE_DEVICE_NUMBER pSdn) { throw ParameterIncorrect (SRC_POS); }
  722         static void WriteEfiBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim, int hashAlg) { throw ParameterIncorrect (SRC_POS); }
  723         static void UpdateSetupConfigFile (bool bForInstall) { throw ParameterIncorrect (SRC_POS); }
  724         static void GetSecureBootConfig (BOOL* pSecureBootEnabled, BOOL *pVeraCryptKeysLoaded) { throw ParameterIncorrect (SRC_POS); }
  725     };
  726 
  727 #endif // SETUP
  728 
  729     File::File (wstring path, bool readOnly, bool create) : Elevated (false), FileOpen (false), ReadOnly (readOnly), LastError(0)
  730     {
  731         Handle = CreateFile (path.c_str(),
  732             readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
  733             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, create ? CREATE_ALWAYS : OPEN_EXISTING,
  734             FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
  735 
  736         if (Handle != INVALID_HANDLE_VALUE)
  737         {
  738             FileOpen = true;
  739         }
  740         else
  741         {
  742             LastError = GetLastError();
  743             if (LastError == ERROR_ACCESS_DENIED && IsUacSupported())
  744             {
  745                 Elevated = true;
  746                 FileOpen = true;
  747             }
  748         }
  749 
  750         FilePointerPosition = 0;
  751         IsDevice = false;
  752         Path = path;
  753     }
  754 
  755     void File::Close ()
  756     {
  757         if (Handle != INVALID_HANDLE_VALUE)
  758         {
  759             CloseHandle (Handle);
  760             Handle = INVALID_HANDLE_VALUE;
  761         }
  762 
  763         FileOpen = false;
  764     }
  765 
  766     DWORD File::Read (byte *buffer, DWORD size)
  767     {
  768         DWORD bytesRead;
  769 
  770         if (!FileOpen)
  771         {
  772             SetLastError (LastError);
  773             throw SystemException (SRC_POS);
  774         }
  775 
  776         if (Elevated)
  777         {
  778             DWORD bytesRead;
  779 
  780             Elevator::ReadWriteFile (false, IsDevice, Path, buffer, FilePointerPosition, size, &bytesRead);
  781             FilePointerPosition += bytesRead;
  782             return bytesRead;
  783         }
  784 
  785         if (!ReadFile (Handle, buffer, size, &bytesRead, NULL))
  786         {
  787             DWORD dwLastError = GetLastError();
  788             if ((dwLastError == ERROR_INVALID_PARAMETER) && IsDevice && (size % 4096))
  789             {                   
  790                 DWORD remainingSize = (size % 4096);
  791                 DWORD alignedSize = size - remainingSize;
  792                 LARGE_INTEGER offset;
  793 
  794                 if (alignedSize)
  795                 {
  796                     if (ReadFile (Handle, buffer, alignedSize, &bytesRead, NULL))
  797                     {
  798                         if (bytesRead < alignedSize)
  799                             return bytesRead;
  800 
  801                         buffer += alignedSize;
  802                         size -= alignedSize;
  803                     }
  804                     else
  805                         throw SystemException (SRC_POS);
  806                 }
  807 
  808 
  809                 if (ReadFile (Handle, ReadBuffer, 4096, &bytesRead, NULL))
  810                 {
  811                     DWORD effectiveSize = min (bytesRead, remainingSize);                   
  812                     memcpy (buffer, ReadBuffer, effectiveSize);
  813                     offset.QuadPart = - ((LONGLONG) bytesRead) + (LONGLONG) effectiveSize;
  814                     throw_sys_if (!SetFilePointerEx (Handle, offset, NULL, FILE_CURRENT));
  815                     return alignedSize + effectiveSize;
  816                 }
  817                 else
  818                     throw SystemException (SRC_POS);
  819             }
  820             else
  821                 throw SystemException (SRC_POS);
  822         }
  823 
  824         return bytesRead;
  825     }
  826 
  827     void File::SeekAt (int64 position)
  828     {
  829         if (!FileOpen)
  830         {
  831             SetLastError (LastError);
  832             throw SystemException (SRC_POS);
  833         }
  834 
  835         FilePointerPosition = position;
  836 
  837         if (!Elevated)
  838         {
  839             LARGE_INTEGER pos;
  840             pos.QuadPart = position;
  841             throw_sys_if (!SetFilePointerEx (Handle, pos, NULL, FILE_BEGIN));
  842         }
  843     }
  844 
  845     void File::GetFileSize (unsigned __int64& size)
  846     {
  847         if (!FileOpen)
  848         {
  849             SetLastError (LastError);
  850             throw SystemException (SRC_POS);
  851         }
  852 
  853         if (Elevated)
  854         {
  855             Elevator::GetFileSize (Path, &size);
  856         }
  857         else
  858         {
  859             LARGE_INTEGER lSize;
  860             lSize.QuadPart = 0;
  861             throw_sys_if (!GetFileSizeEx (Handle, &lSize));
  862             size = (unsigned __int64) lSize.QuadPart;
  863         }
  864     }
  865 
  866     void File::GetFileSize (DWORD& dwSize)
  867     {
  868         unsigned __int64 size64;
  869         GetFileSize (size64);
  870         dwSize = (DWORD) size64;
  871     }
  872 
  873     void File::Write (byte *buffer, DWORD size)
  874     {
  875         DWORD bytesWritten;
  876 
  877         if (!FileOpen)
  878         {
  879             SetLastError (LastError);
  880             throw SystemException (SRC_POS);
  881         }
  882 
  883         try
  884         {
  885             if (Elevated)
  886             {
  887                 Elevator::ReadWriteFile (true, IsDevice, Path, buffer, FilePointerPosition, size, &bytesWritten);
  888                 FilePointerPosition += bytesWritten;
  889                 throw_sys_if (bytesWritten != size);
  890             }
  891             else
  892             {
  893                 if (!WriteFile (Handle, buffer, size, &bytesWritten, NULL))
  894                 {
  895                     DWORD dwLastError = GetLastError ();
  896                     if ((ERROR_INVALID_PARAMETER == dwLastError) && IsDevice && !ReadOnly && (size % 4096))
  897                     {
  898                         bool bSuccess = false;                      
  899                         DWORD remainingSize = (size % 4096);
  900                         DWORD alignedSize = size - remainingSize;
  901                         DWORD bytesRead = 0;
  902                         bytesWritten = 0;
  903                         if (alignedSize)
  904                         {
  905                             if (WriteFile (Handle, buffer, alignedSize, &bytesWritten, NULL))
  906                             {
  907                                 throw_sys_if (bytesWritten != alignedSize);
  908                                 buffer += alignedSize;
  909                                 size -= alignedSize;
  910                             }
  911                             else
  912                             {
  913                                 bytesWritten = 0;
  914                                 dwLastError = GetLastError ();
  915                             }
  916                         }
  917 
  918                         if (!alignedSize || (alignedSize && bytesWritten))
  919                         {
  920                             LARGE_INTEGER offset;
  921 
  922                             throw_sys_if (!ReadFile (Handle, ReadBuffer, 4096, &bytesRead, NULL) || (bytesRead != 4096));
  923                             offset.QuadPart = -4096;
  924                             throw_sys_if (!SetFilePointerEx (Handle, offset, NULL, FILE_CURRENT));
  925 
  926                             memcpy (ReadBuffer, buffer, remainingSize);
  927 
  928                             if (WriteFile (Handle, ReadBuffer, 4096, &bytesWritten, NULL))
  929                             {
  930                                 throw_sys_if (bytesWritten != 4096);
  931                                 bSuccess = true;
  932                             }
  933                             else
  934                             {
  935                                 dwLastError = GetLastError ();
  936                             }
  937                         }
  938 
  939                         if (!bSuccess)
  940                         {
  941                             SetLastError (dwLastError);
  942                             throw SystemException (SRC_POS);
  943                         }
  944                     }
  945                     else
  946                         throw SystemException (SRC_POS);
  947                 }
  948                 else
  949                     throw_sys_if (bytesWritten != size);                
  950             }
  951         }
  952         catch (SystemException &e)
  953         {
  954             if (!IsDevice || e.ErrorCode != ERROR_WRITE_PROTECT)
  955                 throw;
  956 
  957             BootEncryption bootEnc (NULL);
  958 
  959             while (size >= TC_SECTOR_SIZE_BIOS)
  960             {
  961                 bootEnc.WriteBootDriveSector (FilePointerPosition, buffer);
  962 
  963                 FilePointerPosition += TC_SECTOR_SIZE_BIOS;
  964                 buffer += TC_SECTOR_SIZE_BIOS;
  965                 size -= TC_SECTOR_SIZE_BIOS;
  966             }
  967         }
  968     }
  969 
  970     bool File::IoCtl(DWORD code, void* inBuf, DWORD inBufSize, void* outBuf, DWORD outBufSize)
  971     {
  972         if (!FileOpen)
  973         {
  974             SetLastError (LastError);
  975             throw SystemException (SRC_POS);
  976         }
  977 
  978         if (Elevated)
  979         {
  980             return TRUE == Elevator::DeviceIoControl (ReadOnly, IsDevice, Path, code, inBuf, inBufSize, outBuf, outBufSize);
  981         }
  982         else
  983         {
  984             DWORD bytesReturned = 0;
  985             return TRUE == DeviceIoControl(Handle, code, inBuf, inBufSize, outBuf, outBufSize, &bytesReturned, NULL);
  986         }
  987     }
  988 
  989     void Show (HWND parent, const wstring &str)
  990     {
  991         MessageBox (parent, str.c_str(), NULL, 0);
  992     }
  993 
  994 
  995     Device::Device (wstring path, bool readOnly)
  996     {
  997          FileOpen = false;
  998          Elevated = false;
  999 
 1000         Handle = CreateFile ((wstring (L"\\\\.\\") + path).c_str(),
 1001             readOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
 1002             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
 1003             FILE_FLAG_RANDOM_ACCESS | FILE_FLAG_WRITE_THROUGH, NULL);
 1004 
 1005         if (Handle != INVALID_HANDLE_VALUE)
 1006         {
 1007             FileOpen = true;
 1008         }
 1009         else
 1010         {
 1011             LastError = GetLastError ();
 1012             if (LastError == ERROR_ACCESS_DENIED && IsUacSupported())
 1013             {
 1014                 Elevated = true;
 1015                 FileOpen = true;
 1016             }
 1017         }
 1018 
 1019         FilePointerPosition = 0;
 1020         IsDevice = true;
 1021         Path = path;
 1022         ReadOnly = readOnly;
 1023     }
 1024 
 1025     static EfiBoot EfiBootInst;
 1026 
 1027     BootEncryption::BootEncryption (HWND parent, bool postOOBE)
 1028         : DriveConfigValid (false),
 1029         ParentWindow (parent),
 1030         RealSystemDriveSizeValid (false),
 1031         RescueIsoImage (nullptr),
 1032         RescueZipData (nullptr),
 1033         RescueZipSize (0),
 1034         RescueVolumeHeaderValid (false),
 1035         SelectedEncryptionAlgorithmId (0),
 1036         SelectedPrfAlgorithmId (0),
 1037         VolumeHeaderValid (false),
 1038         PostOOBEMode (postOOBE)
 1039     {
 1040       HiddenOSCandidatePartition.IsGPT = FALSE;
 1041       HiddenOSCandidatePartition.Number = (size_t) -1;
 1042       DriveConfig.DriveNumber = -1;
 1043       DriveConfig.ExtraBootPartitionPresent = false;
 1044       DriveConfig.SystemLoaderPresent = false;
 1045       DriveConfig.InitialUnallocatedSpace = 0;
 1046       DriveConfig.TotalUnallocatedSpace = 0;
 1047         Elevator::AddReference();
 1048     }
 1049 
 1050 
 1051     BootEncryption::~BootEncryption ()
 1052     {
 1053         if (RescueIsoImage)
 1054         {
 1055             burn (RescueIsoImage, RescueIsoImageSize);
 1056             delete[] RescueIsoImage;
 1057         }
 1058         if (RescueZipData)
 1059         {
 1060             burn (RescueZipData, RescueZipSize);
 1061             delete [] RescueZipData;
 1062         }
 1063 
 1064         Elevator::Release();
 1065     }
 1066 
 1067 
 1068     void BootEncryption::CallDriver (DWORD ioctl, void *input, DWORD inputSize, void *output, DWORD outputSize)
 1069     {
 1070         try
 1071         {
 1072             DWORD bytesReturned;
 1073             throw_sys_if (!DeviceIoControl (hDriver, ioctl, input, inputSize, output, outputSize, &bytesReturned, NULL));
 1074         }
 1075         catch (SystemException &)
 1076         {
 1077             if (GetLastError() == ERROR_ACCESS_DENIED && IsUacSupported())
 1078                 Elevator::CallDriver (ioctl, input, inputSize, output, outputSize);
 1079             else
 1080                 throw;
 1081         }
 1082     }
 1083 
 1084 
 1085     // Finds the first partition physically located behind the active one and returns its properties
 1086     Partition BootEncryption::GetPartitionForHiddenOS ()
 1087     {
 1088         Partition candidatePartition;
 1089 
 1090         memset (&candidatePartition, 0, sizeof(candidatePartition));
 1091 
 1092         // The user may have modified/added/deleted partitions since the time the partition table was last scanned
 1093         InvalidateCachedSysDriveProperties();
 1094 
 1095         SystemDriveConfiguration config = GetSystemDriveConfiguration ();
 1096         bool activePartitionFound = false;
 1097         bool candidateForHiddenOSFound = false;
 1098 
 1099         if (!config.SystemPartition.IsGPT)
 1100         {
 1101 //              throw ParameterIncorrect (SRC_POS); // It is assumed that CheckRequirements() had been called
 1102 
 1103             // Find the first active partition on the system drive
 1104             foreach (const Partition &partition, config.Partitions)
 1105             {
 1106                 if (partition.Info.BootIndicator)
 1107                 {
 1108                     if (partition.Info.PartitionNumber != config.SystemPartition.Number)
 1109                     {
 1110                         // If there is an extra boot partition, the system partition must be located right behind it
 1111                         if (IsOSAtLeast (WIN_7) && config.ExtraBootPartitionPresent)
 1112                         {
 1113                             int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart;
 1114                             Partition bootPartition = partition;
 1115                             Partition partitionBehindBoot;
 1116 
 1117                             foreach (const Partition &partition, config.Partitions)
 1118                             {
 1119                                 if (partition.Info.StartingOffset.QuadPart > bootPartition.Info.StartingOffset.QuadPart
 1120                                     && partition.Info.StartingOffset.QuadPart < minOffsetFound)
 1121                                 {
 1122                                     minOffsetFound = partition.Info.StartingOffset.QuadPart;
 1123                                     partitionBehindBoot = partition;
 1124                                 }
 1125                             }
 1126 
 1127                             if (minOffsetFound != config.DrivePartition.Info.PartitionLength.QuadPart
 1128                                 && partitionBehindBoot.Number == config.SystemPartition.Number)
 1129                             {
 1130                                 activePartitionFound = true;
 1131                                 break;
 1132                             }
 1133                         }
 1134 
 1135                         throw ErrorException (wstring (GetString ("SYSTEM_PARTITION_NOT_ACTIVE"))
 1136                             + GetRemarksOnHiddenOS(), SRC_POS);
 1137                     }
 1138 
 1139                     activePartitionFound = true;
 1140                     break;
 1141                 }
 1142             }
 1143         } else {
 1144             // For GPT
 1145             activePartitionFound = true;
 1146         }
 1147         /* WARNING: Note that the partition number at the end of a device path (\Device\HarddiskY\PartitionX) must
 1148         NOT be used to find the first partition physically located behind the active one. The reason is that the
 1149         user may have deleted and created partitions during this session and e.g. the second partition could have
 1150         a higer number than the third one. */
 1151 
 1152 
 1153         // Find the first partition physically located behind the active partition
 1154         if (activePartitionFound)
 1155         {
 1156             int64 minOffsetFound = config.DrivePartition.Info.PartitionLength.QuadPart;
 1157 
 1158             foreach (const Partition &partition, config.Partitions)
 1159             {
 1160                 if (partition.Info.StartingOffset.QuadPart > config.SystemPartition.Info.StartingOffset.QuadPart
 1161                     && partition.Info.StartingOffset.QuadPart < minOffsetFound)
 1162                 {
 1163                     minOffsetFound = partition.Info.StartingOffset.QuadPart;
 1164 
 1165                     candidatePartition = partition;
 1166 
 1167                     candidateForHiddenOSFound = true;
 1168                 }
 1169             }
 1170 
 1171             if (!candidateForHiddenOSFound)
 1172             {
 1173                 throw ErrorException (wstring (GetString ("NO_PARTITION_FOLLOWS_BOOT_PARTITION"))
 1174                     + GetRemarksOnHiddenOS(), SRC_POS);
 1175             }
 1176 
 1177             if (config.SystemPartition.Info.PartitionLength.QuadPart > TC_MAX_FAT_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS)
 1178             {
 1179                 if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_NTFS)
 1180                 {
 1181                     throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS_NTFS"))
 1182                         + GetRemarksOnHiddenOS(), SRC_POS);
 1183                 }
 1184             }
 1185             else if ((double) candidatePartition.Info.PartitionLength.QuadPart / config.SystemPartition.Info.PartitionLength.QuadPart < MIN_HIDDENOS_DECOY_PARTITION_SIZE_RATIO_FAT)
 1186             {
 1187                 throw ErrorException (wstring (GetString ("PARTITION_TOO_SMALL_FOR_HIDDEN_OS"))
 1188                     + GetRemarksOnHiddenOS(), SRC_POS);
 1189             }
 1190         }
 1191         else
 1192         {
 1193             // No active partition on the system drive
 1194             throw ErrorException ("SYSTEM_PARTITION_NOT_ACTIVE", SRC_POS);
 1195         }
 1196 
 1197         HiddenOSCandidatePartition = candidatePartition;
 1198         return candidatePartition;
 1199     }
 1200 
 1201 
 1202     DWORD BootEncryption::GetDriverServiceStartType ()
 1203     {
 1204         DWORD startType;
 1205         throw_sys_if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", &startType));
 1206         return startType;
 1207     }
 1208 
 1209 
 1210     wstring BootEncryption::GetRemarksOnHiddenOS ()
 1211     {
 1212         return (wstring (L"\n\n")
 1213                 + GetString ("TWO_SYSTEMS_IN_ONE_PARTITION_REMARK")
 1214                 + L"\n\n"
 1215                 + GetString ("FOR_MORE_INFO_ON_PARTITIONS"));
 1216     }
 1217 
 1218 
 1219     void BootEncryption::SetDriverServiceStartType (DWORD startType)
 1220     {
 1221         if (!IsAdmin() && IsUacSupported())
 1222         {
 1223             Elevator::SetDriverServiceStartType (startType);
 1224             return;
 1225         }
 1226 
 1227         BOOL startOnBoot = (startType == SERVICE_BOOT_START);
 1228 
 1229         SC_HANDLE serviceManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
 1230         throw_sys_if (!serviceManager);
 1231 
 1232         finally_do_arg (SC_HANDLE, serviceManager, { CloseServiceHandle (finally_arg); });
 1233 
 1234         SC_HANDLE service = OpenService (serviceManager, L"veracrypt", SERVICE_CHANGE_CONFIG);
 1235         throw_sys_if (!service);
 1236 
 1237         finally_do_arg (SC_HANDLE, service, { CloseServiceHandle (finally_arg); });
 1238 
 1239         // Windows versions preceding Vista can be installed on FAT filesystem which does not
 1240         // support long filenames during boot. Convert the driver path to short form if required.
 1241         wstring driverPath;
 1242         if (startOnBoot && !IsOSAtLeast (WIN_VISTA))
 1243         {
 1244             wchar_t pathBuf[MAX_PATH];
 1245             wchar_t filesystem[128];
 1246 
 1247             wstring path (GetWindowsDirectory());
 1248             path += L"\\drivers\\veracrypt.sys";
 1249 
 1250             if (GetVolumePathName (path.c_str(), pathBuf, ARRAYSIZE (pathBuf))
 1251                 && GetVolumeInformation (pathBuf, NULL, 0, NULL, NULL, NULL, filesystem, ARRAYSIZE(filesystem))
 1252                 && wmemcmp (filesystem, L"FAT", 3) == 0)
 1253             {
 1254                 throw_sys_if (GetShortPathName (path.c_str(), pathBuf, ARRAYSIZE (pathBuf)) == 0);
 1255 
 1256                 // Convert absolute path to relative to the Windows directory
 1257                 driverPath = pathBuf;
 1258                 driverPath = driverPath.substr (driverPath.rfind (L"\\", driverPath.rfind (L"\\", driverPath.rfind (L"\\") - 1) - 1) + 1);
 1259             }
 1260         }
 1261 
 1262         throw_sys_if (!ChangeServiceConfig (service, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,
 1263             startOnBoot ? SERVICE_ERROR_SEVERE : SERVICE_ERROR_NORMAL,
 1264             driverPath.empty() ? NULL : driverPath.c_str(),
 1265             startOnBoot ? L"Filter" : NULL,
 1266             NULL, NULL, NULL, NULL, NULL));
 1267 
 1268         // ChangeServiceConfig() rejects SERVICE_BOOT_START with ERROR_INVALID_PARAMETER
 1269         throw_sys_if (!WriteLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", startType));
 1270     }
 1271 
 1272 
 1273     void BootEncryption::ProbeRealSystemDriveSize ()
 1274     {
 1275         if (RealSystemDriveSizeValid)
 1276             return;
 1277 
 1278         GetSystemDriveConfiguration();
 1279 
 1280         ProbeRealDriveSizeRequest request;
 1281         StringCchCopyW (request.DeviceName, ARRAYSIZE (request.DeviceName), DriveConfig.DrivePartition.DevicePath.c_str());
 1282 
 1283         CallDriver (TC_IOCTL_PROBE_REAL_DRIVE_SIZE, &request, sizeof (request), &request, sizeof (request));
 1284         DriveConfig.DrivePartition.Info.PartitionLength = request.RealDriveSize;
 1285 
 1286         RealSystemDriveSizeValid = true;
 1287 
 1288         if (request.TimeOut)
 1289             throw TimeOut (SRC_POS);
 1290     }
 1291 
 1292 
 1293     void BootEncryption::InvalidateCachedSysDriveProperties ()
 1294     {
 1295         DriveConfigValid = false;
 1296         RealSystemDriveSizeValid = false;
 1297     }
 1298 
 1299 
 1300     PartitionList BootEncryption::GetDrivePartitions (int driveNumber)
 1301     {
 1302         PartitionList partList;
 1303 
 1304         for (int partNumber = 0; partNumber < 64; ++partNumber)
 1305         {
 1306             wstringstream partPath;
 1307             partPath << L"\\Device\\Harddisk" << driveNumber << L"\\Partition" << partNumber;
 1308 
 1309             DISK_PARTITION_INFO_STRUCT diskPartInfo = {0};
 1310             StringCchCopyW (diskPartInfo.deviceName, ARRAYSIZE (diskPartInfo.deviceName), partPath.str().c_str());
 1311 
 1312             try
 1313             {
 1314                 CallDriver (TC_IOCTL_GET_DRIVE_PARTITION_INFO, &diskPartInfo, sizeof (diskPartInfo), &diskPartInfo, sizeof (diskPartInfo));
 1315             }
 1316             catch (...)
 1317             {
 1318                 continue;
 1319             }
 1320 
 1321             if (    (diskPartInfo.IsGPT == TRUE || diskPartInfo.IsGPT == FALSE)
 1322                 &&  (diskPartInfo.IsDynamic == TRUE || diskPartInfo.IsDynamic == FALSE)
 1323                 &&  (diskPartInfo.partInfo.BootIndicator == TRUE || diskPartInfo.partInfo.BootIndicator == FALSE)
 1324                 &&  (diskPartInfo.partInfo.RecognizedPartition == TRUE || diskPartInfo.partInfo.RecognizedPartition == FALSE)
 1325                 &&  (diskPartInfo.partInfo.RewritePartition == TRUE || diskPartInfo.partInfo.RewritePartition == FALSE)
 1326                 &&  (diskPartInfo.partInfo.StartingOffset.QuadPart >= 0)
 1327                 &&  (diskPartInfo.partInfo.PartitionLength.QuadPart >= 0)
 1328                 )
 1329             {
 1330                 Partition part;
 1331                 part.DevicePath = partPath.str();
 1332                 part.Number = partNumber;
 1333                 part.Info = diskPartInfo.partInfo;
 1334                 part.IsGPT = diskPartInfo.IsGPT;
 1335 
 1336                 // Mount point
 1337                 int driveNumber = GetDiskDeviceDriveLetter ((wchar_t *) partPath.str().c_str());
 1338 
 1339                 if (driveNumber >= 0)
 1340                 {
 1341                     part.MountPoint += (wchar_t) (driveNumber + L'A');
 1342                     part.MountPoint += L":";
 1343                 }
 1344 
 1345                 // Volume ID
 1346                 wchar_t volumePath[TC_MAX_PATH];
 1347                 if (ResolveSymbolicLink ((wchar_t *) partPath.str().c_str(), volumePath, sizeof(volumePath)))
 1348                 {
 1349                     wchar_t volumeName[TC_MAX_PATH];
 1350                     HANDLE fh = FindFirstVolumeW (volumeName, array_capacity (volumeName));
 1351                     if (fh != INVALID_HANDLE_VALUE)
 1352                     {
 1353                         do
 1354                         {
 1355                             wstring volumeNameStr = volumeName;
 1356                             wchar_t devicePath[TC_MAX_PATH];
 1357 
 1358                             if (QueryDosDeviceW (volumeNameStr.substr (4, volumeNameStr.size() - 1 - 4).c_str(), devicePath, array_capacity (devicePath)) != 0
 1359                                 && wcscmp (volumePath, devicePath) == 0)
 1360                             {
 1361                                 part.VolumeNameId = volumeName;
 1362                                 break;
 1363                             }
 1364 
 1365                         } while (FindNextVolumeW (fh, volumeName, array_capacity (volumeName)));
 1366 
 1367                         FindVolumeClose (fh);
 1368                     }
 1369                 }
 1370 
 1371                 partList.push_back (part);
 1372             }
 1373         }
 1374 
 1375         return partList;
 1376     }
 1377 
 1378 
 1379 #ifndef SETUP
 1380 
 1381     DISK_GEOMETRY_EX BootEncryption::GetDriveGeometry (int driveNumber)
 1382     {
 1383         wstringstream devName;
 1384         devName << L"\\Device\\Harddisk" << driveNumber << L"\\Partition0";
 1385 
 1386         DISK_GEOMETRY_EX geometry;
 1387         throw_sys_if (!::GetDriveGeometry (devName.str().c_str(), &geometry));
 1388         return geometry;
 1389     }
 1390 #endif // !SETUP
 1391 
 1392     wstring BootEncryption::GetWindowsDirectory ()
 1393     {
 1394         wchar_t buf[MAX_PATH];
 1395         throw_sys_if (GetSystemDirectory (buf, ARRAYSIZE (buf)) == 0);
 1396 
 1397         return wstring (buf);
 1398     }
 1399 
 1400 
 1401 
 1402     uint16 BootEncryption::GetInstalledBootLoaderVersion ()
 1403     {
 1404         uint16 version;
 1405         CallDriver (TC_IOCTL_GET_BOOT_LOADER_VERSION, NULL, 0, &version, sizeof (version));
 1406         return version;
 1407     }
 1408 
 1409     void BootEncryption::GetInstalledBootLoaderFingerprint (byte fingerprint[WHIRLPOOL_DIGESTSIZE + SHA512_DIGESTSIZE])
 1410     {
 1411         BootLoaderFingerprintRequest request;
 1412         CallDriver (VC_IOCTL_GET_BOOT_LOADER_FINGERPRINT, NULL, 0, &request, sizeof (request));
 1413         memcpy (fingerprint, request.Fingerprint, sizeof (request.Fingerprint));
 1414     }
 1415 
 1416 #ifndef SETUP
 1417     // Note that this does not require admin rights (it just requires the driver to be running)
 1418     bool BootEncryption::IsBootLoaderOnDrive (wchar_t *devicePath)
 1419     {
 1420         try
 1421         {
 1422             OPEN_TEST_STRUCT openTestStruct;
 1423             memset (&openTestStruct, 0, sizeof (openTestStruct));
 1424             DWORD dwResult;
 1425 
 1426             StringCchCopyW (&openTestStruct.wszFileName[0], ARRAYSIZE(openTestStruct.wszFileName),devicePath);
 1427 
 1428             openTestStruct.bDetectTCBootLoader = TRUE;
 1429 
 1430             return (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST,
 1431                    &openTestStruct, sizeof (OPEN_TEST_STRUCT),
 1432                    &openTestStruct, sizeof (OPEN_TEST_STRUCT),
 1433                    &dwResult, NULL) && openTestStruct.TCBootLoaderDetected);
 1434         }
 1435         catch (...)
 1436         {
 1437             return false;
 1438         }
 1439     }
 1440 
 1441 #endif
 1442 
 1443     BootEncryptionStatus BootEncryption::GetStatus ()
 1444     {
 1445         /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
 1446 
 1447         BootEncryptionStatus status;
 1448         CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_STATUS, NULL, 0, &status, sizeof (status));
 1449         return status;
 1450     }
 1451 
 1452 
 1453     void BootEncryption::GetVolumeProperties (VOLUME_PROPERTIES_STRUCT *properties)
 1454     {
 1455         if (properties == NULL)
 1456             throw ParameterIncorrect (SRC_POS);
 1457 
 1458         CallDriver (TC_IOCTL_GET_BOOT_DRIVE_VOLUME_PROPERTIES, NULL, 0, properties, sizeof (*properties));
 1459     }
 1460 
 1461 
 1462     bool BootEncryption::IsHiddenSystemRunning ()
 1463     {
 1464         int hiddenSystemStatus;
 1465 
 1466         CallDriver (TC_IOCTL_IS_HIDDEN_SYSTEM_RUNNING, nullptr, 0, &hiddenSystemStatus, sizeof (hiddenSystemStatus));
 1467         return hiddenSystemStatus != 0;
 1468     }
 1469 
 1470 
 1471     bool BootEncryption::SystemDriveContainsPartitionType (byte type)
 1472     {
 1473         Device device (GetSystemDriveConfiguration().DevicePath, true);
 1474         device.CheckOpened (SRC_POS);
 1475 
 1476         byte mbrBuf[TC_SECTOR_SIZE_BIOS];
 1477         device.SeekAt (0);
 1478         device.Read (mbrBuf, sizeof (mbrBuf));
 1479 
 1480         MBR *mbr = reinterpret_cast <MBR *> (mbrBuf);
 1481         if (mbr->Signature != 0xaa55)
 1482             throw ParameterIncorrect (SRC_POS);
 1483 
 1484         for (size_t i = 0; i < array_capacity (mbr->Partitions); ++i)
 1485         {
 1486             if (mbr->Partitions[i].Type == type)
 1487                 return true;
 1488         }
 1489 
 1490         return false;
 1491     }
 1492 
 1493 
 1494     bool BootEncryption::SystemDriveContainsExtendedPartition ()
 1495     {
 1496         return SystemDriveContainsPartitionType (PARTITION_EXTENDED) || SystemDriveContainsPartitionType (PARTITION_XINT13_EXTENDED);
 1497     }
 1498 
 1499 
 1500     bool BootEncryption::SystemDriveContainsNonStandardPartitions ()
 1501     {
 1502         for (int partitionType = 1; partitionType <= 0xff; ++partitionType)
 1503         {
 1504             switch (partitionType)
 1505             {
 1506             case PARTITION_FAT_12:
 1507             case PARTITION_FAT_16:
 1508             case PARTITION_EXTENDED:
 1509             case PARTITION_HUGE:
 1510             case PARTITION_IFS:
 1511             case PARTITION_FAT32:
 1512             case PARTITION_FAT32_XINT13:
 1513             case PARTITION_XINT13:
 1514             case PARTITION_XINT13_EXTENDED:
 1515                 continue;
 1516             }
 1517 
 1518             if (SystemDriveContainsPartitionType ((byte) partitionType))
 1519                 return true;
 1520         }
 1521 
 1522         return false;
 1523     }
 1524 
 1525 
 1526     bool BootEncryption::SystemDriveIsDynamic ()
 1527     {
 1528         GetSystemDriveConfigurationRequest request;
 1529         memset (&request, 0, sizeof (request));
 1530         StringCchCopyW (request.DevicePath, ARRAYSIZE (request.DevicePath), GetSystemDriveConfiguration().DeviceKernelPath.c_str());
 1531 
 1532         CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
 1533         return request.DriveIsDynamic ? true : false;
 1534     }
 1535 
 1536 
 1537     SystemDriveConfiguration BootEncryption::GetSystemDriveConfiguration ()
 1538     {
 1539         if (DriveConfigValid)
 1540             return DriveConfig;
 1541 
 1542         SystemDriveConfiguration config;
 1543 
 1544         wstring winDir = GetWindowsDirectory();
 1545 
 1546         // Scan all drives
 1547         for (int driveNumber = 0; driveNumber < 32; ++driveNumber)
 1548         {
 1549             bool windowsFound = false;
 1550             bool activePartitionFound = false;
 1551             config.ExtraBootPartitionPresent = false;
 1552             config.SystemLoaderPresent = false;
 1553 
 1554             PartitionList partitions = GetDrivePartitions (driveNumber);
 1555             foreach (const Partition &part, partitions)
 1556             {
 1557                 if (!part.MountPoint.empty()
 1558                     && (_waccess ((part.MountPoint + L"\\bootmgr").c_str(), 0) == 0 || _waccess ((part.MountPoint + L"\\ntldr").c_str(), 0) == 0))
 1559                 {
 1560                     config.SystemLoaderPresent = true;
 1561                 }
 1562                 else if (!part.VolumeNameId.empty()
 1563                     && (_waccess ((part.VolumeNameId + L"\\bootmgr").c_str(), 0) == 0 || _waccess ((part.VolumeNameId + L"\\ntldr").c_str(), 0) == 0))
 1564                 {
 1565                     config.SystemLoaderPresent = true;
 1566                 }
 1567 
 1568                 if (!windowsFound && !part.MountPoint.empty() && ToUpperCase (winDir).find (ToUpperCase (part.MountPoint)) == 0)
 1569                 {
 1570                     config.SystemPartition = part;
 1571                     windowsFound = true;
 1572                 }
 1573 
 1574                 if (!activePartitionFound && part.Info.BootIndicator)
 1575                 {
 1576                     activePartitionFound = true;
 1577 
 1578                     if (part.Info.PartitionLength.QuadPart > 0 && part.Info.PartitionLength.QuadPart <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE)
 1579                         config.ExtraBootPartitionPresent = true;
 1580                 }
 1581             }
 1582 
 1583             if (windowsFound)
 1584             {
 1585                 config.DriveNumber = driveNumber;
 1586 
 1587                 wstringstream ss;
 1588                 ss << L"PhysicalDrive" << driveNumber;
 1589                 config.DevicePath = ss.str();
 1590 
 1591                 wstringstream kernelPath;
 1592                 kernelPath << L"\\Device\\Harddisk" << driveNumber << L"\\Partition0";
 1593                 config.DeviceKernelPath = kernelPath.str();
 1594 
 1595                 config.DrivePartition = partitions.front();
 1596                 partitions.pop_front();
 1597                 config.Partitions = partitions;
 1598 
 1599                 config.InitialUnallocatedSpace = 0x7fffFFFFffffFFFFull;
 1600                 config.TotalUnallocatedSpace = config.DrivePartition.Info.PartitionLength.QuadPart;
 1601 
 1602                 foreach (const Partition &part, config.Partitions)
 1603                 {
 1604                     if (part.Info.StartingOffset.QuadPart < config.InitialUnallocatedSpace)
 1605                         config.InitialUnallocatedSpace = part.Info.StartingOffset.QuadPart;
 1606 
 1607                     config.TotalUnallocatedSpace -= part.Info.PartitionLength.QuadPart;
 1608                 }
 1609 
 1610                 DriveConfig = config;
 1611                 DriveConfigValid = true;
 1612                 return DriveConfig;
 1613             }
 1614         }
 1615 
 1616         throw ParameterIncorrect (SRC_POS);
 1617     }
 1618 
 1619 
 1620     bool BootEncryption::SystemPartitionCoversWholeDrive ()
 1621     {
 1622         SystemDriveConfiguration config = GetSystemDriveConfiguration();
 1623 
 1624         if (IsOSAtLeast (WIN_7)
 1625             && config.Partitions.size() == 2
 1626             && config.ExtraBootPartitionPresent
 1627             && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 164 * BYTES_PER_MB)
 1628         {
 1629             return true;
 1630         }
 1631 
 1632         return config.Partitions.size() == 1
 1633             && config.DrivePartition.Info.PartitionLength.QuadPart - config.SystemPartition.Info.PartitionLength.QuadPart < 64 * BYTES_PER_MB;
 1634     }
 1635 
 1636 
 1637     uint32 BootEncryption::GetChecksum (byte *data, size_t size)
 1638     {
 1639         uint32 sum = 0;
 1640 
 1641         while (size-- > 0)
 1642         {
 1643             sum += *data++;
 1644             sum = _rotl (sum, 1);
 1645         }
 1646 
 1647         return sum;
 1648     }
 1649 
 1650 
 1651     void BootEncryption::CreateBootLoaderInMemory (byte *buffer, size_t bufferSize, bool rescueDisk, bool hiddenOSCreation)
 1652     {
 1653         if (bufferSize < TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE)
 1654             throw ParameterIncorrect (SRC_POS);
 1655 
 1656         ZeroMemory (buffer, bufferSize);
 1657 
 1658         int ea = 0;
 1659         int pkcs5_prf = 0;
 1660         BOOL bIsGPT = GetSystemDriveConfiguration().SystemPartition.IsGPT;
 1661         if (GetStatus().DriveMounted)
 1662         {
 1663             try
 1664             {
 1665                 GetBootEncryptionAlgorithmNameRequest request;
 1666                 // since we added new field to GetBootEncryptionAlgorithmNameRequest since version 1.0f
 1667                 // we zero all the structure so that if we are talking to an older driver, the field
 1668                 // BootPrfAlgorithmName will be an empty string
 1669                 ZeroMemory(&request, sizeof(request));
 1670                 CallDriver (TC_IOCTL_GET_BOOT_ENCRYPTION_ALGORITHM_NAME, NULL, 0, &request, sizeof (request));
 1671 
 1672                 if (_stricmp (request.BootEncryptionAlgorithmName, "AES") == 0)
 1673                     ea = AES;
 1674                 else if (_stricmp (request.BootEncryptionAlgorithmName, "Serpent") == 0)
 1675                     ea = SERPENT;
 1676                 else if (_stricmp (request.BootEncryptionAlgorithmName, "Twofish") == 0)
 1677                     ea = TWOFISH;
 1678                 else if (_stricmp (request.BootEncryptionAlgorithmName, "Camellia") == 0)
 1679                     ea = CAMELLIA;
 1680 #if defined(CIPHER_GOST89)
 1681                 else if (_stricmp (request.BootEncryptionAlgorithmName, "GOST89") == 0)
 1682                     ea = GOST89;
 1683 #endif
 1684 
 1685                 if (_stricmp(request.BootPrfAlgorithmName, "SHA-256") == 0)
 1686                     pkcs5_prf = SHA256;
 1687                 else if (_stricmp(request.BootPrfAlgorithmName, "RIPEMD-160") == 0)
 1688                     pkcs5_prf = RIPEMD160;
 1689                 else if (_stricmp(request.BootPrfAlgorithmName, "SHA-512") == 0)
 1690                     pkcs5_prf = SHA512;
 1691                 else if (_stricmp(request.BootPrfAlgorithmName, "Whirlpool") == 0)
 1692                     pkcs5_prf = WHIRLPOOL;
 1693                 else if (_stricmp(request.BootPrfAlgorithmName, "Streebog") == 0)
 1694                     pkcs5_prf = STREEBOG;
 1695                 else if (strlen(request.BootPrfAlgorithmName) == 0) // case of version < 1.0f
 1696                     pkcs5_prf = RIPEMD160;
 1697             }
 1698             catch (...)
 1699             {
 1700                 try
 1701                 {
 1702                     VOLUME_PROPERTIES_STRUCT properties;
 1703                     GetVolumeProperties (&properties);
 1704                     ea = properties.ea;
 1705                     pkcs5_prf = properties.pkcs5;
 1706                 }
 1707                 catch (...) { }
 1708             }
 1709 
 1710             if (pkcs5_prf == 0)
 1711                 throw ParameterIncorrect (SRC_POS);
 1712         }
 1713         else
 1714         {
 1715             if (SelectedEncryptionAlgorithmId == 0 || SelectedPrfAlgorithmId == 0)
 1716                 throw ParameterIncorrect (SRC_POS);
 1717 
 1718             ea = SelectedEncryptionAlgorithmId;
 1719             pkcs5_prf = SelectedPrfAlgorithmId;
 1720         }
 1721 
 1722         // Only RIPEMD160 and SHA-256 are supported for MBR boot loader     
 1723         if (!bIsGPT && pkcs5_prf != RIPEMD160 && pkcs5_prf != SHA256)
 1724             throw ParameterIncorrect (SRC_POS);
 1725 
 1726         int bootSectorId = 0;
 1727         int bootLoaderId = 0;
 1728 
 1729         if (pkcs5_prf == SHA256)
 1730         {
 1731             bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SHA2 : IDR_BOOT_SECTOR_SHA2;
 1732             bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SHA2 : IDR_BOOT_LOADER_SHA2;
 1733         }
 1734         else
 1735         {
 1736             bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR : IDR_BOOT_SECTOR;
 1737             bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER : IDR_BOOT_LOADER;
 1738         }
 1739 
 1740         switch (ea)
 1741         {
 1742         case AES:
 1743             if (pkcs5_prf == SHA256)
 1744             {
 1745                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES_SHA2 : IDR_BOOT_SECTOR_AES_SHA2;
 1746                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES_SHA2 : IDR_BOOT_LOADER_AES_SHA2;
 1747             }
 1748             else
 1749             {
 1750                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_AES : IDR_BOOT_SECTOR_AES;
 1751                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_AES : IDR_BOOT_LOADER_AES;
 1752             }
 1753             break;
 1754 
 1755         case SERPENT:
 1756             if (pkcs5_prf == SHA256)
 1757             {
 1758                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT_SHA2 : IDR_BOOT_SECTOR_SERPENT_SHA2;
 1759                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT_SHA2 : IDR_BOOT_LOADER_SERPENT_SHA2;
 1760             }
 1761             else
 1762             {
 1763                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_SERPENT : IDR_BOOT_SECTOR_SERPENT;
 1764                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_SERPENT : IDR_BOOT_LOADER_SERPENT;
 1765             }
 1766             break;
 1767 
 1768         case TWOFISH:
 1769             if (pkcs5_prf == SHA256)
 1770             {
 1771                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH_SHA2 : IDR_BOOT_SECTOR_TWOFISH_SHA2;
 1772                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH_SHA2 : IDR_BOOT_LOADER_TWOFISH_SHA2;
 1773             }
 1774             else
 1775             {
 1776                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_TWOFISH : IDR_BOOT_SECTOR_TWOFISH;
 1777                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_TWOFISH : IDR_BOOT_LOADER_TWOFISH;
 1778             }
 1779             break;
 1780             
 1781         case CAMELLIA:
 1782             if (pkcs5_prf == SHA256)
 1783             {
 1784                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_CAMELLIA_SHA2 : IDR_BOOT_SECTOR_CAMELLIA_SHA2;
 1785                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_CAMELLIA_SHA2 : IDR_BOOT_LOADER_CAMELLIA_SHA2;
 1786             }
 1787             else
 1788             {
 1789                 bootSectorId = rescueDisk ? IDR_RESCUE_BOOT_SECTOR_CAMELLIA : IDR_BOOT_SECTOR_CAMELLIA;
 1790                 bootLoaderId = rescueDisk ? IDR_RESCUE_LOADER_CAMELLIA : IDR_BOOT_LOADER_CAMELLIA;
 1791             }
 1792             break;
 1793         }
 1794 
 1795         // Boot sector
 1796         DWORD size;
 1797         byte *bootSecResourceImg = MapResource (L"BIN", bootSectorId, &size);
 1798         if (!bootSecResourceImg || size != TC_SECTOR_SIZE_BIOS)
 1799             throw ParameterIncorrect (SRC_POS);
 1800 
 1801         memcpy (buffer, bootSecResourceImg, size);
 1802 
 1803         *(uint16 *) (buffer + TC_BOOT_SECTOR_VERSION_OFFSET) = BE16 (VERSION_NUM);
 1804 
 1805         if (IsOSAtLeast (WIN_VISTA))
 1806             buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_WINDOWS_VISTA_OR_LATER;
 1807 
 1808         if (rescueDisk && (ReadDriverConfigurationFlags() & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION))
 1809             buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISABLE_HW_ENCRYPTION;
 1810 
 1811         // Checksum of the backup header of the outer volume for the hidden system
 1812         if (hiddenOSCreation)
 1813         {
 1814             Device device (GetSystemDriveConfiguration().DevicePath);
 1815             device.CheckOpened (SRC_POS);
 1816             byte headerSector[TC_SECTOR_SIZE_BIOS];
 1817 
 1818             device.SeekAt (HiddenOSCandidatePartition.Info.StartingOffset.QuadPart + HiddenOSCandidatePartition.Info.PartitionLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE + TC_VOLUME_HEADER_EFFECTIVE_SIZE);
 1819             device.Read (headerSector, sizeof (headerSector));
 1820 
 1821             *(uint32 *) (buffer + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET) = GetCrc32 (headerSector, sizeof (headerSector));
 1822         }
 1823 
 1824         // Decompressor
 1825         byte *decompressor = MapResource (L"BIN", IDR_BOOT_LOADER_DECOMPRESSOR, &size);
 1826         if (!decompressor || size > TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS)
 1827             throw ParameterIncorrect (SRC_POS);
 1828 
 1829         memcpy (buffer + TC_SECTOR_SIZE_BIOS, decompressor, size);
 1830 
 1831         // Compressed boot loader
 1832         byte *bootLoader = MapResource (L"BIN", bootLoaderId, &size);
 1833         if (!bootLoader || size > TC_MAX_BOOT_LOADER_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS)
 1834             throw ParameterIncorrect (SRC_POS);
 1835 
 1836         memcpy (buffer + TC_SECTOR_SIZE_BIOS + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS, bootLoader, size);
 1837 
 1838         // Boot loader and decompressor checksum
 1839         *(uint16 *) (buffer + TC_BOOT_SECTOR_LOADER_LENGTH_OFFSET) = static_cast <uint16> (size);
 1840         *(uint32 *) (buffer + TC_BOOT_SECTOR_LOADER_CHECKSUM_OFFSET) = GetChecksum (buffer + TC_SECTOR_SIZE_BIOS,
 1841             TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS + size);
 1842 
 1843         // Backup of decompressor and boot loader
 1844         if (size + TC_BOOT_LOADER_DECOMPRESSOR_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS <= TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS)
 1845         {
 1846             memcpy (buffer + TC_SECTOR_SIZE_BIOS + TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS,
 1847                 buffer + TC_SECTOR_SIZE_BIOS, TC_BOOT_LOADER_BACKUP_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS);
 1848 
 1849             buffer[TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_BACKUP_LOADER_AVAILABLE;
 1850         }
 1851         else if (!rescueDisk && bootLoaderId != IDR_BOOT_LOADER && bootLoaderId != IDR_BOOT_LOADER_SHA2)
 1852         {
 1853             throw ParameterIncorrect (SRC_POS);
 1854         }
 1855     }
 1856 
 1857     // return false when the user cancel an elevation request
 1858     bool BootEncryption::ReadBootSectorConfig (byte *config, size_t bufLength, byte *userConfig, string *customUserMessage, uint16 *bootLoaderVersion)
 1859     {
 1860         bool bCanceled = false, bExceptionOccured = false;
 1861         try
 1862         {
 1863             if (GetSystemDriveConfiguration().SystemPartition.IsGPT)
 1864             {
 1865                 // for now, we don't support any boot config flags, like hidden OS one
 1866                 if (config)
 1867                     memset (config, 0, bufLength);
 1868 
 1869                 // call ReadESPFile only when needed since it requires elevation
 1870                 if (userConfig || customUserMessage || bootLoaderVersion)
 1871                 {
 1872                     std::string confContent = ReadESPFile (L"\\EFI\\VeraCrypt\\DcsProp", true);
 1873 
 1874                     EfiBootConf conf;
 1875                     conf.Load ((char*) confContent.c_str());
 1876 
 1877                     if (userConfig)
 1878                     {
 1879                         *userConfig = 0;
 1880                         if (!conf.requestPim)
 1881                             *userConfig |= TC_BOOT_USER_CFG_FLAG_DISABLE_PIM;
 1882                         if (!conf.requestHash)
 1883                             *userConfig |= TC_BOOT_USER_CFG_FLAG_STORE_HASH;
 1884 
 1885                     }
 1886 
 1887                     if (customUserMessage)
 1888                         customUserMessage->clear();
 1889 
 1890                     if (bootLoaderVersion)
 1891                     {
 1892                         *bootLoaderVersion = GetStatus().BootLoaderVersion;
 1893                     }
 1894                 }
 1895             }
 1896             else
 1897             {
 1898                 if (config && bufLength < TC_BOOT_CFG_FLAG_AREA_SIZE)
 1899                     throw ParameterIncorrect (SRC_POS);
 1900 
 1901                 GetSystemDriveConfigurationRequest request;
 1902                 memset (&request, 0, sizeof (request));
 1903                 StringCchCopyW (request.DevicePath, ARRAYSIZE (request.DevicePath), GetSystemDriveConfiguration().DeviceKernelPath.c_str());
 1904 
 1905                 CallDriver (TC_IOCTL_GET_SYSTEM_DRIVE_CONFIG, &request, sizeof (request), &request, sizeof (request));
 1906                 if (config)
 1907                     *config = request.Configuration;
 1908 
 1909                 if (userConfig)
 1910                     *userConfig = request.UserConfiguration;
 1911                 
 1912                 if (customUserMessage)
 1913                 {
 1914                     request.CustomUserMessage[TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH] = 0;
 1915                     *customUserMessage = request.CustomUserMessage;
 1916                 }
 1917 
 1918                 if (bootLoaderVersion)
 1919                     *bootLoaderVersion = request.BootLoaderVersion;
 1920             }
 1921         }
 1922         catch (UserAbort&)
 1923         {
 1924             bCanceled = true;
 1925             bExceptionOccured= true;
 1926         }
 1927         catch (...)
 1928         {
 1929             bExceptionOccured = true;
 1930         }
 1931 
 1932         if (bExceptionOccured)
 1933         {
 1934             if (config)
 1935                 *config = 0;
 1936 
 1937             if (userConfig)
 1938                 *userConfig = 0;
 1939             
 1940             if (customUserMessage)
 1941                 customUserMessage->clear();
 1942 
 1943             if (bootLoaderVersion)
 1944                 *bootLoaderVersion = 0;
 1945         }
 1946 
 1947         return !bCanceled;
 1948     }
 1949 
 1950 
 1951     void BootEncryption::WriteBootSectorConfig (const byte newConfig[])
 1952     {
 1953         Device device (GetSystemDriveConfiguration().DevicePath);
 1954         device.CheckOpened (SRC_POS);
 1955         byte mbr[TC_SECTOR_SIZE_BIOS];
 1956 
 1957         device.SeekAt (0);
 1958         device.Read (mbr, sizeof (mbr));
 1959 
 1960         memcpy (mbr + TC_BOOT_SECTOR_CONFIG_OFFSET, newConfig, TC_BOOT_CFG_FLAG_AREA_SIZE);
 1961 
 1962         device.SeekAt (0);
 1963         device.Write (mbr, sizeof (mbr));
 1964 
 1965         byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
 1966         device.SeekAt (0);
 1967         device.Read (mbrVerificationBuf, sizeof (mbr));
 1968 
 1969         if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
 1970             throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
 1971     }
 1972 
 1973     void BootEncryption::WriteEfiBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim, int hashAlg)
 1974     {
 1975         if (!IsAdmin() && IsUacSupported())
 1976         {
 1977             Elevator::WriteEfiBootSectorUserConfig (userConfig, customUserMessage, pim, hashAlg);
 1978         }
 1979         else
 1980         {
 1981             finally_do ({ EfiBootInst.DismountBootPartition(); });
 1982             EfiBootInst.MountBootPartition(0);
 1983 
 1984             if (! (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM))
 1985                 pim = -1;
 1986             if (! (userConfig & TC_BOOT_USER_CFG_FLAG_STORE_HASH))
 1987                 hashAlg = -1;               
 1988 
 1989             EfiBootInst.UpdateConfig (L"\\EFI\\VeraCrypt\\DcsProp", pim, hashAlg, ParentWindow);
 1990         }
 1991     }
 1992 
 1993     void BootEncryption::WriteBootSectorUserConfig (byte userConfig, const string &customUserMessage, int pim, int hashAlg)
 1994     {
 1995         if (GetSystemDriveConfiguration().SystemPartition.IsGPT)
 1996         {
 1997             WriteEfiBootSectorUserConfig (userConfig, customUserMessage, pim, hashAlg);
 1998         }
 1999         else
 2000         {
 2001             Device device (GetSystemDriveConfiguration().DevicePath);
 2002             device.CheckOpened (SRC_POS);
 2003             byte mbr[TC_SECTOR_SIZE_BIOS];
 2004 
 2005             device.SeekAt (0);
 2006             device.Read (mbr, sizeof (mbr));
 2007 
 2008             if (!BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME)
 2009                 || BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET)) != VERSION_NUM)
 2010             {
 2011                 return;
 2012             }
 2013 
 2014             mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = userConfig;
 2015 
 2016             memset (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, 0, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
 2017 
 2018             if (!customUserMessage.empty())
 2019             {
 2020                 if (customUserMessage.size() > TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)
 2021                     throw ParameterIncorrect (SRC_POS);
 2022 
 2023                 memcpy (mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, customUserMessage.c_str(), customUserMessage.size());
 2024             }
 2025             
 2026             if (userConfig & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM)
 2027             {
 2028                 // PIM for pre-boot authentication can be encoded on two bytes since its maximum
 2029                 // value is 65535 (0xFFFF)
 2030                 memcpy (mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
 2031             }
 2032             else
 2033                 memset (mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, 0, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
 2034 
 2035             device.SeekAt (0);
 2036             device.Write (mbr, sizeof (mbr));
 2037 
 2038             byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
 2039             device.SeekAt (0);
 2040             device.Read (mbrVerificationBuf, sizeof (mbr));
 2041 
 2042             if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
 2043                 throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
 2044         }
 2045     }
 2046 
 2047 
 2048     unsigned int BootEncryption::GetHiddenOSCreationPhase ()
 2049     {
 2050         byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
 2051 
 2052         ReadBootSectorConfig (configFlags, sizeof(configFlags));
 2053 
 2054         return (configFlags[0] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE);
 2055     }
 2056 
 2057 
 2058     void BootEncryption::SetHiddenOSCreationPhase (unsigned int newPhase)
 2059     {
 2060 #if TC_BOOT_CFG_FLAG_AREA_SIZE != 1
 2061 #   error TC_BOOT_CFG_FLAG_AREA_SIZE != 1; revise GetHiddenOSCreationPhase() and SetHiddenOSCreationPhase()
 2062 #endif
 2063         byte configFlags [TC_BOOT_CFG_FLAG_AREA_SIZE];
 2064 
 2065         ReadBootSectorConfig (configFlags, sizeof(configFlags));
 2066 
 2067         configFlags[0] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
 2068 
 2069         configFlags[0] |= newPhase;
 2070 
 2071         WriteBootSectorConfig (configFlags);
 2072     }
 2073 
 2074 
 2075 #ifndef SETUP
 2076 
 2077     void BootEncryption::StartDecoyOSWipe (WipeAlgorithmId wipeAlgorithm)
 2078     {
 2079         if (!IsHiddenOSRunning())
 2080             throw ParameterIncorrect (SRC_POS);
 2081 
 2082         WipeDecoySystemRequest request;
 2083         ZeroMemory (&request, sizeof (request));
 2084 
 2085         request.WipeAlgorithm = wipeAlgorithm;
 2086         
 2087         if (Randinit() != ERR_SUCCESS)
 2088         {
 2089             if (CryptoAPILastError == ERROR_SUCCESS)
 2090                 throw RandInitFailed (SRC_POS, GetLastError ());
 2091             else
 2092                 throw CryptoApiFailed (SRC_POS, CryptoAPILastError);
 2093         }
 2094 
 2095         /* force the display of the random enriching dialog */
 2096         SetRandomPoolEnrichedByUserStatus (FALSE);
 2097 
 2098         UserEnrichRandomPool (ParentWindow);
 2099 
 2100         if (!RandgetBytes (ParentWindow, request.WipeKey, sizeof (request.WipeKey), TRUE))
 2101             throw ParameterIncorrect (SRC_POS);
 2102 
 2103         CallDriver (TC_IOCTL_START_DECOY_SYSTEM_WIPE, &request, sizeof (request), NULL, 0);
 2104 
 2105         burn (&request, sizeof (request));
 2106     }
 2107 
 2108 
 2109     void BootEncryption::AbortDecoyOSWipe ()
 2110     {
 2111         CallDriver (TC_IOCTL_ABORT_DECOY_SYSTEM_WIPE);
 2112     }
 2113 
 2114     
 2115     DecoySystemWipeStatus BootEncryption::GetDecoyOSWipeStatus ()
 2116     {
 2117         DecoySystemWipeStatus status;
 2118         CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_STATUS, NULL, 0, &status, sizeof (status));
 2119         return status;
 2120     }
 2121 
 2122 
 2123     void BootEncryption::CheckDecoyOSWipeResult ()
 2124     {
 2125         CallDriver (TC_IOCTL_GET_DECOY_SYSTEM_WIPE_RESULT);
 2126     }
 2127 
 2128 
 2129     void BootEncryption::WipeHiddenOSCreationConfig ()
 2130     {
 2131         if (IsHiddenOSRunning())
 2132             throw ParameterIncorrect (SRC_POS);
 2133 
 2134         if (Randinit() != ERR_SUCCESS)
 2135         {
 2136             if (CryptoAPILastError == ERROR_SUCCESS)
 2137                 throw RandInitFailed (SRC_POS, GetLastError ());
 2138             else
 2139                 throw CryptoApiFailed (SRC_POS, CryptoAPILastError);
 2140         }
 2141 
 2142         Device device (GetSystemDriveConfiguration().DevicePath);
 2143         device.CheckOpened(SRC_POS);
 2144         byte mbr[TC_SECTOR_SIZE_BIOS];
 2145 
 2146         device.SeekAt (0);
 2147         device.Read (mbr, sizeof (mbr));
 2148         
 2149         finally_do_arg (BootEncryption *, this,
 2150         {
 2151             try
 2152             {
 2153                 finally_arg->SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
 2154             } catch (...) { }
 2155         });
 2156 
 2157 #if PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
 2158 #   error PRAND_DISK_WIPE_PASSES > RNG_POOL_SIZE
 2159 #endif
 2160 
 2161         byte randData[PRAND_DISK_WIPE_PASSES];
 2162         if (!RandgetBytes (ParentWindow, randData, sizeof (randData), FALSE))
 2163             throw ParameterIncorrect (SRC_POS);
 2164 
 2165         for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
 2166         {
 2167             for (int i = 0; i < TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE; ++i)
 2168             {
 2169                 mbr[TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + i] = randData[wipePass];
 2170             }
 2171 
 2172             mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] &= (byte) ~TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
 2173             mbr[TC_BOOT_SECTOR_CONFIG_OFFSET] |= randData[wipePass] & TC_BOOT_CFG_MASK_HIDDEN_OS_CREATION_PHASE;
 2174 
 2175             if (wipePass == PRAND_DISK_WIPE_PASSES - 1)
 2176                 memset (mbr + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET, 0, TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE);
 2177 
 2178             device.SeekAt (0);
 2179             device.Write (mbr, sizeof (mbr));
 2180         }
 2181 
 2182         for (int wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES/4 + 1; wipePass++)
 2183         {
 2184             SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
 2185             SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_CLONING);
 2186             SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPING);
 2187             SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_WIPED);
 2188         }
 2189         SetHiddenOSCreationPhase (TC_HIDDEN_OS_CREATION_PHASE_NONE);
 2190     }
 2191 
 2192 #endif // !SETUP
 2193 
 2194     NtQuerySystemInformationFn NtQuerySystemInformationPtr = NULL;
 2195 
 2196     EfiBootConf::EfiBootConf() : passwordType (0),
 2197         passwordMsg ("Password: "),
 2198         passwordPicture ("login.bmp"),
 2199         hashMsg ("(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160 (5) STREEBOG\nHash: "),
 2200         hashAlgo (0),
 2201         requestHash (0),
 2202         pimMsg ("PIM (Leave empty for default): "),
 2203         pim (0),
 2204         requestPim (1),
 2205         authorizeVisible (0),
 2206         authorizeRetry (10),
 2207         bmlLockFlags (0),
 2208         bmlDriverEnabled (0)
 2209     {
 2210 
 2211     }
 2212 
 2213     BOOL EfiBootConf::ReadConfigValue (char* configContent, const char *configKey, char *configValue, int maxValueSize)
 2214     {
 2215         char *xml;
 2216 
 2217         xml = configContent;
 2218         if (xml != NULL)
 2219         {
 2220             xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey);
 2221             if (xml != NULL)
 2222             {
 2223                 XmlGetNodeText (xml, configValue, maxValueSize);
 2224                 return TRUE;
 2225             }
 2226         }
 2227 
 2228         return FALSE;
 2229     }
 2230 
 2231 
 2232     int EfiBootConf::ReadConfigInteger (char* configContent, const char *configKey, int defaultValue)
 2233     {
 2234         char s[32];
 2235         int iRet;
 2236         if (ReadConfigValue (configContent, configKey, s, sizeof (s)))
 2237             iRet = atoi (s);
 2238         else
 2239             iRet = defaultValue;
 2240         burn (s, sizeof (s));
 2241         return iRet;
 2242     }
 2243 
 2244 
 2245     char* EfiBootConf::ReadConfigString (char* configContent, const char *configKey, char *defaultValue, char *str, int maxLen)
 2246     {
 2247         if (ReadConfigValue (configContent, configKey, str, maxLen))
 2248             return str;
 2249         else
 2250         {
 2251             StringCbCopyA (str, maxLen, defaultValue);
 2252             return defaultValue;
 2253         }
 2254     }
 2255 
 2256     BOOL EfiBootConf::WriteConfigString (FILE* configFile, char* configContent, const char *configKey, const char *configValue)
 2257     {
 2258         
 2259         BOOL bRet = FALSE;
 2260         if (configFile)
 2261         {
 2262             char *c;
 2263             // Mark previous config value as updated
 2264             if (configContent != NULL)
 2265             {
 2266                 c = XmlFindElementByAttributeValue (configContent, "config", "key", configKey);
 2267                 if (c != NULL)
 2268                     c[1] = '!';
 2269             }
 2270 
 2271             if ( 0 != fwprintf (
 2272                     configFile, L"\n\t\t<config key=\"%hs\">%hs</config>",
 2273                     configKey, configValue))
 2274             {
 2275                 bRet = TRUE;
 2276             }
 2277         }
 2278         return bRet;
 2279     }
 2280 
 2281     BOOL EfiBootConf::WriteConfigInteger (FILE* configFile, char* configContent, const char *configKey, int configValue)
 2282     {
 2283         BOOL bRet = FALSE;
 2284         if (configFile)
 2285         {
 2286             char val[32];
 2287             StringCbPrintfA (val, sizeof(val), "%d", configValue);
 2288             bRet = WriteConfigString (configFile, configContent, configKey, val);
 2289             burn (val, sizeof (val));
 2290         }
 2291         return bRet;
 2292     }
 2293 
 2294     BOOL EfiBootConf::Load (const wchar_t* fileName)
 2295     {
 2296         DWORD size = 0;
 2297         char* configContent = LoadFile (fileName, &size);
 2298         if (configContent)
 2299         {
 2300             Load (configContent);
 2301             burn (configContent, size);
 2302             free (configContent);
 2303             return TRUE;
 2304         }
 2305         else
 2306             return FALSE;
 2307     }
 2308 
 2309     void EfiBootConf::Load (char* configContent)
 2310     {
 2311         char buffer[1024];
 2312 
 2313         passwordType = ReadConfigInteger (configContent, "PasswordType", 0);
 2314         passwordMsg = ReadConfigString (configContent, "PasswordMsg", "Password: ", buffer, sizeof (buffer));
 2315         passwordPicture = ReadConfigString (configContent, "PasswordPicture", "\\EFI\\VeraCrypt\\login.bmp", buffer, sizeof (buffer));
 2316         //hashMsg = ReadConfigString (configContent, "HashMsg", "(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160 (5) STREEBOG\nHash: ", buffer, sizeof (buffer));
 2317         hashAlgo = ReadConfigInteger (configContent, "Hash", 0);
 2318         requestHash = ReadConfigInteger (configContent, "HashRqt", 1);
 2319         pimMsg = ReadConfigString (configContent, "PimMsg", "PIM: ", buffer, sizeof (buffer));
 2320         pim = ReadConfigInteger (configContent, "Pim", 0);
 2321         requestPim = ReadConfigInteger (configContent, "PimRqt", 1);
 2322         authorizeVisible = ReadConfigInteger (configContent, "AuthorizeVisible", 0);
 2323         authorizeRetry = ReadConfigInteger (configContent, "AuthorizeRetry", 0);
 2324         bmlLockFlags = ReadConfigInteger (configContent, "DcsBmlLockFlags", 0);
 2325         bmlDriverEnabled = ReadConfigInteger (configContent, "DcsBmlDriver", 0);
 2326         actionSuccessValue = ReadConfigString (configContent, "ActionSuccess", "postexec file(EFI\\Microsoft\\Boot\\bootmgfw_ms.vc)", buffer, sizeof (buffer));
 2327 
 2328         burn (buffer, sizeof (buffer));
 2329     }
 2330 
 2331     BOOL EfiBootConf::Save (const wchar_t* fileName, HWND hwnd)
 2332     {
 2333 
 2334         BOOL bRet = FALSE;
 2335         DWORD size = 0;
 2336         char* configContent = LoadFile (fileName, &size);
 2337 
 2338         FILE *configFile = _wfopen (fileName, L"w,ccs=UTF-8");
 2339         if (configFile == NULL) {
 2340             burn (configContent, size);
 2341             free (configContent);
 2342             return FALSE;
 2343         }
 2344         
 2345 
 2346         XmlWriteHeader (configFile);
 2347         fputws (L"\n\t<configuration>", configFile);
 2348 
 2349         WriteConfigInteger (configFile, configContent, "PasswordType", passwordType);
 2350         WriteConfigString (configFile, configContent, "PasswordMsg", passwordMsg.c_str());
 2351         WriteConfigString (configFile, configContent, "PasswordPicture", passwordPicture.c_str());
 2352         WriteConfigString (configFile, configContent, "HashMsg", hashMsg.c_str());
 2353         WriteConfigInteger (configFile, configContent, "Hash", hashAlgo);
 2354         WriteConfigInteger (configFile, configContent, "HashRqt", requestHash);
 2355         WriteConfigString (configFile, configContent, "PimMsg", pimMsg.c_str());
 2356         WriteConfigInteger (configFile, configContent, "Pim", pim);
 2357         WriteConfigInteger (configFile, configContent, "PimRqt", requestPim);
 2358         WriteConfigInteger (configFile, configContent, "AuthorizeVisible", authorizeVisible);
 2359         WriteConfigInteger (configFile, configContent, "AuthorizeRetry", authorizeRetry);
 2360         WriteConfigInteger (configFile, configContent, "DcsBmlLockFlags", bmlLockFlags);
 2361         WriteConfigInteger (configFile, configContent, "DcsBmlDriver", bmlDriverEnabled);
 2362         WriteConfigString (configFile, configContent, "ActionSuccess", actionSuccessValue.c_str());
 2363 
 2364         // Write unmodified values
 2365         char* xml = configContent;
 2366         char key[128], value[2048];
 2367         while (xml && (xml = XmlFindElement (xml, "config")))
 2368         {
 2369             XmlGetAttributeText (xml, "key", key, sizeof (key));
 2370             XmlGetNodeText (xml, value, sizeof (value));
 2371 
 2372             fwprintf (configFile, L"\n\t\t<config key=\"%hs\">%hs</config>", key, value);
 2373             xml++;
 2374         }
 2375 
 2376         fputws (L"\n\t</configuration>", configFile);
 2377         XmlWriteFooter (configFile);
 2378 
 2379         TCFlushFile (configFile);
 2380 
 2381         bRet = CheckFileStreamWriteErrors (hwnd, configFile, fileName);
 2382 
 2383         fclose (configFile);
 2384 
 2385         if (configContent != NULL)
 2386         {
 2387             burn (configContent, size);
 2388             free (configContent);
 2389         }
 2390 
 2391         return bRet;
 2392     }
 2393 
 2394     static const wchar_t*   EfiVarGuid = L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}";
 2395 
 2396     void 
 2397     GetVolumeESP(wstring& path) 
 2398     {
 2399         static wstring g_EspPath;
 2400         static bool g_EspPathInitialized = false;
 2401 
 2402         if (!g_EspPathInitialized)
 2403         {
 2404             ULONG    len;
 2405             NTSTATUS res;
 2406             WCHAR tempBuf[1024];
 2407             memset(tempBuf, 0, sizeof(tempBuf));
 2408 
 2409             // Load NtQuerySystemInformation function point
 2410             if (!NtQuerySystemInformationPtr)
 2411             {
 2412                 NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
 2413                 if (!NtQuerySystemInformationPtr)
 2414                     throw SystemException (SRC_POS);
 2415             }
 2416 
 2417             res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
 2418             if (res != S_OK)
 2419             {
 2420                 SetLastError (res);
 2421                 throw SystemException (SRC_POS);
 2422             }       
 2423 
 2424             PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
 2425             g_EspPath = L"\\\\?";
 2426             g_EspPath += &pStr->Buffer[7];
 2427             g_EspPathInitialized = true;
 2428         }
 2429 
 2430         path = g_EspPath;
 2431     }
 2432 
 2433     std::string ReadESPFile (LPCWSTR szFilePath, bool bSkipUTF8BOM)
 2434     {
 2435         if (!szFilePath || !szFilePath[0])
 2436             throw ParameterIncorrect (SRC_POS);
 2437 
 2438         ByteArray fileContent;
 2439         DWORD dwSize = 0, dwOffset = 0;
 2440         std::wstring pathESP;
 2441 
 2442         GetVolumeESP(pathESP);
 2443         if (szFilePath[0] != L'\\')
 2444             pathESP += L"\\";
 2445         File f(pathESP + szFilePath, true);
 2446         f.GetFileSize(dwSize);
 2447         fileContent.resize(dwSize + 1);
 2448         fileContent[dwSize] = 0;
 2449         f.Read(fileContent.data(), dwSize);
 2450         f.Close();
 2451 
 2452         if (bSkipUTF8BOM)
 2453         {
 2454             // remove UTF-8 BOM if any
 2455             if (0 == memcmp (fileContent.data(), "\xEF\xBB\xBF", 3))
 2456             {
 2457                 dwOffset = 3;
 2458             }
 2459         }
 2460 
 2461         return (const char*) &fileContent[dwOffset];
 2462     }
 2463 
 2464     void WriteESPFile (LPCWSTR szFilePath, LPBYTE pbData, DWORD dwDataLen, bool bAddUTF8BOM)
 2465     {
 2466         if (!szFilePath || !szFilePath[0] || !pbData || !dwDataLen)
 2467             throw ParameterIncorrect (SRC_POS);
 2468 
 2469         ByteArray fileContent;
 2470         DWORD dwSize = dwDataLen, dwOffset = 0;
 2471         std::wstring pathESP;
 2472 
 2473         if (bAddUTF8BOM)
 2474         {
 2475             dwSize += 3;
 2476             dwOffset = 3;
 2477         }
 2478 
 2479         GetVolumeESP(pathESP);
 2480         if (szFilePath[0] != L'\\')
 2481             pathESP += L"\\";
 2482 
 2483         fileContent.resize(dwSize);
 2484         if (bAddUTF8BOM)
 2485             memcpy (fileContent.data(), "\xEF\xBB\xBF", 3);
 2486         memcpy (&fileContent[dwOffset], pbData, dwDataLen);
 2487 
 2488         File f(pathESP + szFilePath, false, true);
 2489         f.Write(fileContent.data(), dwSize);
 2490         f.Close();
 2491 
 2492     }
 2493 
 2494     EfiBoot::EfiBoot() {
 2495         ZeroMemory(EfiBootPartPath, sizeof(EfiBootPartPath));       
 2496         ZeroMemory (BootVolumePath, sizeof (BootVolumePath));
 2497         ZeroMemory (&sdn, sizeof (sdn));
 2498         ZeroMemory (&partInfo, sizeof (partInfo));
 2499         m_bMounted = false;
 2500         bBootVolumePathSelected = false;
 2501     }
 2502 
 2503     void EfiBoot::SelectBootVolumeESP() {
 2504         NTSTATUS res;
 2505         ULONG    len;
 2506         memset(tempBuf, 0, sizeof(tempBuf));
 2507 
 2508         // Load NtQuerySystemInformation function point
 2509         if (!NtQuerySystemInformationPtr)
 2510         {
 2511             NtQuerySystemInformationPtr = (NtQuerySystemInformationFn) GetProcAddress (GetModuleHandle (L"ntdll.dll"), "NtQuerySystemInformation");
 2512             if (!NtQuerySystemInformationPtr)
 2513                 throw SystemException (SRC_POS);
 2514         }
 2515 
 2516         res = NtQuerySystemInformationPtr((SYSTEM_INFORMATION_CLASS)SYSPARTITIONINFORMATION, tempBuf, sizeof(tempBuf), &len);
 2517         if (res != S_OK)
 2518         {
 2519             SetLastError (res);
 2520             throw SystemException (SRC_POS);
 2521         }       
 2522 
 2523         PUNICODE_STRING pStr = (PUNICODE_STRING) tempBuf;
 2524         memcpy (BootVolumePath, pStr->Buffer, min (pStr->Length, (sizeof (BootVolumePath) - 2)));
 2525         bBootVolumePathSelected = true;
 2526     }
 2527 
 2528     void EfiBoot::SelectBootVolume(WCHAR* bootVolumePath) {
 2529         wstring str;
 2530         str = bootVolumePath;
 2531         memcpy (BootVolumePath, &str[0], min (str.length() * 2, (sizeof (BootVolumePath) - 2)));
 2532         bBootVolumePathSelected = true;
 2533     }
 2534 
 2535     void EfiBoot::MountBootPartition(WCHAR letter) {
 2536         if (!bBootVolumePathSelected) {
 2537             SelectBootVolumeESP();
 2538         }
 2539 
 2540         if (!letter) {
 2541             if (!GetFreeDriveLetter(&EfiBootPartPath[0])) {
 2542                 throw ErrorException(L"No free letter to mount EFI boot partition", SRC_POS);
 2543             }
 2544         } else {
 2545             EfiBootPartPath[0] = letter;
 2546         }
 2547         EfiBootPartPath[1] = ':';
 2548         EfiBootPartPath[2] = 0;
 2549         throw_sys_if(!DefineDosDevice(DDD_RAW_TARGET_PATH, EfiBootPartPath, BootVolumePath));       
 2550 
 2551         Device  dev(EfiBootPartPath, TRUE);
 2552 
 2553         try
 2554         {
 2555             dev.CheckOpened(SRC_POS);
 2556         }
 2557         catch (...)
 2558         {
 2559             DefineDosDevice(DDD_REMOVE_DEFINITION, EfiBootPartPath, NULL);
 2560             throw;
 2561         }
 2562         
 2563         bool bSuccess = dev.IoCtl(IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn))
 2564                             && dev.IoCtl(IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partInfo, sizeof(partInfo));
 2565         DWORD dwLastError = GetLastError ();
 2566         dev.Close();
 2567         if (!bSuccess)
 2568         {
 2569             DefineDosDevice(DDD_REMOVE_DEFINITION, EfiBootPartPath, NULL);
 2570             SetLastError (dwLastError);
 2571             throw SystemException(SRC_POS);
 2572         }
 2573 
 2574         m_bMounted = true;
 2575     }
 2576 
 2577     void EfiBoot::DismountBootPartition() {
 2578         if (m_bMounted)
 2579         {
 2580             DefineDosDevice(DDD_REMOVE_DEFINITION, EfiBootPartPath, NULL);
 2581             m_bMounted = false;
 2582         }
 2583     }
 2584 
 2585     bool EfiBoot::IsEfiBoot() {
 2586         DWORD BootOrderLen;
 2587         BootOrderLen = GetFirmwareEnvironmentVariable(L"BootOrder", EfiVarGuid, tempBuf, sizeof(tempBuf));
 2588         return BootOrderLen != 0;
 2589     }
 2590 
 2591     void EfiBoot::DeleteStartExec(uint16 statrtOrderNum, wchar_t* type) {
 2592         SetPrivilege(SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
 2593         // Check EFI
 2594         if (!IsEfiBoot()) {
 2595             throw ErrorException(L"can not detect EFI environment", SRC_POS);
 2596         }
 2597         wchar_t varName[256];
 2598         StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
 2599         SetFirmwareEnvironmentVariable(varName, EfiVarGuid, NULL, 0);
 2600 
 2601         wstring order = L"Order";
 2602         order.insert(0, type == NULL ? L"Boot" : type);
 2603         uint32 startOrderLen = GetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, tempBuf, sizeof(tempBuf));
 2604         uint32 startOrderNumPos = UINT_MAX;
 2605         bool    startOrderUpdate = false;
 2606         uint16* startOrder = (uint16*)tempBuf;
 2607         for (uint32 i = 0; i < startOrderLen / 2; i++) {
 2608             if (startOrder[i] == statrtOrderNum) {
 2609                 startOrderNumPos = i;
 2610                 break;
 2611             }
 2612         }
 2613 
 2614         // delete entry if present
 2615         if (startOrderNumPos != UINT_MAX) {
 2616             for (uint32 i = startOrderNumPos; i < ((startOrderLen / 2) - 1); ++i) {
 2617                 startOrder[i] = startOrder[i + 1];
 2618             }
 2619             startOrderLen -= 2;
 2620             startOrderUpdate = true;
 2621         }
 2622 
 2623         if (startOrderUpdate) {
 2624             SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
 2625 
 2626             // remove ourselves from BootNext value
 2627             uint16 bootNextValue = 0;
 2628             wstring next = L"Next";
 2629             next.insert(0, type == NULL ? L"Boot" : type);
 2630 
 2631             if (    (GetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &bootNextValue, 2) == 2)
 2632                 &&  (bootNextValue == statrtOrderNum)
 2633                 )
 2634             {
 2635                 SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, startOrder, 0);
 2636             }
 2637         }
 2638     }
 2639 
 2640     void EfiBoot::SetStartExec(wstring description, wstring execPath, uint16 statrtOrderNum , wchar_t* type, uint32 attr) {
 2641         SetPrivilege(SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
 2642         // Check EFI
 2643         if (!IsEfiBoot()) {
 2644             throw ErrorException(L"can not detect EFI environment", SRC_POS);
 2645         }
 2646         
 2647         uint32 varSize = 56;
 2648         varSize += ((uint32) description.length()) * 2 + 2;
 2649         varSize += ((uint32) execPath.length()) * 2 + 2;
 2650         byte *startVar = new byte[varSize];
 2651         byte *pVar = startVar;
 2652 
 2653         // Attributes (1b Active, 1000b - Hidden)
 2654         *(uint32 *)pVar = attr;
 2655         pVar += sizeof(uint32);
 2656 
 2657         // Size Of device path + file path
 2658         *(uint16 *)pVar = (uint16)(50 + execPath.length() * 2 + 2);
 2659         pVar += sizeof(uint16);
 2660 
 2661         // description
 2662         for (uint32 i = 0; i < description.length(); i++) {
 2663             *(uint16 *)pVar = description[i];
 2664             pVar += sizeof(uint16);
 2665         }
 2666         *(uint16 *)pVar = 0;
 2667         pVar += sizeof(uint16);
 2668 
 2669         /* EFI_DEVICE_PATH_PROTOCOL (HARDDRIVE_DEVICE_PATH \ FILE_PATH \ END) */
 2670 
 2671         // Type
 2672         *(byte *)pVar = 0x04;
 2673         pVar += sizeof(byte);
 2674 
 2675         // SubType
 2676         *(byte *)pVar = 0x01;
 2677         pVar += sizeof(byte);
 2678 
 2679         // HDD dev path length
 2680         *(uint16 *)pVar = 0x2A; // 42
 2681         pVar += sizeof(uint16);
 2682         
 2683         // PartitionNumber
 2684         *(uint32 *)pVar = (uint32)partInfo.PartitionNumber;
 2685         pVar += sizeof(uint32);
 2686 
 2687         // PartitionStart
 2688         *(uint64 *)pVar = partInfo.StartingOffset.QuadPart >> 9;
 2689         pVar += sizeof(uint64);
 2690 
 2691         // PartitiontSize
 2692         *(uint64 *)pVar = partInfo.PartitionLength.QuadPart >> 9;
 2693         pVar += sizeof(uint64);
 2694 
 2695         // GptGuid
 2696         memcpy(pVar, &partInfo.Gpt.PartitionId, 16);
 2697         pVar += 16;
 2698 
 2699         // MbrType
 2700         *(byte *)pVar = 0x02;
 2701         pVar += sizeof(byte);
 2702 
 2703         // SigType
 2704         *(byte *)pVar = 0x02;
 2705         pVar += sizeof(byte);
 2706 
 2707         // Type and sub type 04 04 (file path)
 2708         *(uint16 *)pVar = 0x0404;
 2709         pVar += sizeof(uint16);
 2710 
 2711         // SizeOfFilePath ((CHAR16)FullPath.length + sizeof(EndOfrecord marker) )
 2712         *(uint16 *)pVar = (uint16)(execPath.length() * 2 + 2 + sizeof(uint32));
 2713         pVar += sizeof(uint16);
 2714 
 2715         // FilePath
 2716         for (uint32 i = 0; i < execPath.length(); i++) {
 2717             *(uint16 *)pVar = execPath[i];
 2718             pVar += sizeof(uint16);
 2719         }
 2720         *(uint16 *)pVar = 0;
 2721         pVar += sizeof(uint16);
 2722 
 2723         // EndOfrecord
 2724         *(uint32 *)pVar = 0x04ff7f;
 2725         pVar += sizeof(uint32);
 2726 
 2727         // Set variable
 2728         wchar_t varName[256];
 2729         StringCchPrintfW(varName, ARRAYSIZE (varName), L"%s%04X", type == NULL ? L"Boot" : type, statrtOrderNum);
 2730         SetFirmwareEnvironmentVariable(varName, EfiVarGuid, startVar, varSize);
 2731         delete [] startVar;
 2732 
 2733         // Update order
 2734         wstring order = L"Order";
 2735         order.insert(0, type == NULL ? L"Boot" : type);
 2736 
 2737         uint32 startOrderLen = GetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, tempBuf, sizeof(tempBuf));
 2738         uint32 startOrderNumPos = UINT_MAX;
 2739         bool    startOrderUpdate = false;
 2740         uint16* startOrder = (uint16*)tempBuf;
 2741         for (uint32 i = 0; i < startOrderLen / 2; i++) {
 2742             if (startOrder[i] == statrtOrderNum) {
 2743                 startOrderNumPos = i;
 2744                 break;
 2745             }
 2746         }
 2747 
 2748         // Create new entry if absent
 2749         if (startOrderNumPos == UINT_MAX) {
 2750             for (uint32 i = startOrderLen / 2; i > 0; --i) {
 2751                 startOrder[i] = startOrder[i - 1];
 2752             }
 2753             startOrder[0] = statrtOrderNum;
 2754             startOrderLen += 2;
 2755             startOrderUpdate = true;
 2756         } else if (startOrderNumPos > 0) {
 2757             for (uint32 i = startOrderNumPos; i > 0; --i) {
 2758                 startOrder[i] = startOrder[i - 1];
 2759             }
 2760             startOrder[0] = statrtOrderNum;
 2761             startOrderUpdate = true;
 2762         }
 2763 
 2764         if (startOrderUpdate) {
 2765             SetFirmwareEnvironmentVariable(order.c_str(), EfiVarGuid, startOrder, startOrderLen);
 2766         }
 2767 
 2768         // set BootNext value
 2769         wstring next = L"Next";
 2770         next.insert(0, type == NULL ? L"Boot" : type);
 2771 
 2772         SetFirmwareEnvironmentVariable(next.c_str(), EfiVarGuid, &statrtOrderNum, 2);
 2773 
 2774     }
 2775 
 2776     void EfiBoot::SaveFile(const wchar_t* name, byte* data, DWORD size) {
 2777         wstring path = EfiBootPartPath;
 2778         path += name;
 2779 
 2780         File f(path, false, true);
 2781         f.Write(data, size);
 2782         f.Close();
 2783 
 2784     }
 2785 
 2786     bool EfiBoot::FileExists(const wchar_t* name) {
 2787         wstring path = EfiBootPartPath;
 2788         path += name;
 2789         File f(path, true);
 2790         bool bRet = f.IsOpened ();
 2791         f.Close();
 2792         return bRet;
 2793     }
 2794 
 2795     void EfiBoot::GetFileSize(const wchar_t* name, unsigned __int64& size) {
 2796         wstring path = EfiBootPartPath;
 2797         path += name;
 2798         File f(path, true);
 2799         f.GetFileSize(size);
 2800         f.Close();
 2801     }
 2802 
 2803     void EfiBoot::ReadFile(const wchar_t* name, byte* data, DWORD size) {
 2804         wstring path = EfiBootPartPath;
 2805         path += name;
 2806         File f(path, true);
 2807         f.Read(data, size);
 2808         f.Close();
 2809     }
 2810 
 2811     void EfiBoot::CopyFile(const wchar_t* name, const wchar_t* targetName) {
 2812         wstring path = EfiBootPartPath;
 2813         path += name;
 2814         wstring targetPath;
 2815         if (targetName[0] == L'\\')
 2816         {
 2817             targetPath = EfiBootPartPath;
 2818             targetPath += targetName;
 2819         }
 2820         else
 2821             targetPath = targetName;
 2822         throw_sys_if (!::CopyFileW (path.c_str(), targetPath.c_str(), FALSE));
 2823     }
 2824 
 2825     BOOL EfiBoot::RenameFile(const wchar_t* name, wchar_t* nameNew, BOOL bForce) {
 2826         wstring path = EfiBootPartPath;
 2827         path += name;
 2828         wstring pathNew = EfiBootPartPath;
 2829         pathNew += nameNew;
 2830         return MoveFileExW(path.c_str(), pathNew.c_str(), bForce? MOVEFILE_REPLACE_EXISTING : 0);
 2831     }
 2832 
 2833     BOOL EfiBoot::DelFile(const wchar_t* name) {
 2834         wstring path = EfiBootPartPath;
 2835         path += name;
 2836         return DeleteFile(path.c_str());
 2837     }
 2838 
 2839     BOOL EfiBoot::MkDir(const wchar_t* name, bool& bAlreadyExists) {
 2840         wstring path = EfiBootPartPath;
 2841         path += name;
 2842         bAlreadyExists = false;
 2843         BOOL bRet = CreateDirectory(path.c_str(), NULL);
 2844         if (!bRet && (GetLastError () == ERROR_ALREADY_EXISTS))
 2845         {
 2846             bRet = TRUE;
 2847             bAlreadyExists = true;
 2848         }
 2849         return bRet;
 2850     }
 2851 
 2852     BOOL EfiBoot::DelDir(const wchar_t* name) {
 2853         wstring path = EfiBootPartPath;
 2854         path += name;
 2855         return DeleteDirectory (path.c_str());
 2856     }
 2857 
 2858     BOOL EfiBoot::ReadConfig (const wchar_t* name, EfiBootConf& conf)
 2859     {
 2860         wstring path = EfiBootPartPath;
 2861         path += name;
 2862 
 2863         return conf.Load (path.c_str());
 2864     }
 2865 
 2866     BOOL EfiBoot::UpdateConfig (const wchar_t* name, int pim, int hashAlgo, HWND hwndDlg)
 2867     {
 2868         BOOL bRet = FALSE;
 2869         EfiBootConf conf;
 2870         wstring path = EfiBootPartPath;
 2871         path += name;
 2872 
 2873         if (conf.Load (path.c_str()))
 2874         {
 2875             if (pim >= 0)
 2876             {
 2877                 conf.pim = pim;
 2878                 conf.requestPim = 0;
 2879             }
 2880             else
 2881             {
 2882                 conf.pim = 0;
 2883                 conf.requestPim = 1;
 2884             }
 2885 
 2886             if (hashAlgo >= 0)
 2887             {
 2888                 conf.hashAlgo = hashAlgo;
 2889                 conf.requestHash = 0;
 2890             }
 2891             else
 2892             {
 2893                 conf.hashAlgo = 0;
 2894                 conf.requestHash = 1;
 2895             }
 2896 
 2897             return conf.Save (path.c_str(), hwndDlg);
 2898         }
 2899 
 2900         return bRet;
 2901     }
 2902 
 2903     BOOL EfiBoot::WriteConfig (const wchar_t* name, bool preserveUserConfig, int pim, int hashAlgo, const char* passPromptMsg, HWND hwndDlg)
 2904     {
 2905         EfiBootConf conf;
 2906         wstring path = EfiBootPartPath;
 2907         path += name;
 2908 
 2909         if (preserveUserConfig)
 2910         {
 2911             conf.Load (path.c_str());
 2912             if (pim >= 0 && (conf.requestPim == 0))
 2913             {
 2914                 conf.pim = pim;
 2915             }
 2916             if (hashAlgo >= 0 && (conf.requestHash == 0))
 2917             {
 2918                 conf.hashAlgo = hashAlgo;
 2919             }
 2920         }
 2921         else
 2922         {
 2923             if (pim >= 0)
 2924             {
 2925                 conf.pim = pim;
 2926                 conf.requestPim = 0;
 2927             }
 2928             else
 2929             {
 2930                 conf.pim = 0;
 2931                 conf.requestPim = 1;
 2932             }
 2933 
 2934             if (hashAlgo >= 0)
 2935             {
 2936                 conf.hashAlgo = hashAlgo;
 2937                 conf.requestHash = 0;
 2938             }
 2939             else
 2940             {
 2941                 conf.hashAlgo = 0;
 2942                 conf.requestHash = 1;
 2943             }
 2944         }
 2945 
 2946         if (passPromptMsg && strlen (passPromptMsg))
 2947         {
 2948             conf.passwordMsg = passPromptMsg;
 2949         }
 2950 
 2951         return conf.Save (path.c_str(), hwndDlg);
 2952     }
 2953 
 2954     void BootEncryption::UpdateSetupConfigFile (bool bForInstall)
 2955     {
 2956         // starting from Windows 10 1607 (Build 14393), ReflectDrivers in Setupconfig.ini is supported
 2957         if (IsOSVersionAtLeast (WIN_10, 0) && CurrentOSBuildNumber >= 14393)
 2958         {
 2959             wchar_t szInstallPath [TC_MAX_PATH];
 2960             wchar_t szSetupconfigLocation [TC_MAX_PATH + 20];
 2961 
 2962             if (bForInstall)
 2963             {
 2964                 GetInstallationPath (NULL, szInstallPath, ARRAYSIZE (szInstallPath), NULL);
 2965                 // remove ending backslash
 2966                 if (szInstallPath [wcslen (szInstallPath) - 1] == L'\\')
 2967                 {
 2968                     szInstallPath [wcslen (szInstallPath) - 1] = 0;
 2969                 }
 2970             }
 2971             if (GetSetupconfigLocation (szSetupconfigLocation, ARRAYSIZE (szSetupconfigLocation)))
 2972             {
 2973                 if (bForInstall)
 2974                     ::CreateDirectoryW (szSetupconfigLocation, NULL);
 2975 
 2976                 StringCchCatW (szSetupconfigLocation, ARRAYSIZE (szSetupconfigLocation), L"SetupConfig.ini");
 2977 
 2978                 if (bForInstall)
 2979                 {
 2980                     wstring szPathParam = L"\"";
 2981                     szPathParam += szInstallPath;
 2982                     szPathParam += L"\"";
 2983                     WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", szPathParam.c_str(), szSetupconfigLocation);
 2984 
 2985                     szPathParam = GetProgramConfigPath (L"SetupComplete.cmd");
 2986                     FILE* scriptFile = _wfopen (szPathParam.c_str(), L"w");
 2987                     if (scriptFile)
 2988                     {
 2989                         fwprintf (scriptFile, L"\"%s\\VeraCrypt.exe\" /PostOOBE\n", szInstallPath);
 2990                         fclose (scriptFile);
 2991 
 2992                         WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", szPathParam.c_str(), szSetupconfigLocation);
 2993                     }
 2994                 }
 2995                 else
 2996                 {
 2997                     if (FileExists (szSetupconfigLocation))
 2998                     {
 2999                         WritePrivateProfileStringW (L"SetupConfig", L"ReflectDrivers", NULL, szSetupconfigLocation);
 3000                         WritePrivateProfileStringW (L"SetupConfig", L"PostOOBE", NULL, szSetupconfigLocation);
 3001                     }
 3002 
 3003                     wstring scriptFilePath = GetProgramConfigPath (L"SetupComplete.cmd");
 3004                     if (FileExists (scriptFilePath.c_str()))
 3005                     {
 3006                         ::DeleteFileW (scriptFilePath.c_str());
 3007                     }
 3008                 }
 3009             }
 3010         }
 3011     }
 3012 
 3013     void BootEncryption::InstallBootLoader (bool preserveUserConfig, bool hiddenOSCreation, int pim, int hashAlg)
 3014     {
 3015         Device device (GetSystemDriveConfiguration().DevicePath);
 3016         device.CheckOpened (SRC_POS);
 3017 
 3018         InstallBootLoader (device, preserveUserConfig, hiddenOSCreation, pim, hashAlg);
 3019     }
 3020 
 3021     void BootEncryption::InstallBootLoader (Device& device, bool preserveUserConfig, bool hiddenOSCreation, int pim, int hashAlg)
 3022     {
 3023         SystemDriveConfiguration config = GetSystemDriveConfiguration();
 3024 
 3025         if (config.SystemPartition.IsGPT) {
 3026             if (!IsAdmin()) {
 3027                 if (IsUacSupported())
 3028                 {
 3029                     Elevator::InstallEfiBootLoader (preserveUserConfig, hiddenOSCreation, pim, hashAlg);
 3030                     return;
 3031                 }
 3032                 else
 3033                 {
 3034                     Warning ("ADMIN_PRIVILEGES_WARN_DEVICES", ParentWindow);
 3035                 }
 3036             }
 3037             DWORD sizeDcsBoot;
 3038 #ifdef _WIN64
 3039             byte *dcsBootImg = MapResource(L"BIN", IDR_EFI_DCSBOOT, &sizeDcsBoot);
 3040 #else
 3041             byte *dcsBootImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSBOOT : IDR_EFI_DCSBOOT32, &sizeDcsBoot);
 3042 #endif
 3043             if (!dcsBootImg)
 3044                 throw ErrorException(L"Out of resource DcsBoot", SRC_POS);
 3045             DWORD sizeDcsInt;
 3046 #ifdef _WIN64
 3047             byte *dcsIntImg = MapResource(L"BIN", IDR_EFI_DCSINT, &sizeDcsInt);
 3048 #else
 3049             byte *dcsIntImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSINT: IDR_EFI_DCSINT32, &sizeDcsInt);
 3050 #endif
 3051             if (!dcsIntImg)
 3052                 throw ErrorException(L"Out of resource DcsInt", SRC_POS);
 3053             DWORD sizeDcsCfg;
 3054 #ifdef _WIN64
 3055             byte *dcsCfgImg = MapResource(L"BIN", IDR_EFI_DCSCFG, &sizeDcsCfg);
 3056 #else
 3057             byte *dcsCfgImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSCFG: IDR_EFI_DCSCFG32, &sizeDcsCfg);
 3058 #endif
 3059             if (!dcsCfgImg)
 3060                 throw ErrorException(L"Out of resource DcsCfg", SRC_POS);
 3061             DWORD sizeLegacySpeaker;
 3062 #ifdef _WIN64
 3063             byte *LegacySpeakerImg = MapResource(L"BIN", IDR_EFI_LEGACYSPEAKER, &sizeLegacySpeaker);
 3064 #else
 3065             byte *LegacySpeakerImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_LEGACYSPEAKER: IDR_EFI_LEGACYSPEAKER32, &sizeLegacySpeaker);
 3066 #endif
 3067             if (!LegacySpeakerImg)
 3068                 throw ErrorException(L"Out of resource LegacySpeaker", SRC_POS);
 3069 #ifdef VC_EFI_CUSTOM_MODE
 3070             DWORD sizeBootMenuLocker;
 3071 #ifdef _WIN64
 3072             byte *BootMenuLockerImg = MapResource(L"BIN", IDR_EFI_DCSBML, &sizeBootMenuLocker);
 3073 #else
 3074             byte *BootMenuLockerImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSBML: IDR_EFI_DCSBML32, &sizeBootMenuLocker);
 3075 #endif
 3076             if (!BootMenuLockerImg)
 3077                 throw ErrorException(L"Out of resource DcsBml", SRC_POS);
 3078 #endif
 3079             DWORD sizeDcsInfo;
 3080 #ifdef _WIN64
 3081             byte *DcsInfoImg = MapResource(L"BIN", IDR_EFI_DCSINFO, &sizeDcsInfo);
 3082 #else
 3083             byte *DcsInfoImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSINFO: IDR_EFI_DCSINFO32, &sizeDcsInfo);
 3084 #endif
 3085             if (!DcsInfoImg)
 3086                 throw ErrorException(L"Out of resource DcsInfo", SRC_POS);
 3087 
 3088             finally_do ({ EfiBootInst.DismountBootPartition(); });
 3089             EfiBootInst.MountBootPartition(0);          
 3090 
 3091             try
 3092             {
 3093                 // Save modules
 3094                 bool bAlreadyExist;
 3095 
 3096                 if (preserveUserConfig)
 3097                 {
 3098                     bool bModifiedMsBoot = true;
 3099                     const char* g_szMsBootString = "bootmgfw.pdb";
 3100                     unsigned __int64 loaderSize = 0;
 3101                     EfiBootInst.GetFileSize(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", loaderSize);
 3102 
 3103                     if (EfiBootInst.FileExists (L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc"))
 3104                     {
 3105                         if (loaderSize > 32768)
 3106                         {
 3107                             std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
 3108 
 3109                             EfiBootInst.ReadFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", &bootLoaderBuf[0], (DWORD) loaderSize);
 3110 
 3111                             // look for bootmgfw.efi identifiant string
 3112                             if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
 3113                             {
 3114                                 bModifiedMsBoot = false;
 3115                                 // replace the backup with this version
 3116                                 EfiBootInst.RenameFile (L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
 3117                             }
 3118                         }
 3119                     }
 3120                     else
 3121                     {                       
 3122                         // DcsBoot.efi is always smaller than 32KB
 3123                         if (loaderSize > 32768)
 3124                         {
 3125                             std::vector<byte> bootLoaderBuf ((size_t) loaderSize);
 3126 
 3127                             EfiBootInst.ReadFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", &bootLoaderBuf[0], (DWORD) loaderSize);
 3128 
 3129                             // look for bootmgfw.efi identifiant string
 3130                             if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
 3131                                 bModifiedMsBoot = false;
 3132                         }
 3133 
 3134                         if (!bModifiedMsBoot)
 3135                         {
 3136                             EfiBootInst.RenameFile (L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
 3137                         }
 3138                         else
 3139                         {
 3140                             bool bFound = false;
 3141                             EfiBootConf conf;
 3142                             if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
 3143                             {
 3144                                 string actionValue = conf.actionSuccessValue;
 3145                                 std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
 3146 
 3147                                 if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
 3148                                 {
 3149                                     char c;
 3150                                     const char* ptr = strstr (actionValue.c_str(), "file(");
 3151                                     ptr += 5;
 3152                                     wstring loaderPath = L"\\";
 3153                                     while ((c = *ptr))
 3154                                     {
 3155                                         if (c == ')' || c == ' ')
 3156                                             break;
 3157                                         loaderPath += (wchar_t) c;
 3158                                         ptr++;
 3159                                     }
 3160                                     bFound = true;
 3161                                     EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", TRUE);
 3162                                 }
 3163                             }
 3164 
 3165                             if (!bFound)
 3166                                 throw ErrorException ("WINDOWS_EFI_BOOT_LOADER_MISSING", SRC_POS);
 3167                         }
 3168                     }
 3169 
 3170                     if (PostOOBEMode)
 3171                     {
 3172                         // check if bootmgfw.efi has been set again to Microsoft version
 3173                         // if yes, replace it with our bootloader after it was copied to bootmgfw_ms.vc
 3174                         if (!bModifiedMsBoot)
 3175                             EfiBootInst.CopyFile (L"\\EFI\\VeraCrypt\\DcsBoot.efi", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
 3176                         return;
 3177                     }
 3178                 }
 3179 
 3180                 const wchar_t * szStdEfiBootloader = Is64BitOs()? L"\\EFI\\Boot\\bootx64.efi": L"\\EFI\\Boot\\bootia32.efi";
 3181 
 3182                 EfiBootInst.MkDir(L"\\EFI\\VeraCrypt", bAlreadyExist);
 3183                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsBoot.efi", dcsBootImg, sizeDcsBoot);
 3184                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsInt.dcs", dcsIntImg, sizeDcsInt);
 3185                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsCfg.dcs", dcsCfgImg, sizeDcsCfg);
 3186                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\LegacySpeaker.dcs", LegacySpeakerImg, sizeLegacySpeaker);
 3187 #ifdef VC_EFI_CUSTOM_MODE
 3188                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsBml.dcs", BootMenuLockerImg, sizeBootMenuLocker);
 3189 #endif
 3190                 EfiBootInst.SaveFile(L"\\EFI\\VeraCrypt\\DcsInfo.dcs", DcsInfoImg, sizeDcsInfo);
 3191                 if (!preserveUserConfig)
 3192                     EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\PlatformInfo");
 3193                 EfiBootInst.SetStartExec(L"VeraCrypt BootLoader (DcsBoot)", L"\\EFI\\VeraCrypt\\DcsBoot.efi");
 3194 
 3195                 if (EfiBootInst.FileExists (szStdEfiBootloader))
 3196                     EfiBootInst.SaveFile(szStdEfiBootloader, dcsBootImg, sizeDcsBoot);
 3197                 EfiBootInst.SaveFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", dcsBootImg, sizeDcsBoot);
 3198                 // move configuration file from old location (if it exists) to new location
 3199                 // we don't force the move operation if the new location already exists
 3200                 EfiBootInst.RenameFile (L"\\DcsProp", L"\\EFI\\VeraCrypt\\DcsProp", FALSE);
 3201                 EfiBootInst.RenameFile (L"\\DcsBoot", L"\\EFI\\VeraCrypt\\DcsBoot", FALSE);
 3202 
 3203                 // move the original bootloader backup from old location (if it exists) to new location
 3204                 // we don't force the move operation if the new location already exists
 3205                 if (Is64BitOs())
 3206                     EfiBootInst.RenameFile (L"\\EFI\\Boot\\original_bootx64_vc_backup.efi", L"\\EFI\\Boot\\original_bootx64.vc_backup", FALSE);
 3207                 else
 3208                     EfiBootInst.RenameFile (L"\\EFI\\Boot\\original_bootia32_vc_backup.efi", L"\\EFI\\Boot\\original_bootia32.vc_backup", FALSE);
 3209 
 3210                 // Clean beta9
 3211                 EfiBootInst.DelFile(L"\\DcsBoot.efi");
 3212                 EfiBootInst.DelFile(L"\\DcsInt.efi");
 3213                 EfiBootInst.DelFile(L"\\DcsCfg.efi");
 3214                 EfiBootInst.DelFile(L"\\LegacySpeaker.efi");
 3215                 EfiBootInst.DelFile(L"\\DcsBoot");
 3216                 EfiBootInst.DelFile(L"\\DcsProp");
 3217 #ifndef VC_EFI_CUSTOM_MODE
 3218                 // remove DcsBml if it exists since we don't use it in non-custom SecureBoot mode
 3219                 EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsBml.dcs");
 3220 #endif
 3221             }
 3222             catch (...)
 3223             {
 3224                 throw;
 3225             }
 3226 
 3227             EfiBootInst.WriteConfig (L"\\EFI\\VeraCrypt\\DcsProp", preserveUserConfig, pim, hashAlg, NULL, ParentWindow);
 3228         }
 3229         else
 3230         {
 3231             byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
 3232             CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, hiddenOSCreation);
 3233 
 3234             // Write MBR
 3235             byte mbr[TC_SECTOR_SIZE_BIOS];
 3236 
 3237             device.SeekAt (0);
 3238             device.Read (mbr, sizeof (mbr));
 3239 
 3240             if (preserveUserConfig && BufferContainsString (mbr, sizeof (mbr), TC_APP_NAME))
 3241             {
 3242                 uint16 version = BE16 (*(uint16 *) (mbr + TC_BOOT_SECTOR_VERSION_OFFSET));
 3243                 if (version != 0)
 3244                 {
 3245                     bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] = mbr[TC_BOOT_SECTOR_USER_CONFIG_OFFSET];
 3246                     memcpy (bootLoaderBuf + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, mbr + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET, TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH);
 3247 
 3248                     if (bootLoaderBuf[TC_BOOT_SECTOR_USER_CONFIG_OFFSET] & TC_BOOT_USER_CFG_FLAG_DISABLE_PIM)
 3249                     {
 3250                         if (pim >= 0)
 3251                         {
 3252                             memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &pim, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
 3253                         }
 3254                         else
 3255                             memcpy (bootLoaderBuf + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, mbr + TC_BOOT_SECTOR_PIM_VALUE_OFFSET, TC_BOOT_SECTOR_PIM_VALUE_SIZE);
 3256                     }
 3257                 }
 3258             }
 3259 
 3260             memcpy (mbr, bootLoaderBuf, TC_MAX_MBR_BOOT_CODE_SIZE);
 3261 
 3262             device.SeekAt (0);
 3263             device.Write (mbr, sizeof (mbr));
 3264 
 3265             byte mbrVerificationBuf[TC_SECTOR_SIZE_BIOS];
 3266             device.SeekAt (0);
 3267             device.Read (mbrVerificationBuf, sizeof (mbr));
 3268 
 3269             if (memcmp (mbr, mbrVerificationBuf, sizeof (mbr)) != 0)
 3270                 throw ErrorException ("ERROR_MBR_PROTECTED", SRC_POS);
 3271 
 3272             // Write boot loader
 3273             device.SeekAt (TC_SECTOR_SIZE_BIOS);
 3274             device.Write (bootLoaderBuf + TC_SECTOR_SIZE_BIOS, sizeof (bootLoaderBuf) - TC_SECTOR_SIZE_BIOS);
 3275         }
 3276 
 3277         if (!IsAdmin() && IsUacSupported())
 3278         {
 3279             Elevator::UpdateSetupConfigFile (true);
 3280         }
 3281         else
 3282         {
 3283             UpdateSetupConfigFile (true);
 3284         }
 3285     }
 3286 
 3287 #ifndef SETUP
 3288     bool BootEncryption::CheckBootloaderFingerprint (bool bSilent)
 3289     {
 3290         SystemDriveConfiguration config = GetSystemDriveConfiguration();
 3291 
 3292         // return true for now when EFI system encryption is used until we implement
 3293         // a dedicated EFI fingerprinting mechanism in VeraCrypt driver
 3294         if (config.SystemPartition.IsGPT)
 3295             return true;
 3296 
 3297         byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE] = {0};
 3298         byte fingerprint[WHIRLPOOL_DIGESTSIZE + SHA512_DIGESTSIZE];
 3299         byte expectedFingerprint[WHIRLPOOL_DIGESTSIZE + SHA512_DIGESTSIZE];
 3300         bool bRet = false;
 3301 
 3302         try
 3303         {
 3304             // read bootloader fingerprint
 3305             GetInstalledBootLoaderFingerprint (fingerprint);
 3306 
 3307             // compute expected fingerprint
 3308             CreateBootLoaderInMemory (bootLoaderBuf, sizeof (bootLoaderBuf), false, false);
 3309             ::ComputeBootloaderFingerprint (bootLoaderBuf, sizeof (bootLoaderBuf), expectedFingerprint);
 3310 
 3311             // compare values
 3312             if (0 == memcmp (fingerprint, expectedFingerprint, sizeof (expectedFingerprint)))
 3313             {
 3314                 bRet = true;
 3315             }
 3316         }
 3317         catch (SystemException &e)
 3318         {
 3319             if (!bSilent && (GetLastError () != ERROR_INVALID_IMAGE_HASH))
 3320                 e.Show (ParentWindow);
 3321         }
 3322         catch (Exception& e)
 3323         {
 3324             if (!bSilent)
 3325                 e.Show (ParentWindow);
 3326         }
 3327 
 3328         return bRet;
 3329     }
 3330 #endif
 3331 
 3332     wstring BootEncryption::GetSystemLoaderBackupPath ()
 3333     {
 3334         WCHAR pathBuf[MAX_PATH];
 3335 
 3336         throw_sys_if (!SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, pathBuf)));
 3337         
 3338         wstring path = wstring (pathBuf) + L"\\" _T(TC_APP_NAME);
 3339         CreateDirectory (path.c_str(), NULL);
 3340 
 3341         return path + L'\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME;
 3342     }
 3343 
 3344 
 3345     void BootEncryption::RenameDeprecatedSystemLoaderBackup ()
 3346     {
 3347         WCHAR pathBuf[MAX_PATH];
 3348 
 3349         if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA, NULL, 0, pathBuf)))
 3350         {
 3351             wstring path = wstring (pathBuf) + L"\\" _T(TC_APP_NAME) + L'\\' + TC_SYS_BOOT_LOADER_BACKUP_NAME_LEGACY;
 3352 
 3353             if (FileExists (path.c_str()) && !FileExists (GetSystemLoaderBackupPath().c_str()))
 3354                 throw_sys_if (_wrename (path.c_str(), GetSystemLoaderBackupPath().c_str()) != 0);
 3355         }
 3356     }
 3357 
 3358 
 3359 #ifndef SETUP
 3360     void BootEncryption::CreateRescueIsoImage (bool initialSetup, const wstring &isoImagePath)
 3361     {
 3362         BootEncryptionStatus encStatus = GetStatus();
 3363         if (encStatus.SetupInProgress)
 3364             throw ParameterIncorrect (SRC_POS);
 3365         BOOL bIsGPT = GetSystemDriveConfiguration().SystemPartition.IsGPT;
 3366         if (bIsGPT)
 3367         {
 3368             // create EFI disk structure
 3369             DWORD sizeDcsBoot;
 3370 #ifdef _WIN64
 3371             byte *dcsBootImg = MapResource(L"BIN", IDR_EFI_DCSBOOT, &sizeDcsBoot);
 3372 #else
 3373             byte *dcsBootImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSBOOT : IDR_EFI_DCSBOOT32, &sizeDcsBoot);
 3374 #endif
 3375             if (!dcsBootImg)
 3376                 throw ParameterIncorrect (SRC_POS);
 3377             DWORD sizeDcsInt;
 3378 #ifdef _WIN64
 3379             byte *dcsIntImg = MapResource(L"BIN", IDR_EFI_DCSINT, &sizeDcsInt);
 3380 #else
 3381             byte *dcsIntImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSINT: IDR_EFI_DCSINT32, &sizeDcsInt);
 3382 #endif
 3383             if (!dcsIntImg)
 3384                 throw ParameterIncorrect (SRC_POS);
 3385             DWORD sizeDcsCfg;
 3386 #ifdef _WIN64
 3387             byte *dcsCfgImg = MapResource(L"BIN", IDR_EFI_DCSCFG, &sizeDcsCfg);
 3388 #else
 3389             byte *dcsCfgImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSCFG: IDR_EFI_DCSCFG32, &sizeDcsCfg);
 3390 #endif
 3391             if (!dcsCfgImg)
 3392                 throw ParameterIncorrect (SRC_POS);
 3393             DWORD sizeLegacySpeaker;
 3394 #ifdef _WIN64
 3395             byte *LegacySpeakerImg = MapResource(L"BIN", IDR_EFI_LEGACYSPEAKER, &sizeLegacySpeaker);
 3396 #else
 3397             byte *LegacySpeakerImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_LEGACYSPEAKER: IDR_EFI_LEGACYSPEAKER32, &sizeLegacySpeaker);
 3398 #endif
 3399             if (!LegacySpeakerImg)
 3400                 throw ParameterIncorrect (SRC_POS);
 3401 #ifdef VC_EFI_CUSTOM_MODE
 3402             DWORD sizeBootMenuLocker;
 3403 #ifdef _WIN64
 3404             byte *BootMenuLockerImg = MapResource(L"BIN", IDR_EFI_DCSBML, &sizeBootMenuLocker);
 3405 #else
 3406             byte *BootMenuLockerImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSBML: IDR_EFI_DCSBML32, &sizeBootMenuLocker);
 3407 #endif
 3408             if (!BootMenuLockerImg)
 3409                 throw ParameterIncorrect (SRC_POS);
 3410 #endif
 3411             DWORD sizeDcsRescue;
 3412 #ifdef _WIN64
 3413             byte *DcsRescueImg = MapResource(L"BIN", IDR_EFI_DCSRE, &sizeDcsRescue);
 3414 #else
 3415             byte *DcsRescueImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSRE: IDR_EFI_DCSRE32, &sizeDcsRescue);
 3416 #endif
 3417             if (!DcsRescueImg)
 3418                 throw ParameterIncorrect (SRC_POS);
 3419             DWORD sizeDcsInfo;
 3420 #ifdef _WIN64
 3421             byte *DcsInfoImg = MapResource(L"BIN", IDR_EFI_DCSINFO, &sizeDcsInfo);
 3422 #else
 3423             byte *DcsInfoImg = MapResource(L"BIN", Is64BitOs()? IDR_EFI_DCSINFO: IDR_EFI_DCSINFO32, &sizeDcsInfo);
 3424 #endif
 3425             if (!DcsInfoImg)
 3426                 throw ParameterIncorrect (SRC_POS);
 3427 
 3428             char szTmpPath[MAX_PATH + 1], szTmpFilePath[MAX_PATH + 1];
 3429             if (!GetTempPathA (MAX_PATH, szTmpPath))
 3430                 throw SystemException (SRC_POS);
 3431             if (!GetTempFileNameA (szTmpPath, "_vrd", 0, szTmpFilePath))
 3432                 throw SystemException (SRC_POS);
 3433 
 3434             finally_do_arg (char*, szTmpFilePath,  { DeleteFileA (finally_arg);});
 3435 
 3436             int ierr;
 3437             zip_t* z = zip_open (szTmpFilePath, ZIP_CREATE | ZIP_TRUNCATE | ZIP_CHECKCONS, &ierr);
 3438             if (!z)
 3439                 throw ParameterIncorrect (SRC_POS);
 3440 
 3441             finally_do_arg (zip_t**, &z, { if (*finally_arg) zip_discard (*finally_arg);});
 3442 
 3443             if (!ZipAdd (z, Is64BitOs()? "EFI/Boot/bootx64.efi": "EFI/Boot/bootia32.efi", DcsRescueImg, sizeDcsRescue))
 3444                 throw ParameterIncorrect (SRC_POS);
 3445 #ifdef VC_EFI_CUSTOM_MODE
 3446             if (!ZipAdd (z, "EFI/VeraCrypt/DcsBml.dcs", BootMenuLockerImg, sizeBootMenuLocker))
 3447                 throw ParameterIncorrect (SRC_POS);
 3448 #endif
 3449             if (!ZipAdd (z, "EFI/VeraCrypt/DcsBoot.efi", dcsBootImg, sizeDcsBoot))
 3450                 throw ParameterIncorrect (SRC_POS);
 3451             if (!ZipAdd (z, "EFI/VeraCrypt/DcsCfg.dcs", dcsCfgImg, sizeDcsCfg))
 3452                 throw ParameterIncorrect (SRC_POS);
 3453             if (!ZipAdd (z, "EFI/VeraCrypt/DcsInt.dcs", dcsIntImg, sizeDcsInt))
 3454                 throw ParameterIncorrect (SRC_POS);
 3455             if (!ZipAdd (z, "EFI/VeraCrypt/LegacySpeaker.dcs", LegacySpeakerImg, sizeLegacySpeaker))
 3456                 throw ParameterIncorrect (SRC_POS);
 3457             if (!ZipAdd (z, "EFI/VeraCrypt/DcsInfo.dcs", DcsInfoImg, sizeDcsInfo))
 3458                 throw ParameterIncorrect (SRC_POS);
 3459 
 3460             Buffer volHeader(TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 3461 
 3462             // Volume header
 3463             if (initialSetup)
 3464             {
 3465                 if (!RescueVolumeHeaderValid)
 3466                     throw ParameterIncorrect (SRC_POS);
 3467 
 3468                 memcpy (volHeader.Ptr (), RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 3469             }
 3470             else
 3471             {
 3472                 Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
 3473                 bootDevice.CheckOpened (SRC_POS);
 3474                 bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
 3475                 bootDevice.Read (volHeader.Ptr (), TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 3476             }
 3477 
 3478             if (!ZipAdd (z, "EFI/VeraCrypt/svh_bak", volHeader.Ptr (), TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE))
 3479                 throw ParameterIncorrect (SRC_POS);
 3480 
 3481             // Original system loader
 3482             Buffer fileBuf (0);
 3483             bool bLoadAdded = false;
 3484             try
 3485             {
 3486                 DWORD fileSize = 0;
 3487                 File sysBakFile (GetSystemLoaderBackupPath(), true);
 3488                 sysBakFile.CheckOpened (SRC_POS);
 3489                 sysBakFile.GetFileSize(fileSize);
 3490                 fileBuf.Resize ((DWORD) fileSize);
 3491                 DWORD sizeLoader = sysBakFile.Read (fileBuf.Ptr (), fileSize);
 3492                 bLoadAdded = ZipAdd (z, Is64BitOs()? "EFI/Boot/original_bootx64.vc_backup": "EFI/Boot/original_bootia32.vc_backup", fileBuf.Ptr (), sizeLoader);                
 3493             }
 3494             catch (Exception &e)
 3495             {
 3496                 e.Show (ParentWindow);
 3497                 Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK", ParentWindow);
 3498             }
 3499 
 3500             if (!bLoadAdded)
 3501                 throw ParameterIncorrect (SRC_POS);         
 3502 
 3503             EfiBootConf conf;
 3504             Buffer propBuf (0);
 3505             wstring dcsPropFileName = GetTempPathString() + L"_dcsproprescue";
 3506             finally_do_arg (wstring, dcsPropFileName, { DeleteFileW (finally_arg.c_str()); });
 3507             if (conf.Save(dcsPropFileName.c_str(), ParentWindow))
 3508             {
 3509                 DWORD fileSize = 0;
 3510                 File propFile (dcsPropFileName, true, false);
 3511                 propFile.CheckOpened (SRC_POS);
 3512                 propFile.GetFileSize(fileSize);
 3513                 propBuf.Resize (fileSize);
 3514                 DWORD sizeDcsProp = propFile.Read (propBuf.Ptr (), fileSize);
 3515 
 3516                 if (!ZipAdd (z, "EFI/VeraCrypt/DcsProp", propBuf.Ptr (), sizeDcsProp))
 3517                     throw ParameterIncorrect (SRC_POS);
 3518             }
 3519             else
 3520                 throw ParameterIncorrect (SRC_POS);
 3521 
 3522             // flush the zip content to the temporary file
 3523             if (zip_close (z) < 0)
 3524                 throw ParameterIncorrect (SRC_POS);
 3525 
 3526             z = NULL;
 3527 
 3528             // read the zip data from the temporary file
 3529             FILE* ftmpFile = fopen (szTmpFilePath, "rb");
 3530             if (!ftmpFile)
 3531                 throw ParameterIncorrect (SRC_POS);
 3532 
 3533             finally_do_arg (FILE*, ftmpFile, { fclose (finally_arg); });
 3534 
 3535             unsigned long ulZipSize = (unsigned long) _filelength (_fileno (ftmpFile));
 3536             RescueZipData = new byte[ulZipSize];
 3537             if (!RescueZipData)
 3538                 throw bad_alloc();
 3539 
 3540             if (ulZipSize != fread (RescueZipData, 1, ulZipSize, ftmpFile))
 3541             {
 3542                 delete [] RescueZipData;
 3543                 RescueZipData = NULL;
 3544                 throw ParameterIncorrect (SRC_POS);
 3545             }
 3546 
 3547             RescueZipSize = ulZipSize;
 3548 
 3549             if (!isoImagePath.empty())
 3550             {
 3551                 File isoFile (isoImagePath, false, true);
 3552                 isoFile.Write (RescueZipData, RescueZipSize);
 3553             }
 3554         }
 3555         else
 3556         {
 3557             Buffer imageBuf (RescueIsoImageSize);
 3558         
 3559             byte *image = imageBuf.Ptr();
 3560             memset (image, 0, RescueIsoImageSize);
 3561 
 3562             // Primary volume descriptor
 3563             const char* szPrimVolDesc = "\001CD001\001";
 3564             const char* szPrimVolLabel = "VeraCrypt Rescue Disk           ";
 3565             memcpy (image + 0x8000, szPrimVolDesc, strlen(szPrimVolDesc) + 1);
 3566             memcpy (image + 0x7fff + 41, szPrimVolLabel, strlen(szPrimVolLabel) + 1);
 3567             *(uint32 *) (image + 0x7fff + 81) = RescueIsoImageSize / 2048;
 3568             *(uint32 *) (image + 0x7fff + 85) = BE32 (RescueIsoImageSize / 2048);
 3569             image[0x7fff + 121] = 1;
 3570             image[0x7fff + 124] = 1;
 3571             image[0x7fff + 125] = 1;
 3572             image[0x7fff + 128] = 1;
 3573             image[0x7fff + 130] = 8;
 3574             image[0x7fff + 131] = 8;
 3575 
 3576             image[0x7fff + 133] = 10;
 3577             image[0x7fff + 140] = 10;
 3578             image[0x7fff + 141] = 0x14;
 3579             image[0x7fff + 157] = 0x22;
 3580             image[0x7fff + 159] = 0x18;
 3581 
 3582             // Boot record volume descriptor
 3583             const char* szBootRecDesc = "CD001\001EL TORITO SPECIFICATION";
 3584             memcpy (image + 0x8801, szBootRecDesc, strlen(szBootRecDesc) + 1);
 3585             image[0x8800 + 0x47] = 0x19;
 3586 
 3587             // Volume descriptor set terminator
 3588             const char* szVolDescTerm = "\377CD001\001";
 3589             memcpy (image + 0x9000, szVolDescTerm, strlen(szVolDescTerm) + 1);
 3590 
 3591             // Path table
 3592             image[0xA000 + 0] = 1;
 3593             image[0xA000 + 2] = 0x18;
 3594             image[0xA000 + 6] = 1;
 3595 
 3596             // Root directory
 3597             image[0xc000 + 0] = 0x22;
 3598             image[0xc000 + 2] = 0x18;
 3599             image[0xc000 + 9] = 0x18;
 3600             image[0xc000 + 11] = 0x08;
 3601             image[0xc000 + 16] = 0x08;
 3602             image[0xc000 + 25] = 0x02;
 3603             image[0xc000 + 28] = 0x01;
 3604             image[0xc000 + 31] = 0x01;
 3605             image[0xc000 + 32] = 0x01;
 3606             image[0xc000 + 34] = 0x22;
 3607             image[0xc000 + 36] = 0x18;
 3608             image[0xc000 + 43] = 0x18;
 3609             image[0xc000 + 45] = 0x08;
 3610             image[0xc000 + 50] = 0x08;
 3611             image[0xc000 + 59] = 0x02;
 3612             image[0xc000 + 62] = 0x01;
 3613             *(uint32 *) (image + 0xc000 + 65) = 0x010101;
 3614 
 3615             // Validation entry
 3616             image[0xc800] = 1;
 3617             int offset = 0xc800 + 0x1c;
 3618             image[offset++] = 0xaa;
 3619             image[offset++] = 0x55;
 3620             image[offset++] = 0x55;
 3621             image[offset] = 0xaa;
 3622 
 3623             // Initial entry
 3624             offset = 0xc820;
 3625             image[offset++] = 0x88;
 3626             image[offset++] = 2;
 3627             image[0xc820 + 6] = 1;
 3628             image[0xc820 + 8] = TC_CD_BOOT_LOADER_SECTOR;
 3629 
 3630             // TrueCrypt Boot Loader
 3631             CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, true);
 3632 
 3633             // Volume header
 3634             if (initialSetup)
 3635             {
 3636                 if (!RescueVolumeHeaderValid)
 3637                     throw ParameterIncorrect (SRC_POS);
 3638 
 3639                 memcpy (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, RescueVolumeHeader, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 3640             }
 3641             else
 3642             {
 3643                 Device bootDevice (GetSystemDriveConfiguration().DevicePath, true);
 3644                 bootDevice.CheckOpened (SRC_POS);
 3645                 bootDevice.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
 3646                 bootDevice.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 3647             }
 3648 
 3649             // Original system loader
 3650             try
 3651             {
 3652                 File sysBakFile (GetSystemLoaderBackupPath(), true);
 3653                 sysBakFile.CheckOpened (SRC_POS);
 3654                 sysBakFile.Read (image + TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE);
 3655             
 3656                 image[TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_SECTOR_CONFIG_OFFSET] |= TC_BOOT_CFG_FLAG_RESCUE_DISK_ORIG_SYS_LOADER;
 3657             }
 3658             catch (Exception &e)
 3659             {
 3660                 e.Show (ParentWindow);
 3661                 Warning ("SYS_LOADER_UNAVAILABLE_FOR_RESCUE_DISK", ParentWindow);
 3662             }
 3663         
 3664             // Boot loader backup
 3665             CreateBootLoaderInMemory (image + TC_CD_BOOTSECTOR_OFFSET + TC_BOOT_LOADER_BACKUP_RESCUE_DISK_SECTOR_OFFSET, TC_BOOT_LOADER_AREA_SIZE, false);
 3666 
 3667             RescueIsoImage = new byte[RescueIsoImageSize];
 3668             if (!RescueIsoImage)
 3669                 throw bad_alloc();
 3670             memcpy (RescueIsoImage, image, RescueIsoImageSize);
 3671 
 3672             if (!isoImagePath.empty())
 3673             {
 3674                 File isoFile (isoImagePath, false, true);
 3675                 isoFile.Write (image, RescueIsoImageSize);
 3676             }
 3677         }
 3678     }
 3679 #endif
 3680 
 3681 
 3682     bool BootEncryption::IsCDRecorderPresent ()
 3683     {
 3684         ICDBurn* pICDBurn;
 3685         BOOL bHasRecorder = FALSE;
 3686 
 3687         if (SUCCEEDED( CoCreateInstance (CLSID_CDBurn, NULL,CLSCTX_INPROC_SERVER,IID_ICDBurn,(LPVOID*)&pICDBurn)))
 3688         {
 3689             if (pICDBurn->HasRecordableDrive (&bHasRecorder) != S_OK)
 3690             {
 3691                 bHasRecorder = FALSE;
 3692             }
 3693             pICDBurn->Release();
 3694         }
 3695         return bHasRecorder? true : false;
 3696     }
 3697 
 3698 
 3699     bool BootEncryption::VerifyRescueDisk ()
 3700     {
 3701         BOOL bIsGPT = GetSystemDriveConfiguration().SystemPartition.IsGPT;
 3702         if ((bIsGPT && !RescueZipData) || (!bIsGPT && !RescueIsoImage))
 3703             throw ParameterIncorrect (SRC_POS);
 3704 
 3705         if (bIsGPT)
 3706         {
 3707             const wchar_t* efi64Files[] = {
 3708                 L"EFI/Boot/bootx64.efi",
 3709 #ifdef VC_EFI_CUSTOM_MODE
 3710                 L"EFI/VeraCrypt/DcsBml.dcs",
 3711 #endif
 3712                 L"EFI/VeraCrypt/DcsBoot.efi",
 3713                 L"EFI/VeraCrypt/DcsCfg.dcs",
 3714                 L"EFI/VeraCrypt/DcsInt.dcs",
 3715                 L"EFI/VeraCrypt/LegacySpeaker.dcs",
 3716                 L"EFI/VeraCrypt/svh_bak",
 3717                 L"EFI/Boot/original_bootx64.vc_backup"
 3718             };
 3719             
 3720             const wchar_t* efi32Files[] = {
 3721                 L"EFI/Boot/bootia32.efi",
 3722 #ifdef VC_EFI_CUSTOM_MODE
 3723                 L"EFI/VeraCrypt/DcsBml.dcs",
 3724 #endif
 3725                 L"EFI/VeraCrypt/DcsBoot.efi",
 3726                 L"EFI/VeraCrypt/DcsCfg.dcs",
 3727                 L"EFI/VeraCrypt/DcsInt.dcs",
 3728                 L"EFI/VeraCrypt/LegacySpeaker.dcs",
 3729                 L"EFI/VeraCrypt/svh_bak",
 3730                 L"EFI/Boot/original_bootia32.vc_backup"
 3731             };
 3732 
 3733             zip_error_t zerr;
 3734             zip_source_t* zsrc = zip_source_buffer_create (RescueZipData, RescueZipSize, 0, &zerr);
 3735             if (!zsrc)
 3736                 throw ParameterIncorrect (SRC_POS);
 3737             zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr);
 3738             if (!z)
 3739             {
 3740                 zip_source_free (zsrc);
 3741                 throw ParameterIncorrect (SRC_POS);
 3742             }
 3743 
 3744             finally_do_arg (zip_t*, z, { zip_close (finally_arg); });
 3745 
 3746             for (WCHAR drive = L'Z'; drive >= L'C'; --drive)
 3747             {
 3748                 try
 3749                 {
 3750                     WCHAR rootPath[4] = { drive, L':', L'\\', 0};
 3751                     UINT driveType = GetDriveType (rootPath);
 3752                     if (DRIVE_REMOVABLE == driveType)
 3753                     {
 3754                         // check if it is FAT/FAT32
 3755                         WCHAR szNameBuffer[TC_MAX_PATH];
 3756                         if (GetVolumeInformationW (rootPath, NULL, 0, NULL, NULL, NULL, szNameBuffer, ARRAYSIZE(szNameBuffer))
 3757                                 && !wcsncmp (szNameBuffer, L"FAT", 3))
 3758                         {
 3759                             int i;      
 3760                             const wchar_t** efiFiles = Is64BitOs()? efi64Files: efi32Files;
 3761                             int efiFilesSize = Is64BitOs()? ARRAYSIZE(efi64Files): ARRAYSIZE(efi32Files);
 3762                             for (i = 0; i < efiFilesSize; i++)
 3763                             {
 3764                                 bool bMatch = false;
 3765                                 zip_int64_t index = zip_name_locate (z, WideToUtf8String (efiFiles[i]).c_str(), ZIP_FL_NOCASE);
 3766                                 if (index >= 0)
 3767                                 {
 3768                                     zip_stat_t stat;
 3769                                     if ((0 == zip_stat_index (z, index, ZIP_FL_NOCASE, &stat)) && (stat.valid & ZIP_STAT_SIZE))
 3770                                     {
 3771                                         // check that the file exists on the disk and that it has the same content
 3772                                         StringCbCopyW (szNameBuffer, sizeof (szNameBuffer), rootPath);
 3773                                         StringCbCatW (szNameBuffer, sizeof (szNameBuffer), efiFiles[i]);
 3774 
 3775                                         try
 3776                                         {
 3777                                             DWORD dwSize = 0;
 3778                                             File diskFile (szNameBuffer, true);
 3779                                             diskFile.CheckOpened (SRC_POS);
 3780                                             diskFile.GetFileSize (dwSize);
 3781                                             if (dwSize == (DWORD) stat.size)
 3782                                             {
 3783                                                 Buffer fileBuf (dwSize);
 3784                                                 if (dwSize == diskFile.Read (fileBuf.Ptr (), dwSize))
 3785                                                 {
 3786                                                     Buffer efiBuf (dwSize);
 3787                                                     zip_file_t* zf = zip_fopen_index (z, index, 0);
 3788                                                     if (zf)
 3789                                                     {
 3790                                                         if (0 < zip_fread (zf, efiBuf.Ptr (), stat.size))
 3791                                                         {
 3792                                                             bMatch = (memcmp (efiBuf.Ptr(), fileBuf.Ptr(), dwSize) == 0);
 3793                                                         }
 3794                                                         zip_fclose (zf);                                                        
 3795                                                     }
 3796                                                 }
 3797                                             }                                       
 3798                                         }
 3799                                         catch (...)
 3800                                         {
 3801                                         }
 3802                                     }
 3803                                 }
 3804                                 else
 3805                                 {
 3806                                     // entry not found in our Rescue ZIP image. Skip it.
 3807                                     bMatch = true;
 3808                                 }
 3809 
 3810                                 if (!bMatch)
 3811                                     break;
 3812                             }
 3813 
 3814                             if (i == efiFilesSize)
 3815                             {
 3816                                 // All entries processed
 3817                                 return true;
 3818                             }
 3819                         }
 3820                     }
 3821                 }
 3822                 catch (...) { }
 3823             }
 3824         }
 3825         else
 3826         {
 3827             size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
 3828             Buffer buffer ((verifiedSectorCount + 1) * 2048);
 3829             for (WCHAR drive = L'Z'; drive >= L'C'; --drive)
 3830             {
 3831                 try
 3832                 {
 3833                     WCHAR rootPath[4] = { drive, L':', L'\\', 0};
 3834                     UINT driveType = GetDriveType (rootPath);
 3835                     // check that it is a CD/DVD drive or a removable media in case a bootable
 3836                     // USB key was created from the rescue disk ISO file
 3837                     if ((DRIVE_CDROM == driveType) || (DRIVE_REMOVABLE == driveType)) 
 3838                     {
 3839                         rootPath[2] = 0; // remove trailing backslash
 3840 
 3841                         Device driveDevice (rootPath, true);
 3842                         driveDevice.CheckOpened (SRC_POS);
 3843 
 3844                         DWORD bytesRead = driveDevice.Read (buffer.Ptr(), (DWORD) buffer.Size());
 3845                         if (bytesRead != buffer.Size())
 3846                             continue;
 3847 
 3848                         if (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
 3849                             return true;
 3850                     }
 3851                 }
 3852                 catch (...) { }
 3853             }
 3854         }
 3855 
 3856         return false;
 3857     }
 3858 
 3859     bool BootEncryption::VerifyRescueDiskImage (const wchar_t* imageFile)
 3860     {
 3861         BOOL bIsGPT = GetSystemDriveConfiguration().SystemPartition.IsGPT;
 3862         if ((bIsGPT && !RescueZipData) || (!bIsGPT && !RescueIsoImage))
 3863             throw ParameterIncorrect (SRC_POS);
 3864 
 3865         if (bIsGPT)
 3866         {
 3867             try
 3868             {
 3869                 DWORD dwSize = 0;
 3870                 File rescueFile (imageFile, true);
 3871                 rescueFile.CheckOpened (SRC_POS);
 3872                 rescueFile.GetFileSize (dwSize);
 3873                 Buffer rescueData (dwSize);
 3874 
 3875                 if (dwSize == rescueFile.Read (rescueData.Ptr (), dwSize))
 3876                 {
 3877                     zip_error_t zerr;
 3878                     zip_source_t* zsrc = zip_source_buffer_create (rescueData.Ptr (), dwSize, 0, &zerr);
 3879                     if (!zsrc)
 3880                         return false;
 3881                     zip_t* zFile = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr);
 3882                     if (!zFile)
 3883                     {
 3884                         zip_source_free (zsrc);
 3885                         throw ParameterIncorrect (SRC_POS);
 3886                     }
 3887 
 3888                     finally_do_arg (zip_t*, zFile, { zip_close (finally_arg); });
 3889 
 3890                     zsrc = zip_source_buffer_create (RescueZipData, RescueZipSize, 0, &zerr);
 3891                     if (!zsrc)
 3892                         return false;
 3893                     zip_t* zMem = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr);
 3894                     if (!zMem)
 3895                     {
 3896                         zip_source_free (zsrc);
 3897                         throw ParameterIncorrect (SRC_POS);
 3898                     }
 3899 
 3900                     finally_do_arg (zip_t*, zMem, { zip_close (finally_arg); });
 3901 
 3902                     const wchar_t* efi64Files[] = {
 3903                         L"EFI/Boot/bootx64.efi",
 3904 #ifdef VC_EFI_CUSTOM_MODE
 3905                         L"EFI/VeraCrypt/DcsBml.dcs",
 3906 #endif
 3907                         L"EFI/VeraCrypt/DcsBoot.efi",
 3908                         L"EFI/VeraCrypt/DcsCfg.dcs",
 3909                         L"EFI/VeraCrypt/DcsInt.dcs",
 3910                         L"EFI/VeraCrypt/LegacySpeaker.dcs",
 3911                         L"EFI/VeraCrypt/svh_bak",
 3912                         L"EFI/Boot/original_bootx64.vc_backup"
 3913                     };
 3914                     
 3915                     const wchar_t* efi32Files[] = {
 3916                         L"EFI/Boot/bootia32.efi",
 3917 #ifdef VC_EFI_CUSTOM_MODE
 3918                         L"EFI/VeraCrypt/DcsBml.dcs",
 3919 #endif
 3920                         L"EFI/VeraCrypt/DcsBoot.efi",
 3921                         L"EFI/VeraCrypt/DcsCfg.dcs",
 3922                         L"EFI/VeraCrypt/DcsInt.dcs",
 3923                         L"EFI/VeraCrypt/LegacySpeaker.dcs",
 3924                         L"EFI/VeraCrypt/svh_bak",
 3925                         L"EFI/Boot/original_bootia32.vc_backup"
 3926                     };
 3927 
 3928                     int i;
 3929                     zip_stat_t statMem, statFile;
 3930                     zip_int64_t indexMem, indexFile;
 3931                     const wchar_t** efiFiles = Is64BitOs()? efi64Files: efi32Files;
 3932                     int efiFilesSize = Is64BitOs()? ARRAYSIZE(efi64Files): ARRAYSIZE(efi32Files);
 3933                     for (i = 0; i < efiFilesSize; i++)
 3934                     {
 3935                         bool bMatch = false;
 3936                         indexMem = zip_name_locate (zMem, WideToUtf8String (efiFiles[i]).c_str(), ZIP_FL_NOCASE);
 3937                         if (indexMem >= 0)
 3938                         {                                   
 3939                             if ((0 == zip_stat_index (zMem, indexMem, ZIP_FL_NOCASE, &statMem)) && (statMem.valid & ZIP_STAT_SIZE))
 3940                             {
 3941                                 indexFile = zip_name_locate (zFile, WideToUtf8String (efiFiles[i]).c_str(), ZIP_FL_NOCASE);
 3942                                 if (indexFile >= 0)
 3943                                 {
 3944                                     if ((0 == zip_stat_index (zFile, indexFile, ZIP_FL_NOCASE, &statFile)) && (statFile.valid & ZIP_STAT_SIZE))
 3945                                     {
 3946                                         if (statMem.size == statFile.size)
 3947                                         {
 3948                                             Buffer fileBuf ((size_t) statFile.size);
 3949                                             Buffer memBuf ((size_t) statMem.size);
 3950 
 3951                                             zip_file_t* zfMem = zip_fopen_index (zMem, indexMem, 0);
 3952                                             if (zfMem)
 3953                                             {
 3954                                                 if (0 < zip_fread (zfMem, memBuf.Ptr (), statMem.size))
 3955                                                 {
 3956                                                     zip_file_t* zfFile = zip_fopen_index (zFile, indexFile, 0);
 3957                                                     if (zfFile)
 3958                                                     {
 3959                                                         if (0 < zip_fread (zfFile, fileBuf.Ptr (), statFile.size))
 3960                                                         {
 3961                                                             bMatch = (memcmp (memBuf.Ptr(), fileBuf.Ptr(), (size_t) statFile.size) == 0);
 3962                                                         }
 3963                                                         zip_fclose (zfFile);
 3964                                                     }                                                           
 3965                                                 }
 3966                                                 zip_fclose (zfMem);                                                     
 3967                                             }
 3968                                         }
 3969                                     }
 3970                                 }
 3971                             }
 3972                         }
 3973                         else
 3974                         {
 3975                             // entry not found in our internal Rescue ZIP image. Skip it.
 3976                             bMatch = true;
 3977                         }
 3978 
 3979                         if (!bMatch)
 3980                             break;
 3981                     }
 3982 
 3983                     if (i == efiFilesSize)
 3984                     {
 3985                         // All entries processed
 3986                         return true;
 3987                     }
 3988                 }
 3989             }
 3990             catch (...) { }
 3991         }
 3992         else
 3993         {
 3994             try
 3995             {
 3996                 File rescueFile (imageFile, true);
 3997                 rescueFile.CheckOpened (SRC_POS);
 3998                 size_t verifiedSectorCount = (TC_CD_BOOTSECTOR_OFFSET + TC_ORIG_BOOT_LOADER_BACKUP_SECTOR_OFFSET + TC_BOOT_LOADER_AREA_SIZE) / 2048;
 3999                 Buffer buffer ((verifiedSectorCount + 1) * 2048);
 4000 
 4001                 DWORD bytesRead = rescueFile.Read (buffer.Ptr(), (DWORD) buffer.Size());
 4002                 if (    (bytesRead == buffer.Size()) 
 4003                     && (memcmp (buffer.Ptr(), RescueIsoImage, buffer.Size()) == 0)
 4004                     )
 4005                 {
 4006                     return true;
 4007                 }
 4008             }
 4009             catch (...) { }
 4010         }
 4011 
 4012         return false;
 4013     }
 4014 
 4015 
 4016 #ifndef SETUP
 4017 
 4018     void BootEncryption::CreateVolumeHeader (uint64 volumeSize, uint64 encryptedAreaStart, Password *password, int ea, int mode, int pkcs5, int pim)
 4019     {
 4020         PCRYPTO_INFO cryptoInfo = NULL;
 4021 
 4022         if (!IsRandomNumberGeneratorStarted())
 4023             throw ParameterIncorrect (SRC_POS);
 4024 
 4025         throw_sys_if (CreateVolumeHeaderInMemory (ParentWindow, TRUE, (char *) VolumeHeader, ea, mode, password, pkcs5, pim, NULL, &cryptoInfo,
 4026             volumeSize, 0, encryptedAreaStart, 0, TC_SYSENC_KEYSCOPE_MIN_REQ_PROG_VERSION, TC_HEADER_FLAG_ENCRYPTED_SYSTEM, TC_SECTOR_SIZE_BIOS, FALSE) != 0);
 4027 
 4028         finally_do_arg (PCRYPTO_INFO*, &cryptoInfo, { crypto_close (*finally_arg); });
 4029 
 4030         // Initial rescue disk assumes encryption of the drive has been completed (EncryptedAreaLength == volumeSize)
 4031         memcpy (RescueVolumeHeader, VolumeHeader, sizeof (RescueVolumeHeader));
 4032         if (0 != ReadVolumeHeader (TRUE, (char *) RescueVolumeHeader, password, pkcs5, pim, FALSE, NULL, cryptoInfo))
 4033             throw ParameterIncorrect (SRC_POS);
 4034 
 4035         DecryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
 4036 
 4037         if (GetHeaderField32 (RescueVolumeHeader, TC_HEADER_OFFSET_MAGIC) != 0x56455241)
 4038             throw ParameterIncorrect (SRC_POS);
 4039 
 4040         byte *fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
 4041         mputInt64 (fieldPos, volumeSize);
 4042 
 4043         // CRC of the header fields
 4044         uint32 crc = GetCrc32 (RescueVolumeHeader + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
 4045         fieldPos = RescueVolumeHeader + TC_HEADER_OFFSET_HEADER_CRC;
 4046         mputLong (fieldPos, crc);
 4047 
 4048         EncryptBuffer (RescueVolumeHeader + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, cryptoInfo);
 4049 
 4050         VolumeHeaderValid = true;
 4051         RescueVolumeHeaderValid = true;
 4052     }
 4053 
 4054 
 4055     void BootEncryption::InstallVolumeHeader ()
 4056     {
 4057         if (!VolumeHeaderValid)
 4058             throw ParameterIncorrect (SRC_POS);
 4059 
 4060         Device device (GetSystemDriveConfiguration().DevicePath);
 4061         device.CheckOpened (SRC_POS);
 4062 
 4063         device.SeekAt (TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
 4064         device.Write ((byte *) VolumeHeader, sizeof (VolumeHeader));
 4065     }
 4066 
 4067 
 4068     // For synchronous operations use AbortSetupWait()
 4069     void BootEncryption::AbortSetup ()
 4070     {
 4071         CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
 4072     }
 4073 
 4074 
 4075     // For asynchronous operations use AbortSetup()
 4076     void BootEncryption::AbortSetupWait ()
 4077     {
 4078         CallDriver (TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP);
 4079 
 4080         BootEncryptionStatus encStatus = GetStatus();
 4081 
 4082         while (encStatus.SetupInProgress)
 4083         {
 4084             Sleep (TC_ABORT_TRANSFORM_WAIT_INTERVAL);
 4085             encStatus = GetStatus();
 4086         }
 4087     }
 4088 
 4089     void BootEncryption::BackupSystemLoader ()
 4090     {
 4091         if (GetSystemDriveConfiguration().SystemPartition.IsGPT)
 4092         {
 4093             if (!IsAdmin()) {
 4094                 if (IsUacSupported())
 4095                 {
 4096                     Elevator::BackupEfiSystemLoader ();
 4097                     return;
 4098                 }
 4099                 else
 4100                 {
 4101                     Warning ("ADMIN_PRIVILEGES_WARN_DEVICES", ParentWindow);
 4102                 }
 4103             }
 4104             unsigned __int64 loaderSize = 0;
 4105             std::vector<byte> bootLoaderBuf;
 4106             const wchar_t * szStdEfiBootloader = Is64BitOs()? L"\\EFI\\Boot\\bootx64.efi": L"\\EFI\\Boot\\bootia32.efi";
 4107             const wchar_t * szBackupEfiBootloader = Is64BitOs()? L"\\EFI\\Boot\\original_bootx64.vc_backup": L"\\EFI\\Boot\\original_bootia32.vc_backup";
 4108             const wchar_t * szStdMsBootloader = L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi";
 4109             const wchar_t * szBackupMsBootloader = L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc";
 4110             const char* g_szMsBootString = "bootmgfw.pdb";
 4111             bool bModifiedMsBoot = true;
 4112 
 4113             finally_do ({ EfiBootInst.DismountBootPartition(); });
 4114 
 4115             EfiBootInst.MountBootPartition(0);      
 4116 
 4117             EfiBootInst.GetFileSize(szStdMsBootloader, loaderSize);
 4118             bootLoaderBuf.resize ((size_t) loaderSize);
 4119             EfiBootInst.ReadFile(szStdMsBootloader, &bootLoaderBuf[0], (DWORD) loaderSize);
 4120 
 4121             // DcsBoot.efi is always smaller than 32KB
 4122             if (loaderSize > 32768)
 4123             {
 4124                 // look for bootmgfw.efi identifiant string
 4125                 if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
 4126                     bModifiedMsBoot = false;
 4127             }
 4128             else
 4129             {
 4130                 if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, _T(TC_APP_NAME), wcslen (_T(TC_APP_NAME)) * 2))
 4131                 {
 4132                     if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED", ParentWindow) == IDNO)
 4133                         throw UserAbort (SRC_POS);
 4134 
 4135                     // check if backup exists already and if it has bootmgfw signature
 4136                     if (EfiBootInst.FileExists (szBackupMsBootloader))
 4137                     {
 4138                         EfiBootInst.GetFileSize(szBackupMsBootloader, loaderSize);
 4139                         bootLoaderBuf.resize ((size_t) loaderSize);
 4140                         EfiBootInst.ReadFile(szBackupMsBootloader, &bootLoaderBuf[0], (DWORD) loaderSize);
 4141 
 4142                         if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, g_szMsBootString, strlen (g_szMsBootString)))
 4143                         {
 4144                             // copy it to original location
 4145                             EfiBootInst.CopyFile (szBackupMsBootloader, szStdMsBootloader);
 4146                             bModifiedMsBoot = false;
 4147                         }
 4148                     }
 4149 
 4150                     if (bModifiedMsBoot)
 4151                         return;
 4152                 }
 4153             }
 4154 
 4155             if (bModifiedMsBoot)
 4156             {
 4157                 Error ("WINDOWS_EFI_BOOT_LOADER_MISSING", ParentWindow);
 4158                 throw UserAbort (SRC_POS);
 4159             }
 4160 
 4161             EfiBootInst.CopyFile (szStdMsBootloader, szBackupMsBootloader);
 4162 
 4163             if (EfiBootInst.FileExists (szStdEfiBootloader))
 4164             {
 4165                 EfiBootInst.GetFileSize (szStdEfiBootloader, loaderSize);
 4166 
 4167                 bootLoaderBuf.resize ((size_t) loaderSize);
 4168 
 4169                 EfiBootInst.ReadFile (szStdEfiBootloader, &bootLoaderBuf[0], (DWORD) loaderSize);
 4170 
 4171                 // Prevent VeraCrypt EFI loader from being backed up
 4172                 if (BufferHasPattern (bootLoaderBuf.data (), (size_t) loaderSize, _T(TC_APP_NAME), wcslen (_T(TC_APP_NAME)) * 2))
 4173                 {
 4174                     if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED", ParentWindow) == IDNO)
 4175                         throw UserAbort (SRC_POS);
 4176 
 4177                     // check if backup exists already and if it has bootmgfw signature
 4178                     if (EfiBootInst.FileExists (szBackupEfiBootloader))
 4179                     {
 4180                         // perform the backup on disk using this file
 4181                         EfiBootInst.CopyFile (szBackupEfiBootloader, GetSystemLoaderBackupPath().c_str());
 4182                     }
 4183 
 4184                     return;
 4185                 }
 4186 
 4187                 EfiBootInst.CopyFile (szStdEfiBootloader, GetSystemLoaderBackupPath().c_str());
 4188                 EfiBootInst.CopyFile (szStdEfiBootloader, szBackupEfiBootloader);
 4189             }
 4190             else
 4191                 EfiBootInst.CopyFile (szStdMsBootloader, GetSystemLoaderBackupPath().c_str());
 4192 
 4193         }
 4194         else
 4195         {
 4196             Device device (GetSystemDriveConfiguration().DevicePath, true);
 4197             device.CheckOpened (SRC_POS);
 4198             byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS];
 4199 
 4200             device.SeekAt (0);
 4201             device.Read (bootLoaderBuf, sizeof (bootLoaderBuf));
 4202 
 4203             // Prevent TrueCrypt loader from being backed up
 4204             for (size_t i = 0; i < sizeof (bootLoaderBuf) - strlen (TC_APP_NAME); ++i)
 4205             {
 4206                 if (memcmp (bootLoaderBuf + i, TC_APP_NAME, strlen (TC_APP_NAME)) == 0)
 4207                 {
 4208                     if (AskWarnNoYes ("TC_BOOT_LOADER_ALREADY_INSTALLED", ParentWindow) == IDNO)
 4209                         throw UserAbort (SRC_POS);
 4210                     return;
 4211                 }
 4212             }
 4213 
 4214             File backupFile (GetSystemLoaderBackupPath(), false, true);
 4215             backupFile.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
 4216         }
 4217     }
 4218 
 4219 
 4220     void BootEncryption::RestoreSystemLoader ()
 4221     {
 4222         SystemDriveConfiguration config = GetSystemDriveConfiguration();
 4223         if (config.SystemPartition.IsGPT) {
 4224             if (!IsAdmin()) {
 4225                 if (IsUacSupported())
 4226                 {
 4227                     Elevator::RestoreEfiSystemLoader ();
 4228                     return;
 4229                 }
 4230                 else
 4231                 {
 4232                     Warning ("ADMIN_PRIVILEGES_WARN_DEVICES", ParentWindow);
 4233                 }
 4234             }
 4235 
 4236             finally_do ({ EfiBootInst.DismountBootPartition(); });
 4237 
 4238             EfiBootInst.MountBootPartition(0);          
 4239 
 4240             EfiBootInst.DeleteStartExec();
 4241             EfiBootInst.DeleteStartExec(0xDC5B, L"Driver"); // remove DcsBml boot driver it was installed
 4242             if (Is64BitOs())
 4243                 EfiBootInst.RenameFile(L"\\EFI\\Boot\\original_bootx64.vc_backup", L"\\EFI\\Boot\\bootx64.efi", TRUE);
 4244             else
 4245                 EfiBootInst.RenameFile(L"\\EFI\\Boot\\original_bootia32.vc_backup", L"\\EFI\\Boot\\bootia32.efi", TRUE);
 4246 
 4247             if (!EfiBootInst.RenameFile(L"\\EFI\\Microsoft\\Boot\\bootmgfw_ms.vc", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE))
 4248             {
 4249                 EfiBootConf conf;
 4250                 if (EfiBootInst.ReadConfig (L"\\EFI\\VeraCrypt\\DcsProp", conf) && strlen (conf.actionSuccessValue.c_str()))
 4251                 {
 4252                     string actionValue = conf.actionSuccessValue;
 4253                     std::transform(actionValue.begin(), actionValue.end(), actionValue.begin(), ::tolower);
 4254 
 4255                     if (strstr (actionValue.c_str(), "postexec") && strstr (actionValue.c_str(), "file("))
 4256                     {
 4257                         char c;
 4258                         const char* ptr = strstr (actionValue.c_str(), "file(");
 4259                         ptr += 5;
 4260                         wstring loaderPath = L"\\";
 4261                         while ((c = *ptr))
 4262                         {
 4263                             if (c == ')' || c == ' ')
 4264                                 break;
 4265                             loaderPath += (wchar_t) c;
 4266                             ptr++;
 4267                         }
 4268 
 4269                         EfiBootInst.RenameFile(loaderPath.c_str(), L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi", TRUE);
 4270                     }
 4271                 }
 4272             }
 4273 
 4274 
 4275             EfiBootInst.DelFile(L"\\DcsBoot.efi");
 4276             EfiBootInst.DelFile(L"\\DcsInt.efi");
 4277             EfiBootInst.DelFile(L"\\DcsCfg.efi");
 4278             EfiBootInst.DelFile(L"\\LegacySpeaker.efi");
 4279             EfiBootInst.DelFile(L"\\DcsBoot");
 4280             EfiBootInst.DelFile(L"\\DcsProp");
 4281             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsBoot.efi");
 4282             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsInt.dcs");
 4283             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsCfg.dcs");
 4284             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\LegacySpeaker.dcs");
 4285             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsBml.dcs");
 4286             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsBoot");
 4287             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsInfo.dcs");
 4288             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\PlatformInfo");
 4289             EfiBootInst.DelFile(L"\\EFI\\VeraCrypt\\DcsProp");
 4290             EfiBootInst.DelDir (L"\\EFI\\VeraCrypt");
 4291         }
 4292         else
 4293         {
 4294             byte bootLoaderBuf[TC_BOOT_LOADER_AREA_SECTOR_COUNT * TC_SECTOR_SIZE_BIOS];
 4295 
 4296             File backupFile (GetSystemLoaderBackupPath(), true);
 4297             backupFile.CheckOpened(SRC_POS);
 4298             if (backupFile.Read (bootLoaderBuf, sizeof (bootLoaderBuf)) != sizeof (bootLoaderBuf))
 4299                 throw ParameterIncorrect (SRC_POS);
 4300 
 4301             Device device (GetSystemDriveConfiguration().DevicePath);
 4302             device.CheckOpened (SRC_POS);
 4303 
 4304             // Preserve current partition table
 4305             byte mbr[TC_SECTOR_SIZE_BIOS];
 4306             device.SeekAt (0);
 4307             device.Read (mbr, sizeof (mbr));
 4308             memcpy (bootLoaderBuf + TC_MAX_MBR_BOOT_CODE_SIZE, mbr + TC_MAX_MBR_BOOT_CODE_SIZE, sizeof (mbr) - TC_MAX_MBR_BOOT_CODE_SIZE);
 4309 
 4310             device.SeekAt (0);
 4311             device.Write (bootLoaderBuf, sizeof (bootLoaderBuf));
 4312         }
 4313 
 4314         if (!IsAdmin() && IsUacSupported())
 4315         {
 4316             Elevator::UpdateSetupConfigFile (false);
 4317         }
 4318         else
 4319         {
 4320             UpdateSetupConfigFile (false);
 4321         }
 4322     }
 4323 
 4324 #endif // SETUP
 4325 
 4326     static bool CompareMultiString (const char* str1, const char* str2)
 4327     {
 4328         size_t l1, l2;
 4329         if (!str1 || !str2)
 4330             return false;
 4331         while (true)
 4332         {
 4333             l1 = strlen (str1);
 4334             l2 = strlen (str2);
 4335             if (l1 == l2)
 4336             {