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

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:                {
1.1.1.2 ! root      391:                        LVCOLUMNW LvCol;
1.1       root      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: 
1.1.1.2 ! root      402:                        SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
1.1       root      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;  
1.1.1.2 ! root      408:                        LvCol.pszText = GetString ("KEYFILE");                           
        !           409:                        LvCol.cx = 366;
1.1       root      410:                        LvCol.fmt = LVCFMT_LEFT;
1.1.1.2 ! root      411:                        SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol);
1.1       root      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: 
1.1.1.2 ! root      426:                        if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, FALSE, FALSE))
1.1       root      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.