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

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

unix.superglobalmegacorp.com

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