Annotation of truecrypt/common/volumes.c, revision 1.1.1.7

1.1.1.6   root        1: /* Legal Notice: The source code contained in this file has been derived from
                      2:    the source code of Encryption for the Masses 2.02a, which is Copyright (c)
                      3:    1998-99 Paul Le Roux and which is covered by the 'License Agreement for
                      4:    Encryption for the Masses'. Modifications and additions to that source code
                      5:    contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and
                      6:    Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0
                      7:    the full text of which is contained in the file License.txt included in
                      8:    TrueCrypt binary and source code distribution archives.  */
1.1       root        9: 
1.1.1.6   root       10: #include "Tcdefs.h"
1.1       root       11: 
                     12: #include <fcntl.h>
                     13: #include <sys/types.h>
                     14: #include <sys/stat.h>
                     15: #include <time.h>
                     16: 
1.1.1.6   root       17: #ifdef _WIN32
                     18: #include <io.h>
                     19: #include "Random.h"
                     20: #endif
                     21: 
                     22: #include "Crypto.h"
                     23: #include "Endian.h"
                     24: #include "Volumes.h"
                     25: 
                     26: #include "Pkcs5.h"
                     27: #include "Crc.h"
1.1       root       28: 
                     29: 
1.1.1.6   root       30: #define NBR_KEY_BYTES_TO_DISPLAY       16
1.1       root       31: 
                     32: 
                     33: // Volume header structure:
                     34: //
                     35: // Offset      Length  Description
                     36: // ------------------------------------------
                     37: // Unencrypted:
1.1.1.6   root       38: // 0           64              Salt
1.1       root       39: // Encrypted:
1.1.1.4   root       40: // 64          4               ASCII string 'TRUE'
1.1       root       41: // 68          2               Header version
                     42: // 70          2               Required program version
1.1.1.7 ! root       43: // 72          4               CRC-32 checksum of the (decrypted) bytes 256-511
1.1       root       44: // 76          8               Volume creation time
                     45: // 84          8               Header creation time
1.1.1.4   root       46: // 92          8               Size of hidden volume in bytes (0 = normal volume)
1.1.1.7 ! root       47: // 100         156             Reserved (set to zero)
        !            48: // 256         32              Secondary key (LRW mode)
        !            49: // 288         224             Master key(s)
1.1       root       50: 
                     51: int
1.1.1.6   root       52: VolumeReadHeader (char *encryptedHeader, Password *password, PCRYPTO_INFO *retInfo)
1.1       root       53: {
1.1.1.6   root       54:        char header[HEADER_SIZE];
1.1       root       55:        unsigned char *input = (unsigned char *) header;
                     56:        KEY_INFO keyInfo;
                     57:        PCRYPTO_INFO cryptoInfo;
1.1.1.6   root       58:        int nKeyLen;
1.1       root       59:        char dk[DISKKEY_SIZE];
                     60:        int pkcs5;
                     61:        int headerVersion, requiredVersion;
1.1.1.6   root       62:        int status;
                     63: 
1.1.1.7 ! root       64: 
1.1       root       65:        cryptoInfo = *retInfo = crypto_open ();
                     66:        if (cryptoInfo == NULL)
                     67:                return ERR_OUTOFMEMORY;
                     68: 
1.1.1.6   root       69:        crypto_loadkey (&keyInfo, password->Text, password->Length);
1.1       root       70: 
1.1.1.7 ! root       71:        // PKCS5 is used to derive the header key and the secondary header key (LRW mode) from the user password
1.1.1.6   root       72:        memcpy (keyInfo.key_salt, encryptedHeader + HEADER_USERKEY_SALT, PKCS5_SALT_SIZE);
1.1       root       73: 
1.1.1.3   root       74:        // Test all available PKCS5 PRFs
                     75:        for (pkcs5 = 1; pkcs5 <= LAST_PRF_ID; pkcs5++)
1.1       root       76:        {
1.1.1.7 ! root       77:                BOOL lrw64InitDone = FALSE;
        !            78:                BOOL lrw128InitDone = FALSE;
        !            79: 
1.1.1.6   root       80:                keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5);
                     81: 
                     82:                switch (pkcs5)
1.1.1.3   root       83:                {
1.1.1.6   root       84:                case SHA1:
                     85:                        derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                     86:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                     87:                        break;
                     88: 
                     89:                case RIPEMD160:
                     90:                        derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                     91:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                     92:                        break;
                     93: 
                     94:                case WHIRLPOOL:
                     95:                        derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                     96:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                     97:                        break;
1.1.1.4   root       98:                } 
1.1       root       99: 
1.1.1.4   root      100:                // Test all available encryption algorithms
1.1.1.7 ! root      101:                for (cryptoInfo->ea = EAGetFirst ();
        !           102:                        cryptoInfo->ea != 0;
        !           103:                        cryptoInfo->ea = EAGetNext (cryptoInfo->ea))
1.1.1.3   root      104:                {
1.1.1.7 ! root      105:                        int blockSize = CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea));
1.1.1.6   root      106: 
                    107:                        status = EAInit (cryptoInfo->ea, dk + DISK_IV_SIZE, cryptoInfo->ks);
                    108:                        if (status == ERR_CIPHER_INIT_FAILURE)
                    109:                                goto err;
                    110: 
1.1.1.7 ! root      111:                        // Test all available modes of operation
        !           112:                        for (cryptoInfo->mode = EAGetFirstMode (cryptoInfo->ea);
        !           113:                                cryptoInfo->mode != 0;
        !           114:                                cryptoInfo->mode = EAGetNextMode (cryptoInfo->ea, cryptoInfo->mode))
1.1.1.6   root      115:                        {
1.1.1.7 ! root      116:                                // Copy header for decryption and init an encryption algorithm
        !           117:                                memcpy (header, encryptedHeader, SECTOR_SIZE);  
        !           118:                                memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);
        !           119: 
        !           120:                                if (cryptoInfo->mode == LRW
        !           121:                                        && (blockSize == 8 && !lrw64InitDone || blockSize == 16 && !lrw128InitDone))
        !           122:                                {
        !           123:                                        if (!EAInitMode (cryptoInfo))
        !           124:                                        {
        !           125:                                                status = ERR_MODE_INIT_FAILED;
        !           126:                                                goto err;
        !           127:                                        }
        !           128: 
        !           129:                                        if (blockSize == 8)
        !           130:                                                lrw64InitDone = TRUE;
        !           131:                                        else if (blockSize == 16)
        !           132:                                                lrw128InitDone = TRUE;
        !           133:                                }
        !           134: 
        !           135:                                input = header;
        !           136: 
        !           137:                                // Try to decrypt header 
        !           138: 
        !           139:                                DecryptBuffer ((unsigned __int32 *) (header + HEADER_ENCRYPTEDDATA), HEADER_ENCRYPTEDDATASIZE,
        !           140:                                        cryptoInfo);
        !           141: 
        !           142:                                input += HEADER_ENCRYPTEDDATA;
        !           143: 
        !           144:                                // Magic 'TRUE'
        !           145:                                if (mgetLong (input) != 0x54525545)
        !           146:                                        continue;
        !           147: 
        !           148:                                // Header version
        !           149:                                headerVersion = mgetWord (input);
        !           150: 
        !           151:                                // Required program version
        !           152:                                requiredVersion = mgetWord (input);
        !           153: 
        !           154:                                // Check CRC of the key set
        !           155:                                if (mgetLong (input) != crc32 (header + HEADER_DISKKEY, DISKKEY_SIZE))
        !           156:                                        continue;
        !           157: 
        !           158:                                // Now we have the correct password, cipher, hash algorithm, and volume type
        !           159: 
        !           160:                                // Check the version required to handle this volume
        !           161:                                if (requiredVersion > VERSION_NUM)
        !           162:                                {
        !           163:                                        status = ERR_NEW_VERSION_REQUIRED;
        !           164:                                        goto err;
        !           165:                                }
        !           166: 
        !           167:                                // Volume creation time
        !           168:                                cryptoInfo->volume_creation_time = mgetInt64 (input);
        !           169: 
        !           170:                                // Header creation time
        !           171:                                cryptoInfo->header_creation_time = mgetInt64 (input);
        !           172: 
        !           173:                                // Hidden volume size (if any)
        !           174:                                cryptoInfo->hiddenVolumeSize = mgetInt64 (input);
        !           175: 
        !           176:                                // Disk key
        !           177:                                nKeyLen = DISKKEY_SIZE;
        !           178:                                memcpy (keyInfo.key, header + HEADER_DISKKEY, nKeyLen);
        !           179: 
        !           180:                                memcpy (cryptoInfo->master_key, keyInfo.key, nKeyLen);
        !           181:                                memcpy (cryptoInfo->key_salt, keyInfo.key_salt, PKCS5_SALT_SIZE);
        !           182:                                cryptoInfo->pkcs5 = pkcs5;
        !           183:                                cryptoInfo->noIterations = keyInfo.noIterations;
        !           184: 
        !           185:                                // Init the encryption algorithm with the decrypted master key
        !           186:                                status = EAInit (cryptoInfo->ea, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);
        !           187:                                if (status == ERR_CIPHER_INIT_FAILURE)
        !           188:                                        goto err;
        !           189: 
        !           190:                                // The secondary key (LRW mode) for the data area
        !           191:                                memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);
        !           192: 
        !           193:                                // Mode of operation
        !           194:                                if (!EAInitMode (cryptoInfo))
        !           195:                                {
        !           196:                                        status = ERR_MODE_INIT_FAILED;
        !           197:                                        goto err;
        !           198:                                }
1.1.1.6   root      199: 
1.1.1.7 ! root      200:                                // Clear out the temp. key buffers
        !           201:                                burn (dk, sizeof(dk));
1.1.1.6   root      202: 
1.1.1.7 ! root      203:                                return 0;
1.1.1.6   root      204: 
1.1.1.7 ! root      205:                        }
1.1.1.2   root      206:                }
1.1       root      207:        }
1.1.1.6   root      208:        status = ERR_PASSWORD_WRONG;
1.1       root      209: 
1.1.1.6   root      210: err:
1.1       root      211:        crypto_close(cryptoInfo);
1.1.1.7 ! root      212:        *retInfo = NULL; 
1.1       root      213:        burn (&keyInfo, sizeof (keyInfo));
1.1.1.6   root      214:        return status;
1.1       root      215: }
                    216: 
                    217: #ifndef DEVICE_DRIVER
                    218: 
                    219: #ifdef VOLFORMAT
1.1.1.3   root      220: extern BOOL showKeys;
1.1       root      221: extern HWND hDiskKey;
1.1.1.3   root      222: extern HWND hHeaderKey;
1.1       root      223: #endif
                    224: 
1.1.1.6   root      225: #ifdef _WIN32
                    226: 
1.1       root      227: // VolumeWriteHeader:
                    228: // Creates volume header in memory
                    229: int
1.1.1.7 ! root      230: VolumeWriteHeader (char *header, int ea, int mode, Password *password,
1.1.1.4   root      231:                   int pkcs5, char *masterKey, unsigned __int64 volumeCreationTime, PCRYPTO_INFO * retInfo,
1.1.1.6   root      232:                   unsigned __int64 hiddenVolumeSize, BOOL bWipeMode)
1.1       root      233: {
                    234:        unsigned char *p = (unsigned char *) header;
1.1.1.6   root      235:        static KEY_INFO keyInfo;
1.1       root      236: 
1.1.1.6   root      237:        int nUserKeyLen = password->Length;
1.1       root      238:        PCRYPTO_INFO cryptoInfo = crypto_open ();
1.1.1.6   root      239:        static char dk[DISKKEY_SIZE];
1.1       root      240:        int x;
1.1.1.6   root      241:        int retVal = 0;
1.1       root      242: 
                    243:        if (cryptoInfo == NULL)
                    244:                return ERR_OUTOFMEMORY;
                    245: 
                    246:        memset (header, 0, SECTOR_SIZE);
1.1.1.2   root      247:        VirtualLock (&keyInfo, sizeof (keyInfo));
1.1.1.6   root      248:        VirtualLock (&dk, sizeof (dk));
1.1       root      249: 
1.1.1.6   root      250:        /* Encryption setup */
1.1       root      251: 
1.1.1.7 ! root      252:        // If necessary, generate the master key and the secondary key (LRW mode)
1.1.1.2   root      253:        if(masterKey == 0)
1.1.1.7 ! root      254:        {
1.1.1.2   root      255:                RandgetBytes (keyInfo.key, DISKKEY_SIZE, TRUE);
1.1.1.7 ! root      256: 
        !           257:                // Verify that the secondary key is not weak
        !           258:                if (DetectWeakSecondaryKey (keyInfo.key, CipherGetBlockSize (EAGetFirstCipher (ea))))
        !           259:                        return ERR_CIPHER_INIT_WEAK_KEY; 
        !           260:        }
1.1.1.2   root      261:        else
                    262:                memcpy (keyInfo.key, masterKey, DISKKEY_SIZE);
                    263: 
1.1.1.6   root      264:        // User key 
                    265:        memcpy (keyInfo.userKey, password->Text, nUserKeyLen);
1.1       root      266:        keyInfo.keyLength = nUserKeyLen;
1.1.1.6   root      267:        keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5);
1.1       root      268: 
                    269:        // User selected encryption algorithm
1.1.1.4   root      270:        cryptoInfo->ea = ea;
1.1       root      271: 
1.1.1.7 ! root      272:        // Mode of operation
        !           273:        cryptoInfo->mode = mode;
        !           274: 
1.1       root      275:        // Salt for header key derivation 
1.1.1.6   root      276:        RandgetBytes (keyInfo.key_salt, PKCS5_SALT_SIZE, !bWipeMode);
1.1       root      277: 
1.1.1.7 ! root      278:        // PKCS5 is used to derive the header key and the secondary header key (LRW mode) from the password
1.1.1.6   root      279:        switch (pkcs5)
1.1       root      280:        {
1.1.1.6   root      281:        case SHA1:
                    282:                derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                    283:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                    284:                break;
                    285: 
                    286:        case RIPEMD160:
                    287:                derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                    288:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                    289:                break;
                    290: 
                    291:        case WHIRLPOOL:
                    292:                derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
                    293:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
                    294:                break;
                    295:        } 
1.1.1.7 ! root      296:        // Verify that the secondary key is not weak
        !           297:        if (DetectWeakSecondaryKey (dk, CipherGetBlockSize (EAGetFirstCipher (ea))))
        !           298:                return ERR_CIPHER_INIT_WEAK_KEY; 
        !           299: 
1.1       root      300: 
1.1.1.6   root      301:        /* Header setup */
1.1       root      302: 
                    303:        // Salt
1.1.1.6   root      304:        mputBytes (p, keyInfo.key_salt, PKCS5_SALT_SIZE);       
1.1       root      305: 
                    306:        // Magic
                    307:        mputLong (p, 'TRUE');
                    308: 
                    309:        // Header version
1.1.1.4   root      310:        mputWord (p, VOLUME_HEADER_VERSION);
1.1       root      311: 
                    312:        // Required program version to handle this volume
1.1.1.4   root      313:        mputWord (p, VOL_REQ_PROG_VERSION);
1.1       root      314: 
1.1.1.7 ! root      315:        // CRC of the key set
1.1       root      316:        x = crc32(keyInfo.key, DISKKEY_SIZE);
                    317:        mputLong (p, x);
                    318: 
                    319:        // Time
                    320:        {
                    321:                SYSTEMTIME st;
                    322:                FILETIME ft;
                    323: 
                    324:                // Volume creation time
                    325:                if (volumeCreationTime == 0)
                    326:                {
                    327:                        GetLocalTime (&st);
                    328:                        SystemTimeToFileTime (&st, &ft);
                    329:                }
                    330:                else
                    331:                {
                    332:                        ft.dwHighDateTime = (DWORD)(volumeCreationTime >> 32);
                    333:                        ft.dwLowDateTime = (DWORD)volumeCreationTime;
                    334:                }
                    335:                mputLong (p, ft.dwHighDateTime);
                    336:                mputLong (p, ft.dwLowDateTime);
                    337: 
1.1.1.6   root      338:                // Header modification time/date
1.1       root      339:                GetLocalTime (&st);
                    340:                SystemTimeToFileTime (&st, &ft);
                    341:                mputLong (p, ft.dwHighDateTime);
                    342:                mputLong (p, ft.dwLowDateTime);
                    343:        }
                    344: 
1.1.1.4   root      345:        // Hidden volume size
                    346:        cryptoInfo->hiddenVolumeSize = hiddenVolumeSize;
                    347:        mputInt64 (p, cryptoInfo->hiddenVolumeSize);
1.1.1.7 ! root      348:        cryptoInfo->hiddenVolume = cryptoInfo->hiddenVolumeSize != 0;
1.1.1.4   root      349: 
1.1.1.7 ! root      350:        // The key set
1.1       root      351:        memcpy (header + HEADER_DISKKEY, keyInfo.key, DISKKEY_SIZE);
                    352: 
                    353: 
1.1.1.6   root      354:        /* Header encryption */
1.1       root      355: 
                    356:        memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);
1.1.1.6   root      357:        retVal = EAInit (cryptoInfo->ea, dk + DISK_IV_SIZE, cryptoInfo->ks);
                    358:        if (retVal != 0)
                    359:                return retVal;
1.1       root      360: 
1.1.1.7 ! root      361:        // Mode of operation
        !           362:        if (!EAInitMode (cryptoInfo))
        !           363:                return ERR_OUTOFMEMORY;
        !           364: 
        !           365:        EncryptBuffer ((unsigned __int32 *) (header + HEADER_ENCRYPTEDDATA),
        !           366:                HEADER_ENCRYPTEDDATASIZE,
        !           367:                cryptoInfo);
1.1       root      368: 
                    369: 
1.1.1.6   root      370:        /* cryptoInfo setup for further use (disk format) */
1.1       root      371: 
1.1.1.6   root      372:        // Init with the master key 
                    373:        retVal = EAInit (cryptoInfo->ea, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);
                    374:        if (retVal != 0)
                    375:                return retVal;
1.1       root      376: 
1.1.1.7 ! root      377:        // The secondary key (LRW mode)
1.1       root      378:        memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);
                    379: 
1.1.1.7 ! root      380:        // Mode of operation
        !           381:        if (!EAInitMode (cryptoInfo))
        !           382:                return ERR_OUTOFMEMORY;
        !           383: 
1.1.1.2   root      384: 
1.1       root      385: #ifdef VOLFORMAT
1.1.1.3   root      386:        if (showKeys)
1.1       root      387:        {
                    388:                char tmp[64];
                    389:                BOOL dots3 = FALSE;
                    390:                int i, j;
                    391: 
1.1.1.4   root      392:                j = EAGetKeySize (ea);
1.1       root      393: 
1.1.1.6   root      394:                if (j > NBR_KEY_BYTES_TO_DISPLAY)
1.1       root      395:                {
                    396:                        dots3 = TRUE;
1.1.1.6   root      397:                        j = NBR_KEY_BYTES_TO_DISPLAY;
1.1       root      398:                }
                    399: 
                    400:                tmp[0] = 0;
                    401:                for (i = 0; i < j; i++)
                    402:                {
                    403:                        char tmp2[8] =
                    404:                        {0};
                    405:                        sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.key[i + DISK_IV_SIZE]);
                    406:                        strcat (tmp, tmp2);
                    407:                }
                    408: 
1.1.1.6   root      409:                if (dots3)
1.1       root      410:                {
                    411:                        strcat (tmp, "...");
                    412:                }
                    413: 
                    414: 
                    415:                SetWindowText (hDiskKey, tmp);
                    416: 
                    417:                tmp[0] = 0;
1.1.1.6   root      418:                for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++)
1.1       root      419:                {
                    420:                        char tmp2[8];
1.1.1.3   root      421:                        sprintf (tmp2, "%02X", (int) (unsigned char) dk[DISK_IV_SIZE + i]);
1.1       root      422:                        strcat (tmp, tmp2);
                    423:                }
                    424: 
1.1.1.6   root      425:                if (dots3)
1.1.1.3   root      426:                {
                    427:                        strcat (tmp, "...");
                    428:                }
                    429: 
                    430:                SetWindowText (hHeaderKey, tmp);
1.1       root      431:        }
                    432: #endif
                    433: 
1.1.1.3   root      434:        burn (dk, sizeof(dk));
1.1       root      435:        burn (&keyInfo, sizeof (keyInfo));
                    436: 
                    437:        *retInfo = cryptoInfo;
                    438:        return 0;
                    439: }
                    440: 
1.1.1.6   root      441: #endif                         /* WIN32 */
                    442: 
1.1       root      443: #endif                         /* !NT4_DRIVER */
1.1.1.4   root      444: 
1.1.1.7 ! root      445: 
        !           446: BOOL DetectWeakSecondaryKey (unsigned char *key, int len)
        !           447: {
        !           448:        int i;
        !           449: 
        !           450:        for (i = 0; i < len; i++)
        !           451:        {
        !           452:                if (key[i] != 0)
        !           453:                        return FALSE;
        !           454:        }
        !           455:        return TRUE;
        !           456: }

unix.superglobalmegacorp.com

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