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

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
1.1.1.7 ! root      273:           header. Each pass will use the same master key, and also the same header key, secondary key (LRW),
        !           274:           etc. derived from the new password. The only item that will be different for each pass will be
        !           275:           the salt. This is sufficient to cause each "version" of the header to differ substantially and
        !           276:           in a random manner from the versions written during the other passes. */
1.1.1.6   root      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,
1.1.1.7 ! root      302:                        cryptoInfo->mode,
1.1.1.6   root      303:                        newPassword,
                    304:                        cryptoInfo->pkcs5,
                    305:                        cryptoInfo->master_key,
                    306:                        cryptoInfo->volume_creation_time,
                    307:                        &ci,
                    308:                        volumeType == VOLUME_TYPE_HIDDEN ? cryptoInfo->hiddenVolumeSize : 0,
                    309:                        wipePass < DISK_WIPE_PASSES - 1);
1.1       root      310: 
1.1.1.6   root      311:                if (ci != NULL)
                    312:                        crypto_close (ci);
1.1       root      313: 
1.1.1.6   root      314:                if (nStatus != 0)
                    315:                        goto error;
1.1.1.4   root      316: 
1.1.1.6   root      317:                // Write the new header 
                    318:                nStatus = (*write) ((HFILE) dev, buffer, HEADER_SIZE);
                    319:                if (nStatus != HEADER_SIZE)
                    320:                {
                    321:                        nStatus = ERR_VOL_WRITING;
                    322:                        goto error;
                    323:                }
                    324:                FlushFileBuffers (dev);
1.1       root      325:        }
                    326: 
1.1.1.6   root      327:        /* Password successfully changed */
1.1       root      328:        nStatus = 0;
                    329: 
1.1.1.6   root      330: error:
1.1       root      331:        burn (buffer, sizeof (buffer));
                    332: 
                    333:        if (cryptoInfo != NULL)
                    334:                crypto_close (cryptoInfo);
                    335: 
                    336:        dwError = GetLastError ();
                    337: 
1.1.1.4   root      338:        if (bTimeStampValid)
1.1       root      339:        {
1.1.1.4   root      340:                // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). 
                    341:                if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6   root      342:                        MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1.1.4   root      343:        }
                    344: 
                    345:        CloseHandle ((HANDLE) dev);
1.1       root      346: 
1.1.1.6   root      347:        if (bDevice && nDosLinkCreated != 0)
1.1.1.4   root      348:        {
                    349:                int x = RemoveFakeDosName (szDiskFile, szDosDevice);
                    350:                if (x != 0)
1.1       root      351:                {
1.1.1.4   root      352:                        dwError = GetLastError ();
                    353:                        nStatus = x;
1.1       root      354:                }
                    355:        }
                    356: 
                    357:        SetLastError (dwError);
                    358: 
                    359:        NormalCursor ();
                    360: 
1.1.1.6   root      361:        Randfree ();
                    362: 
1.1       root      363:        return nStatus;
                    364: }
1.1.1.4   root      365: 

unix.superglobalmegacorp.com

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