Annotation of truecrypt/common/password.c, revision 1.1.1.13

1.1.1.10  root        1: /*
1.1.1.12  root        2:  Legal Notice: Some portions of the source code contained in this file were
                      3:  derived from the source code of Encryption for the Masses 2.02a, which is
                      4:  Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
                      5:  Agreement for Encryption for the Masses'. Modifications and additions to
                      6:  the original source code (contained in this file) and all other portions of
                      7:  this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
1.1.1.13! root        8:  by the TrueCrypt License 2.5 the full text of which is contained in the
1.1.1.12  root        9:  file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10  root       10:  packages. */
1.1.1.6   root       11: 
                     12: #include "Tcdefs.h"
                     13: 
                     14: #include "Crypto.h"
                     15: #include "Fat.h"
                     16: #include "Format.h"
                     17: #include "Volumes.h"
                     18: #include "Password.h"
                     19: #include "Apidrvr.h"
                     20: #include "Dlgcode.h"
                     21: #include "Language.h"
                     22: #include "Pkcs5.h"
1.1.1.10  root       23: #include "Common/Endian.h"
1.1.1.6   root       24: #include "Resource.h"
                     25: #include "Random.h"
1.1       root       26: 
                     27: #include <io.h>
                     28: 
                     29: void
                     30: VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword,
1.1.1.12  root       31:                         HWND hVerify, unsigned char *szPassword,
1.1.1.6   root       32:                         char *szVerify,
                     33:                         BOOL keyFilesEnabled)
1.1       root       34: {
                     35:        char szTmp1[MAX_PASSWORD + 1];
                     36:        char szTmp2[MAX_PASSWORD + 1];
                     37:        int k = GetWindowTextLength (hPassword);
                     38:        BOOL bEnable = FALSE;
                     39: 
                     40:        if (hwndDlg);           /* Remove warning */
                     41: 
                     42:        GetWindowText (hPassword, szTmp1, sizeof (szTmp1));
                     43:        GetWindowText (hVerify, szTmp2, sizeof (szTmp2));
                     44: 
                     45:        if (strcmp (szTmp1, szTmp2) != 0)
                     46:                bEnable = FALSE;
                     47:        else
                     48:        {
1.1.1.6   root       49:                if (k >= MIN_PASSWORD || keyFilesEnabled)
1.1       root       50:                        bEnable = TRUE;
                     51:                else
                     52:                        bEnable = FALSE;
                     53:        }
                     54: 
                     55:        if (szPassword != NULL)
                     56:                memcpy (szPassword, szTmp1, sizeof (szTmp1));
                     57: 
                     58:        if (szVerify != NULL)
                     59:                memcpy (szVerify, szTmp2, sizeof (szTmp2));
                     60: 
                     61:        burn (szTmp1, sizeof (szTmp1));
                     62:        burn (szTmp2, sizeof (szTmp2));
                     63: 
                     64:        EnableWindow (hButton, bEnable);
                     65: }
                     66: 
1.1.1.6   root       67: 
                     68: BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
                     69: {
1.1.1.8   root       70:        int i, len;
1.1.1.6   root       71:        
                     72:        if (hPassword == NULL)
                     73:        {
1.1.1.8   root       74:                unsigned char *pw;
1.1.1.6   root       75:                len = ptrPw->Length;
                     76:                pw = (unsigned char *) ptrPw->Text;
1.1.1.8   root       77: 
                     78:                for (i = 0; i < len; i++)
                     79:                {
                     80:                        if (pw[i] >= 0x7f || pw[i] < 0x20)      // A non-ASCII or non-printable character?
                     81:                                return FALSE;
                     82:                }
1.1.1.6   root       83:        }
                     84:        else
                     85:        {
1.1.1.8   root       86:                wchar_t s[MAX_PASSWORD + 1];
1.1.1.6   root       87:                len = GetWindowTextLength (hPassword);
                     88: 
1.1.1.8   root       89:                if (len > MAX_PASSWORD)
                     90:                        return FALSE; 
                     91: 
                     92:                GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t));
                     93: 
                     94:                for (i = 0; i < len; i++)
                     95:                {
                     96:                        if (s[i] >= 0x7f || s[i] < 0x20)        // A non-ASCII or non-printable character?
                     97:                                break;
                     98:                }
                     99: 
                    100:                burn (s, sizeof(s));
                    101: 
                    102:                if (i < len)
                    103:                        return FALSE; 
1.1.1.6   root      104:        }
1.1.1.8   root      105: 
1.1.1.6   root      106:        return TRUE;
                    107: }
                    108: 
                    109: 
                    110: BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem)
                    111: {
                    112:        if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING)
                    113:        {
                    114:                if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES)
                    115:                        return FALSE;
                    116:        }
                    117:        return TRUE;
                    118: }
                    119: 
1.1       root      120: int
1.1.1.6   root      121: ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg)
1.1       root      122: {
1.1.1.10  root      123:        int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
1.1       root      124:        char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
                    125:        char szDosDevice[TC_MAX_PATH];
1.1.1.13! root      126:        char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1       root      127:        PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
                    128:        void *dev = INVALID_HANDLE_VALUE;
                    129:        DWORD dwError;
                    130:        BOOL bDevice;
1.1.1.13! root      131:        unsigned __int64 hostSize = 0;
1.1.1.6   root      132:        int volumeType;
                    133:        int wipePass;
1.1.1.4   root      134:        FILETIME ftCreationTime;
                    135:        FILETIME ftLastWriteTime;
                    136:        FILETIME ftLastAccessTime;
                    137:        BOOL bTimeStampValid = FALSE;
1.1.1.13! root      138:        LARGE_INTEGER headerOffset;
        !           139:        BOOL backupHeader;
1.1.1.10  root      140: 
1.1.1.6   root      141:        if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;
1.1       root      142: 
1.1.1.10  root      143:        WaitCursor ();
                    144: 
1.1       root      145:        CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice);
                    146: 
1.1.1.4   root      147:        if (bDevice == FALSE)
                    148:        {
                    149:                strcpy (szCFDevice, szDiskFile);
                    150:        }
                    151:        else
1.1       root      152:        {
1.1.1.4   root      153:                nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE);
1.1.1.10  root      154:                
1.1.1.4   root      155:                if (nDosLinkCreated != 0)
1.1.1.10  root      156:                        goto error;
1.1.1.4   root      157:        }
1.1       root      158: 
1.1.1.4   root      159:        dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                    160: 
1.1.1.6   root      161:        if (bDevice)
1.1.1.4   root      162:        {
1.1.1.6   root      163:                /* This is necessary to determine the hidden volume header offset */
1.1.1.4   root      164: 
                    165:                if (dev == INVALID_HANDLE_VALUE)
1.1       root      166:                {
1.1.1.10  root      167:                        goto error;
1.1       root      168:                }
                    169:                else
                    170:                {
1.1.1.6   root      171:                        PARTITION_INFORMATION diskInfo;
1.1.1.4   root      172:                        DWORD dwResult;
                    173:                        BOOL bResult;
                    174: 
1.1.1.10  root      175:                        bResult = GetPartitionInfo (lpszVolume, &diskInfo);
1.1.1.4   root      176: 
1.1.1.6   root      177:                        if (bResult)
1.1       root      178:                        {
1.1.1.13! root      179:                                hostSize = diskInfo.PartitionLength.QuadPart;
1.1.1.6   root      180:                        }
                    181:                        else
                    182:                        {
                    183:                                DISK_GEOMETRY driveInfo;
1.1.1.4   root      184: 
1.1.1.6   root      185:                                bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
                    186:                                        &driveInfo, sizeof (driveInfo), &dwResult, NULL);
1.1.1.4   root      187: 
1.1.1.6   root      188:                                if (!bResult)
1.1.1.10  root      189:                                        goto error;
1.1.1.6   root      190: 
1.1.1.13! root      191:                                hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
1.1.1.4   root      192:                                        driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
1.1       root      193:                        }
1.1.1.6   root      194: 
1.1.1.13! root      195:                        if (hostSize == 0)
1.1.1.6   root      196:                        {
1.1.1.10  root      197:                                nStatus = ERR_VOL_SIZE_WRONG;
                    198:                                goto error;
1.1.1.6   root      199:                        }
1.1       root      200:                }
                    201:        }
1.1.1.13! root      202:        else
        !           203:        {
        !           204:                LARGE_INTEGER fileSize;
        !           205:                if (!GetFileSizeEx (dev, &fileSize))
        !           206:                {
        !           207:                        nStatus = ERR_OS_ERROR;
        !           208:                        goto error;
        !           209:                }
        !           210: 
        !           211:                hostSize = fileSize.QuadPart;
        !           212:        }
1.1.1.4   root      213: 
1.1.1.6   root      214:        if (dev == INVALID_HANDLE_VALUE) 
1.1.1.10  root      215:                goto error;
1.1.1.4   root      216: 
1.1.1.6   root      217:        if (Randinit ())
1.1.1.10  root      218:                goto error;
1.1.1.6   root      219: 
                    220:        if (!bDevice && bPreserveTimestamp)
1.1       root      221:        {
1.1.1.4   root      222:                /* Remember the container modification/creation date and time, (used to reset file date and time of
1.1.1.6   root      223:                file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability
1.1.1.4   root      224:                of hidden volumes (last password change time is stored in the volume header). */
1.1       root      225: 
1.1.1.4   root      226:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1       root      227:                {
1.1.1.4   root      228:                        bTimeStampValid = FALSE;
1.1.1.6   root      229:                        MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1       root      230:                }
1.1.1.4   root      231:                else
                    232:                        bTimeStampValid = TRUE;
1.1       root      233:        }
                    234: 
1.1.1.13! root      235:        for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
1.1       root      236:        {
1.1.1.13! root      237:                // Seek the volume header
        !           238:                switch (volumeType)
        !           239:                {
        !           240:                case TC_VOLUME_TYPE_NORMAL:
        !           241:                        headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
        !           242:                        break;
1.1       root      243: 
1.1.1.13! root      244:                case TC_VOLUME_TYPE_HIDDEN:
        !           245:                        if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
        !           246:                                continue;
1.1       root      247: 
1.1.1.13! root      248:                        headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
        !           249:                        break;
        !           250: 
        !           251:                case TC_VOLUME_TYPE_HIDDEN_LEGACY:
        !           252:                        headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
        !           253:                        break;
        !           254:                }
        !           255: 
        !           256:                if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6   root      257:                {
1.1.1.13! root      258:                        nStatus = ERR_OS_ERROR;
        !           259:                        goto error;
1.1.1.6   root      260:                }
1.1       root      261: 
1.1.1.13! root      262:                /* Read in volume header */
1.1.1.8   root      263:                nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
1.1.1.6   root      264:                if (nStatus != sizeof (buffer))
                    265:                {
                    266:                        nStatus = ERR_VOL_SIZE_WRONG;
                    267:                        goto error;
                    268:                }
1.1       root      269: 
1.1.1.6   root      270:                /* Try to decrypt the header */
1.1       root      271: 
1.1.1.12  root      272:                nStatus = VolumeReadHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6   root      273:                if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
                    274:                        nStatus = 0;    // We can ignore this error here
1.1       root      275: 
1.1.1.6   root      276:                if (nStatus == ERR_PASSWORD_WRONG)
                    277:                {
                    278:                        continue;               // Try next volume type
                    279:                }
                    280:                else if (nStatus != 0)
                    281:                {
                    282:                        cryptoInfo = NULL;
                    283:                        goto error;
                    284:                }
                    285:                else 
                    286:                        break;
                    287:        }
1.1.1.4   root      288: 
1.1       root      289:        if (nStatus != 0)
                    290:        {
                    291:                cryptoInfo = NULL;
                    292:                goto error;
                    293:        }
                    294: 
1.1.1.13! root      295:        if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
        !           296:        {
        !           297:                nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
        !           298:                goto error;
        !           299:        }
        !           300: 
1.1.1.6   root      301:        // Change the PKCS-5 PRF if requested by user
                    302:        if (pkcs5 != 0)
                    303:                cryptoInfo->pkcs5 = pkcs5;
1.1       root      304: 
1.1.1.13! root      305:        RandSetHashFunction (cryptoInfo->pkcs5);
        !           306: 
1.1       root      307: 
1.1.1.6   root      308:        /* Re-encrypt the volume header */ 
1.1.1.13! root      309:        backupHeader = FALSE;
1.1.1.6   root      310: 
1.1.1.13! root      311:        while (TRUE)
1.1.1.6   root      312:        {
1.1.1.13! root      313:                /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using 
        !           314:                techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
        !           315:                to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
        !           316:                times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
        !           317:                impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
        !           318:                valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
        !           319:                recommends. During each pass we will write a valid working header. Each pass will use the same master
        !           320:                key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
        !           321:                item that will be different for each pass will be the salt. This is sufficient to cause each "version"
        !           322:                of the header to differ substantially and in a random manner from the versions written during the
        !           323:                other passes. */
        !           324: 
        !           325:                for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
        !           326:                {
        !           327:                        // Prepare new volume header
        !           328:                        nStatus = VolumeWriteHeader (FALSE,
        !           329:                                buffer,
        !           330:                                cryptoInfo->ea,
        !           331:                                cryptoInfo->mode,
        !           332:                                newPassword,
        !           333:                                cryptoInfo->pkcs5,
        !           334:                                cryptoInfo->master_keydata,
        !           335:                                &ci,
        !           336:                                cryptoInfo->VolumeSize.Value,
        !           337:                                (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0,
        !           338:                                cryptoInfo->EncryptedAreaStart.Value,
        !           339:                                cryptoInfo->EncryptedAreaLength.Value,
        !           340:                                cryptoInfo->RequiredProgramVersion,
        !           341:                                cryptoInfo->HeaderFlags,
        !           342:                                wipePass < PRAND_DISK_WIPE_PASSES - 1);
        !           343: 
        !           344:                        if (ci != NULL)
        !           345:                                crypto_close (ci);
        !           346: 
        !           347:                        if (nStatus != 0)
        !           348:                                goto error;
        !           349: 
        !           350:                        if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6   root      351:                        {
1.1.1.13! root      352:                                nStatus = ERR_OS_ERROR;
1.1.1.6   root      353:                                goto error;
                    354:                        }
1.1.1.3   root      355: 
1.1.1.13! root      356:                        nStatus = _lwrite ((HFILE) dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
        !           357:                        if (nStatus != TC_VOLUME_HEADER_EFFECTIVE_SIZE)
1.1.1.6   root      358:                        {
1.1.1.13! root      359:                                nStatus = ERR_OS_ERROR;
1.1.1.6   root      360:                                goto error;
                    361:                        }
1.1       root      362: 
1.1.1.13! root      363:                        FlushFileBuffers (dev);
1.1.1.6   root      364:                }
1.1.1.13! root      365: 
        !           366:                if (backupHeader || cryptoInfo->LegacyVolume)
        !           367:                        break;
        !           368:                        
        !           369:                backupHeader = TRUE;
        !           370:                headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1       root      371:        }
                    372: 
1.1.1.6   root      373:        /* Password successfully changed */
1.1       root      374:        nStatus = 0;
                    375: 
1.1.1.6   root      376: error:
1.1.1.10  root      377:        dwError = GetLastError ();
                    378: 
1.1       root      379:        burn (buffer, sizeof (buffer));
                    380: 
                    381:        if (cryptoInfo != NULL)
                    382:                crypto_close (cryptoInfo);
                    383: 
1.1.1.4   root      384:        if (bTimeStampValid)
1.1       root      385:        {
1.1.1.4   root      386:                // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). 
                    387:                if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6   root      388:                        MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      389:        }
                    390: 
1.1.1.10  root      391:        if (dev != INVALID_HANDLE_VALUE)
                    392:                CloseHandle ((HANDLE) dev);
1.1       root      393: 
1.1.1.10  root      394:        if (nDosLinkCreated == 0)
                    395:                RemoveFakeDosName (szDiskFile, szDosDevice);
                    396: 
                    397:        NormalCursor ();
                    398:        Randfree ();
1.1       root      399: 
                    400:        SetLastError (dwError);
                    401: 
1.1.1.10  root      402:        if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
                    403:                && bDevice
                    404:                && !UacElevated
                    405:                && IsUacSupported ())
                    406:                return nStatus;
1.1       root      407: 
1.1.1.10  root      408:        if (nStatus != 0)
                    409:                handleError (hwndDlg, nStatus);
1.1.1.6   root      410: 
1.1       root      411:        return nStatus;
                    412: }
1.1.1.4   root      413: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.