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

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
1.1.1.15  root        7:  this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed
1.1.1.16! root        8:  by the TrueCrypt License 2.7 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 "Volumes.h"
                     16: #include "Password.h"
                     17: #include "Dlgcode.h"
                     18: #include "Language.h"
                     19: #include "Pkcs5.h"
1.1.1.14  root       20: #include "Endian.h"
1.1.1.6   root       21: #include "Random.h"
1.1       root       22: 
                     23: #include <io.h>
                     24: 
1.1.1.14  root       25: void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword,
1.1.1.12  root       26:                         HWND hVerify, unsigned char *szPassword,
1.1.1.6   root       27:                         char *szVerify,
                     28:                         BOOL keyFilesEnabled)
1.1       root       29: {
                     30:        char szTmp1[MAX_PASSWORD + 1];
                     31:        char szTmp2[MAX_PASSWORD + 1];
                     32:        int k = GetWindowTextLength (hPassword);
                     33:        BOOL bEnable = FALSE;
                     34: 
                     35:        if (hwndDlg);           /* Remove warning */
                     36: 
                     37:        GetWindowText (hPassword, szTmp1, sizeof (szTmp1));
                     38:        GetWindowText (hVerify, szTmp2, sizeof (szTmp2));
                     39: 
                     40:        if (strcmp (szTmp1, szTmp2) != 0)
                     41:                bEnable = FALSE;
                     42:        else
                     43:        {
1.1.1.6   root       44:                if (k >= MIN_PASSWORD || keyFilesEnabled)
1.1       root       45:                        bEnable = TRUE;
                     46:                else
                     47:                        bEnable = FALSE;
                     48:        }
                     49: 
                     50:        if (szPassword != NULL)
                     51:                memcpy (szPassword, szTmp1, sizeof (szTmp1));
                     52: 
                     53:        if (szVerify != NULL)
                     54:                memcpy (szVerify, szTmp2, sizeof (szTmp2));
                     55: 
                     56:        burn (szTmp1, sizeof (szTmp1));
                     57:        burn (szTmp2, sizeof (szTmp2));
                     58: 
                     59:        EnableWindow (hButton, bEnable);
                     60: }
                     61: 
1.1.1.6   root       62: 
                     63: BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
                     64: {
1.1.1.8   root       65:        int i, len;
1.1.1.6   root       66:        
                     67:        if (hPassword == NULL)
                     68:        {
1.1.1.8   root       69:                unsigned char *pw;
1.1.1.6   root       70:                len = ptrPw->Length;
                     71:                pw = (unsigned char *) ptrPw->Text;
1.1.1.8   root       72: 
                     73:                for (i = 0; i < len; i++)
                     74:                {
                     75:                        if (pw[i] >= 0x7f || pw[i] < 0x20)      // A non-ASCII or non-printable character?
                     76:                                return FALSE;
                     77:                }
1.1.1.6   root       78:        }
                     79:        else
                     80:        {
1.1.1.8   root       81:                wchar_t s[MAX_PASSWORD + 1];
1.1.1.6   root       82:                len = GetWindowTextLength (hPassword);
                     83: 
1.1.1.8   root       84:                if (len > MAX_PASSWORD)
                     85:                        return FALSE; 
                     86: 
                     87:                GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t));
                     88: 
                     89:                for (i = 0; i < len; i++)
                     90:                {
                     91:                        if (s[i] >= 0x7f || s[i] < 0x20)        // A non-ASCII or non-printable character?
                     92:                                break;
                     93:                }
                     94: 
                     95:                burn (s, sizeof(s));
                     96: 
                     97:                if (i < len)
                     98:                        return FALSE; 
1.1.1.6   root       99:        }
1.1.1.8   root      100: 
1.1.1.6   root      101:        return TRUE;
                    102: }
                    103: 
                    104: 
                    105: BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem)
                    106: {
                    107:        if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING)
                    108:        {
1.1.1.14  root      109: #ifndef _DEBUG
1.1.1.6   root      110:                if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES)
                    111:                        return FALSE;
1.1.1.14  root      112: #endif
1.1.1.6   root      113:        }
                    114:        return TRUE;
                    115: }
                    116: 
1.1.1.14  root      117: int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg)
1.1       root      118: {
1.1.1.10  root      119:        int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
1.1       root      120:        char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
                    121:        char szDosDevice[TC_MAX_PATH];
1.1.1.13  root      122:        char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1       root      123:        PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
                    124:        void *dev = INVALID_HANDLE_VALUE;
                    125:        DWORD dwError;
                    126:        BOOL bDevice;
1.1.1.13  root      127:        unsigned __int64 hostSize = 0;
1.1.1.6   root      128:        int volumeType;
                    129:        int wipePass;
1.1.1.4   root      130:        FILETIME ftCreationTime;
                    131:        FILETIME ftLastWriteTime;
                    132:        FILETIME ftLastAccessTime;
                    133:        BOOL bTimeStampValid = FALSE;
1.1.1.13  root      134:        LARGE_INTEGER headerOffset;
                    135:        BOOL backupHeader;
1.1.1.10  root      136: 
1.1.1.6   root      137:        if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;
1.1       root      138: 
1.1.1.10  root      139:        WaitCursor ();
                    140: 
1.1       root      141:        CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice);
                    142: 
1.1.1.4   root      143:        if (bDevice == FALSE)
                    144:        {
                    145:                strcpy (szCFDevice, szDiskFile);
                    146:        }
                    147:        else
1.1       root      148:        {
1.1.1.4   root      149:                nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE);
1.1.1.10  root      150:                
1.1.1.4   root      151:                if (nDosLinkCreated != 0)
1.1.1.10  root      152:                        goto error;
1.1.1.4   root      153:        }
1.1       root      154: 
1.1.1.4   root      155:        dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                    156: 
1.1.1.14  root      157:        if (dev == INVALID_HANDLE_VALUE) 
                    158:                goto error;
                    159: 
1.1.1.6   root      160:        if (bDevice)
1.1.1.4   root      161:        {
1.1.1.6   root      162:                /* This is necessary to determine the hidden volume header offset */
1.1.1.4   root      163: 
                    164:                if (dev == INVALID_HANDLE_VALUE)
1.1       root      165:                {
1.1.1.10  root      166:                        goto error;
1.1       root      167:                }
                    168:                else
                    169:                {
1.1.1.6   root      170:                        PARTITION_INFORMATION diskInfo;
1.1.1.4   root      171:                        DWORD dwResult;
                    172:                        BOOL bResult;
                    173: 
1.1.1.10  root      174:                        bResult = GetPartitionInfo (lpszVolume, &diskInfo);
1.1.1.4   root      175: 
1.1.1.6   root      176:                        if (bResult)
1.1       root      177:                        {
1.1.1.13  root      178:                                hostSize = diskInfo.PartitionLength.QuadPart;
1.1.1.6   root      179:                        }
                    180:                        else
                    181:                        {
                    182:                                DISK_GEOMETRY driveInfo;
1.1.1.4   root      183: 
1.1.1.6   root      184:                                bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
                    185:                                        &driveInfo, sizeof (driveInfo), &dwResult, NULL);
1.1.1.4   root      186: 
1.1.1.6   root      187:                                if (!bResult)
1.1.1.10  root      188:                                        goto error;
1.1.1.6   root      189: 
1.1.1.13  root      190:                                hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
1.1.1.4   root      191:                                        driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
1.1       root      192:                        }
1.1.1.6   root      193: 
1.1.1.13  root      194:                        if (hostSize == 0)
1.1.1.6   root      195:                        {
1.1.1.10  root      196:                                nStatus = ERR_VOL_SIZE_WRONG;
                    197:                                goto error;
1.1.1.6   root      198:                        }
1.1       root      199:                }
                    200:        }
1.1.1.13  root      201:        else
                    202:        {
                    203:                LARGE_INTEGER fileSize;
                    204:                if (!GetFileSizeEx (dev, &fileSize))
                    205:                {
                    206:                        nStatus = ERR_OS_ERROR;
                    207:                        goto error;
                    208:                }
                    209: 
                    210:                hostSize = fileSize.QuadPart;
                    211:        }
1.1.1.4   root      212: 
1.1.1.6   root      213:        if (Randinit ())
1.1.1.10  root      214:                goto error;
1.1.1.6   root      215: 
                    216:        if (!bDevice && bPreserveTimestamp)
1.1       root      217:        {
1.1.1.4   root      218:                /* Remember the container modification/creation date and time, (used to reset file date and time of
1.1.1.6   root      219:                file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability
1.1.1.4   root      220:                of hidden volumes (last password change time is stored in the volume header). */
1.1       root      221: 
1.1.1.4   root      222:                if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1       root      223:                {
1.1.1.4   root      224:                        bTimeStampValid = FALSE;
1.1.1.6   root      225:                        MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1       root      226:                }
1.1.1.4   root      227:                else
                    228:                        bTimeStampValid = TRUE;
1.1       root      229:        }
                    230: 
1.1.1.13  root      231:        for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
1.1       root      232:        {
1.1.1.13  root      233:                // Seek the volume header
                    234:                switch (volumeType)
                    235:                {
                    236:                case TC_VOLUME_TYPE_NORMAL:
                    237:                        headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
                    238:                        break;
1.1       root      239: 
1.1.1.13  root      240:                case TC_VOLUME_TYPE_HIDDEN:
                    241:                        if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
                    242:                                continue;
1.1       root      243: 
1.1.1.13  root      244:                        headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
                    245:                        break;
                    246: 
                    247:                case TC_VOLUME_TYPE_HIDDEN_LEGACY:
                    248:                        headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
                    249:                        break;
                    250:                }
                    251: 
                    252:                if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6   root      253:                {
1.1.1.13  root      254:                        nStatus = ERR_OS_ERROR;
                    255:                        goto error;
1.1.1.6   root      256:                }
1.1       root      257: 
1.1.1.13  root      258:                /* Read in volume header */
1.1.1.8   root      259:                nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
1.1.1.6   root      260:                if (nStatus != sizeof (buffer))
                    261:                {
1.1.1.14  root      262:                        // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS 
                    263:                        memset (buffer, 0, sizeof (buffer));
1.1.1.6   root      264:                }
1.1       root      265: 
1.1.1.6   root      266:                /* Try to decrypt the header */
1.1       root      267: 
1.1.1.14  root      268:                nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6   root      269:                if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
                    270:                        nStatus = 0;    // We can ignore this error here
1.1       root      271: 
1.1.1.6   root      272:                if (nStatus == ERR_PASSWORD_WRONG)
                    273:                {
                    274:                        continue;               // Try next volume type
                    275:                }
                    276:                else if (nStatus != 0)
                    277:                {
                    278:                        cryptoInfo = NULL;
                    279:                        goto error;
                    280:                }
                    281:                else 
                    282:                        break;
                    283:        }
1.1.1.4   root      284: 
1.1       root      285:        if (nStatus != 0)
                    286:        {
                    287:                cryptoInfo = NULL;
                    288:                goto error;
                    289:        }
                    290: 
1.1.1.13  root      291:        if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
                    292:        {
                    293:                nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
                    294:                goto error;
                    295:        }
                    296: 
1.1.1.6   root      297:        // Change the PKCS-5 PRF if requested by user
                    298:        if (pkcs5 != 0)
                    299:                cryptoInfo->pkcs5 = pkcs5;
1.1       root      300: 
1.1.1.13  root      301:        RandSetHashFunction (cryptoInfo->pkcs5);
                    302: 
1.1.1.15  root      303:        NormalCursor();
                    304:        UserEnrichRandomPool (hwndDlg);
1.1.1.16! root      305:        EnableElevatedCursorChange (hwndDlg);
1.1.1.15  root      306:        WaitCursor();
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
1.1.1.14  root      328:                        nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.13  root      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.15  root      363:                        if (bDevice
                    364:                                && !cryptoInfo->LegacyVolume
                    365:                                && !cryptoInfo->hiddenVolume
                    366:                                && cryptoInfo->HeaderVersion == 4
                    367:                                && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
                    368:                                && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
                    369:                        {
                    370:                                nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
                    371:                                if (nStatus != ERR_SUCCESS)
                    372:                                        goto error;
                    373:                        }
                    374: 
1.1.1.13  root      375:                        FlushFileBuffers (dev);
1.1.1.6   root      376:                }
1.1.1.13  root      377: 
                    378:                if (backupHeader || cryptoInfo->LegacyVolume)
                    379:                        break;
                    380:                        
                    381:                backupHeader = TRUE;
                    382:                headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1       root      383:        }
                    384: 
1.1.1.6   root      385:        /* Password successfully changed */
1.1       root      386:        nStatus = 0;
                    387: 
1.1.1.6   root      388: error:
1.1.1.10  root      389:        dwError = GetLastError ();
                    390: 
1.1       root      391:        burn (buffer, sizeof (buffer));
                    392: 
                    393:        if (cryptoInfo != NULL)
                    394:                crypto_close (cryptoInfo);
                    395: 
1.1.1.4   root      396:        if (bTimeStampValid)
1.1       root      397:        {
1.1.1.4   root      398:                // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). 
                    399:                if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6   root      400:                        MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      401:        }
                    402: 
1.1.1.10  root      403:        if (dev != INVALID_HANDLE_VALUE)
                    404:                CloseHandle ((HANDLE) dev);
1.1       root      405: 
1.1.1.10  root      406:        if (nDosLinkCreated == 0)
                    407:                RemoveFakeDosName (szDiskFile, szDosDevice);
                    408: 
1.1.1.15  root      409:        RandStop (FALSE);
1.1.1.10  root      410:        NormalCursor ();
1.1       root      411: 
                    412:        SetLastError (dwError);
                    413: 
1.1.1.10  root      414:        if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
                    415:                && bDevice
                    416:                && !UacElevated
                    417:                && IsUacSupported ())
                    418:                return nStatus;
1.1       root      419: 
1.1.1.10  root      420:        if (nStatus != 0)
                    421:                handleError (hwndDlg, nStatus);
1.1.1.6   root      422: 
1.1       root      423:        return nStatus;
                    424: }
1.1.1.4   root      425: 

unix.superglobalmegacorp.com

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