VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/doc/html/Incompatibilities.html
blob: 84610d9edb361e8e3e39589d1792cc8dc0e1e7c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>VeraCrypt - Free Open source disk encryption with strong security for the Paranoid</title>
<meta name="description" content="VeraCrypt is free open-source disk encryption software for Windows, Mac OS X and Linux. In case an attacker forces you to reveal the password, VeraCrypt provides plausible deniability. In contrast to file encryption, data encryption performed by VeraCrypt is real-time (on-the-fly), automatic, transparent, needs very little memory, and does not involve temporary unencrypted files."/>
<meta name="keywords" content="encryption, security"/>
<link href="styles.css" rel="stylesheet" type="text/css" />
</head>
<body>

<div>                      
<a href="https://www.veracrypt.fr/en/Home.html"><img src="VeraCrypt128x128.png" alt="VeraCrypt"/></a>
</div>

<div id="menu">
	<ul>
	  <li><a href="Home.html">Home</a></li>
	  <li><a href="/code/">Source Code</a></li>
	  <li><a href="Downloads.html">Downloads</a></li>
	  <li><a class="active" href="Documentation.html">Documentation</a></li>
	  <li><a href="Donation.html">Donate</a></li>
	  <li><a href="https://sourceforge.net/p/veracrypt/discussion/" target="_blank">Forums</a></li>
	</ul>
</div>

<div>
<p>
<a href="Documentation.html">Documentation</a>           
<img src="arrow_right.gif" alt=">>" style="margin-top: 5px">
<a href="Incompatibilities.html">Incompatibilities</a>
</p></div>

<div class="wikidoc">
<h1>Incompatibilities</h1>
<h4 style="text-align:left; font-family:Arial,Helvetica,Verdana,sans-serif; font-weight:bold; margin-top:0px; font-size:12px; margin-bottom:1px">
Activation of Adobe Photoshop&reg; and Other Products Using FLEXnet Publisher&reg; / SafeCast</h4>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
<em style="text-align:left">Note: The issue described below does <strong style="text-align:left">
not</strong> affect you if you use a non-cascade encryption algorithm (i.e., AES, Serpent, or Twofish).* The issue also does
<strong style="text-align:left">not</strong> affect you if you do not use <a href="System%20Encryption.html" style="text-align:left; color:#0080c0; text-decoration:none.html">
system encryption</a> (pre-boot authentication).</em></div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
Acresso FLEXnet Publisher activation software, formerly Macrovision SafeCast, (used for activation of third-party software, such as Adobe Photoshop) writes data to the first drive track. If this happens when your system partition/drive is encrypted by VeraCrypt,
 a portion of the VeraCrypt Boot Loader will be damaged and you will not be able to start Windows. In that case, please use your
<a href="VeraCrypt%20Rescue%20Disk.html" style="text-align:left; color:#0080c0; text-decoration:none.html">
VeraCrypt Rescue Disk</a> to regain access to your system. There are two ways to do so:</div>
<ol style="text-align:left; margin-top:18px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
<li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px">
You may keep the third-party software activated but you will need to boot your system from the VeraCrypt Rescue Disk CD/DVD
<em style="text-align:left">every time</em>. Just insert your Rescue Disk into your CD/DVD drive and then enter your password in the Rescue Disk screen.
</li><li style="text-align:left; margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px">
If you do not want to boot your system from the VeraCrypt Rescue Disk CD/DVD every time, you can restore the VeraCrypt Boot Loader on the system drive. To do so, in the Rescue Disk screen, select
<em style="text-align:left">Repair Options</em> &gt; <em style="text-align:left">
Restore VeraCrypt Boot Loader</em>. However, note that this will deactivate the third-party software.
</li></ol>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
For information on how to use your VeraCrypt Rescue Disk, please see the chapter <a href="VeraCrypt%20Rescue%20Disk.html" style="text-align:left; color:#0080c0; text-decoration:none.html">
VeraCrypt Rescue Disk</a>.</div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
<strong style="text-align:left">Possible permanent solution</strong>: decrypt the system partition/drive, and then re-encrypt it using a non-cascade encryption algorithm (i.e., AES, Serpent, or Twofish).*</div>
<div style="text-align:left; margin-top:19px; margin-bottom:19px; padding-top:0px; padding-bottom:0px">
Please note that this not a bug in VeraCrypt (the issue is caused by inappropriate design of the third-party activation software).</div>
<p>&nbsp;</p>
<hr align="left" size="1" width="189" style="text-align:left; height:0px; border-width:0px 1px 1px; border-style:solid; border-color:#000000">
<p><span style="text-align:left; font-size:10px; line-height:12px">* The reason is that the VeraCrypt Boot Loader is smaller than the one used for cascades of ciphers and, therefore, there is enough space in the first drive track for a backup of the VeraCrypt
 Boot Loader. Hence, whenever the VeraCrypt Boot Loader is damaged, its backup copy is run automatically instead.</span><br style="text-align:left">
<br style="text-align:left">
<br style="text-align:left">
<br style="text-align:left">
&nbsp;&nbsp;See also: <a href="Issues%20and%20Limitations.html" style="text-align:left; color:#0080c0; text-decoration:none; font-weight:bold.html">
Known Issues &amp; Limitations</a>,&nbsp;&nbsp;<a href="Troubleshooting.html" style="text-align:left; color:#0080c0; text-decoration:none; font-weight:bold.html">Troubleshooting</a></p>
</div><div class="ClearBoth"></div></body></html>
Derivation; }; } EncryptionThreadPoolWorkItem; static volatile BOOL ThreadPoolRunning = FALSE; static volatile BOOL StopPending = FALSE; static uint32 ThreadCount; static TC_THREAD_HANDLE ThreadHandles[TC_ENC_THREAD_POOL_MAX_THREAD_COUNT]; static EncryptionThreadPoolWorkItem WorkItemQueue[TC_ENC_THREAD_POOL_QUEUE_SIZE]; static volatile int EnqueuePosition; static volatile int DequeuePosition; static TC_MUTEX EnqueueMutex; static TC_MUTEX DequeueMutex; static TC_EVENT WorkItemReadyEvent; static TC_EVENT WorkItemCompletedEvent; static WorkItemState GetWorkItemState (EncryptionThreadPoolWorkItem *workItem) { return InterlockedExchangeAdd ((LONG *) &workItem->State, 0); } static void SetWorkItemState (EncryptionThreadPoolWorkItem *workItem, WorkItemState newState) { InterlockedExchange ((LONG *) &workItem->State, (LONG) newState); } static TC_THREAD_PROC EncryptionThreadProc (void *threadArg) { EncryptionThreadPoolWorkItem *workItem; while (!StopPending) { TC_ACQUIRE_MUTEX (&DequeueMutex); workItem = &WorkItemQueue[DequeuePosition++]; if (DequeuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) DequeuePosition = 0; while (!StopPending && GetWorkItemState (workItem) != WorkItemReady) { TC_WAIT_EVENT (WorkItemReadyEvent); } SetWorkItemState (workItem, WorkItemBusy); TC_RELEASE_MUTEX (&DequeueMutex); if (StopPending) break; switch (workItem->Type) { case DecryptDataUnitsWork: DecryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); break; case EncryptDataUnitsWork: EncryptDataUnitsCurrentThread (workItem->Encryption.Data, &workItem->Encryption.StartUnitNo, workItem->Encryption.UnitCount, workItem->Encryption.CryptoInfo); break; case DeriveKeyWork: switch (workItem->KeyDerivation.Pkcs5Prf) { case RIPEMD160: derive_key_ripemd160 (TRUE, workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); break; case SHA512: derive_key_sha512 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); break; case WHIRLPOOL: derive_key_whirlpool (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); break; case SHA1: derive_key_sha1 (workItem->KeyDerivation.Password, workItem->KeyDerivation.PasswordLength, workItem->KeyDerivation.Salt, PKCS5_SALT_SIZE, workItem->KeyDerivation.IterationCount, workItem->KeyDerivation.DerivedKey, GetMaxPkcs5OutSize()); break; default: TC_THROW_FATAL_EXCEPTION; } InterlockedExchange (workItem->KeyDerivation.CompletionFlag, TRUE); TC_SET_EVENT (*workItem->KeyDerivation.CompletionEvent); if (InterlockedDecrement (workItem->KeyDerivation.OutstandingWorkItemCount) == 0) TC_SET_EVENT (*workItem->KeyDerivation.NoOutstandingWorkItemEvent); SetWorkItemState (workItem, WorkItemFree); TC_SET_EVENT (WorkItemCompletedEvent); continue; default: TC_THROW_FATAL_EXCEPTION; } if (workItem != workItem->FirstFragment) { SetWorkItemState (workItem, WorkItemFree); TC_SET_EVENT (WorkItemCompletedEvent); } if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0) TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent); } #ifdef DEVICE_DRIVER PsTerminateSystemThread (STATUS_SUCCESS); #else _endthreadex (0); return 0; #endif } BOOL EncryptionThreadPoolStart (size_t encryptionFreeCpuCount) { size_t cpuCount, i; if (ThreadPoolRunning) return TRUE; #ifdef DEVICE_DRIVER cpuCount = GetCpuCount(); #else { SYSTEM_INFO sysInfo; GetSystemInfo (&sysInfo); cpuCount = sysInfo.dwNumberOfProcessors; } #endif if (cpuCount > encryptionFreeCpuCount) cpuCount -= encryptionFreeCpuCount; if (cpuCount < 2) return TRUE; if (cpuCount > TC_ENC_THREAD_POOL_MAX_THREAD_COUNT) cpuCount = TC_ENC_THREAD_POOL_MAX_THREAD_COUNT; StopPending = FALSE; DequeuePosition = 0; EnqueuePosition = 0; #ifdef DEVICE_DRIVER KeInitializeEvent (&WorkItemReadyEvent, SynchronizationEvent, FALSE); KeInitializeEvent (&WorkItemCompletedEvent, SynchronizationEvent, FALSE); #else WorkItemReadyEvent = CreateEvent (NULL, FALSE, FALSE, NULL); if (!WorkItemReadyEvent) return FALSE; WorkItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); if (!WorkItemCompletedEvent) return FALSE; #endif #ifdef DEVICE_DRIVER ExInitializeFastMutex (&DequeueMutex); ExInitializeFastMutex (&EnqueueMutex); #else DequeueMutex = CreateMutex (NULL, FALSE, NULL); if (!DequeueMutex) return FALSE; EnqueueMutex = CreateMutex (NULL, FALSE, NULL); if (!EnqueueMutex) return FALSE; #endif memset (WorkItemQueue, 0, sizeof (WorkItemQueue)); for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) { WorkItemQueue[i].State = WorkItemFree; #ifdef DEVICE_DRIVER KeInitializeEvent (&WorkItemQueue[i].ItemCompletedEvent, SynchronizationEvent, FALSE); #else WorkItemQueue[i].ItemCompletedEvent = CreateEvent (NULL, FALSE, FALSE, NULL); if (!WorkItemQueue[i].ItemCompletedEvent) { EncryptionThreadPoolStop(); return FALSE; } #endif } for (ThreadCount = 0; ThreadCount < cpuCount; ++ThreadCount) { #ifdef DEVICE_DRIVER if (!NT_SUCCESS (TCStartThread (EncryptionThreadProc, NULL, &ThreadHandles[ThreadCount]))) #else if (!(ThreadHandles[ThreadCount] = (HANDLE) _beginthreadex (NULL, 0, EncryptionThreadProc, NULL, 0, NULL))) #endif { EncryptionThreadPoolStop(); return FALSE; } } ThreadPoolRunning = TRUE; return TRUE; } void EncryptionThreadPoolStop () { size_t i; if (!ThreadPoolRunning) return; StopPending = TRUE; TC_SET_EVENT (WorkItemReadyEvent); for (i = 0; i < ThreadCount; ++i) { #ifdef DEVICE_DRIVER TCStopThread (ThreadHandles[i], &WorkItemReadyEvent); #else TC_WAIT_EVENT (ThreadHandles[i]); #endif } ThreadCount = 0; #ifndef DEVICE_DRIVER CloseHandle (DequeueMutex); CloseHandle (EnqueueMutex); CloseHandle (WorkItemReadyEvent); CloseHandle (WorkItemCompletedEvent); for (i = 0; i < sizeof (WorkItemQueue) / sizeof (WorkItemQueue[0]); ++i) { if (WorkItemQueue[i].ItemCompletedEvent) CloseHandle (WorkItemQueue[i].ItemCompletedEvent); } #endif ThreadPoolRunning = FALSE; } void EncryptionThreadPoolBeginKeyDerivation (TC_EVENT *completionEvent, TC_EVENT *noOutstandingWorkItemEvent, LONG *completionFlag, LONG *outstandingWorkItemCount, int pkcs5Prf, char *password, int passwordLength, char *salt, int iterationCount, char *derivedKey) { EncryptionThreadPoolWorkItem *workItem; if (!ThreadPoolRunning) TC_THROW_FATAL_EXCEPTION; TC_ACQUIRE_MUTEX (&EnqueueMutex); workItem = &WorkItemQueue[EnqueuePosition++]; if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) EnqueuePosition = 0; while (GetWorkItemState (workItem) != WorkItemFree) { TC_WAIT_EVENT (WorkItemCompletedEvent); } workItem->Type = DeriveKeyWork; workItem->KeyDerivation.CompletionEvent = completionEvent; workItem->KeyDerivation.CompletionFlag = completionFlag; workItem->KeyDerivation.DerivedKey = derivedKey; workItem->KeyDerivation.IterationCount = iterationCount; workItem->KeyDerivation.NoOutstandingWorkItemEvent = noOutstandingWorkItemEvent; workItem->KeyDerivation.OutstandingWorkItemCount = outstandingWorkItemCount; workItem->KeyDerivation.Password = password; workItem->KeyDerivation.PasswordLength = passwordLength; workItem->KeyDerivation.Pkcs5Prf = pkcs5Prf; workItem->KeyDerivation.Salt = salt; InterlockedIncrement (outstandingWorkItemCount); TC_CLEAR_EVENT (*noOutstandingWorkItemEvent); SetWorkItemState (workItem, WorkItemReady); TC_SET_EVENT (WorkItemReadyEvent); TC_RELEASE_MUTEX (&EnqueueMutex); } void EncryptionThreadPoolDoWork (EncryptionThreadPoolWorkType type, byte *data, const UINT64_STRUCT *startUnitNo, uint32 unitCount, PCRYPTO_INFO cryptoInfo) { uint32 fragmentCount; uint32 unitsPerFragment; uint32 remainder; byte *fragmentData; uint64 fragmentStartUnitNo; EncryptionThreadPoolWorkItem *workItem; EncryptionThreadPoolWorkItem *firstFragmentWorkItem; if (unitCount == 0) return; if (!ThreadPoolRunning || unitCount == 1) { switch (type) { case DecryptDataUnitsWork: DecryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); break; case EncryptDataUnitsWork: EncryptDataUnitsCurrentThread (data, startUnitNo, unitCount, cryptoInfo); break; default: TC_THROW_FATAL_EXCEPTION; } return; } if (unitCount <= ThreadCount) { fragmentCount = unitCount; unitsPerFragment = 1; remainder = 0; } else { /* Note that it is not efficient to divide the data into fragments smaller than a few hundred bytes. The reason is that the overhead associated with thread handling would in most cases make a multi-threaded process actually slower than a single-threaded process. */ fragmentCount = ThreadCount; unitsPerFragment = unitCount / ThreadCount; remainder = unitCount % ThreadCount; if (remainder > 0) ++unitsPerFragment; } fragmentData = data; fragmentStartUnitNo = startUnitNo->Value; TC_ACQUIRE_MUTEX (&EnqueueMutex); firstFragmentWorkItem = &WorkItemQueue[EnqueuePosition]; while (GetWorkItemState (firstFragmentWorkItem) != WorkItemFree) { TC_WAIT_EVENT (WorkItemCompletedEvent); } firstFragmentWorkItem->OutstandingFragmentCount = fragmentCount; while (fragmentCount-- > 0) { workItem = &WorkItemQueue[EnqueuePosition++]; if (EnqueuePosition >= TC_ENC_THREAD_POOL_QUEUE_SIZE) EnqueuePosition = 0; while (GetWorkItemState (workItem) != WorkItemFree) { TC_WAIT_EVENT (WorkItemCompletedEvent); } workItem->Type = type; workItem->FirstFragment = firstFragmentWorkItem; workItem->Encryption.CryptoInfo = cryptoInfo; workItem->Encryption.Data = fragmentData; workItem->Encryption.UnitCount = unitsPerFragment; workItem->Encryption.StartUnitNo.Value = fragmentStartUnitNo; fragmentData += unitsPerFragment * ENCRYPTION_DATA_UNIT_SIZE; fragmentStartUnitNo += unitsPerFragment; if (remainder > 0 && --remainder == 0) --unitsPerFragment; SetWorkItemState (workItem, WorkItemReady); TC_SET_EVENT (WorkItemReadyEvent); } TC_RELEASE_MUTEX (&EnqueueMutex); TC_WAIT_EVENT (firstFragmentWorkItem->ItemCompletedEvent); SetWorkItemState (firstFragmentWorkItem, WorkItemFree); TC_SET_EVENT (WorkItemCompletedEvent); } size_t GetEncryptionThreadCount () { return ThreadPoolRunning ? ThreadCount : 0; } size_t GetMaxEncryptionThreadCount () { return TC_ENC_THREAD_POOL_MAX_THREAD_COUNT; } BOOL IsEncryptionThreadPoolRunning () { return ThreadPoolRunning; }