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

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