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

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

unix.superglobalmegacorp.com

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