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

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

unix.superglobalmegacorp.com

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