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

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
                     43: // 72          4               CRC32 of disk IV and key
                     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)
                     47: // 100         156             Unused
1.1       root       48: // 256         32              Disk IV
                     49: // 288         224             Disk key
                     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       root       64:        cryptoInfo = *retInfo = crypto_open ();
                     65:        if (cryptoInfo == NULL)
                     66:                return ERR_OUTOFMEMORY;
                     67: 
1.1.1.6 ! root       68:        crypto_loadkey (&keyInfo, password->Text, password->Length);
1.1       root       69: 
                     70:        // PKCS5 is used to derive header key and IV from user password
1.1.1.6 ! root       71:        memcpy (keyInfo.key_salt, encryptedHeader + HEADER_USERKEY_SALT, PKCS5_SALT_SIZE);
1.1       root       72: 
1.1.1.3   root       73:        // Test all available PKCS5 PRFs
                     74:        for (pkcs5 = 1; pkcs5 <= LAST_PRF_ID; pkcs5++)
1.1       root       75:        {
1.1.1.6 ! root       76:                keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5);
        !            77: 
        !            78:                switch (pkcs5)
1.1.1.3   root       79:                {
1.1.1.6 ! root       80:                case SHA1:
        !            81:                        derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !            82:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !            83:                        break;
        !            84: 
        !            85:                case RIPEMD160:
        !            86:                        derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !            87:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !            88:                        break;
        !            89: 
        !            90:                case WHIRLPOOL:
        !            91:                        derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !            92:                                PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !            93:                        break;
1.1.1.4   root       94:                } 
1.1       root       95: 
1.1.1.4   root       96:                // Test all available encryption algorithms
                     97:                for (cryptoInfo->ea = EAGetFirst (); cryptoInfo->ea != 0; cryptoInfo->ea = EAGetNext (cryptoInfo->ea))
1.1.1.3   root       98:                {
1.1.1.6 ! root       99:                        // Copy header for decryption and init an encryption algorithm
        !           100:                        memcpy (header, encryptedHeader, SECTOR_SIZE);  
        !           101:                        memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);
        !           102: 
        !           103:                        status = EAInit (cryptoInfo->ea, dk + DISK_IV_SIZE, cryptoInfo->ks);
        !           104:                        if (status == ERR_CIPHER_INIT_FAILURE)
        !           105:                                goto err;
        !           106: 
        !           107:                        input = header;
        !           108: 
        !           109:                        // Try to decrypt header 
        !           110: 
        !           111:                        DecryptBuffer ((unsigned __int32 *) (header + HEADER_ENCRYPTEDDATA), HEADER_ENCRYPTEDDATASIZE,
        !           112:                                cryptoInfo->ks, cryptoInfo->iv, &cryptoInfo->iv[8], cryptoInfo->ea);
        !           113: 
        !           114:                        input += HEADER_ENCRYPTEDDATA;
        !           115: 
        !           116:                        // Magic 'TRUE'
        !           117:                        if (mgetLong (input) != 0x54525545)
        !           118:                                continue;
1.1.1.3   root      119: 
1.1.1.6 ! root      120:                        // Header version
        !           121:                        headerVersion = mgetWord (input);
        !           122: 
        !           123:                        // Required program version
        !           124:                        requiredVersion = mgetWord (input);
        !           125: 
        !           126:                        // Check CRC of disk IV and key
        !           127:                        if (mgetLong (input) != crc32 (header + HEADER_DISKKEY, DISKKEY_SIZE))
        !           128:                                continue;
        !           129: 
        !           130:                        // Now we have the correct password, cipher, hash algorithm, and volume type
        !           131: 
        !           132:                        // Check the version required to handle this volume
        !           133:                        if (requiredVersion > VERSION_NUM)
        !           134:                        {
        !           135:                                status = ERR_NEW_VERSION_REQUIRED;
        !           136:                                goto err;
1.1.1.4   root      137:                        }
1.1.1.6 ! root      138: 
        !           139:                        // Volume creation time
        !           140:                        cryptoInfo->volume_creation_time = mgetInt64 (input);
        !           141: 
        !           142:                        // Header creation time
        !           143:                        cryptoInfo->header_creation_time = mgetInt64 (input);
        !           144: 
        !           145:                        // Hidden volume size (if any)
        !           146:                        cryptoInfo->hiddenVolumeSize = mgetInt64 (input);
        !           147: 
        !           148:                        // Disk key
        !           149:                        nKeyLen = DISKKEY_SIZE;
        !           150:                        memcpy (keyInfo.key, header + HEADER_DISKKEY, nKeyLen);
        !           151: 
        !           152:                        memcpy (cryptoInfo->master_key, keyInfo.key, nKeyLen);
        !           153:                        memcpy (cryptoInfo->key_salt, keyInfo.key_salt, PKCS5_SALT_SIZE);
        !           154:                        cryptoInfo->pkcs5 = pkcs5;
        !           155:                        cryptoInfo->noIterations = keyInfo.noIterations;
        !           156: 
        !           157:                        // Init the encryption algorithm with the decrypted master key
        !           158:                        status = EAInit (cryptoInfo->ea, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);
        !           159:                        if (status == ERR_CIPHER_INIT_FAILURE)
        !           160:                                goto err;
        !           161: 
        !           162:                        // Data area IV seed
        !           163:                        memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);
        !           164: 
        !           165:                        // Clear out the temp. key buffers
        !           166:                        burn (dk, sizeof(dk));
        !           167: 
        !           168:                        return 0;
        !           169: 
1.1.1.2   root      170:                }
1.1       root      171:        }
1.1.1.6 ! root      172:        status = ERR_PASSWORD_WRONG;
1.1       root      173: 
1.1.1.6 ! root      174: err:
1.1       root      175:        crypto_close(cryptoInfo);
                    176:        burn (&keyInfo, sizeof (keyInfo));
1.1.1.6 ! root      177:        return status;
1.1       root      178: }
                    179: 
                    180: #ifndef DEVICE_DRIVER
                    181: 
                    182: #ifdef VOLFORMAT
1.1.1.3   root      183: extern BOOL showKeys;
1.1       root      184: extern HWND hDiskKey;
1.1.1.3   root      185: extern HWND hHeaderKey;
1.1       root      186: #endif
                    187: 
1.1.1.6 ! root      188: #ifdef _WIN32
        !           189: 
1.1       root      190: // VolumeWriteHeader:
                    191: // Creates volume header in memory
                    192: int
1.1.1.6 ! root      193: VolumeWriteHeader (char *header, int ea, Password *password,
1.1.1.4   root      194:                   int pkcs5, char *masterKey, unsigned __int64 volumeCreationTime, PCRYPTO_INFO * retInfo,
1.1.1.6 ! root      195:                   unsigned __int64 hiddenVolumeSize, BOOL bWipeMode)
1.1       root      196: {
                    197:        unsigned char *p = (unsigned char *) header;
1.1.1.6 ! root      198:        static KEY_INFO keyInfo;
1.1       root      199: 
1.1.1.6 ! root      200:        int nUserKeyLen = password->Length;
1.1       root      201:        PCRYPTO_INFO cryptoInfo = crypto_open ();
1.1.1.6 ! root      202:        static char dk[DISKKEY_SIZE];
1.1       root      203:        int x;
1.1.1.6 ! root      204:        int retVal = 0;
1.1       root      205: 
                    206:        if (cryptoInfo == NULL)
                    207:                return ERR_OUTOFMEMORY;
                    208: 
                    209:        memset (header, 0, SECTOR_SIZE);
1.1.1.2   root      210:        VirtualLock (&keyInfo, sizeof (keyInfo));
1.1.1.6 ! root      211:        VirtualLock (&dk, sizeof (dk));
1.1       root      212: 
1.1.1.6 ! root      213:        /* Encryption setup */
1.1       root      214: 
1.1.1.6 ! root      215:        // If necessary, generate the master key, IV and whitening seeds
1.1.1.2   root      216:        if(masterKey == 0)
                    217:                RandgetBytes (keyInfo.key, DISKKEY_SIZE, TRUE);
                    218:        else
                    219:                memcpy (keyInfo.key, masterKey, DISKKEY_SIZE);
                    220: 
1.1.1.6 ! root      221:        // User key 
        !           222:        memcpy (keyInfo.userKey, password->Text, nUserKeyLen);
1.1       root      223:        keyInfo.keyLength = nUserKeyLen;
1.1.1.6 ! root      224:        keyInfo.noIterations = get_pkcs5_iteration_count (pkcs5);
1.1       root      225: 
                    226:        // User selected encryption algorithm
1.1.1.4   root      227:        cryptoInfo->ea = ea;
1.1       root      228: 
                    229:        // Salt for header key derivation 
1.1.1.6 ! root      230:        RandgetBytes (keyInfo.key_salt, PKCS5_SALT_SIZE, !bWipeMode);
1.1       root      231: 
1.1.1.4   root      232:        // PKCS5 is used to derive the header key and IV from the password
1.1.1.6 ! root      233:        switch (pkcs5)
1.1       root      234:        {
1.1.1.6 ! root      235:        case SHA1:
        !           236:                derive_key_sha1 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !           237:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !           238:                break;
        !           239: 
        !           240:        case RIPEMD160:
        !           241:                derive_key_ripemd160 (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !           242:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !           243:                break;
        !           244: 
        !           245:        case WHIRLPOOL:
        !           246:                derive_key_whirlpool (keyInfo.userKey, keyInfo.keyLength, keyInfo.key_salt,
        !           247:                        PKCS5_SALT_SIZE, keyInfo.noIterations, dk, DISK_IV_SIZE + EAGetLargestKey());
        !           248:                break;
        !           249:        } 
1.1       root      250: 
1.1.1.6 ! root      251:        /* Header setup */
1.1       root      252: 
                    253:        // Salt
1.1.1.6 ! root      254:        mputBytes (p, keyInfo.key_salt, PKCS5_SALT_SIZE);       
1.1       root      255: 
                    256:        // Magic
                    257:        mputLong (p, 'TRUE');
                    258: 
                    259:        // Header version
1.1.1.4   root      260:        mputWord (p, VOLUME_HEADER_VERSION);
1.1       root      261: 
                    262:        // Required program version to handle this volume
1.1.1.4   root      263:        mputWord (p, VOL_REQ_PROG_VERSION);
1.1       root      264: 
                    265:        // CRC of disk key
                    266:        x = crc32(keyInfo.key, DISKKEY_SIZE);
                    267:        mputLong (p, x);
                    268: 
                    269:        // Time
                    270:        {
                    271:                SYSTEMTIME st;
                    272:                FILETIME ft;
                    273: 
                    274:                // Volume creation time
                    275:                if (volumeCreationTime == 0)
                    276:                {
                    277:                        GetLocalTime (&st);
                    278:                        SystemTimeToFileTime (&st, &ft);
                    279:                }
                    280:                else
                    281:                {
                    282:                        ft.dwHighDateTime = (DWORD)(volumeCreationTime >> 32);
                    283:                        ft.dwLowDateTime = (DWORD)volumeCreationTime;
                    284:                }
                    285:                mputLong (p, ft.dwHighDateTime);
                    286:                mputLong (p, ft.dwLowDateTime);
                    287: 
1.1.1.6 ! root      288:                // Header modification time/date
1.1       root      289:                GetLocalTime (&st);
                    290:                SystemTimeToFileTime (&st, &ft);
                    291:                mputLong (p, ft.dwHighDateTime);
                    292:                mputLong (p, ft.dwLowDateTime);
                    293:        }
                    294: 
1.1.1.4   root      295:        // Hidden volume size
                    296:        cryptoInfo->hiddenVolumeSize = hiddenVolumeSize;
                    297:        mputInt64 (p, cryptoInfo->hiddenVolumeSize);
                    298: 
1.1       root      299:        // Disk key and IV
                    300:        memcpy (header + HEADER_DISKKEY, keyInfo.key, DISKKEY_SIZE);
                    301: 
                    302: 
1.1.1.6 ! root      303:        /* Header encryption */
1.1       root      304: 
                    305:        memcpy (cryptoInfo->iv, dk, DISK_IV_SIZE);
1.1.1.6 ! root      306:        retVal = EAInit (cryptoInfo->ea, dk + DISK_IV_SIZE, cryptoInfo->ks);
        !           307:        if (retVal != 0)
        !           308:                return retVal;
1.1       root      309: 
1.1.1.6 ! root      310:        EncryptBuffer ((unsigned __int32 *) (header + HEADER_ENCRYPTEDDATA), HEADER_ENCRYPTEDDATASIZE,
1.1.1.4   root      311:                        cryptoInfo->ks, cryptoInfo->iv, &cryptoInfo->iv[8], cryptoInfo->ea);
1.1       root      312: 
                    313: 
1.1.1.6 ! root      314:        /* cryptoInfo setup for further use (disk format) */
1.1       root      315: 
1.1.1.6 ! root      316:        // Init with the master key 
        !           317:        retVal = EAInit (cryptoInfo->ea, keyInfo.key + DISK_IV_SIZE, cryptoInfo->ks);
        !           318:        if (retVal != 0)
        !           319:                return retVal;
1.1       root      320: 
                    321:        // Disk IV
                    322:        memcpy (cryptoInfo->iv, keyInfo.key, DISK_IV_SIZE);
                    323: 
1.1.1.2   root      324: 
1.1       root      325: #ifdef VOLFORMAT
1.1.1.3   root      326:        if (showKeys)
1.1       root      327:        {
                    328:                char tmp[64];
                    329:                BOOL dots3 = FALSE;
                    330:                int i, j;
                    331: 
1.1.1.4   root      332:                j = EAGetKeySize (ea);
1.1       root      333: 
1.1.1.6 ! root      334:                if (j > NBR_KEY_BYTES_TO_DISPLAY)
1.1       root      335:                {
                    336:                        dots3 = TRUE;
1.1.1.6 ! root      337:                        j = NBR_KEY_BYTES_TO_DISPLAY;
1.1       root      338:                }
                    339: 
                    340:                tmp[0] = 0;
                    341:                for (i = 0; i < j; i++)
                    342:                {
                    343:                        char tmp2[8] =
                    344:                        {0};
                    345:                        sprintf (tmp2, "%02X", (int) (unsigned char) keyInfo.key[i + DISK_IV_SIZE]);
                    346:                        strcat (tmp, tmp2);
                    347:                }
                    348: 
1.1.1.6 ! root      349:                if (dots3)
1.1       root      350:                {
                    351:                        strcat (tmp, "...");
                    352:                }
                    353: 
                    354: 
                    355:                SetWindowText (hDiskKey, tmp);
                    356: 
                    357:                tmp[0] = 0;
1.1.1.6 ! root      358:                for (i = 0; i < NBR_KEY_BYTES_TO_DISPLAY; i++)
1.1       root      359:                {
                    360:                        char tmp2[8];
1.1.1.3   root      361:                        sprintf (tmp2, "%02X", (int) (unsigned char) dk[DISK_IV_SIZE + i]);
1.1       root      362:                        strcat (tmp, tmp2);
                    363:                }
                    364: 
1.1.1.6 ! root      365:                if (dots3)
1.1.1.3   root      366:                {
                    367:                        strcat (tmp, "...");
                    368:                }
                    369: 
                    370:                SetWindowText (hHeaderKey, tmp);
1.1       root      371:        }
                    372: #endif
                    373: 
1.1.1.3   root      374:        burn (dk, sizeof(dk));
1.1       root      375:        burn (&keyInfo, sizeof (keyInfo));
                    376: 
                    377:        *retInfo = cryptoInfo;
                    378:        return 0;
                    379: }
                    380: 
1.1.1.6 ! root      381: #endif                         /* WIN32 */
        !           382: 
1.1       root      383: #endif                         /* !NT4_DRIVER */
1.1.1.4   root      384: 

unix.superglobalmegacorp.com

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