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

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