Security assessment of TrueCrypt (english)

Mon 08 December 2008 by fred

Let us summarize: the CSPN (Certification de Sécurité de Premier Niveau - First Level Security Certification) is a security assessment proposed by the DCSSI, the main organisation in France dealing with these matters in France. The purpose is to get a quick evaluation in a given time (20 days if there is no crypto, 30 otherwise) using real expert skills.

One of the CSPN we had to perform was on TrueCrypt (version 6.0a). This article explains what we found in regards to some fixes which occur in the new TrueCrypt version (6.1a). You will also find the evaluation report for both the software and the cryptography.

First, have a look at a quote :


December 1, 2008

Improvements, bug fixes, and security enhancements:

- Minor improvements, bug fixes, and security enhancements. (Windows, Mac OS X, and Linux)

Note: If you are using an older version of TrueCrypt, it is
highly recommended that you upgrade to the latest stable version.

The assessment we did reveals some flaws. First of all, here are important points to keep in mind:

  • The security target was focusing on the new features introduced in version 6 (e.g. partition ciphering).
  • We gave our results to TrueCrypt Foundation, but according to them, none of them were a security issue ... which is not new when dealing with software publisher and security flaws.
  • TrueCrypt is a nice efficient and easy to use software.

It is funny (or appalling) to notice that TrueCrypt's answer is not different from the previous one they offered:

* Vendor denies the vulnerability
* Fixed in updated versions

So, nothing new in the end. Let's move on what we found during the software assessment:

  • Reading BIOS memory, an attacker can retrieve the size of the password (modulo 16) (not fixed).
  • TrueCrypt Driver is prone to a DoS attack (at least a DoS, maybe more, we did not investigate further) (fixed).
  • Path to the keyfiles can be retrieved in memory (not fixed).
  • Ciphering key can be retrieved in memory when user saves the header of a volume (fixed) ;
  • Password can be retrieved in memory when one creates a new volume (not fixed but they are not responsible for that)

Regarding the crypto:

  • An attacker can easily build collisions with keyfiles (not fixed).

Since none of them are security issues, we disclose the details.

Bugs and fixes (or not)

Size of the password used to encrypt a partition

When a system partition is ciphered, the user must provide a password in order to decipher the given partition. The buffer used by the BIOS containing the password has already been at the origin of a flaw since it was not erased once used [iviz, bugtraq]. If this latter bug has been fixed, the developers should also have reseted the pointers used to handle this buffer in order to conceal the password's size. Putting 2 pointers to NULL is really easy...

DoS in the driver

When sending the IRP TC_IOCTL_REOPEN_BOOT_VOLUME_HEADER, data handled by the driver are not properly checked. Input is a structure called Password, build with both the password of the volume and the size of the password.

Size is a signed integer. Upper bound is checked in function ReopenBootVolumeHeader. However, lower bound is never checked.

The fix is straightforward by forcing the size to be unsigned:

--- 6.1/Common/Password.h       2008-10-30 19:39:28.000000000 +0100
+++ 6.1a/Common/Password.h      2008-11-07 12:28:54.000000000 +0100
@@ -25,7 +25,7 @@
 typedef struct {
        // Modifying this structure can introduce incompatibility with previous versions
-       __int32 Length;
+       unsigned __int32 Length;
        unsigned char Text[MAX_PASSWORD + 1];
        char Pad[3]; // keep 64-bit alignment
 } Password;

Path to the keyfiles in memory

A user can mount TrueCrypt's volumes based on keyfiles instead of password. The list of files is provided by the user when he attempts to access the volume. The internal representation of this list is built by function SelectMultipleFiles. This function copies the list in a global variable SelectMultipleFilesPath, which is never erased.

Ciphering key in memory when headers are backed up

During the back-up, the header is deciphered with the user password, then re-encrypted. The ciphering keys are not changed, only a new salt is generated. During the creation of the backup files, the new header is ciphered with 2 temporary keys in order to create random data.

The secondary key of the volume is saved in buffer originalK2. Temporary aster key is saved in temporaryKey. These 2 keys are not reset in memory.

This fix is performed in the same way other buffers are cleaned, that is by calling the function burn:

--- ./6.1/Mount/Mount.c    2008-10-30 19:39:28.000000000 +0100
+++ ./6.1a/Mount/Mount.c   2008-11-27 09:23:14.000000000 +0100
@@ -6887,6 +6882,8 @@

        burn (&VolumePassword, sizeof (VolumePassword));
        burn (&hiddenVolPassword, sizeof (hiddenVolPassword));
+       burn (temporaryKey, sizeof (temporaryKey));
+       burn (originalK2, sizeof (originalK2));


Password in memory when a new volume is created

The function VerifyPasswordAndUpdate is called when a user gives his password for a new volume. It is entered 2 times in order to ensure there is no mistake. This function compares the 2 given passwords and activates a button in the GUI if they match.

This function is based upon Windows's functions GetWindowTextLength and GetWindowText, designed to retrieve the length of the password, and the password itself. These two functions do not clean their stack, including the password. This is related to Windows internals, and not directly to the use of TrueCrypt.

Collision with keyfiles

Keyfiles are derived into a structure Password. The password is computed by "hashing" the content of the files. Then it is written in a 64 byte buffer. Instead of a cryptographic hash function, several CRC32 are used. Therefore, it is really easy to generate 2 files leading to the same "hash", also known as the same password.

Security impact is mitigated for a protected volume. However, using the secure hash function should have been an obvious choice.