"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Password.c" (10 Oct 2018, 14552 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 "Password.c" 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  Legal Notice: Some portions of the source code contained in this file were
    3  derived from the source code of TrueCrypt 7.1a, which is
    4  Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
    5  governed by the TrueCrypt License 3.0, also from the source code of
    6  Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
    7  and which is governed by the 'License Agreement for Encryption for the Masses'
    8  Modifications and additions to the original source code (contained in this file)
    9  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
   10  and are governed by the Apache License 2.0 the full text of which is
   11  contained in the file License.txt included in VeraCrypt binary and source
   12  code distribution packages. */
   13 
   14 #include "Tcdefs.h"
   15 
   16 #include "Crypto.h"
   17 #include "Volumes.h"
   18 #include "Password.h"
   19 #include "Dlgcode.h"
   20 #include "Language.h"
   21 #include "Pkcs5.h"
   22 #include "Endian.h"
   23 #include "Random.h"
   24 
   25 #include <io.h>
   26 
   27 #ifndef SRC_POS
   28 #define SRC_POS (__FUNCTION__ ":" TC_TO_STRING(__LINE__))
   29 #endif
   30 
   31 void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword,
   32              HWND hVerify, unsigned char *szPassword,
   33              char *szVerify,
   34              BOOL keyFilesEnabled)
   35 {
   36     wchar_t szTmp1[MAX_PASSWORD + 1];
   37     wchar_t szTmp2[MAX_PASSWORD + 1];
   38     char szTmp1Utf8[MAX_PASSWORD + 1];
   39     char szTmp2Utf8[MAX_PASSWORD + 1];
   40     int k = GetWindowTextLength (hPassword);
   41     BOOL bEnable = FALSE;
   42     int utf8Len1, utf8Len2;
   43 
   44     UNREFERENCED_PARAMETER (hwndDlg);       /* Remove warning */
   45 
   46     GetWindowText (hPassword, szTmp1, ARRAYSIZE (szTmp1));
   47     GetWindowText (hVerify, szTmp2, ARRAYSIZE (szTmp2));
   48 
   49     utf8Len1 = WideCharToMultiByte (CP_UTF8, 0, szTmp1, -1, szTmp1Utf8, MAX_PASSWORD + 1, NULL, NULL);
   50     utf8Len2 = WideCharToMultiByte (CP_UTF8, 0, szTmp2, -1, szTmp2Utf8, MAX_PASSWORD + 1, NULL, NULL);
   51 
   52     if (wcscmp (szTmp1, szTmp2) != 0)
   53         bEnable = FALSE;
   54     else if (utf8Len1 <= 0)
   55         bEnable = FALSE;
   56     else
   57     {
   58         if (k >= MIN_PASSWORD || keyFilesEnabled)
   59             bEnable = TRUE;
   60         else
   61             bEnable = FALSE;
   62     }
   63 
   64     if (szPassword != NULL)
   65     {
   66         if (utf8Len1 > 0)
   67             memcpy (szPassword, szTmp1Utf8, sizeof (szTmp1Utf8));
   68         else
   69             szPassword [0] = 0;
   70     }
   71 
   72     if (szVerify != NULL)
   73     {
   74         if (utf8Len2 > 0)
   75             memcpy (szVerify, szTmp2Utf8, sizeof (szTmp2Utf8));
   76         else
   77             szVerify [0] = 0;
   78     }
   79 
   80     burn (szTmp1, sizeof (szTmp1));
   81     burn (szTmp2, sizeof (szTmp2));
   82     burn (szTmp1Utf8, sizeof (szTmp1Utf8));
   83     burn (szTmp2Utf8, sizeof (szTmp2Utf8));
   84 
   85     EnableWindow (hButton, bEnable);
   86 }
   87 
   88 
   89 BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
   90 {
   91     int i, len;
   92 
   93     if (hPassword == NULL)
   94     {
   95         if (ptrPw)
   96         {
   97             unsigned char *pw;
   98             len = ptrPw->Length;
   99             pw = (unsigned char *) ptrPw->Text;
  100 
  101             for (i = 0; i < len; i++)
  102             {
  103                 if (pw[i] >= 0x7f || pw[i] < 0x20)  // A non-ASCII or non-printable character?
  104                     return FALSE;
  105             }
  106         }
  107         else
  108             return FALSE;
  109     }
  110     else
  111     {
  112         wchar_t s[MAX_PASSWORD + 1];
  113         len = GetWindowTextLength (hPassword);
  114 
  115         if (len > MAX_PASSWORD)
  116             return FALSE;
  117 
  118         GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t));
  119 
  120         for (i = 0; i < len; i++)
  121         {
  122             if (s[i] >= 0x7f || s[i] < 0x20)    // A non-ASCII or non-printable character?
  123                 break;
  124         }
  125 
  126         burn (s, sizeof(s));
  127 
  128         if (i < len)
  129             return FALSE;
  130     }
  131 
  132     return TRUE;
  133 }
  134 
  135 
  136 BOOL CheckPasswordLength (HWND hwndDlg, unsigned __int32 passwordLength, int pim, BOOL bForBoot, int bootPRF, BOOL bSkipPasswordWarning, BOOL bSkipPimWarning)
  137 {
  138     BOOL bootPimCondition = (bForBoot && (bootPRF != SHA512 && bootPRF != WHIRLPOOL))? TRUE : FALSE;
  139     BOOL bCustomPimSmall = ((pim != 0) && (pim < (bootPimCondition? 98 : 485)))? TRUE : FALSE;
  140     if (passwordLength < PASSWORD_LEN_WARNING)
  141     {
  142         if (bCustomPimSmall)
  143         {
  144             Error (bootPimCondition? "BOOT_PIM_REQUIRE_LONG_PASSWORD": "PIM_REQUIRE_LONG_PASSWORD", hwndDlg);
  145             return FALSE;
  146         }
  147 
  148 #ifndef _DEBUG
  149         if (!bSkipPasswordWarning && (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES))
  150             return FALSE;
  151 #endif
  152     }
  153 #ifndef _DEBUG
  154     else if (bCustomPimSmall)
  155     {
  156         if (!bSkipPimWarning && AskWarnNoYes ("PIM_SMALL_WARNING", hwndDlg) != IDYES)
  157             return FALSE;
  158     }
  159 #endif
  160 
  161     if ((pim != 0) && (pim > (bootPimCondition? 98 : 485)))
  162     {
  163         // warn that mount/boot will take more time
  164         Warning ("PIM_LARGE_WARNING", hwndDlg);
  165 
  166     }
  167     return TRUE;
  168 }
  169 
  170 int ChangePwd (const wchar_t *lpszVolume, Password *oldPassword, int old_pkcs5, int old_pim, BOOL truecryptMode, Password *newPassword, int pkcs5, int pim, int wipePassCount, HWND hwndDlg)
  171 {
  172     int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
  173     wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
  174     wchar_t szDosDevice[TC_MAX_PATH];
  175     char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
  176     PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
  177     void *dev = INVALID_HANDLE_VALUE;
  178     DWORD dwError;
  179     DWORD bytesRead;
  180     BOOL bDevice;
  181     unsigned __int64 hostSize = 0;
  182     int volumeType;
  183     int wipePass;
  184     FILETIME ftCreationTime;
  185     FILETIME ftLastWriteTime;
  186     FILETIME ftLastAccessTime;
  187     BOOL bTimeStampValid = FALSE;
  188     LARGE_INTEGER headerOffset;
  189     BOOL backupHeader;
  190 
  191     if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;
  192 
  193     if ((wipePassCount <= 0) || (truecryptMode && (old_pkcs5 == SHA256)))
  194     {
  195       nStatus = ERR_PARAMETER_INCORRECT;
  196       handleError (hwndDlg, nStatus, SRC_POS);
  197       return nStatus;
  198     }
  199 
  200    if (!lpszVolume)
  201    {
  202       nStatus = ERR_OUTOFMEMORY;
  203       handleError (hwndDlg, nStatus, SRC_POS);
  204       return nStatus;
  205    }
  206 
  207     WaitCursor ();
  208 
  209     CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), lpszVolume, &bDevice);
  210 
  211     if (bDevice == FALSE)
  212     {
  213         wcscpy (szCFDevice, szDiskFile);
  214     }
  215     else
  216     {
  217         nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice),FALSE);
  218 
  219         if (nDosLinkCreated != 0)
  220             goto error;
  221     }
  222 
  223     dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  224 
  225     if (dev == INVALID_HANDLE_VALUE)
  226         goto error;
  227 
  228     if (bDevice)
  229     {
  230         /* This is necessary to determine the hidden volume header offset */
  231 
  232         if (dev == INVALID_HANDLE_VALUE)
  233         {
  234             goto error;
  235         }
  236         else
  237         {
  238             BYTE dgBuffer[256];
  239             PARTITION_INFORMATION diskInfo;
  240             DWORD dwResult;
  241             BOOL bResult;
  242 
  243             bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0,
  244                 dgBuffer, sizeof (dgBuffer), &dwResult, NULL);
  245 
  246             if (!bResult)
  247             {
  248                 DISK_GEOMETRY geo;
  249                 if (DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (LPVOID) &geo, sizeof (geo), &dwResult, NULL))
  250                 {
  251                     ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector;
  252 
  253                     if (CurrentOSMajor >= 6)
  254                     {
  255                         STORAGE_READ_CAPACITY storage = {0};
  256 
  257                         storage.Version = sizeof (STORAGE_READ_CAPACITY);
  258                         storage.Size = sizeof (STORAGE_READ_CAPACITY);
  259                         if (DeviceIoControl (dev, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, (LPVOID) &storage, sizeof (storage), &bytesRead, NULL)
  260                             && (bytesRead >= sizeof (storage))
  261                             && (storage.Size == sizeof (STORAGE_READ_CAPACITY))
  262                             )
  263                         {
  264                             ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = storage.DiskLength.QuadPart;
  265                         }
  266                     }
  267                 }
  268                 else
  269                 {
  270                     goto error;
  271                 }
  272 
  273             }
  274 
  275             bResult = GetPartitionInfo (lpszVolume, &diskInfo);
  276 
  277             if (bResult)
  278             {
  279                 hostSize = diskInfo.PartitionLength.QuadPart;
  280             }
  281             else
  282             {
  283                 hostSize = ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart;
  284             }
  285 
  286             if (hostSize == 0)
  287             {
  288                 nStatus = ERR_VOL_SIZE_WRONG;
  289                 goto error;
  290             }
  291         }
  292     }
  293     else
  294     {
  295         LARGE_INTEGER fileSize;
  296         if (!GetFileSizeEx (dev, &fileSize))
  297         {
  298             nStatus = ERR_OS_ERROR;
  299             goto error;
  300         }
  301 
  302         hostSize = fileSize.QuadPart;
  303     }
  304 
  305     if (Randinit ())
  306     {
  307         if (CryptoAPILastError == ERROR_SUCCESS)
  308             nStatus = ERR_RAND_INIT_FAILED;
  309         else
  310             nStatus = ERR_CAPI_INIT_FAILED;
  311         goto error;
  312     }
  313 
  314     SetRandomPoolEnrichedByUserStatus (FALSE); /* force the display of the random enriching dialog */
  315 
  316     if (!bDevice && bPreserveTimestamp)
  317     {
  318         if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
  319             bTimeStampValid = FALSE;
  320         else
  321             bTimeStampValid = TRUE;
  322     }
  323 
  324     for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
  325     {
  326         // Seek the volume header
  327         switch (volumeType)
  328         {
  329         case TC_VOLUME_TYPE_NORMAL:
  330             headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
  331             break;
  332 
  333         case TC_VOLUME_TYPE_HIDDEN:
  334             if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
  335                 continue;
  336 
  337             headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
  338             break;
  339 
  340         }
  341 
  342         if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
  343         {
  344             nStatus = ERR_OS_ERROR;
  345             goto error;
  346         }
  347 
  348         /* Read in volume header */
  349         if (!ReadEffectiveVolumeHeader (bDevice, dev, buffer, &bytesRead))
  350         {
  351             nStatus = ERR_OS_ERROR;
  352             goto error;
  353         }
  354 
  355         if (bytesRead != sizeof (buffer))
  356         {
  357             // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS
  358             memset (buffer, 0, sizeof (buffer));
  359         }
  360 
  361         /* Try to decrypt the header */
  362 
  363         nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, old_pkcs5, old_pim, truecryptMode, &cryptoInfo, NULL);
  364         if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
  365             nStatus = 0;    // We can ignore this error here
  366 
  367         if (nStatus == ERR_PASSWORD_WRONG)
  368         {
  369             continue;       // Try next volume type
  370         }
  371         else if (nStatus != 0)
  372         {
  373             cryptoInfo = NULL;
  374             goto error;
  375         }
  376         else
  377             break;
  378     }
  379 
  380     if (nStatus != 0)
  381     {
  382         cryptoInfo = NULL;
  383         goto error;
  384     }
  385 
  386     if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
  387     {
  388         nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
  389         goto error;
  390     }
  391 
  392     // Change the PKCS-5 PRF if requested by user
  393     if (pkcs5 != 0)
  394         cryptoInfo->pkcs5 = pkcs5;
  395 
  396     RandSetHashFunction (cryptoInfo->pkcs5);
  397 
  398     NormalCursor();
  399     UserEnrichRandomPool (hwndDlg);
  400     EnableElevatedCursorChange (hwndDlg);
  401     WaitCursor();
  402 
  403     /* Re-encrypt the volume header */
  404     backupHeader = FALSE;
  405 
  406     while (TRUE)
  407     {
  408         /* The header will be re-encrypted wipePassCount times to prevent adversaries from using
  409         techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
  410         to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
  411         times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
  412         impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
  413         valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
  414         recommends. During each pass we will write a valid working header. Each pass will use the same master
  415         key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
  416         item that will be different for each pass will be the salt. This is sufficient to cause each "version"
  417         of the header to differ substantially and in a random manner from the versions written during the
  418         other passes. */
  419 
  420         for (wipePass = 0; wipePass < wipePassCount; wipePass++)
  421         {
  422             // Prepare new volume header
  423             nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
  424                 buffer,
  425                 cryptoInfo->ea,
  426                 cryptoInfo->mode,
  427                 newPassword,
  428                 cryptoInfo->pkcs5,
  429                 pim,
  430                 cryptoInfo->master_keydata,
  431                 &ci,
  432                 cryptoInfo->VolumeSize.Value,
  433                 (volumeType == TC_VOLUME_TYPE_HIDDEN) ? cryptoInfo->hiddenVolumeSize : 0,
  434                 cryptoInfo->EncryptedAreaStart.Value,
  435                 cryptoInfo->EncryptedAreaLength.Value,
  436                 truecryptMode? 0 : cryptoInfo->RequiredProgramVersion,
  437                 cryptoInfo->HeaderFlags,
  438                 cryptoInfo->SectorSize,
  439                 wipePass < wipePassCount - 1);
  440 
  441             if (ci != NULL)
  442                 crypto_close (ci);
  443 
  444             if (nStatus != 0)
  445                 goto error;
  446 
  447             if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
  448             {
  449                 nStatus = ERR_OS_ERROR;
  450                 goto error;
  451             }
  452 
  453             if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
  454             {
  455                 nStatus = ERR_OS_ERROR;
  456                 goto error;
  457             }
  458 
  459             if (bDevice
  460                 && !cryptoInfo->LegacyVolume
  461                 && !cryptoInfo->hiddenVolume
  462                 && cryptoInfo->HeaderVersion == 4
  463                 && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
  464                 && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
  465             {
  466                 PCRYPTO_INFO dummyInfo = NULL;
  467                 LARGE_INTEGER hiddenOffset;
  468 
  469                 nStatus = WriteRandomDataToReservedHeaderAreas (hwndDlg, dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
  470                 if (nStatus != ERR_SUCCESS)
  471                     goto error;
  472 
  473                 // write fake hidden volume header to protect against attacks that use statistical entropy
  474                 // analysis to detect presence of hidden volumes
  475                 hiddenOffset.QuadPart = backupHeader ? cryptoInfo->VolumeSize.Value + TC_VOLUME_HEADER_GROUP_SIZE + TC_HIDDEN_VOLUME_HEADER_OFFSET: TC_HIDDEN_VOLUME_HEADER_OFFSET;
  476 
  477                 nStatus = CreateVolumeHeaderInMemory (hwndDlg, FALSE,
  478                     buffer,
  479                     cryptoInfo->ea,
  480                     cryptoInfo->mode,
  481                     NULL,
  482                     0,
  483                     0,
  484                     NULL,
  485                     &dummyInfo,
  486                     cryptoInfo->VolumeSize.Value,
  487                     cryptoInfo->VolumeSize.Value,
  488                     cryptoInfo->EncryptedAreaStart.Value,
  489                     cryptoInfo->EncryptedAreaLength.Value,
  490                     truecryptMode? 0 : cryptoInfo->RequiredProgramVersion,
  491                     cryptoInfo->HeaderFlags,
  492                     cryptoInfo->SectorSize,
  493                     wipePass < wipePassCount - 1);
  494 
  495                 if (nStatus != ERR_SUCCESS)
  496                     goto error;
  497 
  498                 crypto_close (dummyInfo);
  499 
  500                 if (!SetFilePointerEx ((HANDLE) dev, hiddenOffset, NULL, FILE_BEGIN))
  501                 {
  502                     nStatus = ERR_OS_ERROR;
  503                     goto error;
  504                 }
  505 
  506                 if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
  507                 {
  508                     nStatus = ERR_OS_ERROR;
  509                     goto error;
  510                 }
  511             }
  512 
  513             FlushFileBuffers (dev);
  514         }
  515 
  516         if (backupHeader || cryptoInfo->LegacyVolume)
  517             break;
  518 
  519         backupHeader = TRUE;
  520         headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
  521     }
  522 
  523     /* Password successfully changed */
  524     nStatus = 0;
  525 
  526 error:
  527     dwError = GetLastError ();
  528 
  529     burn (buffer, sizeof (buffer));
  530 
  531     if (cryptoInfo != NULL)
  532         crypto_close (cryptoInfo);
  533 
  534     if (bTimeStampValid)
  535         SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
  536 
  537     if (dev != INVALID_HANDLE_VALUE)
  538         CloseHandle ((HANDLE) dev);
  539 
  540     if (nDosLinkCreated == 0)
  541         RemoveFakeDosName (szDiskFile, szDosDevice);
  542 
  543     RandStop (FALSE);
  544     NormalCursor ();
  545 
  546     SetLastError (dwError);
  547 
  548     if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
  549         && bDevice
  550         && !UacElevated
  551         && IsUacSupported ())
  552         return nStatus;
  553 
  554     if (nStatus != 0)
  555         handleError (hwndDlg, nStatus, SRC_POS);
  556 
  557     return nStatus;
  558 }
  559