Annotation of truecrypt/common/keyfiles.c, revision 1.1

1.1     ! root        1: /* 
        !             2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. 
        !             3: 
        !             4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file
        !             5: License.txt included in TrueCrypt binary and source code distribution archives. 
        !             6: */
        !             7: 
        !             8: #include <sys/stat.h>
        !             9: #include <sys/types.h>
        !            10: 
        !            11: #include "Tcdefs.h"
        !            12: #include "Keyfiles.h"
        !            13: #include "Crc.h"
        !            14: 
        !            15: #ifdef _WIN32
        !            16: 
        !            17: #include <io.h>
        !            18: #include "Dlgcode.h"
        !            19: #include "Language.h"
        !            20: #include "../common/resource.h"
        !            21: 
        !            22: #define stat _stat
        !            23: #define S_IFDIR _S_IFDIR
        !            24: #define snprintf _snprintf
        !            25: 
        !            26: #else
        !            27: 
        !            28: #include <dirent.h>
        !            29: #include <utime.h>
        !            30: 
        !            31: #endif
        !            32: 
        !            33: KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile)
        !            34: {
        !            35:        KeyFile *kf = firstKeyFile;
        !            36: 
        !            37:        if (firstKeyFile != NULL)
        !            38:        {
        !            39:                while (kf->Next)
        !            40:                        kf = kf->Next;
        !            41: 
        !            42:                kf->Next = keyFile;
        !            43:        }
        !            44:        else
        !            45:                firstKeyFile = keyFile;
        !            46: 
        !            47:        keyFile->Next = NULL;
        !            48: 
        !            49:        return firstKeyFile;
        !            50: }
        !            51: 
        !            52: 
        !            53: // Returns first keyfile, NULL if last keyfile was removed
        !            54: static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile)
        !            55: {
        !            56:        KeyFile *prevkf = NULL, *kf = firstKeyFile;
        !            57: 
        !            58:        if (firstKeyFile == NULL) return NULL;
        !            59:        do
        !            60:        {
        !            61:                if (kf == keyFile)
        !            62:                {
        !            63:                        if (prevkf == NULL)
        !            64:                                firstKeyFile = kf->Next;
        !            65:                        else
        !            66:                                prevkf->Next = kf->Next;
        !            67: 
        !            68:                        memset (keyFile, 0, sizeof(*keyFile));  // wipe
        !            69:                        free (keyFile);
        !            70:                        break;
        !            71:                }
        !            72:                prevkf = kf;
        !            73:        }
        !            74:        while (kf = kf->Next);
        !            75: 
        !            76:        return firstKeyFile;
        !            77: }
        !            78: 
        !            79: 
        !            80: void KeyFileRemoveAll (KeyFile **firstKeyFile)
        !            81: {
        !            82:        KeyFile *kf = *firstKeyFile;
        !            83:        while (kf != NULL)
        !            84:        {
        !            85:                KeyFile *d = kf;
        !            86:                kf = kf->Next;
        !            87:                burn (d, sizeof(*d));   // wipe
        !            88:                free (d);
        !            89:        }
        !            90: 
        !            91:        *firstKeyFile = NULL;
        !            92: }
        !            93: 
        !            94: 
        !            95: KeyFile *KeyFileClone (KeyFile *keyFile)
        !            96: {
        !            97:        KeyFile *clone;
        !            98: 
        !            99:        if (keyFile == NULL) return NULL;
        !           100: 
        !           101:        clone = malloc (sizeof (KeyFile));
        !           102:        strcpy (clone->FileName, keyFile->FileName);
        !           103:        clone->Next = NULL;
        !           104:        return clone;
        !           105: }
        !           106: 
        !           107: 
        !           108: KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile)
        !           109: {
        !           110:        KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile);
        !           111:        KeyFile *kf;
        !           112: 
        !           113:        if (firstKeyFile == NULL) return NULL;
        !           114:        kf = firstKeyFile->Next;
        !           115:        while (kf != NULL)
        !           116:        {
        !           117:                KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf));
        !           118:                kf = kf->Next;
        !           119:        }
        !           120: 
        !           121:        return cloneFirstKeyFile;
        !           122: }
        !           123: 
        !           124: 
        !           125: static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile, BOOL preserveTimestamp)
        !           126: {
        !           127:        FILE *f;
        !           128:        unsigned __int8 buffer[64 * 1024];
        !           129:        unsigned __int32 crc = 0xffffffff;
        !           130:        int writePos = 0;
        !           131:        size_t bytesRead, totalRead = 0;
        !           132: 
        !           133: #ifdef _WIN32
        !           134:        HANDLE src;
        !           135:        FILETIME ftCreationTime;
        !           136:        FILETIME ftLastWriteTime;
        !           137:        FILETIME ftLastAccessTime;
        !           138: #else
        !           139:        struct stat kfStat;
        !           140: #endif
        !           141: 
        !           142:        BOOL bTimeStampValid = FALSE;
        !           143: 
        !           144:        if (preserveTimestamp)
        !           145:        {
        !           146:                /* Remember the last access time of the keyfile. It will be preserved in order to prevent
        !           147:                   an adversary from determining which file may have been used as keyfile. */
        !           148: #ifdef _WIN32
        !           149:                src = CreateFile (keyFile->FileName,
        !           150:                        preserveTimestamp ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ,
        !           151:                        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
        !           152: 
        !           153:                if (src != INVALID_HANDLE_VALUE)
        !           154:                {
        !           155:                        if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
        !           156:                                bTimeStampValid = TRUE;
        !           157:                        else
        !           158:                                Warning ("GETFILETIME_FAILED_KEYFILE");
        !           159:                }
        !           160: #else
        !           161:                bTimeStampValid = stat (keyFile->FileName, &kfStat) == 0;
        !           162: #endif
        !           163:        }
        !           164: 
        !           165:        f = fopen (keyFile->FileName, "rb");
        !           166:        if (f == NULL) return FALSE;
        !           167: 
        !           168:        while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
        !           169:        {
        !           170:                size_t i;
        !           171: 
        !           172:                for (i = 0; i < bytesRead; i++)
        !           173:                {
        !           174:                        crc = UPDC32 (buffer[i], crc);
        !           175: 
        !           176:                        keyPool[writePos++] += (unsigned __int8) (crc >> 24);
        !           177:                        keyPool[writePos++] += (unsigned __int8) (crc >> 16);
        !           178:                        keyPool[writePos++] += (unsigned __int8) (crc >> 8);
        !           179:                        keyPool[writePos++] += (unsigned __int8) crc;
        !           180: 
        !           181:                        if (writePos >= KEYFILE_POOL_SIZE)
        !           182:                                writePos = 0;
        !           183: 
        !           184:                        if (++totalRead >= KEYFILE_MAX_READ_LEN)
        !           185:                                goto close;
        !           186:                }
        !           187:        }
        !           188: 
        !           189: close:
        !           190:        fclose (f);
        !           191: 
        !           192:        if (bTimeStampValid)
        !           193:        {
        !           194:                // Restore the keyfile timestamp
        !           195: #ifdef _WIN32
        !           196:                if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
        !           197:                        Warning ("SETFILETIME_FAILED_KEYFILE");
        !           198:                CloseHandle (src);
        !           199: #else
        !           200:                struct utimbuf u;
        !           201:                u.actime = kfStat.st_atime;
        !           202:                u.modtime = kfStat.st_atime;
        !           203:                utime (keyFile->FileName, &u);
        !           204: #endif
        !           205:        }
        !           206: 
        !           207:        return TRUE;
        !           208: }
        !           209: 
        !           210: 
        !           211: BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile, BOOL preserveTimestamp)
        !           212: {
        !           213:        BOOL status = TRUE;
        !           214:        KeyFile kfSubStruct;
        !           215:        KeyFile *kf;
        !           216:        KeyFile *kfSub = &kfSubStruct;
        !           217:        static unsigned __int8 keyPool [KEYFILE_POOL_SIZE];
        !           218:        int i;
        !           219:        struct stat statStruct;
        !           220:        char searchPath [TC_MAX_PATH*2];
        !           221: #ifdef _WIN32
        !           222:        struct _finddata_t fBuf;
        !           223:        intptr_t searchHandle;
        !           224: #else
        !           225:        struct dirent *fBuf;
        !           226:        DIR *searchHandle;
        !           227: #endif
        !           228: 
        !           229:        if (firstKeyFile == NULL) return TRUE;
        !           230: 
        !           231: #ifdef _WIN32
        !           232:        VirtualLock (keyPool, sizeof (keyPool));
        !           233: #endif
        !           234:        memset (keyPool, 0, sizeof (keyPool));
        !           235: 
        !           236:        for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
        !           237:        {
        !           238:                // Determine whether it's a path or a file
        !           239:                if (stat (kf->FileName, &statStruct) != 0)
        !           240:                {
        !           241: #ifdef _WIN32
        !           242:                        Error ("ERR_PROCESS_KEYFILE");
        !           243: #else
        !           244:                        perror ("stat");
        !           245: #endif
        !           246:                        status = FALSE;
        !           247:                        continue;
        !           248:                }
        !           249: 
        !           250:                if (statStruct.st_mode & S_IFDIR)               // If it's a directory
        !           251:                {
        !           252:                        /* Find and process all keyfiles in the directory */
        !           253: 
        !           254: #ifdef _WIN32
        !           255:                        snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName);
        !           256:                        if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1)
        !           257: #else
        !           258:                        if ((searchHandle = opendir (kf->FileName)) == NULL)
        !           259: #endif
        !           260:                        {
        !           261: #ifdef _WIN32
        !           262:                                Error ("ERR_PROCESS_KEYFILE_PATH");
        !           263: #endif
        !           264:                                status = FALSE;
        !           265:                                continue;
        !           266:                        }
        !           267: 
        !           268: #ifdef _WIN32
        !           269:                        do
        !           270: #else
        !           271:                        while ((fBuf = readdir (searchHandle)) != NULL)
        !           272: #endif
        !           273:                        {
        !           274:                                snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName,
        !           275: #ifdef _WIN32
        !           276:                                        '\\',
        !           277:                                        fBuf.name
        !           278: #else
        !           279:                                        '/',
        !           280:                                        fBuf->d_name
        !           281: #endif
        !           282:                                        );
        !           283: 
        !           284:                                // Determine whether it's a path or a file
        !           285:                                if (stat (kfSub->FileName, &statStruct) != 0)
        !           286:                                {
        !           287: #ifdef _WIN32
        !           288:                                        Error ("ERR_PROCESS_KEYFILE");
        !           289: #endif
        !           290:                                        status = FALSE;
        !           291:                                        continue;
        !           292:                                }
        !           293:                                else if (statStruct.st_mode & S_IFDIR)          // If it's a directory
        !           294:                                {
        !           295:                                        // Prevent recursive folder scanning
        !           296:                                        continue;        
        !           297:                                }
        !           298: 
        !           299: 
        !           300:                                // Apply keyfile to the pool
        !           301:                                if (!KeyFileProcess (keyPool, kfSub, preserveTimestamp))
        !           302:                                {
        !           303: #ifdef _WIN32
        !           304:                                        handleWin32Error (NULL);
        !           305:                                        Error ("ERR_PROCESS_KEYFILE");
        !           306: #endif
        !           307:                                        status = FALSE;
        !           308:                                }
        !           309: 
        !           310: #ifdef _WIN32
        !           311:                        } while (_findnext (searchHandle, &fBuf) != -1);
        !           312:                        _findclose (searchHandle);
        !           313: #else
        !           314:                        }
        !           315:                        closedir (searchHandle);
        !           316: #endif
        !           317: 
        !           318:                        burn (&kfSubStruct, sizeof (kfSubStruct));
        !           319: 
        !           320:                }
        !           321:                // Apply keyfile to the pool
        !           322:                else if (!KeyFileProcess (keyPool, kf, preserveTimestamp))
        !           323:                {
        !           324: #ifdef _WIN32
        !           325:                        handleWin32Error (NULL);
        !           326:                        Error ("ERR_PROCESS_KEYFILE");
        !           327: #endif
        !           328:                        status = FALSE;
        !           329:                }
        !           330:        }
        !           331: 
        !           332:        /* Mix the keyfile pool contents into the password */
        !           333: 
        !           334:        for (i = 0; i < (int)sizeof(keyPool); i++)
        !           335:        {
        !           336:                if (i < password->Length)
        !           337:                        password->Text[i] += keyPool[i];
        !           338:                else
        !           339:                        password->Text[i] = keyPool[i];
        !           340:        }
        !           341: 
        !           342:        if (password->Length < (int)sizeof (keyPool))
        !           343:         password->Length = sizeof (keyPool);
        !           344: 
        !           345:        burn (keyPool, sizeof (keyPool));
        !           346: 
        !           347:        return status;
        !           348: }
        !           349: 
        !           350: #ifdef _WIN32
        !           351: 
        !           352: static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile)
        !           353: {
        !           354:        KeyFile *kf;
        !           355:        LVITEM LvItem;
        !           356:        int line = 0;
        !           357:        HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
        !           358: 
        !           359:        ListView_DeleteAllItems (hList);
        !           360:        EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE);
        !           361:        EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL);
        !           362:        SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL);
        !           363: 
        !           364:        for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
        !           365:        {
        !           366:                memset (&LvItem,0,sizeof(LvItem));
        !           367:                LvItem.mask = LVIF_TEXT|LVIF_PARAM;
        !           368:                LvItem.iItem = line++;
        !           369:                LvItem.iSubItem = 0;
        !           370:                LvItem.pszText = kf->FileName;
        !           371:                LvItem.lParam = (LPARAM) kf;
        !           372:                SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
        !           373:        }
        !           374: }
        !           375: 
        !           376: #if KEYFILE_POOL_SIZE % 4 != 0
        !           377: #error KEYFILE_POOL_SIZE must be a multiple of 4
        !           378: #endif
        !           379: 
        !           380: BOOL WINAPI KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
        !           381: {
        !           382:        static KeyFilesDlgParam *param;
        !           383:        static KeyFilesDlgParam origParam;
        !           384: 
        !           385:        WORD lw = LOWORD (wParam);
        !           386: 
        !           387:        switch (msg)
        !           388:        {
        !           389:        case WM_INITDIALOG:
        !           390:                {
        !           391:                        LVCOLUMN LvCol;
        !           392:                        HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
        !           393: 
        !           394:                        param = (KeyFilesDlgParam *) lParam;
        !           395:                        origParam = *(KeyFilesDlgParam *) lParam;
        !           396: 
        !           397:                        param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile);
        !           398: 
        !           399:                        LocalizeDialog (hwndDlg, "IDD_KEYFILES");
        !           400:                        DragAcceptFiles (hwndDlg, TRUE);
        !           401: 
        !           402:                        SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
        !           403:                                LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP
        !           404:                                ); 
        !           405: 
        !           406:                        memset (&LvCol,0,sizeof(LvCol));               
        !           407:                        LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;  
        !           408:                        LvCol.pszText = "Keyfile";                           
        !           409:                        LvCol.cx = 357;
        !           410:                        LvCol.fmt = LVCFMT_LEFT;
        !           411:                        SendMessage (hList, LVM_INSERTCOLUMN, 0, (LPARAM)&LvCol);
        !           412: 
        !           413:                        LoadKeyList (hwndDlg, param->FirstKeyFile);
        !           414:                        SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles);
        !           415: 
        !           416:                        SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("IDT_KEYFILES_NOTE"));
        !           417:                }
        !           418:                return 1;
        !           419: 
        !           420:        case WM_COMMAND:
        !           421: 
        !           422:                if (lw == IDC_KEYADD)
        !           423:                {
        !           424:                        KeyFile *kf = malloc (sizeof (KeyFile));
        !           425: 
        !           426:                        if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, FALSE))
        !           427:                        {
        !           428:                                param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
        !           429:                                LoadKeyList (hwndDlg, param->FirstKeyFile);
        !           430:                        }
        !           431:                        else
        !           432:                        {
        !           433:                                free (kf);
        !           434:                        }
        !           435:                        return 1;
        !           436:                }
        !           437: 
        !           438:                if (lw == IDC_ADD_KEYFILE_PATH)
        !           439:                {
        !           440:                        KeyFile *kf = malloc (sizeof (KeyFile));
        !           441: 
        !           442:                        if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName))
        !           443:                        {
        !           444:                                param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
        !           445:                                LoadKeyList (hwndDlg, param->FirstKeyFile);
        !           446:                        }
        !           447:                        else
        !           448:                        {
        !           449:                                free (kf);
        !           450:                        }
        !           451:                        return 1;
        !           452:                }
        !           453: 
        !           454:                if (lw == IDC_KEYREMOVE)
        !           455:                {
        !           456:                        HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST);
        !           457:                        LVITEM LvItem;
        !           458:                        memset (&LvItem, 0, sizeof(LvItem));
        !           459:                        LvItem.mask = LVIF_PARAM;   
        !           460:                        LvItem.iItem = -1;
        !           461: 
        !           462:                        while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED)))
        !           463:                        {
        !           464:                                ListView_GetItem (list, &LvItem);
        !           465:                                param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam);
        !           466:                        } 
        !           467:                        
        !           468:                        LoadKeyList (hwndDlg, param->FirstKeyFile);
        !           469:                        return 1;
        !           470:                }
        !           471: 
        !           472:                if (lw == IDC_KEYREMOVEALL)
        !           473:                {
        !           474:                        KeyFileRemoveAll (&param->FirstKeyFile);
        !           475:                        LoadKeyList (hwndDlg, NULL);
        !           476:                        return 1;
        !           477:                }
        !           478: 
        !           479:                if (lw == IDC_GENERATE_KEYFILE)
        !           480:                {
        !           481:                        DialogBoxParamW (hInst, 
        !           482:                                MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg,
        !           483:                                (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0);
        !           484:                        return 1;
        !           485:                }
        !           486: 
        !           487:                if (lw == IDOK)
        !           488:                {
        !           489:                        param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE));
        !           490:                        EndDialog (hwndDlg, IDOK);
        !           491:                        return 1;
        !           492:                }
        !           493: 
        !           494:                if (lw == IDCANCEL)
        !           495:                {
        !           496:                        KeyFileRemoveAll (&param->FirstKeyFile);
        !           497:                        *param = origParam;
        !           498: 
        !           499:                        EndDialog (hwndDlg, IDCLOSE);
        !           500:                        return 1;
        !           501:                }
        !           502: 
        !           503:        case WM_DROPFILES:
        !           504:                {
        !           505:                        HDROP hdrop = (HDROP) wParam;
        !           506: 
        !           507:                        int i = 0, count = DragQueryFile (hdrop, -1, NULL, 0);
        !           508: 
        !           509:                        while (count-- > 0)
        !           510:                        {
        !           511:                                KeyFile *kf = malloc (sizeof (KeyFile));
        !           512:                                DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName));
        !           513:                                param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
        !           514:                                LoadKeyList (hwndDlg, param->FirstKeyFile);
        !           515:                        }
        !           516: 
        !           517:                        DragFinish (hdrop);
        !           518:                }
        !           519:                return 1;
        !           520: 
        !           521:        case WM_NOTIFY:
        !           522:                if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
        !           523:                {
        !           524:                        EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE),
        !           525:                                ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1);
        !           526:                        return 1;
        !           527:                }
        !           528:                break;
        !           529: 
        !           530:        case WM_CLOSE:
        !           531:                KeyFileRemoveAll (&param->FirstKeyFile);
        !           532:                *param = origParam;
        !           533: 
        !           534:                EndDialog (hwndDlg, IDCLOSE);
        !           535:                return 1;
        !           536: 
        !           537:                break;
        !           538: 
        !           539:        }
        !           540: 
        !           541:        return 0;
        !           542: }
        !           543: 
        !           544: 
        !           545: #endif /* #ifdef _WIN32 */

unix.superglobalmegacorp.com

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